From d03526fbea86e2416eeae64a3fafe81d1ccaea48 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 10 Sep 2026 21:35:36 +0100 Subject: [PATCH 001/154] feat: assign Wiser devices to room areas --- custom_components/wiser/__init__.py | 19 ++++++-- custom_components/wiser/device.py | 22 +++++++-- tests/test_device.py | 75 +++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 6 deletions(-) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index 8faf9899..246ac83e 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -11,7 +11,11 @@ from homeassistant.const import CONF_NAME from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import ConfigEntryNotReady -from homeassistant.helpers import device_registry as dr, entity_registry as er +from homeassistant.helpers import ( + area_registry as ar, + device_registry as dr, + entity_registry as er, +) from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC from .const import ( @@ -32,6 +36,7 @@ ) from .coordinator import WiserUpdateCoordinator from .device import ( + assign_device_area_if_unset, merge_legacy_hub_device, migrate_room_device, register_hub_device, @@ -260,13 +265,14 @@ def register_room_assigned_devices( ): """Register physical Wiser devices in their matching Wiser room.""" data = hass.data[DOMAIN][config_entry.entry_id][DATA] + area_registry = ar.async_get(hass) device_registry = dr.async_get(hass) for device in data.wiserhub.devices.all: room = data.wiserhub.rooms.get_by_device_id(device.id) if room is None: continue - register_room_assigned_device( + device_entry = register_room_assigned_device( device_registry, config_entry.entry_id, (DOMAIN, get_identifier(data, device.id)), @@ -277,16 +283,20 @@ def register_room_assigned_devices( model=device.product_type, sw_version=device.firmware_version, ) + assign_device_area_if_unset( + device_registry, area_registry, device_entry, room.name + ) def migrate_room_device_registry(hass: HomeAssistant, config_entry): """Migrate all logical room devices away from name-derived identifiers.""" data = hass.data[DOMAIN][config_entry.entry_id][DATA] + area_registry = ar.async_get(hass) device_registry = dr.async_get(hass) entity_registry = er.async_get(hass) for room in data.wiserhub.rooms.all: - migrate_room_device( + device_entry = migrate_room_device( device_registry, entity_registry, config_entry.entry_id, @@ -294,6 +304,9 @@ def migrate_room_device_registry(hass: HomeAssistant, config_entry): (DOMAIN, get_legacy_room_identifier(data, room.id)), get_device_name(data, room.id, "room"), ) + assign_device_area_if_unset( + device_registry, area_registry, device_entry, room.name + ) def update_hub_device_names(hass: HomeAssistant): diff --git a/custom_components/wiser/device.py b/custom_components/wiser/device.py index 778a716b..d47e2283 100644 --- a/custom_components/wiser/device.py +++ b/custom_components/wiser/device.py @@ -1,6 +1,17 @@ """Device registry helpers for the Wiser integration.""" +def assign_device_area_if_unset( + device_registry, area_registry, device, suggested_area +): + """Assign a device to its Wiser room without overriding a user area.""" + if device is None or device.area_id is not None or not suggested_area: + return device + + area = area_registry.async_get_or_create(suggested_area) + return device_registry.async_update_device(device.id, area_id=area.id) + + def register_room_assigned_device( device_registry, config_entry_id, @@ -122,9 +133,14 @@ def migrate_room_device( ) if room_device is not None: - device_registry.async_update_device( - room_device.id, new_identifiers={identifier}, name=name - ) + updates = {"new_identifiers": {identifier}, "name": name} + if ( + room_device.area_id is None + and legacy_device is not None + and legacy_device.area_id is not None + ): + updates["area_id"] = legacy_device.area_id + room_device = device_registry.async_update_device(room_device.id, **updates) if legacy_device is not None and legacy_device.id != room_device.id: for entity in list(entity_registry.entities.values()): if entity.device_id == legacy_device.id: diff --git a/tests/test_device.py b/tests/test_device.py index b137c478..367a2c4f 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -33,6 +33,24 @@ class EntityEntry: device_id: str | None +@dataclass +class AreaEntry: + """Minimal area-registry entry used by the tests.""" + + id: str + + +class AreaRegistry: + """Minimal Home Assistant area registry.""" + + def __init__(self) -> None: + self.requested = [] + + def async_get_or_create(self, name): + self.requested.append(name) + return AreaEntry(name.lower().replace(" ", "_")) + + class EntityRegistry: """Minimal Home Assistant entity registry.""" @@ -245,6 +263,41 @@ def test_registers_device_with_area_and_physical_hub_parent(self) -> None: ) +class AssignDeviceAreaIfUnsetTest(unittest.TestCase): + """Test conservative assignment of Wiser devices to areas.""" + + def test_assigns_unassigned_device_to_wiser_room_area(self) -> None: + device_registry = DeviceRegistry() + area_registry = AreaRegistry() + + result = DEVICE.assign_device_area_if_unset( + device_registry, + area_registry, + DeviceEntry("room-device"), + "Andys Bedroom", + ) + + self.assertEqual(area_registry.requested, ["Andys Bedroom"]) + self.assertEqual( + device_registry.updated, + [("room-device", {"area_id": "andys_bedroom"})], + ) + self.assertEqual(result.id, "room-device") + + def test_preserves_existing_user_area(self) -> None: + device_registry = DeviceRegistry() + area_registry = AreaRegistry() + device = DeviceEntry("room-device", area_id="custom_area") + + result = DEVICE.assign_device_area_if_unset( + device_registry, area_registry, device, "Andys Bedroom" + ) + + self.assertIs(result, device) + self.assertEqual(area_registry.requested, []) + self.assertEqual(device_registry.updated, []) + + class MigrateRoomDeviceTest(unittest.TestCase): """Test migration of logical Wiser room devices.""" @@ -311,3 +364,25 @@ def test_merges_duplicate_legacy_room_into_stable_room(self) -> None: [("sensor.temperature", {"device_id": "stable-room"})], ) self.assertEqual(registry.removed, ["legacy-room"]) + + def test_preserves_legacy_area_when_merging_duplicate_room(self) -> None: + registry = DeviceRegistry( + { + (self.identifier, self.config_entry_id): DeviceEntry("stable-room"), + (self.legacy_identifier, self.config_entry_id): DeviceEntry( + "legacy-room", area_id="custom_area" + ), + } + ) + + DEVICE.migrate_room_device( + registry, + EntityRegistry(), + self.config_entry_id, + self.identifier, + self.legacy_identifier, + "Wiser Room", + ) + + self.assertEqual(registry.updated[0][0], "stable-room") + self.assertEqual(registry.updated[0][1]["area_id"], "custom_area") From d0302eea443108b31203d928b68d38ad934d7dd0 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Fri, 11 Sep 2026 13:56:01 +0100 Subject: [PATCH 002/154] fix: use gas burner icon for estimated boiler output --- custom_components/wiser/sensor.py | 4 +++- tests/test_sensor.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index 6d4bb46f..f4d3ad96 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -1393,7 +1393,9 @@ def icon(self): return "mdi:delta" if self._sensor_key == "boiler_exhaust_temperature": return "mdi:smoke" - if self._sensor_key in {"estimated_boiler_output", "maximum_capacity_kw"}: + if self._sensor_key == "estimated_boiler_output": + return "mdi:gas-burner" + if self._sensor_key == "maximum_capacity_kw": return "mdi:flash" if self._sensor_key == "coprocessor_version": return "mdi:chip" diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 45e07b1a..3176d915 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -680,7 +680,7 @@ def test_estimated_boiler_output_uses_capacity_and_modulation(self): self.assertEqual(sensor.native_unit_of_measurement, "kW") self.assertEqual(sensor.device_class, "power") self.assertEqual(sensor.state_class, "measurement") - self.assertEqual(sensor.icon, "mdi:flash") + self.assertEqual(sensor.icon, "mdi:gas-burner") self.opentherm.operational_data.json_data["SlaveStatus"] = 0 sensor._handle_coordinator_update() From c548d6e8946fcc6fec20c995dadc37dfa2f51b64 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Fri, 11 Sep 2026 13:57:25 +0100 Subject: [PATCH 003/154] fix: use gas burner icon for boiler capacity --- custom_components/wiser/sensor.py | 2 +- tests/test_sensor.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index f4d3ad96..7c838083 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -1396,7 +1396,7 @@ def icon(self): if self._sensor_key == "estimated_boiler_output": return "mdi:gas-burner" if self._sensor_key == "maximum_capacity_kw": - return "mdi:flash" + return "mdi:gas-burner" if self._sensor_key == "coprocessor_version": return "mdi:chip" if self._sensor_key == "coprocessor_update_status": diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 3176d915..81f20f56 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -643,7 +643,7 @@ def test_delta_t_has_temperature_measurement_metadata(self): def test_additional_boiler_readings_have_native_metadata(self): readings = { "boiler_exhaust_temperature": (28, "°C", "temperature", "mdi:smoke"), - "maximum_capacity_kw": (30, "kW", "power", "mdi:flash"), + "maximum_capacity_kw": (30, "kW", "power", "mdi:gas-burner"), "minimum_modulation_level": (27, "%", None, "mdi:percent"), } for key, (value, unit, device_class, icon) in readings.items(): From b1436a439bc27166c78c943a2ac6460f8a78cc8c Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Sat, 12 Sep 2026 08:14:11 +0100 Subject: [PATCH 004/154] fix: use via_device_id for hot water switch --- custom_components/wiser/switch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/wiser/switch.py b/custom_components/wiser/switch.py index d6d2e2f2..acb4a75f 100755 --- a/custom_components/wiser/switch.py +++ b/custom_components/wiser/switch.py @@ -1104,7 +1104,7 @@ def device_info(self): }, "manufacturer": MANUFACTURER, "model": HOT_WATER.title(), - "via_device": (DOMAIN, self._data.wiserhub.system.name), + **get_hub_via_device_info(self._data), } @hub_error_handler From 94812ba4e02d53e168aba7ca80410ae2aa8a8870 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Sat, 19 Sep 2026 10:05:01 +0100 Subject: [PATCH 005/154] Add UI options for legacy device naming --- custom_components/wiser/__init__.py | 7 +- custom_components/wiser/config_flow.py | 40 +++++++- custom_components/wiser/const.py | 1 + custom_components/wiser/coordinator.py | 3 + custom_components/wiser/helpers.py | 10 ++ custom_components/wiser/strings.json | 12 ++- custom_components/wiser/translations/de.json | 12 ++- custom_components/wiser/translations/en.json | 12 ++- custom_components/wiser/translations/fr.json | 12 ++- tests/test_hub_naming.py | 42 ++++++++ tests/test_ui_options.py | 101 +++++++++++++++++++ 11 files changed, 243 insertions(+), 9 deletions(-) create mode 100644 tests/test_ui_options.py diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index 246ac83e..fe3b33a3 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -26,6 +26,7 @@ CONF_AUTOMATIONS_PASSIVE, CONF_AUTOMATIONS_PASSIVE_TEMP_INCREMENT, CONF_DEPRECATED_HW_TARGET_TEMP, + CONF_LEGACY_NAMING, DATA, DOMAIN, MANUFACTURER, @@ -117,8 +118,12 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> migrated_count, ) + if config_entry.minor_version < 5: + # Keep room context visible for installations upgrading to UI options. + new_options.setdefault(CONF_LEGACY_NAMING, True) + hass.config_entries.async_update_entry( - config_entry, options=new_options, minor_version=4, version=1 + config_entry, options=new_options, minor_version=5, version=1 ) _LOGGER.debug( diff --git a/custom_components/wiser/config_flow.py b/custom_components/wiser/config_flow.py index c7acd9a1..20043feb 100755 --- a/custom_components/wiser/config_flow.py +++ b/custom_components/wiser/config_flow.py @@ -23,6 +23,8 @@ CONF_PASSWORD, CONF_PORT, CONF_SCAN_INTERVAL, + MAJOR_VERSION, + MINOR_VERSION, UnitOfTemperature, ) from homeassistant.core import HomeAssistant, callback @@ -49,6 +51,7 @@ CONF_HEATING_BOOST_TIME, CONF_HOSTNAME, CONF_HW_BOOST_TIME, + CONF_LEGACY_NAMING, CONF_OPENTHERM_SENSORS, CONF_RESTORE_MANUAL_TEMP_OPTION, CONF_SETPOINT_MODE, @@ -115,7 +118,7 @@ class WiserFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): """ VERSION = 1 - MINOR_VERSION = 4 + MINOR_VERSION = 5 CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL def __init__(self) -> None: @@ -156,7 +159,11 @@ async def async_step_user(self, user_input=None): user_input[CONF_NAME] = validated["title"] return self.async_create_entry( - title=validated["title"], data=user_input + title=validated["title"], + data=user_input, + options={ + CONF_LEGACY_NAMING: (MAJOR_VERSION, MINOR_VERSION) < (2026, 8) + }, ) return self.async_show_form( @@ -217,7 +224,11 @@ async def async_step_zeroconf_confirm( # Add hub name to config user_input[CONF_NAME] = validated["title"] return self.async_create_entry( - title=validated["title"], data=user_input + title=validated["title"], + data=user_input, + options={ + CONF_LEGACY_NAMING: (MAJOR_VERSION, MINOR_VERSION) < (2026, 8) + }, ) return self.async_show_form( @@ -255,7 +266,7 @@ def _opentherm(self): async def async_step_init(self, user_input=None): """Handle options flow.""" - menu_options = ["main_params", "automation_params"] + menu_options = ["main_params", "automation_params", "ui_options"] if self._opentherm() is not None: menu_options.append("opentherm_sensors") return self.async_show_menu( @@ -263,6 +274,27 @@ async def async_step_init(self, user_input=None): menu_options=menu_options, ) + async def async_step_ui_options(self, user_input=None): + """Configure device naming for the Home Assistant UI.""" + if user_input is not None: + return self.async_create_entry( + data=self.config_entry.options | user_input + ) + + return self.async_show_form( + step_id="ui_options", + data_schema=vol.Schema( + { + vol.Optional( + CONF_LEGACY_NAMING, + default=self.config_entry.options.get( + CONF_LEGACY_NAMING, True + ), + ): BooleanSelector(), + } + ), + ) + async def async_step_opentherm_sensors(self, user_input=None): """Choose an OpenTherm sensor category.""" opentherm = self._opentherm() diff --git a/custom_components/wiser/const.py b/custom_components/wiser/const.py index 3bb16874..485b066b 100755 --- a/custom_components/wiser/const.py +++ b/custom_components/wiser/const.py @@ -9,6 +9,7 @@ VERSION = "3.4.21b0" DOMAIN = "wiser" +CONF_LEGACY_NAMING = "legacy_naming" DATA_WISER_CONFIG = "wiser_config" URL_BASE = "/wiser" diff --git a/custom_components/wiser/coordinator.py b/custom_components/wiser/coordinator.py index 9905137b..b8d316ef 100644 --- a/custom_components/wiser/coordinator.py +++ b/custom_components/wiser/coordinator.py @@ -38,6 +38,7 @@ CONF_HEATING_BOOST_TEMP, CONF_HEATING_BOOST_TIME, CONF_HW_BOOST_TIME, + CONF_LEGACY_NAMING, CONF_RESTORE_MANUAL_TEMP_OPTION, CONF_SETPOINT_MODE, CUSTOM_DATA_STORE, @@ -113,6 +114,8 @@ def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry) -> None: self.minimum_temp = TEMP_MINIMUM self.maximum_temp = TEMP_MAXIMUM + self.legacy_naming = config_entry.options.get(CONF_LEGACY_NAMING, True) + # Main option params self.boost_temp = config_entry.options.get( CONF_HEATING_BOOST_TEMP, DEFAULT_BOOST_TEMP diff --git a/custom_components/wiser/helpers.py b/custom_components/wiser/helpers.py index 1275f3f2..24cc8b09 100644 --- a/custom_components/wiser/helpers.py +++ b/custom_components/wiser/helpers.py @@ -68,6 +68,7 @@ async def wrapper(*args, **kwargs): def get_device_name(data, device_id, device_type="device"): + legacy_naming = getattr(data, "legacy_naming", False) if device_type == "device": device = data.wiserhub.devices.get_by_id(device_id) @@ -90,6 +91,8 @@ def get_device_name(data, device_id, device_type="device"): if device.product_type == "RoomStat": device_room = data.wiserhub.rooms.get_by_device_id(device_id) if device_room: + if legacy_naming: + return f"{ENTITY_PREFIX} Thermostat {device_room.name}" return f"{ENTITY_PREFIX} Thermostat" return f"{ENTITY_PREFIX} Thermostat {device.id}" @@ -126,6 +129,10 @@ def get_device_name(data, device_id, device_type="device"): return f"{ENTITY_PREFIX} {device.product_type} {device.name}" if device.product_type == "TemperatureHumiditySensor": + if legacy_naming: + device_room = data.wiserhub.rooms.get_by_device_id(device_id) + suffix = device_room.name if device_room else device.name + return f"{ENTITY_PREFIX} Temperature/Humidity Sensor {suffix}" return f"{ENTITY_PREFIX} Temperature/Humidity Sensor" if device.product_type in [ @@ -146,6 +153,9 @@ def get_device_name(data, device_id, device_type="device"): return f"{ENTITY_PREFIX} {device.serial_number}" elif device_type == "room": + if legacy_naming: + room = data.wiserhub.rooms.get_by_id(device_id) + return f"{ENTITY_PREFIX} {room.name}" return f"{ENTITY_PREFIX} Room" else: diff --git a/custom_components/wiser/strings.json b/custom_components/wiser/strings.json index 02e4f87c..fe7b8324 100755 --- a/custom_components/wiser/strings.json +++ b/custom_components/wiser/strings.json @@ -41,7 +41,17 @@ "menu_options": { "main_params": "Main Parameters", "automation_params": "Automation Parameters", - "opentherm_sensors": "OpenTherm sensors" + "opentherm_sensors": "OpenTherm sensors", + "ui_options": "UI options" + } + }, + "ui_options": { + "title": "UI options", + "data": { + "legacy_naming": "Legacy naming" + }, + "data_description": { + "legacy_naming": "Include room names in Wiser device names. If enabled, using Home Assistant to regenerate entity IDs with the default format in Settings → System → Entity ID format (Home Assistant 2026.8 and later) will duplicate area names when the area and Wiser room names match. Changing this option does not rename existing entity IDs." } }, "main_params": { diff --git a/custom_components/wiser/translations/de.json b/custom_components/wiser/translations/de.json index d0107c82..63d5de74 100644 --- a/custom_components/wiser/translations/de.json +++ b/custom_components/wiser/translations/de.json @@ -41,7 +41,17 @@ "menu_options": { "main_params": "Hauptparameter", "automation_params": "Aktivieren Sie integrierte Automatisierungen", - "opentherm_sensors": "OpenTherm-Sensoren" + "opentherm_sensors": "OpenTherm-Sensoren", + "ui_options": "UI-Optionen" + } + }, + "ui_options": { + "title": "UI-Optionen", + "data": { + "legacy_naming": "Bisherige Namensgebung" + }, + "data_description": { + "legacy_naming": "Raumnamen in Wiser-Gerätenamen aufnehmen. Wenn diese Option aktiviert ist, werden Bereichsnamen beim Neuerstellen der Entitäts-IDs mit dem Standardformat unter Einstellungen → System → Entitäts-ID-Format (Home Assistant 2026.8 und neuer) doppelt verwendet, wenn Bereichs- und Wiser-Raumname übereinstimmen. Diese Option ändert keine bestehenden Entitäts-IDs." } }, "main_params": { diff --git a/custom_components/wiser/translations/en.json b/custom_components/wiser/translations/en.json index 5ba00193..9d79e073 100755 --- a/custom_components/wiser/translations/en.json +++ b/custom_components/wiser/translations/en.json @@ -41,7 +41,17 @@ "menu_options": { "main_params": "Main Parameters", "automation_params": "Automation Parameters", - "opentherm_sensors": "OpenTherm sensors" + "opentherm_sensors": "OpenTherm sensors", + "ui_options": "UI options" + } + }, + "ui_options": { + "title": "UI options", + "data": { + "legacy_naming": "Legacy naming" + }, + "data_description": { + "legacy_naming": "Include room names in Wiser device names. If enabled, using Home Assistant to regenerate entity IDs with the default format in Settings → System → Entity ID format (Home Assistant 2026.8 and later) will duplicate area names when the area and Wiser room names match. Changing this option does not rename existing entity IDs." } }, "main_params": { diff --git a/custom_components/wiser/translations/fr.json b/custom_components/wiser/translations/fr.json index 4d9a6475..56b07641 100644 --- a/custom_components/wiser/translations/fr.json +++ b/custom_components/wiser/translations/fr.json @@ -41,7 +41,17 @@ "menu_options": { "main_params": "Paramètres principaux", "automation_params": "Paramètres d'automatisation", - "opentherm_sensors": "Capteurs OpenTherm" + "opentherm_sensors": "Capteurs OpenTherm", + "ui_options": "Options de l’interface" + } + }, + "ui_options": { + "title": "Options de l’interface", + "data": { + "legacy_naming": "Nommage historique" + }, + "data_description": { + "legacy_naming": "Inclure le nom des pièces dans le nom des appareils Wiser. Si cette option est activée, la régénération des identifiants d’entité avec le format par défaut dans Paramètres → Système → Format des identifiants d’entité (Home Assistant 2026.8 et versions ultérieures) répétera le nom de la zone si celui-ci correspond au nom de la pièce Wiser. Cette option ne renomme pas les identifiants d’entité existants." } }, "main_params": { diff --git a/tests/test_hub_naming.py b/tests/test_hub_naming.py index 3a1f2e16..9a57f2e3 100644 --- a/tests/test_hub_naming.py +++ b/tests/test_hub_naming.py @@ -194,6 +194,48 @@ def test_roomstat_name_uses_area_for_room_context(self) -> None: "WiserHeatNOTUSED Wiser RoomStat Andys Bedroom", ) + def test_legacy_naming_restores_room_context_without_changing_identity(self): + for device_type, device_id, expected in ( + ("room", 7, "Wiser Andys Bedroom"), + ("device", 21, "Wiser Thermostat Andys Bedroom"), + ): + self.data.legacy_naming = False + identifier = self.helpers.get_identifier(self.data, device_id, device_type) + unique_id = self.helpers.get_unique_id(self.data, "sensor", "Temperature", device_id) + self.data.legacy_naming = True + self.assertEqual( + self.helpers.get_device_name(self.data, device_id, device_type), expected + ) + self.assertEqual( + self.helpers.get_identifier(self.data, device_id, device_type), identifier + ) + self.assertEqual( + self.helpers.get_unique_id(self.data, "sensor", "Temperature", device_id), unique_id + ) + + def test_legacy_temperature_sensor_name_and_unassigned_fallback(self): + self.data.wiserhub.devices.get_by_id = lambda device_id: SimpleNamespace( + id=device_id, name="Sensor 31", product_type="TemperatureHumiditySensor" + ) + self.data.legacy_naming = False + identifier = self.helpers.get_identifier(self.data, 31) + self.data.legacy_naming = True + self.assertEqual( + self.helpers.get_device_name(self.data, 31), + "Wiser Temperature/Humidity Sensor Andys Bedroom", + ) + self.assertEqual(self.helpers.get_identifier(self.data, 31), identifier) + self.data.wiserhub.rooms.get_by_device_id = lambda _id: None + self.assertEqual( + self.helpers.get_device_name(self.data, 31), + "Wiser Temperature/Humidity Sensor Sensor 31", + ) + self.data.legacy_naming = False + self.assertEqual( + self.helpers.get_device_name(self.data, 31), + "Wiser Temperature/Humidity Sensor", + ) + def test_physical_device_suggests_its_wiser_room_as_area(self) -> None: self.assertEqual( self.helpers.get_device_area_info(self.data, 21), diff --git a/tests/test_ui_options.py b/tests/test_ui_options.py new file mode 100644 index 00000000..11a34c1a --- /dev/null +++ b/tests/test_ui_options.py @@ -0,0 +1,101 @@ +"""Exercise UI options and migrations without requiring a running HA instance.""" + +from __future__ import annotations + +import ast +import logging +from pathlib import Path +from types import SimpleNamespace +import unittest +from unittest.mock import AsyncMock, Mock + +COMPONENT = Path(__file__).parents[1] / "custom_components/wiser" + + +def load_functions(filename, names, namespace): + """Execute actual flow/migration methods with minimal HA dependencies.""" + tree = ast.parse((COMPONENT / filename).read_text()) + functions = [ + node for node in ast.walk(tree) + if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)) + and node.name in names + ] + for node in functions: + node.decorator_list = [] + module = ast.Module(body=functions, type_ignores=[]) + exec(compile(module, filename, "exec", dont_inherit=True), namespace) + return SimpleNamespace(**namespace) + + +class UIOptionsTest(unittest.IsolatedAsyncioTestCase): + def setUp(self): + self.namespace = { + "CONF_LEGACY_NAMING": "legacy_naming", + "CONF_NAME": "name", + "HomeAssistant": object, + "ConfigEntry": object, + "FlowResult": dict, + "Any": object, + "_LOGGER": logging.getLogger(__name__), + "validate_input": AsyncMock(return_value={"title": "Wiser", "unique_id": "1"}), + "MAJOR_VERSION": 2026, + "MINOR_VERSION": 8, + } + + async def test_new_manual_and_discovered_install_defaults(self): + for method in ("async_step_user", "async_step_zeroconf_confirm"): + for version, expected in (((2025, 12), True), ((2026, 7), True), + ((2026, 8), False), ((2026, 9), False), + ((2027, 1), False)): + with self.subTest(method=method, version=version): + self.namespace.update(MAJOR_VERSION=version[0], MINOR_VERSION=version[1]) + functions = load_functions("config_flow.py", {method}, self.namespace) + flow = SimpleNamespace( + hass=object(), async_set_unique_id=AsyncMock(), + _abort_if_unique_id_configured=Mock(), + async_create_entry=lambda **kwargs: kwargs, + ) + result = await getattr(functions, method)(flow, {"host": "test"}) + self.assertEqual(result["options"], {"legacy_naming": expected}) + + async def test_migration_enables_legacy_and_preserves_other_options(self): + functions = load_functions("__init__.py", {"async_migrate_entry"}, self.namespace) + for options, expected in (({"scan_interval": 30}, True), + ({"legacy_naming": False}, False)): + entry = SimpleNamespace(version=1, minor_version=4, options=options) + update = Mock() + hass = SimpleNamespace(config_entries=SimpleNamespace(async_update_entry=update)) + self.assertTrue(await functions.async_migrate_entry(hass, entry)) + saved = update.call_args.kwargs + self.assertEqual(saved["options"], options | {"legacy_naming": expected}) + self.assertEqual(saved["minor_version"], 5) + + async def test_menu_available_without_opentherm(self): + functions = load_functions("config_flow.py", {"async_step_init"}, self.namespace) + flow = SimpleNamespace(_opentherm=lambda: None, async_show_menu=lambda **kw: kw) + result = await functions.async_step_init(flow) + self.assertIn("ui_options", result["menu_options"]) + + async def test_saving_ui_options_preserves_other_options(self): + functions = load_functions("config_flow.py", {"async_step_ui_options"}, self.namespace) + for enabled in (False, True): + flow = SimpleNamespace( + config_entry=SimpleNamespace(options={"scan_interval": 30}), + async_create_entry=lambda **kwargs: kwargs, + ) + result = await functions.async_step_ui_options(flow, {"legacy_naming": enabled}) + self.assertEqual(result["data"], {"scan_interval": 30, "legacy_naming": enabled}) + + async def test_form_uses_saved_preference(self): + self.namespace.update( + vol=SimpleNamespace(Optional=lambda key, default: (key, default), Schema=lambda data: data), + BooleanSelector=lambda: bool, + ) + functions = load_functions("config_flow.py", {"async_step_ui_options"}, self.namespace) + for enabled in (False, True): + flow = SimpleNamespace( + config_entry=SimpleNamespace(options={"legacy_naming": enabled}), + async_show_form=lambda **kwargs: kwargs, + ) + result = await functions.async_step_ui_options(flow) + self.assertIn(("legacy_naming", enabled), result["data_schema"]) From b2416c22b33a8f5875bcbccfb8a08cd56cb88deb Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Sat, 12 Sep 2026 13:46:47 +0100 Subject: [PATCH 006/154] feat: add configurable Wiser schedules sidebar panel --- README.md | 4 + custom_components/wiser/__init__.py | 8 +- custom_components/wiser/config_flow.py | 5 + custom_components/wiser/const.py | 4 +- custom_components/wiser/frontend/sidebar.py | 131 + .../wiser/frontend/wiser-schedule-card.js | 3872 +++++++---------- custom_components/wiser/strings.json | 1 + custom_components/wiser/translations/de.json | 1 + custom_components/wiser/translations/en.json | 1 + custom_components/wiser/translations/fr.json | 1 + custom_components/wiser/websockets.py | 17 + tests/test_schedule_card_hide_hw_schedule.py | 151 +- tests/test_schedules_sidebar.py | 185 + 13 files changed, 1921 insertions(+), 2460 deletions(-) create mode 100644 custom_components/wiser/frontend/sidebar.py create mode 100644 tests/test_schedules_sidebar.py diff --git a/README.md b/README.md index 8bafdf60..aff61649 100755 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ For the latest version of the Wiser Home Assistant Platform please install via H **This integration requires a minimum HA version of 2025.5.** +To open the schedule editor in a dedicated sidebar panel, go to **Settings → Devices & services → Wiser → Configure → Main Parameters** and enable **Show Wiser Schedules in sidebar**. The option is off by default. With multiple hubs, the panel shows schedules for each hub with this option enabled. Use the cog in the panel header to edit its display settings (administrators only). These are saved in the integration configuration for backups and are separate from the configuration of schedule cards on dashboards. + Detailed information about this integration has now been moved to our [Wiki pages](https://github.com/asantaga/wiserHomeAssistantPlatform/wiki) For more information checkout the AMAZING community thread available on @@ -217,3 +219,5 @@ For more information checkout the AMAZING community thread available on - Reduced log error level for failed update form hub to warning A full change log can be seen on our wiki [here](https://github.com/asantaga/wiserHomeAssistantPlatform/wiki/Full-Change-Log) + +The sidebar panel is built together with the schedule card in the `wiser-schedule-card` repository. The integration distributes that matching bundle; it does not maintain a separate panel JavaScript source. diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index fe3b33a3..0b75cfc6 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -45,6 +45,9 @@ ) from .entity_migration import migrate_entity_unique_ids from .frontend import JSModuleRegistration +from .frontend.sidebar import ( + async_handle_entry_update, async_update_schedules_panel, integration_reload_settings, +) from .helpers import ( build_light_unique_id_migration, get_device_name, @@ -194,6 +197,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): hass.data[DOMAIN][config_entry.entry_id] = { DATA: coordinator, UPDATE_LISTENER: update_listener, + "reload_settings": integration_reload_settings(config_entry), } update_hub_device_names(hass) @@ -229,6 +233,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): # Register custom cards moodule_register = JSModuleRegistration(hass) await moodule_register.async_register() + await async_update_schedules_panel(hass) _LOGGER.info( "Wiser Component Setup Completed (%s)", coordinator.wiserhub.system.name @@ -334,7 +339,7 @@ def update_hub_device_names(hass: HomeAssistant): async def _async_update_listener(hass: HomeAssistant, config_entry): """Handle options update.""" - await hass.config_entries.async_reload(config_entry.entry_id) + await async_handle_entry_update(hass, config_entry) async def async_remove_config_entry_device( @@ -386,6 +391,7 @@ async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry): _LOGGER.debug("Unload integration") if unload_ok: hass.data[DOMAIN].pop(config_entry.entry_id) + await async_update_schedules_panel(hass) update_hub_device_names(hass) return unload_ok diff --git a/custom_components/wiser/config_flow.py b/custom_components/wiser/config_flow.py index 20043feb..a740b591 100755 --- a/custom_components/wiser/config_flow.py +++ b/custom_components/wiser/config_flow.py @@ -55,6 +55,7 @@ CONF_OPENTHERM_SENSORS, CONF_RESTORE_MANUAL_TEMP_OPTION, CONF_SETPOINT_MODE, + CONF_SHOW_SCHEDULES_SIDEBAR, CUSTOM_DATA_STORE, DEFAULT_BOOST_TEMP, DEFAULT_BOOST_TEMP_TIME, @@ -391,6 +392,10 @@ async def async_step_main_params(self, user_input=None): return self.async_create_entry(data=options) data_schema = { + vol.Optional( + CONF_SHOW_SCHEDULES_SIDEBAR, + default=self.config_entry.options.get(CONF_SHOW_SCHEDULES_SIDEBAR, False), + ): BooleanSelector(), vol.Required(CONF_HOST, default=self.config_entry.data[CONF_HOST]): str, vol.Optional( CONF_PORT, default=self.config_entry.data.get(CONF_PORT, 80) diff --git a/custom_components/wiser/const.py b/custom_components/wiser/const.py index 485b066b..2a147677 100755 --- a/custom_components/wiser/const.py +++ b/custom_components/wiser/const.py @@ -12,12 +12,14 @@ CONF_LEGACY_NAMING = "legacy_naming" DATA_WISER_CONFIG = "wiser_config" URL_BASE = "/wiser" +CONF_SHOW_SCHEDULES_SIDEBAR = "show_schedules_sidebar" +CONF_SCHEDULES_PANEL_CONFIG = "schedules_panel_config" JSMODULES = [ { "name": "Wiser Schedule Card", "filename": "wiser-schedule-card.js", - "version": "1.5.6", + "version": "2.0.0-dev.60", }, { "name": "Wiser Zigbee Card", diff --git a/custom_components/wiser/frontend/sidebar.py b/custom_components/wiser/frontend/sidebar.py new file mode 100644 index 00000000..27f7aee2 --- /dev/null +++ b/custom_components/wiser/frontend/sidebar.py @@ -0,0 +1,131 @@ +"""Manage the shared Wiser schedules sidebar panel.""" + +from homeassistant.components import frontend, panel_custom + +from ..const import ( + CONF_SHOW_SCHEDULES_SIDEBAR, CONF_SCHEDULES_PANEL_CONFIG, + DATA, DOMAIN, JSMODULES, URL_BASE, +) + +PANEL_PATH = "wiser-schedules" +PANEL_STATE = "wiser_schedules_panel" + + +async def async_update_schedules_panel(hass): + """Show schedules for loaded hubs that have opted into the sidebar.""" + loaded = hass.data.get(DOMAIN, {}) + hubs = [ + loaded[entry.entry_id][DATA].wiserhub.system.name + for entry in hass.config_entries.async_entries(DOMAIN) + if entry.entry_id in loaded + and not entry.disabled_by + and entry.options.get(CONF_SHOW_SCHEDULES_SIDEBAR, False) + ] + card_configs = { + loaded[entry.entry_id][DATA].wiserhub.system.name: + dict(entry.options.get(CONF_SCHEDULES_PANEL_CONFIG, {})) + for entry in hass.config_entries.async_entries(DOMAIN) + if entry.entry_id in loaded + and loaded[entry.entry_id][DATA].wiserhub.system.name in hubs + } + state = {"hubs": hubs, "card_configs": card_configs} + if state == hass.data.get(PANEL_STATE) or (not hubs and PANEL_STATE not in hass.data): + return + + if not hubs and PANEL_STATE in hass.data: + frontend.async_remove_panel(hass, PANEL_PATH) + hass.data.pop(PANEL_STATE) + + if hubs: + card = next( + module for module in JSMODULES + if module["filename"] == "wiser-schedule-card.js" + ) + config = { + **state, + "card_url": f"{URL_BASE}/{card['filename']}?v={card['version']}", + } + module_url = config["card_url"] + if PANEL_STATE in hass.data: + # Keep the route registered while notifying clients of new settings. + frontend.async_register_built_in_panel( + hass, + component_name="custom", + frontend_url_path=PANEL_PATH, + sidebar_title="Wiser Schedules", + sidebar_icon="mdi:calendar-clock", + config={ + **config, + "_panel_custom": { + "name": "wiser-schedules-panel", + "module_url": module_url, + "embed_iframe": False, + "trust_external": False, + }, + }, + update=True, + ) + else: + await panel_custom.async_register_panel( + hass, + frontend_url_path=PANEL_PATH, + webcomponent_name="wiser-schedules-panel", + sidebar_title="Wiser Schedules", + sidebar_icon="mdi:calendar-clock", + module_url=module_url, + config=config, + ) + hass.data[PANEL_STATE] = state + + +def save_schedules_panel_config(hass, configs): + """Validate all submitted settings before updating integration options.""" + loaded = hass.data.get(DOMAIN, {}) + entries = { + loaded[entry.entry_id][DATA].wiserhub.system.name: entry + for entry in hass.config_entries.async_entries(DOMAIN) + if entry.entry_id in loaded + and not entry.disabled_by + and entry.options.get(CONF_SHOW_SCHEDULES_SIDEBAR, False) + } + field_types = { + "name": str, "selected_schedule": str, "view_type": str, "home_screen": str, + "theme_colors": bool, "show_badges": bool, "show_schedule_id": bool, + "display_only": bool, "hide_hw_schedule": bool, "admin_only": bool, + "hide_card_borders": bool, "hide_card_background": bool, "overview_details": bool, + } + updates = [] + for hub, config in configs.items(): + if hub not in entries: + raise ValueError("Hub is not enabled in the schedules panel") + settings = {} + for key, value in config.items(): + if key in {"type", "hub"}: + continue + if key not in field_types or type(value) is not field_types[key]: + raise ValueError(f"Invalid schedule card setting: {key}") + settings[key] = value + updates.append((entries[hub], settings)) + for entry, settings in updates: + hass.config_entries.async_update_entry( + entry, options={**entry.options, CONF_SCHEDULES_PANEL_CONFIG: settings} + ) + + +def integration_reload_settings(entry): + """Capture connection and entity options, excluding panel-only preferences.""" + return ( + dict(entry.data), + {key: value for key, value in entry.options.items() + if key != CONF_SCHEDULES_PANEL_CONFIG}, + ) + + +async def async_handle_entry_update(hass, entry): + """Apply panel preferences live; retain reloads for other integration changes.""" + loaded = hass.data.get(DOMAIN, {}).get(entry.entry_id) + settings = integration_reload_settings(entry) + if loaded is not None and loaded.get("reload_settings") == settings: + await async_update_schedules_panel(hass) + return + await hass.config_entries.async_reload(entry.entry_id) diff --git a/custom_components/wiser/frontend/wiser-schedule-card.js b/custom_components/wiser/frontend/wiser-schedule-card.js index 86522707..74fe1ace 100644 --- a/custom_components/wiser/frontend/wiser-schedule-card.js +++ b/custom_components/wiser/frontend/wiser-schedule-card.js @@ -1,47 +1,787 @@ -var wiserschedulecard=function(t){"use strict";var e=function(t,i){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&(t[i]=e[i])},e(t,i)};function i(t,i){if("function"!=typeof i&&null!==i)throw new TypeError("Class extends value "+String(i)+" is not a constructor or null");function s(){this.constructor=t}e(t,i),t.prototype=null===i?Object.create(i):(s.prototype=i.prototype,new s)}var s=function(){return s=Object.assign||function(t){for(var e,i=1,s=arguments.length;i=0;a--)(n=t[a])&&(o=(r<3?n(o):r>3?n(e,i,o):n(e,i))||o);return r>3&&o&&Object.defineProperty(e,i,o),o}function r(t){var e="function"==typeof Symbol&&Symbol.iterator,i=e&&t[e],s=0;if(i)return i.call(t);if(t&&"number"==typeof t.length)return{next:function(){return t&&s>=t.length&&(t=void 0),{value:t&&t[s++],done:!t}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}"function"==typeof SuppressedError&&SuppressedError; -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const o=globalThis,a=o.ShadowRoot&&(void 0===o.ShadyCSS||o.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,l=Symbol(),d=new WeakMap;let c=class{constructor(t,e,i){if(this._$cssResult$=!0,i!==l)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(a&&void 0===t){const i=void 0!==e&&1===e.length;i&&(t=d.get(e)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&d.set(e,t))}return t}toString(){return this.cssText}};const h=(t,...e)=>{const i=1===t.length?t[0]:e.reduce((e,i,s)=>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[s+1],t[0]);return new c(i,t,l)},p=(t,e)=>{if(a)t.adoptedStyleSheets=e.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(const i of e){const e=document.createElement("style"),s=o.litNonce;void 0!==s&&e.setAttribute("nonce",s),e.textContent=i.cssText,t.appendChild(e)}},u=a?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new c("string"==typeof t?t:t+"",void 0,l))(e)})(t):t,{is:m,defineProperty:f,getOwnPropertyDescriptor:g,getOwnPropertyNames:v,getOwnPropertySymbols:_,getPrototypeOf:b}=Object,y=globalThis,x=y.trustedTypes,$=x?x.emptyScript:"",w=y.reactiveElementPolyfillSupport,A=(t,e)=>t,E={toAttribute(t,e){switch(e){case Boolean:t=t?$: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}},S=(t,e)=>!m(t,e),C={attribute:!0,type:String,converter:E,reflect:!1,useDefault:!1,hasChanged:S}; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */Symbol.metadata??=Symbol("metadata"),y.litPropertyMetadata??=new WeakMap;let T=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=C){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(),s=this.getPropertyDescriptor(t,i,e);void 0!==s&&f(this.prototype,t,s)}}static getPropertyDescriptor(t,e,i){const{get:s,set:n}=g(this.prototype,t)??{get(){return this[e]},set(t){this[e]=t}};return{get:s,set(e){const r=s?.call(this);n?.call(this,e),this.requestUpdate(t,r,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??C}static _$Ei(){if(this.hasOwnProperty(A("elementProperties")))return;const t=b(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(A("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(A("properties"))){const t=this.properties,e=[...v(t),..._(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(u(t))}else void 0!==t&&e.push(u(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 p(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),s=this.constructor._$Eu(t,i);if(void 0!==s&&!0===i.reflect){const n=(void 0!==i.converter?.toAttribute?i.converter:E).toAttribute(e,i.type);this._$Em=t,null==n?this.removeAttribute(s):this.setAttribute(s,n),this._$Em=null}}_$AK(t,e){const i=this.constructor,s=i._$Eh.get(t);if(void 0!==s&&this._$Em!==s){const t=i.getPropertyOptions(s),n="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:E;this._$Em=s;const r=n.fromAttribute(e,t.type);this[s]=r??this._$Ej?.get(s)??r,this._$Em=null}}requestUpdate(t,e,i){if(void 0!==t){const s=this.constructor,n=this[t];if(i??=s.getPropertyOptions(t),!((i.hasChanged??S)(n,e)||i.useDefault&&i.reflect&&n===this._$Ej?.get(t)&&!this.hasAttribute(s._$Eu(t,i))))return;this.C(t,e,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(t,e,{useDefault:i,reflect:s,wrapped:n},r){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,r??e??this[t]),!0!==n||void 0!==r)||(this._$AL.has(t)||(this.hasUpdated||i||(e=void 0),this._$AL.set(t,e)),!0===s&&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}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),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){const{wrapped:t}=i,s=this[e];!0!==t||this._$AL.has(e)||void 0===s||this.C(e,void 0,i,s)}}let t=!1;const e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),this._$EO?.forEach(t=>t.hostUpdate?.()),this.update(e)):this._$EM()}catch(e){throw t=!1,this._$EM(),e}t&&this._$AE(e)}willUpdate(t){}_$AE(t){this._$EO?.forEach(t=>t.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach(t=>this._$ET(t,this[t])),this._$EM()}updated(t){}firstUpdated(t){}};T.elementStyles=[],T.shadowRootOptions={mode:"open"},T[A("elementProperties")]=new Map,T[A("finalized")]=new Map,w?.({ReactiveElement:T}),(y.reactiveElementVersions??=[]).push("2.1.1"); -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const I=globalThis,O=I.trustedTypes,k=O?O.createPolicy("lit-html",{createHTML:t=>t}):void 0,R="$lit$",P=`lit$${Math.random().toFixed(9).slice(2)}$`,L="?"+P,M=`<${L}>`,N=document,D=()=>N.createComment(""),H=t=>null===t||"object"!=typeof t&&"function"!=typeof t,U=Array.isArray,z="[ \t\n\f\r]",F=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,B=/-->/g,V=/>/g,j=RegExp(`>|${z}(?:([^\\s"'>=/]+)(${z}*=${z}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),W=/'/g,q=/"/g,Y=/^(?:script|style|textarea|title)$/i,X=(t=>(e,...i)=>({_$litType$:t,strings:e,values:i}))(1),G=Symbol.for("lit-noChange"),K=Symbol.for("lit-nothing"),J=new WeakMap,Z=N.createTreeWalker(N,129);function Q(t,e){if(!U(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==k?k.createHTML(e):e}let tt=class t{constructor({strings:e,_$litType$:i},s){let n;this.parts=[];let r=0,o=0;const a=e.length-1,l=this.parts,[d,c]=((t,e)=>{const i=t.length-1,s=[];let n,r=2===e?"":3===e?"":"",o=F;for(let e=0;e"===l[0]?(o=n??F,d=-1):void 0===l[1]?d=-2:(d=o.lastIndex-l[2].length,a=l[1],o=void 0===l[3]?j:'"'===l[3]?q:W):o===q||o===W?o=j:o===B||o===V?o=F:(o=j,n=void 0);const h=o===j&&t[e+1].startsWith("/>")?" ":"";r+=o===F?i+M:d>=0?(s.push(a),i.slice(0,d)+R+i.slice(d)+P+h):i+P+(-2===d?e:h)}return[Q(t,r+(t[i]||"")+(2===e?"":3===e?"":"")),s]})(e,i);if(this.el=t.createElement(d,s),Z.currentNode=this.el.content,2===i||3===i){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(n=Z.nextNode())&&l.length0){n.textContent=O?O.emptyScript:"";for(let i=0;iU(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!==K&&H(this._$AH)?this._$AA.nextSibling.data=t:this.T(N.createTextNode(t)),this._$AH=t}$(t){const{values:e,_$litType$:i}=t,s="number"==typeof i?this._$AC(t):(void 0===i.el&&(i.el=tt.createElement(Q(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===s)this._$AH.p(e);else{const t=new it(s,this),i=t.u(this.options);t.p(e),this.T(i),this._$AH=t}}_$AC(t){let e=J.get(t.strings);return void 0===e&&J.set(t.strings,e=new tt(t)),e}k(e){U(this._$AH)||(this._$AH=[],this._$AR());const i=this._$AH;let s,n=0;for(const r of e)n===i.length?i.push(s=new t(this.O(D()),this.O(D()),this,this.options)):s=i[n],s._$AI(r),n++;n2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=K}_$AI(t,e=this,i,s){const n=this.strings;let r=!1;if(void 0===n)t=et(this,t,e,0),r=!H(t)||t!==this._$AH&&t!==G,r&&(this._$AH=t);else{const s=t;let o,a;for(t=n[0],o=0;o{const s=i?.renderBefore??e;let n=s._$litPart$;if(void 0===n){const t=i?.renderBefore??null;s._$litPart$=n=new st(e.insertBefore(D(),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 G}};ht._$litElement$=!0,ht.finalized=!0,ct.litElementHydrateSupport?.({LitElement:ht});const pt=ct.litElementPolyfillSupport;pt?.({LitElement:ht}),(ct.litElementVersions??=[]).push("4.2.1"); -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)}):customElements.define(t,e)},mt={attribute:!0,type:String,converter:E,reflect:!1,hasChanged:S},ft=(t=mt,e,i)=>{const{kind:s,metadata:n}=i;let r=globalThis.litPropertyMetadata.get(n);if(void 0===r&&globalThis.litPropertyMetadata.set(n,r=new Map),"setter"===s&&((t=Object.create(t)).wrapped=!0),r.set(i.name,t),"accessor"===s){const{name:s}=i;return{set(i){const n=e.get.call(this);e.set.call(this,i),this.requestUpdate(s,n,t)},init(e){return void 0!==e&&this.C(s,void 0,t,e),e}}}if("setter"===s){const{name:s}=i;return function(i){const n=this[s];e.call(this,i),this.requestUpdate(s,n,t)}}throw Error("Unsupported decorator location: "+s)}; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */function gt(t){return(e,i)=>"object"==typeof i?ft(t,e,i):((t,e,i)=>{const s=e.hasOwnProperty(i);return e.constructor.createProperty(i,t),s?Object.getOwnPropertyDescriptor(e,i):void 0})(t,e,i)} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */function vt(t){return gt({...t,state:!0,attribute:!1})} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */var _t,bt;!function(t){t.language="language",t.system="system",t.comma_decimal="comma_decimal",t.decimal_comma="decimal_comma",t.space_comma="space_comma",t.none="none"}(_t||(_t={})),function(t){t.language="language",t.system="system",t.am_pm="12",t.twenty_four="24"}(bt||(bt={}));var yt=function(t,e,i,s){s=s||{},i=null==i?{}:i;var n=new Event(e,{bubbles:void 0===s.bubbles||s.bubbles,cancelable:Boolean(s.cancelable),composed:void 0===s.composed||s.composed});return n.detail=i,t.dispatchEvent(n),n};function xt(t,e,i){if(e.has("config")||i)return!0;if(t.config.entity){var s=e.get("hass");return!s||s.states[t.config.entity]!==t.hass.states[t.config.entity]}return!1}const $t="1.5.6",wt=86400;var At,Et,St,Ct;!function(t){t.Heating="mdi:radiator",t.OnOff="mdi:power-socket-uk",t.Shutters="mdi:blinds",t.Lighting="mdi:lightbulb-outline"}(At||(At={})),function(t){t.Overview="OVERVIEW",t.ScheduleEdit="SCHEDULE_EDIT",t.ScheduleCopy="SCHEDULE_COPY",t.ScheduleAdd="SCHEDULE_ADD",t.ScheduleRename="SCHEDULE_RENAME"}(Et||(Et={})),function(t){t.Heating="19",t.OnOff="Off",t.Lighting="0",t.Shutters="100"}(St||(St={})),function(t){t.Heating="°C",t.OnOff="",t.Lighting="%",t.Shutters="%"}(Ct||(Ct={}));const Tt=["Heating","OnOff","Lighting","Shutters"],It=["Lighting","Shutters"],Ot=["Weekdays","Weekend"],kt=["Monday","Tuesday","Wednesday","Thursday","Friday"],Rt=["Saturday","Sunday"],Pt=kt.concat(Rt),Lt=["Sunrise","Sunset"];var Mt;!function(t){t.Sunrise="3000",t.Sunset="4000"}(Mt||(Mt={}));var Nt={version:"Version",invalid_configuration:"Invalid configuration",no_schedules:"No Schedules Found",name_required:"Name is required"},Dt={actions:{copy:"Copy",files:"Files",rename:"Rename",add:"Add",view:"View",add_schedule:"Add Schedule"},labels:{setting:"Setting",name:"Name",assigns:"Assigns",start:"Start",end:"End",to:"to"},days:{monday:"Monday",tuesday:"Tuesday",wednesday:"Wednesday",thursday:"Thursday",friday:"Friday",saturday:"Saturday",sunday:"Sunday",weekdays:"Weekdays",weekend:"Weekend",all:"All",short:{monday:"Mon",tuesday:"Tue",wednesday:"Wed",thursday:"Thu",friday:"Fri",saturday:"Sat",sunday:"Sun"}},headings:{schedule_actions:"Schedule Actions",schedule_type:"Schedule Type",schedule_id:"Schedule Id",schedule_name:"Schedule Name",schedule_assignment:"Room/Device Assignment",not_assigned:"(Not Assigned)",rename_schedule:"Rename Schedule",copy_schedule:"Copy Schedule",delete_schedule:"Delete Schedule"},helpers:{enter_new_name:"Enter the new name for the Schedule",select_copy_schedule:"Select the schedule to copy to",delete_schedule_confirm:"Are you sure you wish to delete the schedule",select_a_schedule:"Select a schedule to view",add_schedule:"Select the schedule type and enter a name for the schedule to create"}},Ht={common:Nt,wiser:Dt},Ut={version:"Déclinaison",invalid_configuration:"Configuration Invalide",no_schedules:"Aucun Programme Trouvé",name_required:"Nom est obligatoire"},zt={actions:{copy:"Copie",files:"Fichier",rename:"Renommer",add:"Ajouter",view:"Voir",add_schedule:"Ajouter un Programme"},labels:{setting:"Paramètre",name:"Nom",assigns:"Attribuers",start:"Début",end:"Fin",to:"à"},days:{monday:"Lundi",tuesday:"Mardi",wednesday:"Mercredi",thursday:"Jeudi",friday:"Vendredi",saturday:"Samedi",sunday:"Dimanche",weekdays:"Lun à Ven",weekend:"Sam et Dim",all:"Toute",short:{monday:"Lun",tuesday:"Mar",wednesday:"Mer",thursday:"Jeu",friday:"Ven",saturday:"Sam",sunday:"Dim"}},headings:{schedule_actions:"Programmer des Actions",schedule_type:"Type de Programme",schedule_id:"Numéro de Programme",schedule_name:"Nom de Programme",schedule_assignment:"Attribuer de Programme",not_assigned:"(Non Attribué)",rename_schedule:"Renommer le Programme",copy_schedule:"Copier le Programme",delete_schedule:"Supprimer le Programme"},helpers:{enter_new_name:"Entrez un nom pour le Programme",select_copy_schedule:"Sélectionnez le calendrier ci-dessous pour le copier",delete_schedule_confirm:"Êtes-vous sûr de vouloir effacer ce programme",select_a_schedule:"Sélectionner un programme à afficher",add_schedule:"Sélectionnez le type de programme et entrez un nom pour la programme à créer"}},Ft={common:Ut,wiser:zt};const Bt={en:Object.freeze({__proto__:null,common:Nt,default:Ht,wiser:Dt}),fr:Object.freeze({__proto__:null,common:Ut,default:Ft,wiser:zt})};function Vt(t,e="",i=""){const s=(localStorage.getItem("selectedLanguage")||"en").replace(/['"]+/g,"").replace("-","_");let n;try{n=t.split(".").reduce((t,e)=>t[e],Bt[s]),n||(n=t.split(".").reduce((t,e)=>t[e],Bt.en))}catch(e){try{n=t.split(".").reduce((t,e)=>t[e],Bt.en)}catch(t){n=""}}return void 0===n&&(n=t.split(".").reduce((t,e)=>t[e],Bt.en)),""!==e&&""!==i&&(n=n.replace(e,i)),n}const jt=h` +function e(e,t,i,s){var o,a=arguments.length,r=a<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,i,s);else for(var n=e.length-1;n>=0;n--)(o=e[n])&&(r=(a<3?o(r):a>3?o(t,i,r):o(t,i))||r);return a>3&&r&&Object.defineProperty(t,i,r),r}function t(e){return t=>{customElements.get(e)||customElements.define(e,t)}} +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */"function"==typeof SuppressedError&&SuppressedError;const i=globalThis,s=i.ShadowRoot&&(void 0===i.ShadyCSS||i.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,o=Symbol(),a=new WeakMap;let r=class{constructor(e,t,i){if(this._$cssResult$=!0,i!==o)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=e,this.t=t}get styleSheet(){let e=this.o;const t=this.t;if(s&&void 0===e){const i=void 0!==t&&1===t.length;i&&(e=a.get(t)),void 0===e&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),i&&a.set(t,e))}return e}toString(){return this.cssText}};const n=(e,...t)=>{const i=1===e.length?e[0]:t.reduce((t,i,s)=>t+(e=>{if(!0===e._$cssResult$)return e.cssText;if("number"==typeof e)return e;throw Error("Value passed to 'css' function must be a 'css' function result: "+e+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+e[s+1],e[0]);return new r(i,e,o)},l=s?e=>e:e=>e instanceof CSSStyleSheet?(e=>{let t="";for(const i of e.cssRules)t+=i.cssText;return(e=>new r("string"==typeof e?e:e+"",void 0,o))(t)})(e):e,{is:d,defineProperty:c,getOwnPropertyDescriptor:h,getOwnPropertyNames:p,getOwnPropertySymbols:u,getPrototypeOf:m}=Object,g=globalThis,v=g.trustedTypes,y=v?v.emptyScript:"",_=g.reactiveElementPolyfillSupport,f=(e,t)=>e,b={toAttribute(e,t){switch(t){case Boolean:e=e?y:null;break;case Object:case Array:e=null==e?e:JSON.stringify(e)}return e},fromAttribute(e,t){let i=e;switch(t){case Boolean:i=null!==e;break;case Number:i=null===e?null:Number(e);break;case Object:case Array:try{i=JSON.parse(e)}catch(e){i=null}}return i}},w=(e,t)=>!d(e,t),x={attribute:!0,type:String,converter:b,reflect:!1,useDefault:!1,hasChanged:w}; +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */Symbol.metadata??=Symbol("metadata"),g.litPropertyMetadata??=new WeakMap;let $=class extends HTMLElement{static addInitializer(e){this._$Ei(),(this.l??=[]).push(e)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(e,t=x){if(t.state&&(t.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(e)&&((t=Object.create(t)).wrapped=!0),this.elementProperties.set(e,t),!t.noAccessor){const i=Symbol(),s=this.getPropertyDescriptor(e,i,t);void 0!==s&&c(this.prototype,e,s)}}static getPropertyDescriptor(e,t,i){const{get:s,set:o}=h(this.prototype,e)??{get(){return this[t]},set(e){this[t]=e}};return{get:s,set(t){const a=s?.call(this);o?.call(this,t),this.requestUpdate(e,a,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)??x}static _$Ei(){if(this.hasOwnProperty(f("elementProperties")))return;const e=m(this);e.finalize(),void 0!==e.l&&(this.l=[...e.l]),this.elementProperties=new Map(e.elementProperties)}static finalize(){if(this.hasOwnProperty(f("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(f("properties"))){const e=this.properties,t=[...p(e),...u(e)];for(const i of t)this.createProperty(i,e[i])}const e=this[Symbol.metadata];if(null!==e){const t=litPropertyMetadata.get(e);if(void 0!==t)for(const[e,i]of t)this.elementProperties.set(e,i)}this._$Eh=new Map;for(const[e,t]of this.elementProperties){const i=this._$Eu(e,t);void 0!==i&&this._$Eh.set(i,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(e){const t=[];if(Array.isArray(e)){const i=new Set(e.flat(1/0).reverse());for(const e of i)t.unshift(l(e))}else void 0!==e&&t.push(l(e));return t}static _$Eu(e,t){const i=t.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof e?e.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(e=>this.enableUpdating=e),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(e=>e(this))}addController(e){(this._$EO??=new Set).add(e),void 0!==this.renderRoot&&this.isConnected&&e.hostConnected?.()}removeController(e){this._$EO?.delete(e)}_$E_(){const e=new Map,t=this.constructor.elementProperties;for(const i of t.keys())this.hasOwnProperty(i)&&(e.set(i,this[i]),delete this[i]);e.size>0&&(this._$Ep=e)}createRenderRoot(){const e=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return((e,t)=>{if(s)e.adoptedStyleSheets=t.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(const s of t){const t=document.createElement("style"),o=i.litNonce;void 0!==o&&t.setAttribute("nonce",o),t.textContent=s.cssText,e.appendChild(t)}})(e,this.constructor.elementStyles),e}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(e=>e.hostConnected?.())}enableUpdating(e){}disconnectedCallback(){this._$EO?.forEach(e=>e.hostDisconnected?.())}attributeChangedCallback(e,t,i){this._$AK(e,i)}_$ET(e,t){const i=this.constructor.elementProperties.get(e),s=this.constructor._$Eu(e,i);if(void 0!==s&&!0===i.reflect){const o=(void 0!==i.converter?.toAttribute?i.converter:b).toAttribute(t,i.type);this._$Em=e,null==o?this.removeAttribute(s):this.setAttribute(s,o),this._$Em=null}}_$AK(e,t){const i=this.constructor,s=i._$Eh.get(e);if(void 0!==s&&this._$Em!==s){const e=i.getPropertyOptions(s),o="function"==typeof e.converter?{fromAttribute:e.converter}:void 0!==e.converter?.fromAttribute?e.converter:b;this._$Em=s;const a=o.fromAttribute(t,e.type);this[s]=a??this._$Ej?.get(s)??a,this._$Em=null}}requestUpdate(e,t,i,s=!1,o){if(void 0!==e){const a=this.constructor;if(!1===s&&(o=this[e]),i??=a.getPropertyOptions(e),!((i.hasChanged??w)(o,t)||i.useDefault&&i.reflect&&o===this._$Ej?.get(e)&&!this.hasAttribute(a._$Eu(e,i))))return;this.C(e,t,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(e,t,{useDefault:i,reflect:s,wrapped:o},a){i&&!(this._$Ej??=new Map).has(e)&&(this._$Ej.set(e,a??t??this[e]),!0!==o||void 0!==a)||(this._$AL.has(e)||(this.hasUpdated||i||(t=void 0),this._$AL.set(e,t)),!0===s&&this._$Em!==e&&(this._$Eq??=new Set).add(e))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(e){Promise.reject(e)}const e=this.scheduleUpdate();return null!=e&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[e,t]of this._$Ep)this[e]=t;this._$Ep=void 0}const e=this.constructor.elementProperties;if(e.size>0)for(const[t,i]of e){const{wrapped:e}=i,s=this[t];!0!==e||this._$AL.has(t)||void 0===s||this.C(t,void 0,i,s)}}let e=!1;const t=this._$AL;try{e=this.shouldUpdate(t),e?(this.willUpdate(t),this._$EO?.forEach(e=>e.hostUpdate?.()),this.update(t)):this._$EM()}catch(t){throw e=!1,this._$EM(),t}e&&this._$AE(t)}willUpdate(e){}_$AE(e){this._$EO?.forEach(e=>e.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(e){return!0}update(e){this._$Eq&&=this._$Eq.forEach(e=>this._$ET(e,this[e])),this._$EM()}updated(e){}firstUpdated(e){}};$.elementStyles=[],$.shadowRootOptions={mode:"open"},$[f("elementProperties")]=new Map,$[f("finalized")]=new Map,_?.({ReactiveElement:$}),(g.reactiveElementVersions??=[]).push("2.1.2"); +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const S=globalThis,k=e=>e,C=S.trustedTypes,E=C?C.createPolicy("lit-html",{createHTML:e=>e}):void 0,A="$lit$",z=`lit$${Math.random().toFixed(9).slice(2)}$`,D="?"+z,T=`<${D}>`,M=document,N=()=>M.createComment(""),O=e=>null===e||"object"!=typeof e&&"function"!=typeof e,I=Array.isArray,L="[ \t\n\f\r]",P=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,R=/-->/g,H=/>/g,j=RegExp(`>|${L}(?:([^\\s"'>=/]+)(${L}*=${L}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),U=/'/g,V=/"/g,B=/^(?:script|style|textarea|title)$/i,W=(e=>(t,...i)=>({_$litType$:e,strings:t,values:i}))(1),q=Symbol.for("lit-noChange"),F=Symbol.for("lit-nothing"),Y=new WeakMap,J=M.createTreeWalker(M,129);function Z(e,t){if(!I(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==E?E.createHTML(t):t}const G=(e,t)=>{const i=e.length-1,s=[];let o,a=2===t?"":3===t?"":"",r=P;for(let t=0;t"===l[0]?(r=o??P,d=-1):void 0===l[1]?d=-2:(d=r.lastIndex-l[2].length,n=l[1],r=void 0===l[3]?j:'"'===l[3]?V:U):r===V||r===U?r=j:r===R||r===H?r=P:(r=j,o=void 0);const h=r===j&&e[t+1].startsWith("/>")?" ":"";a+=r===P?i+T:d>=0?(s.push(n),i.slice(0,d)+A+i.slice(d)+z+h):i+z+(-2===d?t:h)}return[Z(e,a+(e[i]||"")+(2===t?"":3===t?"":"")),s]};class K{constructor({strings:e,_$litType$:t},i){let s;this.parts=[];let o=0,a=0;const r=e.length-1,n=this.parts,[l,d]=G(e,t);if(this.el=K.createElement(l,i),J.currentNode=this.el.content,2===t||3===t){const e=this.el.content.firstChild;e.replaceWith(...e.childNodes)}for(;null!==(s=J.nextNode())&&n.length0){s.textContent=C?C.emptyScript:"";for(let i=0;iI(e)||"function"==typeof e?.[Symbol.iterator])(e)?this.k(e):this._(e)}O(e){return this._$AA.parentNode.insertBefore(e,this._$AB)}T(e){this._$AH!==e&&(this._$AR(),this._$AH=this.O(e))}_(e){this._$AH!==F&&O(this._$AH)?this._$AA.nextSibling.data=e:this.T(M.createTextNode(e)),this._$AH=e}$(e){const{values:t,_$litType$:i}=e,s="number"==typeof i?this._$AC(e):(void 0===i.el&&(i.el=K.createElement(Z(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===s)this._$AH.p(t);else{const e=new Q(s,this),i=e.u(this.options);e.p(t),this.T(i),this._$AH=e}}_$AC(e){let t=Y.get(e.strings);return void 0===t&&Y.set(e.strings,t=new K(e)),t}k(e){I(this._$AH)||(this._$AH=[],this._$AR());const t=this._$AH;let i,s=0;for(const o of e)s===t.length?t.push(i=new ee(this.O(N()),this.O(N()),this,this.options)):i=t[s],i._$AI(o),s++;s2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=F}_$AI(e,t=this,i,s){const o=this.strings;let a=!1;if(void 0===o)e=X(this,e,t,0),a=!O(e)||e!==this._$AH&&e!==q,a&&(this._$AH=e);else{const s=e;let r,n;for(e=o[0],r=0;r{const s=i?.renderBefore??t;let o=s._$litPart$;if(void 0===o){const e=i?.renderBefore??null;s._$litPart$=o=new ee(t.insertBefore(N(),e),e,void 0,i??{})}return o._$AI(e),o})(t,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return q}}le._$litElement$=!0,le.finalized=!0,ne.litElementHydrateSupport?.({LitElement:le});const de=ne.litElementPolyfillSupport;de?.({LitElement:le}),(ne.litElementVersions??=[]).push("4.2.2"); +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const ce={attribute:!0,type:String,converter:b,reflect:!1,hasChanged:w},he=(e=ce,t,i)=>{const{kind:s,metadata:o}=i;let a=globalThis.litPropertyMetadata.get(o);if(void 0===a&&globalThis.litPropertyMetadata.set(o,a=new Map),"setter"===s&&((e=Object.create(e)).wrapped=!0),a.set(i.name,e),"accessor"===s){const{name:s}=i;return{set(i){const o=t.get.call(this);t.set.call(this,i),this.requestUpdate(s,o,e,!0,i)},init(t){return void 0!==t&&this.C(s,void 0,e,t),t}}}if("setter"===s){const{name:s}=i;return function(i){const o=this[s];t.call(this,i),this.requestUpdate(s,o,e,!0,i)}}throw Error("Unsupported decorator location: "+s)};function pe(e){return(t,i)=>"object"==typeof i?he(e,t,i):((e,t,i)=>{const s=t.hasOwnProperty(i);return t.constructor.createProperty(i,e),s?Object.getOwnPropertyDescriptor(t,i):void 0})(e,t,i)} +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */function ue(e){return pe({...e,state:!0,attribute:!1})} +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */var me,ge;!function(e){e.language="language",e.system="system",e.comma_decimal="comma_decimal",e.decimal_comma="decimal_comma",e.space_comma="space_comma",e.none="none"}(me||(me={})),function(e){e.language="language",e.system="system",e.am_pm="12",e.twenty_four="24"}(ge||(ge={}));var ve=function(e,t,i,s){s=s||{},i=null==i?{}:i;var o=new Event(t,{bubbles:void 0===s.bubbles||s.bubbles,cancelable:Boolean(s.cancelable),composed:void 0===s.composed||s.composed});return o.detail=i,e.dispatchEvent(o),o};const ye="2.0.0-dev.60",_e=86400;var fe,be,we;!function(e){e.Overview="OVERVIEW",e.RoomSchedule="ROOM_SCHEDULE",e.ScheduleEdit="SCHEDULE_EDIT",e.ScheduleCopy="SCHEDULE_COPY",e.ScheduleAdd="SCHEDULE_ADD",e.ScheduleRename="SCHEDULE_RENAME"}(fe||(fe={})),function(e){e.Heating="19",e.OnOff="Off",e.Lighting="0",e.Shutters="100"}(be||(be={})),function(e){e.Heating="°C",e.OnOff="",e.Lighting="%",e.Shutters="%"}(we||(we={}));const xe=["Heating","OnOff","Lighting","Shutters"],$e=["Lighting","Shutters"],Se=["Weekdays","Weekend"],ke=["Monday","Tuesday","Wednesday","Thursday","Friday"],Ce=["Saturday","Sunday"],Ee=ke.concat(Ce),Ae=["Sunrise","Sunset"];var ze;!function(e){e.Sunrise="3000",e.Sunset="4000"}(ze||(ze={}));var De={version:"Version",invalid_configuration:"Invalid configuration",no_schedules:"No Schedules Found",name_required:"Name is required",loading:"Loading schedules…",retry:"Try again",load_failed:"Unable to load schedules.",integration_unavailable:"The Wiser integration is not available."},Te={actions:{copy:"Copy",files:"Files",rename:"Rename",add:"Add",view:"View",add_schedule:"Add Schedule",export:"Export schedule",import:"Import schedule"},labels:{setting:"Setting",name:"Name",assigns:"Assigns",start:"Start",end:"End",to:"to"},days:{monday:"Monday",tuesday:"Tuesday",wednesday:"Wednesday",thursday:"Thursday",friday:"Friday",saturday:"Saturday",sunday:"Sunday",weekdays:"Weekdays",weekend:"Weekend",all:"All",short:{monday:"Mon",tuesday:"Tue",wednesday:"Wed",thursday:"Thu",friday:"Fri",saturday:"Sat",sunday:"Sun"}},headings:{schedule_actions:"Schedule Actions",schedule_type:"Schedule Type",schedule_id:"Schedule Id",schedule_name:"Schedule Name",schedule_assignment:"Room/Device Assignment",not_assigned:"(Not Assigned)",rename_schedule:"Rename Schedule",copy_schedule:"Copy Schedule",delete_schedule:"Delete Schedule"},helpers:{enter_new_name:"Enter the new name for the Schedule",select_copy_schedule:"Select the schedule to copy to",delete_schedule_confirm:"Are you sure you wish to delete the schedule",select_a_schedule:"Select a schedule to view",add_schedule:"Select the schedule type and enter a name for the schedule to create",add_schedule_name:"Enter a name for the new schedule",no_supported_types:"No compatible schedule types are available for this device."},rooms:{title:"Rooms",schedules:"Schedules",manage:"Manage schedules",back:"Back to home",missing:"This room or device is no longer available.",current:"Current schedule",unassigned:"No schedule assigned",choose:"Choose a schedule",no_schedules:"No compatible schedules available. Create one using + in the toolbar.",assigning:"Assigning…",assign:"Assign schedule",saved:"Schedule assigned.",view_schedule:"View / edit schedule",shared:"This schedule is shared. Editing its times affects every assigned room or device.",select:"Select a room to choose its schedule",empty:"No Wiser rooms found.",edit:"Edit schedule",save_edit:"Save schedule",cancel_edit:"Cancel editing",delete:"Delete schedule",available:"Available schedule",none:"No schedule",removed:"Schedule unassigned."},moments:{title:"Moments",heating:"Room heating",description:"Preset actions for your home. Use Home Assistant automations to run them on a schedule.",loading:"Loading Moments…",failed:"Moments could not be loaded. Registry access may be restricted for this account.",empty:"No enabled Wiser Moments found for this hub. Create Moments in the Wiser app.",open:"Open controls",unavailable:"Unavailable"},home:{title:"Home",heating:"Heating",hotwater:"Hot water",devices:"Lighting & devices",empty:"No scheduled Wiser rooms or devices found.",screen:"Home screen",no_schedules:"No schedules yet. Use + to create one.",assignments:"assigned",assign_devices:"Assigned rooms / devices",apply_devices:"Apply assignments",no_devices:"No compatible devices available.",schedules:"Schedules",overview:"Overview",overview_hint:"Planned schedule changes for each device, shown in the Home Assistant timezone.",schedule_name:"Schedule name",schedule_id:"Schedule ID",schedule_type:"Schedule type",next_day:"Next day",next_change:"Next change",next_setting:"Next scheduled setting",no_next_change:"No upcoming timed change available.",overview_details:"Overview Details",show:"Show",hide:"Hide",device_details:"Schedule details"},editor:{hub:"Wiser hub",permissions:"Permissions",appearance:"Appearance",display_only:"Read-only mode",admin_only:"Only admins can manage schedules",theme_colors:"Use theme colours",hide_card_borders:"Hide card borders",display_only_help:"Prevent schedule and heating changes, including for admins.",hide_card_background:"Hide card background"},heating:{status:"Schedule status",activity:"Heating",mode:"Heating mode",following:"Following schedule",auto:"Auto",manual:"Manual",off:"Off",override:"Temporary override",boost:"Boost active",away:"Away mode",comfort:"Comfort adjustment",eco:"EcoIQ adjustment",passive:"Passive mode",unknown:"Unknown",unavailable:"Status unavailable",unassigned:"No schedule assigned",heating:"Heating",idle:"Idle",resume:"Resume schedule",failed:"Unable to change heating mode."}},Me={common:De,wiser:Te},Ne={version:"Déclinaison",invalid_configuration:"Configuration Invalide",no_schedules:"Aucun Programme Trouvé",name_required:"Nom est obligatoire",loading:"Chargement des programmes…",retry:"Réessayer",load_failed:"Impossible de charger les programmes.",integration_unavailable:"L’intégration Wiser n’est pas disponible."},Oe={actions:{copy:"Copie",files:"Fichier",rename:"Renommer",add:"Ajouter",view:"Voir",add_schedule:"Ajouter un Programme",export:"Exporter le programme",import:"Importer un programme"},labels:{setting:"Paramètre",name:"Nom",assigns:"Attribuers",start:"Début",end:"Fin",to:"à"},days:{monday:"Lundi",tuesday:"Mardi",wednesday:"Mercredi",thursday:"Jeudi",friday:"Vendredi",saturday:"Samedi",sunday:"Dimanche",weekdays:"Lun à Ven",weekend:"Sam et Dim",all:"Toute",short:{monday:"Lun",tuesday:"Mar",wednesday:"Mer",thursday:"Jeu",friday:"Ven",saturday:"Sam",sunday:"Dim"}},headings:{schedule_actions:"Programmer des Actions",schedule_type:"Type de Programme",schedule_id:"Numéro de Programme",schedule_name:"Nom de Programme",schedule_assignment:"Attribuer de Programme",not_assigned:"(Non Attribué)",rename_schedule:"Renommer le Programme",copy_schedule:"Copier le Programme",delete_schedule:"Supprimer le Programme"},helpers:{enter_new_name:"Entrez un nom pour le Programme",select_copy_schedule:"Sélectionnez le calendrier ci-dessous pour le copier",delete_schedule_confirm:"Êtes-vous sûr de vouloir effacer ce programme",select_a_schedule:"Sélectionner un programme à afficher",add_schedule:"Sélectionnez le type de programme et entrez un nom pour la programme à créer",add_schedule_name:"Saisissez un nom pour le nouveau programme",no_supported_types:"Aucun type de programme compatible avec cet appareil."},rooms:{title:"Pièces",schedules:"Programmes",manage:"Gérer les programmes",back:"Retour à l’accueil",missing:"Cette pièce ou cet appareil n’est plus disponible.",current:"Programme actuel",unassigned:"Aucun programme attribué",choose:"Choisir un programme",no_schedules:"Aucun programme compatible. Créez-en un avec +.",assigning:"Attribution…",assign:"Attribuer le programme",saved:"Programme attribué.",view_schedule:"Voir / modifier le programme",shared:"Ce programme est partagé : les modifications affectent toutes les pièces et appareils associés.",select:"Sélectionnez une pièce pour choisir son programme",empty:"Aucune pièce Wiser trouvée.",edit:"Modifier le programme",save_edit:"Enregistrer le programme",cancel_edit:"Annuler les modifications",delete:"Supprimer le programme",available:"Programme disponible",none:"Aucun programme",removed:"Programme désaffecté."},moments:{title:"Moments",heating:"Chauffage des pièces",description:"Actions prédéfinies pour votre maison. Utilisez les automatisations Home Assistant pour les programmer.",loading:"Chargement des Moments…",failed:"Impossible de charger les Moments. L’accès aux registres peut être limité pour ce compte.",empty:"Aucun Moment Wiser activé pour ce hub. Créez des Moments dans l’application Wiser.",open:"Ouvrir les commandes",unavailable:"Indisponible"},home:{title:"Maison",heating:"Chauffage",hotwater:"Eau chaude",devices:"Éclairage et appareils",empty:"Aucune pièce ni appareil Wiser programmable trouvé.",screen:"Écran d’accueil",no_schedules:"Aucun programme. Utilisez + pour en créer un.",assignments:"affectations",assign_devices:"Pièces / appareils affectés",apply_devices:"Appliquer les affectations",no_devices:"Aucun appareil compatible disponible.",schedules:"Plannings",overview:"Vue d’ensemble",overview_hint:"Changements planifiés par appareil, dans le fuseau horaire de Home Assistant.",schedule_name:"Nom du planning",schedule_id:"ID du planning",schedule_type:"Type de planning",next_day:"Prochain jour",next_change:"Prochain changement",next_setting:"Prochaine consigne planifiée",no_next_change:"Aucun prochain changement horaire disponible.",overview_details:"Détails de la vue d’ensemble",show:"Afficher",hide:"Masquer",device_details:"Détails du planning"},editor:{hub:"Hub Wiser",permissions:"Autorisations",appearance:"Apparence",display_only:"Mode lecture seule",admin_only:"Seuls les administrateurs peuvent gérer les plannings",theme_colors:"Utiliser les couleurs du thème",hide_card_borders:"Masquer les bordures de la carte",display_only_help:"Empêcher les modifications des plannings et du chauffage, même pour les administrateurs.",hide_card_background:"Masquer le fond de la carte"},heating:{status:"État du planning",activity:"Chauffage",mode:"Mode de chauffage",following:"Suit le planning",auto:"Auto",manual:"Manuel",off:"Arrêt",override:"Dérogation temporaire",boost:"Boost actif",away:"Mode absence",comfort:"Ajustement Comfort",eco:"Ajustement EcoIQ",passive:"Mode passif",unknown:"Inconnu",unavailable:"État indisponible",unassigned:"Aucun planning attribué",heating:"En chauffe",idle:"Au repos",resume:"Reprendre le planning",failed:"Impossible de changer le mode de chauffage."}},Ie={common:Ne,wiser:Oe};const Le={en:Object.freeze({__proto__:null,common:De,default:Me,wiser:Te}),fr:Object.freeze({__proto__:null,common:Ne,default:Ie,wiser:Oe})},Pe={"wiser.heating.auto":"ui.common.auto","wiser.heating.unknown":"state.default.unknown","wiser.heating.mode":"ui.card.climate.mode","wiser.home.overview":"panel.states","wiser.home.show":"ui.common.show","wiser.home.hide":"ui.common.hide","wiser.actions.rename":"ui.common.rename","wiser.actions.copy":"ui.common.copy","wiser.actions.add":"ui.common.add","wiser.rooms.back":"ui.common.back","wiser.rooms.edit":"ui.common.edit","wiser.rooms.delete":"ui.common.delete","wiser.rooms.cancel_edit":"ui.common.cancel","wiser.rooms.save_edit":"ui.common.save"};function Re(e,t){const i=t.split(".").reduce((e,t)=>e&&"object"==typeof e?e[t]:void 0,Le[e]);return"string"==typeof i?i:void 0}function He(e,t="",i="",s){const o=Re((s||localStorage.getItem("selectedLanguage")||"en").replace(/['"]+/g,"").toLowerCase().split(/[-_]/)[0],e)||Re("en",e)||e;return t&&i?o.replace(t,i):o}function je(e,t,i="",s=""){var o;const a=Pe[t],r=a?null==e?void 0:e.localize(a):void 0;return r&&r!==a?i&&s?r.replace(i,s):r:He(t,i,s,(null===(o=null==e?void 0:e.locale)||void 0===o?void 0:o.language)||(null==e?void 0:e.language))}const Ue=n` + .tool { + color: var(--secondary-text-color); + } + .tool[aria-pressed='true'], + .tool:not(:disabled):hover { + color: var(--primary-color); + } + .tool:disabled { + color: var(--disabled-text-color); + opacity: 1; + } +`;let Ve=class extends le{constructor(){super(...arguments),this.editable=!1,this.assigned=!1,this.busy=!1,this.error=""}text(e){return je(this.hass,"wiser.heating."+e)}get entity(){var e;return this.entityId?null===(e=this.hass)||void 0===e?void 0:e.states[this.entityId]:void 0}get available(){return this.entity&&!["unknown","unavailable"].includes(this.entity.state)}get canResume(){var e,t,i;const s=null===(e=this.entity)||void 0===e?void 0:e.attributes;return this.assigned&&"auto"===(null===(t=this.entity)||void 0===t?void 0:t.state)&&((null==s?void 0:s.is_boosted)||(null==s?void 0:s.is_override))&&(null===(i=null==s?void 0:s.preset_modes)||void 0===i?void 0:i.includes("Cancel Overrides"))}async change(e){var t,i,s;if(!this.hass||!this.entityId||!this.editable||this.busy||!this.available)return;if(!["auto","heat","off"].includes(e)||!(null===(t=this.entity.attributes.hvac_modes)||void 0===t?void 0:t.includes(e))||"auto"===e&&!this.assigned)return;const o=this.entityId;this.busy=!0,this.error="";try{this.entity.state!==e&&await this.hass.callService("climate","set_hvac_mode",{entity_id:o,hvac_mode:e}),"auto"===e&&(null===(s=null===(i=this.entity)||void 0===i?void 0:i.attributes.preset_modes)||void 0===s?void 0:s.includes("Cancel Overrides"))&&(this.entity.attributes.is_override||this.entity.attributes.is_boosted)&&await this.hass.callService("climate","set_preset_mode",{entity_id:o,preset_mode:"Cancel Overrides"})}catch(e){this.error=e.message||this.text("failed")}finally{this.busy=!1}}render(){const e=this.entity;if(!this.hass)return W``;const t=null==e?void 0:e.attributes,i=null==t?void 0:t.target_temperature_origin,s=this.available?this.assigned?"off"===e.state?"off":"heat"===e.state?"manual":(null==t?void 0:t.is_passive)?"passive":(null==t?void 0:t.is_boosted)?"boost":(null==t?void 0:t.is_override)?"override":{FromSchedule:"following",FromAwayMode:"away",FromComfortMode:"comfort",FromEcoIQ:"eco",FromManualOverrideDuringAway:"away",FromBoostDuringAway:"away"}[i]||"unknown":"unassigned":"unavailable",o=((null==e?void 0:e.attributes.hvac_modes)||[]).filter(e=>["auto","heat","off"].includes(e)&&("auto"!==e||this.assigned));return W`
${this.text("status")}: ${this.text(s)}
+ ${this.available?W`

${this.text("activity")}: ${!0===(null==t?void 0:t.is_heating)||"heating"===(null==t?void 0:t.hvac_action)?this.text("heating"):!1===(null==t?void 0:t.is_heating)||"idle"===(null==t?void 0:t.hvac_action)?this.text("idle"):this.text("unknown")}

`:""} + ${this.editable&&e?W`({value:e,label:this.text("heat"===e?"manual":e)}))}}} + .value=${e.state} + .required=${!0} + .disabled=${!this.available||this.busy} + @value-changed=${e=>{e.stopPropagation(),this.change(e.detail.value)}} + > + ${this.canResume?W`this.change("auto")}>${this.text("resume")}`:""}`:""} + ${this.error?W`

${this.error}

`:""}`}};Ve.styles=n` + :host { + display: block; + border-top: 1px solid var(--divider-color); + margin-top: 12px; + padding-top: 12px; + } + .status, + p { + font-size: inherit; + line-height: 1.5; + } + p { + margin: 8px 0; + color: var(--secondary-text-color); + } + ha-selector { + display: block; + margin-top: 12px; + max-width: 300px; + } + `,e([pe({attribute:!1})],Ve.prototype,"hass",void 0),e([pe()],Ve.prototype,"entityId",void 0),e([pe({type:Boolean})],Ve.prototype,"editable",void 0),e([pe({type:Boolean})],Ve.prototype,"assigned",void 0),e([ue()],Ve.prototype,"busy",void 0),e([ue()],Ve.prototype,"error",void 0),Ve=e([t("wiser-heating-status")],Ve);const Be=e=>e.callWS({type:"wiser/hubs"}),We=(e,t)=>e.callWS({type:"wiser/suntimes",hub:t}),qe=(e,t,i="")=>e.callWS({type:"wiser/schedules",hub:t,schedule_type:i}),Fe=(e,t,i,s)=>e.callWS({type:"wiser/schedule/id",hub:t,schedule_type:i,schedule_id:s}),Ye=(e,t)=>e.callWS({type:"wiser/rooms",hub:t}),Je=(e,t,i)=>e.callWS({type:"wiser/devices",device_type:i,hub:t}),Ze=(e,t,i,s,o,a=!1)=>e.callWS({type:"wiser/schedule/assign",hub:t,schedule_type:i,schedule_id:s,entity_id:o,remove:a});function Ge(e,t,i){ve(e,"show-dialog",{dialogTag:"wiser-dialog-error",dialogImport:()=>Promise.resolve().then(function(){return Xt}),dialogParams:{title:t,error:i}})}async function Ke(e,t){const[i,s,o]=await Promise.all([e.callWS({type:"config/entity_registry/list"}),e.callWS({type:"config/device_registry/list"}),t?Promise.resolve([t]):Be(e)]),a=new Set(s.filter(e=>e.identifiers.some(([e,i])=>"wiser"===e&&i===(t||o[0]))).map(e=>e.id)),r=new Set(s.filter(e=>e.via_device_id&&a.has(e.via_device_id)).map(e=>e.id));return i.filter(e=>"wiser"===e.platform&&e.entity_id.startsWith("climate.")&&!e.disabled_by&&e.device_id&&r.has(e.device_id)).map(e=>e.entity_id)}let Xe=class extends le{constructor(){super(...arguments),this.active="schedules",this.canAdd=!1}localize(e,t="",i=""){return je(this.hass,e,t,i)}render(){return W`${["schedules","overview"].map(e=>W``)}`}};Xe.styles=n` + :host { + display: inline-flex; + gap: 6px; + } + button { + display: grid; + place-items: center; + width: 44px; + height: 44px; + border: 1px solid transparent; + border-radius: 10px; + background: transparent; + color: var(--secondary-text-color); + cursor: pointer; + } + button[aria-pressed='true'] { + color: var(--primary-color); + background: var(--secondary-background-color); + border-color: var(--secondary-text-color); + } + button:disabled { + color: var(--disabled-text-color); + opacity: 1; + cursor: default; + } + button:not(:disabled):hover { + background: var(--secondary-background-color); + } + button:focus-visible { + outline: 2px solid var(--primary-color); + outline-offset: 2px; + } + ${Ue} + `,e([pe({attribute:!1})],Xe.prototype,"hass",void 0),e([pe()],Xe.prototype,"active",void 0),e([pe({type:Boolean})],Xe.prototype,"canAdd",void 0),Xe=e([t("wiser-home-navigation")],Xe);const Qe=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];let et=class extends le{render(){var e;const t=null===(e=this.config)||void 0===e?void 0:e.name;return W`
+ ${t?W`

Wiser${"Wiser Schedule"!==t?W`${t}`:""}

`:""} +
+
`}};et.styles=n` + :host { + display: block; + margin-bottom: 20px; + } + header { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 12px; + min-height: 44px; + } + h2 { + display: flex; + align-items: center; + gap: 14px; + margin: 0; + min-width: 0; + line-height: 1.2; + } + .brand { + color: var(--wiser-brand-color, #279f43); + font-family: 'Arial Rounded MT Bold', 'Trebuchet MS', sans-serif; + font-size: calc(32px + 1pt); + font-weight: 700; + letter-spacing: -1.5px; + } + .title { + padding-inline-start: 14px; + border-inline-start: 1px solid var(--divider-color, #ddd); + color: var(--primary-text-color); + font-size: calc(15px + 1pt); + font-weight: 500; + overflow-wrap: anywhere; + } + .actions { + margin-inline-start: auto; + min-width: 0; + max-width: 100%; + } + `,e([pe({attribute:!1})],et.prototype,"config",void 0),et=e([t("wiser-card-header")],et);let tt=class extends le{constructor(){super(...arguments),this.hub="",this.entities=[],this.loading=!0,this.failed=!1,this.request=0}localize(e,t="",i=""){return je(this.hass,e,t,i)}updated(e){(e.has("hub")||e.has("hass")&&!e.get("hass"))&&this.load()}async load(){if(!this.hass)return;const e=++this.request;this.loading=!0,this.failed=!1;try{const[t,i,s]=await Promise.all([this.hass.callWS({type:"config/entity_registry/list"}),this.hass.callWS({type:"config/device_registry/list"}),this.hub?Promise.resolve([this.hub]):Be(this.hass)]);if(e!==this.request)return;const o=this.hub||s[0],a=new Set(i.filter(e=>e.identifiers.some(([e,t])=>"wiser"===e&&t===o)).map(e=>e.id));this.entities=t.filter(e=>{var t;return"wiser"===e.platform&&e.entity_id.startsWith("button.")&&!e.disabled_by&&!e.hidden_by&&e.device_id&&a.has(e.device_id)&&("moment"===e.translation_key||(null===(t=e.original_name)||void 0===t?void 0:t.startsWith("Moments "))||e.unique_id.includes("-button-Moments "))})}catch(t){e===this.request&&(this.entities=[],this.failed=!0)}finally{e===this.request&&(this.loading=!1)}}renderMoment(e){const t=this.hass.states[e.entity_id];return W``}render(){const e=this.entities.filter(e=>{var t;return null===(t=this.hass)||void 0===t?void 0:t.states[e.entity_id]});if(!this.loading&&!this.failed&&!e.length)return W``;let t;return t=this.loading?W`

${this.localize("wiser.moments.loading")}

`:this.failed?W`

${this.localize("wiser.moments.failed")}

+ `:W`
${e.map(e=>this.renderMoment(e))}
`,W`
+

${this.localize("wiser.moments.title")}

+

${this.localize("wiser.moments.description")}

+ ${t} +
`}};tt.styles=n` + :host { + display: block; + } + section { + margin-top: 24px; + padding-top: 20px; + border-top: 1px solid var(--divider-color, #ddd); + } + h3 { + font-size: calc(15px + 1pt); + font-weight: 600; + margin: 0 0 8px; + color: var(--primary-text-color); + } + p { + font-size: calc(14px + 1pt); + line-height: 1.5; + margin: 0 0 14px; + color: var(--secondary-text-color); + } + .moments { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(min(100%, 210px), 1fr)); + gap: 10px; + } + button { + font: inherit; + color: var(--primary-text-color); + border: 1px solid var(--divider-color, #ddd); + border-radius: 12px; + background: var(--card-background-color, white); + padding: 14px; + min-height: 44px; + cursor: pointer; + } + .moment { + display: flex; + align-items: center; + gap: 12px; + text-align: start; + } + .moment span:nth-child(2) { + flex: 1; + min-width: 0; + overflow-wrap: anywhere; + } + strong { + display: block; + font-size: calc(14px + 1pt); + font-weight: 500; + } + small { + display: block; + color: var(--secondary-text-color); + margin-top: 4px; + } + ha-icon { + color: var(--primary-color); + flex-shrink: 0; + } + button:hover { + border-color: var(--primary-color); + } + button:focus-visible { + outline: 2px solid var(--primary-color); + outline-offset: 3px; + } + `,e([pe({attribute:!1})],tt.prototype,"hass",void 0),e([pe({attribute:!1})],tt.prototype,"hub",void 0),e([ue()],tt.prototype,"entities",void 0),e([ue()],tt.prototype,"loading",void 0),e([ue()],tt.prototype,"failed",void 0),tt=e([t("wiser-moments")],tt);const it={GB:"uk",IE:"uk",MT:"uk",CY:"uk",SG:"uk",MY:"uk",HK:"uk",US:"us",CA:"us",MX:"us",AU:"au",NZ:"au",CN:"au",AR:"au",JP:"jp",CH:"ch",LI:"ch",IT:"it",FR:"fr",BE:"fr",PL:"fr",CZ:"fr",SK:"fr",DE:"de",AT:"de",NL:"de",ES:"de",PT:"de",SE:"de",NO:"de",FI:"de",IS:"de",GR:"de"};function st(e){const t=it[(null==e?void 0:e.trim().toUpperCase())||""];return t?`mdi:power-socket-${t}`:"mdi:power-plug"}let ot;function at(){return customElements.get("ha-selector")?Promise.resolve():(ot||(ot=(async()=>{var e;const t=window;if(!t.loadCardHelpers)throw new Error("Home Assistant controls are not available yet. Please retry.");const i=(await t.loadCardHelpers()).createCardElement({type:"entities",entities:[]}).constructor;if(await(null===(e=i.getConfigElement)||void 0===e?void 0:e.call(i)),!customElements.get("ha-selector"))throw new Error("Home Assistant controls could not be loaded. Please retry.")})().catch(e=>{throw ot=void 0,e})),ot)}const rt="a-f\\d",nt=`#?[${rt}]{3}[${rt}]?`,lt=`#?[${rt}]{6}([${rt}]{2})?`,dt=new RegExp(`[^#${rt}]`,"gi"),ct=new RegExp(`^${nt}$|^${lt}$`,"i");const ht=Math.trunc;function pt(e){return null!=e}function ut(e){if(function(e){return 6===(e=String(e).replace("#","")).length&&!isNaN(Number("0x"+e))}(e)){const t=function(e,t={}){if("string"!=typeof e||dt.test(e)||!ct.test(e))throw new TypeError("Expected a valid hex string");let i=1;8===(e=e.replace(/^#/,"")).length&&(i=Number.parseInt(e.slice(6,8),16)/255,e=e.slice(0,6)),4===e.length&&(i=Number.parseInt(e.slice(3,4).repeat(2),16)/255,e=e.slice(0,3)),3===e.length&&(e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]);const s=Number.parseInt(e,16),o=s>>16,a=s>>8&255,r=255&s,n="number"==typeof t.alpha?t.alpha:i;if("array"===t.format)return[o,a,r,n];if("css"===t.format)return`rgb(${o} ${a} ${r}${1===n?"":` / ${Number((100*n).toFixed(2))}%`})`;return{red:o,green:a,blue:r,alpha:n}}(e);return String(t.red+","+t.green+","+t.blue+","+t.alpha)}return"100,100,100"}function mt(e,t){return getComputedStyle(e).getPropertyValue(t).trim()}function gt(e,t,i){if("Unknown"==i)return"100,100,100";if("onoff"===t.toLowerCase())return ut(mt(e,"On"==i?"--green-color":"--red-color"));if(["lighting","shutters"].includes(t.toLowerCase()))return(0==(s=parseInt(i))?"50,50,50":ht(50+1.85*s)+","+ht(50+1.5*s)+",0")+",1";{if(-20==parseFloat(i))return"138, 138, 138";const e=45,t=-10,s=(parseFloat(i)-t)/(e-t);return 235+","+Math.floor(255*(1-s))+","+0+",1"}var s}function vt(e,t){return!t.display_only&&!!(t.admin_only&&e.user.is_admin||!t.admin_only)}function yt(e,t){return 0==e.slots.length||e.slots.length-1==t?"23:59":e.slots[t+1].Time}function _t(e,t,i){return-1==t?function(e,t){const i=[...Ee.slice(Ee.indexOf(e.day)),...Ee.slice(0,Ee.indexOf(e.day))].reverse();let s;for(s of i){const e=t.ScheduleData.filter(e=>e.day==s)[0];if(e&&e.slots.length>0)return e.slots[e.slots.length-1].Setpoint}return"Unknown"}(e,i):e.slots[t].Setpoint}function ft(e){const[t,i]=e.split(":");return 3600*+t+60*+i}const bt=e=>e.locale||{language:e.selectedLanguage,number_format:me.system,time_format:ge.system},wt=t=>{class i extends t{connectedCallback(){super.connectedCallback(),this.__checkSubscribed()}disconnectedCallback(){if(super.disconnectedCallback(),this.__unsubs){for(;this.__unsubs.length;){const e=this.__unsubs.pop();e instanceof Promise?e.then(e=>e()):pt(e)&&e()}this.__unsubs=void 0}}updated(e){super.updated(e),e.has("hass")&&this.__checkSubscribed()}hassSubscribe(){return[]}__checkSubscribed(){void 0===this.__unsubs&&this.isConnected&&void 0!==this.hass&&(this.__unsubs=this.hassSubscribe())}}return e([pe({attribute:!1})],i.prototype,"hass",void 0),i};async function xt(e){await e.updateComplete,e.isConnected&&e.dispatchEvent(new CustomEvent("wiser-view-ready",{bubbles:!0,composed:!0}))}let $t=class extends(wt(le)){constructor(){super(...arguments),this.climateEntities=[],this.now=new Date,this.expandedDevices={},this.target_type="heating",this.openCreatedEditor=!1,this.devices=[],this.rooms=[],this.schedules=[],this.loading=!0,this.loaded=!1,this.error="",this.saving=!1,this.selected="",this.saved=!1,this.editing=!1,this.editorSaving=!1,this.editorReady=!1,this.requestId=0}localize(e,t="",i=""){return je(this.hass,e,t,i)}connectedCallback(){super.connectedCallback(),this.clock=setInterval(()=>{this.now=new Date},3e4)}disconnectedCallback(){super.disconnectedCallback(),clearInterval(this.clock)}hassSubscribe(){return[this.hass.connection.subscribeMessage(e=>{"wiser_updated"!==e.event||this.config.hub&&e.hub!==this.config.hub||this.saving||this.editing||this.loadData()},{type:"wiser_updated"})]}updated(e){super.updated(e),(e.has("config")||e.has("room_id")||e.has("target_type")||e.has("hass")&&!e.get("hass"))&&(this.loaded=!1,this.selected="",this.saved=!1,this.loadData())}compatible(e){return this.schedules.filter(t=>"hotwater"===e?1e3===t.Id:1e3!==t.Id&&("heating"===e?t.Type:t.SubType||t.Type).toLowerCase()===e)}get target(){return"heating"===this.target_type?this.rooms.find(e=>e.Id===this.room_id):this.devices.find(e=>e.Id===this.room_id&&e.kind===this.target_type)}currentSchedule(e,t=this.target_type){return"hotwater"===t?this.schedules.find(e=>1e3===e.Id):this.compatible(t).find(t=>t.Assignments.some(t=>{var i,s;const o=t,a=null!==(i=o.id)&&void 0!==i?i:o.Id;return void 0!==a?String(a)===String(e.Id):(null!==(s=o.name)&&void 0!==s?s:o.Name)===e.Name}))}async loadData(){var e,t,i,s;if(!this.hass||!this.config)return;const o=++this.requestId;this.loading=!0,this.error="";try{await at();const[a,r,n,l,...d]=await Promise.all([Ye(this.hass,this.config.hub),qe(this.hass,this.config.hub),We(this.hass,this.config.hub).catch(()=>{}),Ke(this.hass,this.config.hub).catch(()=>[]),...["lighting","onoff","shutters"].map(e=>Je(this.hass,this.config.hub,e))]),c=await Promise.all(r.map(e=>Fe(this.hass,this.config.hub,e.Type,e.Id)));if(o!==this.requestId)return;this.rooms=[...a].sort((e,t)=>e.Name.localeCompare(t.Name)),this.schedules=c,this.sun=n,this.climateEntities=l,this.devices=d.reduce((e,t,i)=>e.concat(t.map(e=>Object.assign(Object.assign({},e),{kind:["lighting","onoff","shutters"][i]}))),[]),c.some(e=>1e3===e.Id)&&this.devices.unshift({Id:1e3,Name:this.localize("wiser.home.hotwater"),kind:"hotwater"}),this.loaded=!0;const h=this.target;if(h){const o=this.compatible(this.target_type);this.created_schedule&&o.some(e=>e.Id===this.created_schedule.Id&&e.Type===this.created_schedule.Type)?(this.selected=String(this.created_schedule.Id),this.openCreatedEditor=!0,this.dispatchEvent(new CustomEvent("createdScheduleOpened"))):"none"===this.selected||(o.length<=1?this.selected=String(null!==(t=null===(e=o[0])||void 0===e?void 0:e.Id)&&void 0!==t?t:""):o.some(e=>String(e.Id)===this.selected)||(this.selected=String(null!==(s=null===(i=this.currentSchedule(h))||void 0===i?void 0:i.Id)&&void 0!==s?s:"none")))}}catch(e){o===this.requestId&&(this.error=(null==e?void 0:e.message)||this.localize("common.load_failed"))}finally{o===this.requestId&&(this.loading=!1,await this.updateComplete,this.editor&&!this.editorReady||await xt(this))}}async assign(){const e=this.target,t="none"===this.selected,i=t&&e?this.currentSchedule(e):this.compatible(this.target_type).find(e=>String(e.Id)===this.selected);if("hotwater"!==this.target_type&&e&&i&&!this.saving&&vt(this.hass,this.config)){this.saving=!0,this.saved=!1,this.error="";try{await Ze(this.hass,this.config.hub,i.Type,i.Id,String(e.Id),t),await this.loadData(),this.saved=!this.error}catch(e){this.error=(null==e?void 0:e.message)||this.localize("common.load_failed")}finally{this.saving=!1,await xt(this)}}}get editor(){return this.renderRoot.querySelector("wiser-schedule-edit-card")}scheduleAction(e,t){this.dispatchEvent(new CustomEvent("scheduleAction",{detail:{schedule_type:e.Type,schedule_id:e.Id,action:t}}))}tool(e,t,i,s=!1){const o=this.localize(e);return W``}render(){var e;if(!this.hass||!this.config)return W``;const t=this.target,i=void 0!==this.room_id?W``:"";if(this.loading&&!this.loaded)return W`${i} +
${this.localize("common.loading")}
`;if(this.error)return W`${i} + + `;if(void 0!==this.room_id){if(!t)return W`${i} +
${this.localize("wiser.rooms.missing")}
`;const s=this.currentSchedule(t),o=this.compatible(this.target_type),a="hotwater"===this.target_type,r="none"===this.selected?void 0:o.find(e=>String(e.Id)===this.selected)||s,n=vt(this.hass,this.config),l=this.saving||this.editing||this.editorSaving;return W` + {var t,i;const s=e.target,o=null===(t=s.files)||void 0===t?void 0:t[0];s.value="",o&&(null===(i=this.editor)||void 0===i||i.importSchedule(o))}} + /> + +
+ ${this.editing?W` + ${this.tool("wiser.rooms.cancel_edit","mdi:close",()=>{var e;return null===(e=this.editor)||void 0===e?void 0:e.cancelClick()},this.editorSaving)} + ${this.tool("wiser.rooms.save_edit","mdi:content-save",()=>{var e;null===(e=this.editor)||void 0===e||e.saveClick()},this.editorSaving)} + `:W` + ${this.tool("wiser.rooms.back","mdi:arrow-left",()=>this.dispatchEvent(new CustomEvent("roomsBack")),l)} + ${n&&r?this.tool("wiser.actions.export","mdi:download",()=>{var e;return null===(e=this.editor)||void 0===e?void 0:e.exportSchedule()},l||!this.editorReady):""} + ${n&&r?this.tool("wiser.actions.import","mdi:upload",()=>{var e;return null===(e=this.renderRoot.querySelector(".import-file"))||void 0===e?void 0:e.click()},l||!this.editorReady):""} + ${n&&r?W` + ${this.tool("wiser.rooms.edit","mdi:pencil",()=>{var e;return null===(e=this.editor)||void 0===e?void 0:e.editClick()},l||!this.editorReady)} + ${this.tool("wiser.actions.rename","mdi:form-textbox",()=>this.scheduleAction(r,"rename"),l)} + ${this.tool("wiser.actions.copy","mdi:content-copy",()=>this.scheduleAction(r,"copy"),l||a)} + ${this.tool("wiser.rooms.delete","mdi:delete-outline",()=>{var e;null===(e=this.editor)||void 0===e||e.deleteClick()},l||!this.editorReady||a)} + `:""} + ${n&&!a?W` + ${this.tool("wiser.actions.add_schedule","mdi:plus",()=>this.dispatchEvent(new CustomEvent("addScheduleClick")),l)} + ${this.tool("wiser.rooms.assign","mdi:check",()=>{this.assign()},l||!this.selected||("none"===this.selected?!s:this.selected===String(null==s?void 0:s.Id)))} + `:""} + `} +
+
+

${t.Name}

+

+ ${this.localize("wiser.rooms.current")}: + ${null!==(e=null==s?void 0:s.Name)&&void 0!==e?e:this.localize("wiser.rooms.unassigned")} +

+ ${n&&!a?W` + ${o.length>0?W`({value:String(e.Id),label:e.Name}))}}} + .value=${"none"===this.selected?void 0:this.selected||void 0} + .required=${!1} + .disabled=${l} + @value-changed=${e=>{e.stopPropagation(),l||null!=e.detail.value&&""!==e.detail.value&&!o.some(t=>String(t.Id)===e.detail.value)||(this.selected=e.detail.value||"none",this.saved=!1)}} + >`:1!==o.length||s?"":W`

+ ${this.localize("wiser.rooms.available")}: ${o[0].Name} +

`} + ${o.length?"":W`

${this.localize("wiser.rooms.no_schedules")}

`} + `:""} + ${r?W` + {var t;this.editing=e.detail.editing,this.editorSaving=e.detail.saving,this.editorReady=e.detail.ready,this.openCreatedEditor&&e.detail.ready&&!e.detail.editing&&(this.openCreatedEditor=!1,null===(t=this.editor)||void 0===t||t.editClick())}} + @scheduleDeleted=${()=>{this.selected="",this.loadData()}} + > + + `:""} + ${this.saved?W`

${this.localize("none"===this.selected?"wiser.rooms.removed":"wiser.rooms.saved")}

`:""} + ${r&&r.Assignments.length>1?W`

${this.localize("wiser.rooms.shared")}

`:""} + ${this.saving?W`

${this.localize("wiser.rooms.assigning")}

`:""} + `}const s=[{title:"heating",items:this.rooms.map(e=>Object.assign(Object.assign({},e),{kind:"heating"}))},{title:"hotwater",items:this.devices.filter(e=>"hotwater"===e.kind)},{title:"devices",items:this.devices.filter(e=>"hotwater"!==e.kind)}];return W` + {if("overview"!==e.detail)return;e.stopPropagation();const t=Array.from(this.renderRoot.querySelectorAll(".details-toggle:not(:disabled)")),i=t.some(e=>"true"!==e.getAttribute("aria-expanded"));this.expandedDevices=Object.assign(Object.assign({},this.expandedDevices),t.reduce((e,t)=>(e[t.dataset.key]=i,e),{})),xt(this)}} + > +

${this.localize("wiser.home.overview")}

+ ${"overview"!==this.config.home_screen||!1!==this.config.overview_details?W`

${this.localize("wiser.home.overview_hint")}

`:""} + ${s.filter(e=>e.items.length).map(e=>W`
+

${this.localize("wiser.home."+e.title)}

+
${e.items.map(e=>this.renderDeviceOverview(e))}
+
`)} + ${this.rooms.length||this.devices.length?"":W`

${this.localize("wiser.home.empty")}

`} + + `}renderDeviceOverview(e){var t,i,s,o;const a=this.currentSchedule(e,e.kind),r=a?function(e,t,i,s){var o;const a=new Intl.DateTimeFormat("en-GB",{timeZone:i,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1}).formatToParts(t),r=e=>{var t;return Number(null===(t=a.find(t=>t.type===e))||void 0===t?void 0:t.value)},n=Date.UTC(r("year"),r("month")-1,r("day")),l=3600*r("hour")+60*r("minute")+r("second");for(let t=0;t<=7;t++){const i=new Date(n+864e5*t),a=Qe[i.getUTCDay()],r=((null===(o=e.ScheduleData.find(e=>e.day.toLowerCase()===a.toLowerCase()))||void 0===o?void 0:o.slots)||[]).map(e=>{var o;let r=e.Time;if("sunrise"===r.toLowerCase()||"sunset"===r.toLowerCase()){const e="sunrise"===r.toLowerCase()?null==s?void 0:s.Sunrises:null==s?void 0:s.Sunsets;r=(null===(o=null==e?void 0:e.find(e=>e.day.toLowerCase()===a.toLowerCase()))||void 0===o?void 0:o.time)||""}const n=/^(\d{1,2}):(\d{2})(?::(\d{2}))?$/.exec(r);if(!n)return;const[,d,c,h="0"]=n,p=3600*Number(d)+60*Number(c)+Number(h);return Number(d)>23||Number(c)>59||Number(h)>59||!t&&p<=l?void 0:{day:a,date:i.toISOString().slice(0,10),time:`${d.padStart(2,"0")}:${c}`,setpoint:e.Setpoint,seconds:p}}).filter(e=>Boolean(e)).sort((e,t)=>e.seconds-t.seconds);if(r.length)return r[0]}}(a,this.now,this.hass.config.time_zone||"UTC",this.sun):void 0,n=r?`${r.setpoint}${"heating"===e.kind?"°C":["lighting","shutters"].includes(e.kind)?"%":""}`:"",l=`${e.kind}-${e.Id}`,d=null!==(t=this.expandedDevices[l])&&void 0!==t?t:"overview"!==this.config.home_screen||!1!==this.config.overview_details,c=(e,t)=>W`
+
${this.localize("wiser.home."+e)}
+
${t}
+
`;return W`
+
+ + +
+ ${a?W`
+
+ ${c("schedule_name",a.Name)}${c("schedule_id",a.Id)} + ${c("schedule_type",a.SubType||a.Type)} + ${r?W`${c("next_day",this.localize("wiser.days."+r.day.toLowerCase()))}${c("next_change",new Intl.DateTimeFormat((null===(o=this.hass.locale)||void 0===o?void 0:o.language)||"en",{year:"numeric",month:"short",day:"numeric",timeZone:"UTC"}).format(new Date(r.date+"T00:00:00Z"))+" · "+r.time)}${c("next_setting",n)}`:W`

${this.localize("wiser.home.no_next_change")}

`} +
+ ${"heating"===e.kind?this.renderHeating(e,!0):""} +
`:"heating"===e.kind?W`
+ ${this.renderHeating(e,!1)} +
`:""} +
`}renderHeating(e,t){return W`{var s;return(null===(s=e.states[t])||void 0===s?void 0:s.attributes.name)===i});return 1===s.length?s[0]:void 0}(this.hass,this.climateEntities,e.Name)} + .editable=${vt(this.hass,this.config)} + .assigned=${t} + >`}};$t.styles=n` + .device-heading { + display: flex; + align-items: center; + gap: 8px; + } + .device-heading .details-toggle { + flex: 0 0 44px; + padding: 0; + width: 44px; + border: 0; + background: transparent; + color: var(--primary-color); + } + .device-heading .overview-device { + border: 0; + background: transparent; + padding: 8px; + min-width: 0; + } + .overview-grid { + align-items: start; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); + gap: 12px; + } + .device-overview { + border: 1px solid var(--divider-color); + border-radius: 14px; + padding: 16px; + background: var(--card-background-color); + min-width: 0; + } + .overview-device { + display: flex; + align-items: center; + gap: 12px; + width: 100%; + text-align: start; + } + .device-summary { + display: flex; + flex-direction: column; + gap: 4px; + min-width: 0; + } + .device-summary { + flex: 1; + overflow-wrap: anywhere; + } + .overview-device ha-icon { + color: var(--primary-color); + } + dl { + margin: 12px 0 0; + } + dl > div { + display: flex; + justify-content: space-between; + gap: 16px; + padding: 8px 0; + } + dt { + color: var(--secondary-text-color); + } + dd { + margin: 0; + text-align: end; + overflow-wrap: anywhere; + } + + :host { + display: block; + color: var(--primary-text-color); + } + section + section { + margin-top: 24px; + padding-top: 20px; + border-top: 1px solid var(--divider-color, #ddd); + } + .room-heading { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + gap: 12px; + } + .tools { + display: flex; + flex-wrap: wrap; + gap: 6px; + margin-inline-start: auto; + } + .tool { + width: 44px; + padding: 0; + display: grid; + place-items: center; + color: var(--secondary-text-color); + } + .tool:disabled { + color: var(--disabled-text-color); + opacity: 1; + } + .tool:not(:disabled):hover { + color: var(--primary-color); + } + + h3 { + margin: 16px 0 8px; + font-size: calc(22px + 1pt); + } + .section-heading { + font-size: calc(15px + 1pt); + font-weight: 600; + margin: 0 0 8px; + } + .intro, + .secondary { + color: var(--secondary-text-color); + font-size: calc(14px + 1pt); + line-height: 1.5; + } + .intro { + margin: 0 0 16px; + } + button, + select { + font: inherit; + color: var(--primary-text-color); + border: 1px solid var(--divider-color, #ddd); + border-radius: 12px; + background: var(--card-background-color, white); + min-height: 44px; + padding: 10px 14px; + } + button { + cursor: pointer; + } + button:disabled { + opacity: 0.5; + cursor: default; + } + button:not(:disabled):hover { + border-color: var(--primary-color); + } + button:focus-visible, + select:focus-visible { + outline: 2px solid var(--primary-color); + outline-offset: 3px; + } + .back { + border: 0; + background: none; + color: var(--primary-color); + padding-inline-start: 0; + } + .schedule-picker { + display: block; + width: 100%; + max-width: 420px; + margin: 20px 0 12px; + } + label { + display: grid; + gap: 8px; + margin: 20px 0 12px; + font-size: calc(14px + 1pt); + } + select { + width: 100%; + box-sizing: border-box; + } + .primary { + background: var(--primary-color); + color: var(--text-primary-color, white); + border-color: transparent; + } + .schedule-link { + margin-top: 24px; + border-top: 1px solid var(--divider-color, #ddd); + padding-top: 16px; + } + .status { + padding: 24px; + border-radius: 12px; + background: var(--secondary-background-color); + color: var(--secondary-text-color); + } + ${Ue} + `,e([pe({attribute:!1})],$t.prototype,"config",void 0),e([ue()],$t.prototype,"climateEntities",void 0),e([ue()],$t.prototype,"sun",void 0),e([ue()],$t.prototype,"now",void 0),e([ue()],$t.prototype,"expandedDevices",void 0),e([pe({attribute:!1})],$t.prototype,"room_id",void 0),e([pe({attribute:!1})],$t.prototype,"target_type",void 0),e([pe({attribute:!1})],$t.prototype,"created_schedule",void 0),e([ue()],$t.prototype,"devices",void 0),e([ue()],$t.prototype,"rooms",void 0),e([ue()],$t.prototype,"schedules",void 0),e([ue()],$t.prototype,"loading",void 0),e([ue()],$t.prototype,"loaded",void 0),e([ue()],$t.prototype,"error",void 0),e([ue()],$t.prototype,"saving",void 0),e([ue()],$t.prototype,"selected",void 0),e([ue()],$t.prototype,"saved",void 0),e([ue()],$t.prototype,"editing",void 0),e([ue()],$t.prototype,"editorSaving",void 0),e([ue()],$t.prototype,"editorReady",void 0),$t=e([t("wiser-room-schedules")],$t);let St=class extends(wt(le)){constructor(){super(...arguments),this.schedules=[],this.loading=!0,this.error="",this.request=0}localize(e,t="",i=""){return je(this.hass,e,t,i)}hassSubscribe(){return[this.hass.connection.subscribeMessage(e=>{"wiser_updated"!==e.event||this.config.hub&&e.hub!==this.config.hub||this.load()},{type:"wiser_updated"})]}updated(e){super.updated(e),(e.has("config")||e.has("hass")&&!e.get("hass"))&&this.load()}async load(){if(!this.hass||!this.config)return;const e=++this.request;this.error="";try{const t=await qe(this.hass,this.config.hub);e===this.request&&(this.schedules=[...t].sort((e,t)=>e.Name.localeCompare(t.Name)))}catch(t){e===this.request&&(this.error=t.message||this.localize("common.load_failed"))}finally{e===this.request&&(this.loading=!1,await xt(this))}}render(){return this.hass?W` + + +

${this.localize("wiser.rooms.schedules")}

+ ${this.error?W`

${this.error}

+ `:this.loading?W`

${this.localize("common.loading")}

`:this.schedules.length?W`
+ ${this.schedules.map(e=>W``)} +
`:W`

${this.localize("wiser.home.no_schedules")}

`} + `:W``}};St.styles=n` + :host { + display: block; + color: var(--primary-text-color); + } + .home-tools { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 6px; + } + .heading { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 16px; + } + h3 { + margin: 0; + font-size: calc(15px + 1pt); + } + button { + font: inherit; + color: var(--primary-text-color); + background: var(--card-background-color); + border: 1px solid var(--divider-color); + border-radius: 12px; + padding: 14px; + min-height: 44px; + cursor: pointer; + } + button:focus-visible { + outline: 2px solid var(--primary-color); + outline-offset: 3px; + } + button:hover { + border-color: var(--primary-color); + } + ha-icon { + color: var(--primary-color); + flex-shrink: 0; + } + .tiles { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(min(100%, 210px), 1fr)); + gap: 10px; + } + .tiles.list { + grid-template-columns: 1fr; + } + .schedule-tile { + display: flex; + align-items: center; + gap: 12px; + text-align: start; + min-height: 82px; + } + .schedule-tile span:first-of-type { + flex: 1; + min-width: 0; + overflow-wrap: anywhere; + } + strong { + display: block; + font-weight: 500; + } + small { + display: block; + color: var(--secondary-text-color); + margin-top: 4px; + } + `,e([pe({attribute:!1})],St.prototype,"config",void 0),e([ue()],St.prototype,"schedules",void 0),e([ue()],St.prototype,"loading",void 0),e([ue()],St.prototype,"error",void 0),St=e([t("wiser-schedules-home")],St);const kt=n` + button { + font: inherit; + color: var(--primary-color, #16859a); + background: transparent; + border: 1px solid transparent; + border-radius: 10px; + min-height: 44px; + padding: 8px 14px; + margin: 3px 0; + cursor: pointer; + } + button:not(:disabled):hover { + background: var(--secondary-background-color, #eee); + } + button:disabled { + opacity: 0.45; + cursor: default; + } + button[appearance='filled'], + button.active { + background: var(--primary-color); + color: var(--text-primary-color, white); + } + button[variant='danger'] { + color: var(--error-color, #c33); + } + button:focus-visible, + input:focus-visible { + outline: 2px solid var(--primary-color); + outline-offset: 3px; + } + input { + font: inherit; + accent-color: var(--primary-color); + } + input[type='text'] { + box-sizing: border-box; + width: 100%; + min-height: 44px; + border: 1px solid var(--divider-color, #aaa); + border-radius: 10px; + padding: 10px 12px; + background: var(--card-background-color, white); + color: var(--primary-text-color); + } + input[type='checkbox'] { + width: 22px; + height: 22px; + } + input[type='range'] { + width: 100%; + min-height: 44px; + } + label.schedule-name { + display: grid; + gap: 8px; + } + progress { + width: 36px; + height: 6px; + accent-color: var(--primary-color); + } + button svg { + width: 24px; + height: 24px; + fill: currentColor; + pointer-events: none; + } +`,Ct=n` + ${kt} + :host { + display: block; + color: var(--primary-text-color); + } + ha-textfield { + width: 100%; + } + ha-button { + margin: 3px 0; + } + .card-actions { + margin-top: 20px; + } + ha-button:focus-visible { + outline: 2px solid var(--primary-color); + outline-offset: 3px; + } + .card-header { display: flex; justify-content: space-between; @@ -80,7 +820,7 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} color: var(--secondary-text-color); text-transform: uppercase; font-weight: 500; - font-size: 12px; + font-size: calc(12px + 1pt); margin: 20px 0px 0px 0px; display: flex; flex-direction: row; @@ -88,7 +828,7 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} div.header .switch { text-transform: none; font-weight: normal; - font-size: 14px; + font-size: calc(14px + 1pt); display: flex; flex-grow: 1; justify-content: flex-end; @@ -142,236 +882,64 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} a:visited { color: var(--accent-color); } -`,Wt=(t,e)=>t.callWS({type:"wiser/schedules/types",hub:e}),qt=(t,e,i="")=>t.callWS({type:"wiser/schedules",hub:e,schedule_type:i}),Yt=(t,e,i,s)=>t.callWS({type:"wiser/schedule/id",hub:e,schedule_type:i,schedule_id:s});const Xt="a-f\\d",Gt=`#?[${Xt}]{3}[${Xt}]?`,Kt=`#?[${Xt}]{6}([${Xt}]{2})?`,Jt=new RegExp(`[^#${Xt}]`,"gi"),Zt=new RegExp(`^${Gt}$|^${Kt}$`,"i");const Qt=Math.trunc;function te(t){return null!=t}function ee(t){if(function(t){return 6===(t=String(t).replace("#","")).length&&!isNaN(Number("0x"+t))}(t)){const e=function(t,e={}){if("string"!=typeof t||Jt.test(t)||!Zt.test(t))throw new TypeError("Expected a valid hex string");let i=1;8===(t=t.replace(/^#/,"")).length&&(i=Number.parseInt(t.slice(6,8),16)/255,t=t.slice(0,6)),4===t.length&&(i=Number.parseInt(t.slice(3,4).repeat(2),16)/255,t=t.slice(0,3)),3===t.length&&(t=t[0]+t[0]+t[1]+t[1]+t[2]+t[2]);const s=Number.parseInt(t,16),n=s>>16,r=s>>8&255,o=255&s,a="number"==typeof e.alpha?e.alpha:i;if("array"===e.format)return[n,r,o,a];if("css"===e.format)return`rgb(${n} ${r} ${o}${1===a?"":` / ${Number((100*a).toFixed(2))}%`})`;return{red:n,green:r,blue:o,alpha:a}}(t);return String(e.red+","+e.green+","+e.blue+","+e.alpha)}return"100,100,100"}function ie(t,e){return getComputedStyle(t).getPropertyValue(e).trim()}function se(t,e,i){if("Unknown"==i)return"100,100,100";if("onoff"===e.toLowerCase())return ee(ie(t,"On"==i?"--green-color":"--red-color"));if(["lighting","shutters"].includes(e.toLowerCase()))return(0==(s=parseInt(i))?"50,50,50":Qt(50+1.85*s)+","+Qt(50+1.5*s)+",0")+",1";{if(-20==parseFloat(i))return"138, 138, 138";const t=45,e=-10,s=(parseFloat(i)-e)/(t-e);return 235+","+Math.floor(255*(1-s))+","+0+",1"}var s}function ne(t,e){return!e.display_only&&!!(e.admin_only&&t.user.is_admin||!e.admin_only)}function re(t,e){return 0==t.slots.length||t.slots.length-1==e?"23:59":t.slots[e+1].Time}function oe(t,e,i){return-1==e?function(t,e){const i=[...Pt.slice(Pt.indexOf(t.day)),...Pt.slice(0,Pt.indexOf(t.day))].reverse();let s;for(s of i){const t=e.ScheduleData.filter(t=>t.day==s)[0];if(t&&t.slots.length>0)return t.slots[t.slots.length-1].Setpoint}return"Unknown"}(t,i):t.slots[e].Setpoint}function ae(t){const[e,i]=t.split(":");return 3600*+e+60*+i}const le=t=>t.locale||{language:t.selectedLanguage,number_format:_t.system,time_format:bt.system},de=t=>{class e extends t{connectedCallback(){super.connectedCallback(),this.__checkSubscribed()}disconnectedCallback(){if(super.disconnectedCallback(),this.__unsubs){for(;this.__unsubs.length;){const t=this.__unsubs.pop();t instanceof Promise?t.then(t=>t()):te(t)&&t()}this.__unsubs=void 0}}updated(t){super.updated(t),t.has("hass")&&this.__checkSubscribed()}hassSubscribe(){return[]}__checkSubscribed(){void 0===this.__unsubs&&this.isConnected&&void 0!==this.hass&&(this.__unsubs=this.hassSubscribe())}}return n([gt({attribute:!1})],e.prototype,"hass",void 0),e};let ce=class extends(de(ht)){constructor(){super(...arguments),this.component_loaded=!1,this.connectionError=!1}async initialise(){return await this.isComponentLoaded()&&(this.component_loaded=!0,await this.loadData()),!0}async isComponentLoaded(){for(;!this.hass||!this.hass.config.components.includes("wiser");)await new Promise(t=>setTimeout(t,100));return!0}hassSubscribe(){return this.initialise(),[this.hass.connection.subscribeMessage(t=>this.handleUpdate(t),{type:"wiser_updated"})]}async handleUpdate(t){this.config.hub&&t.hub!=this.config.hub||"wiser_updated"!=t.event||await this.loadData()}async loadData(){this.error=void 0,await Wt(this.hass,this.config.hub).then(t=>{this.supported_schedule_types=t}).catch(t=>{this.error=t}),this.supported_schedule_types&&await qt(this.hass,this.config.hub).then(t=>{this.schedule_list=t}).catch(t=>{this.error=t})}shouldUpdate(t){return!!t.has("schedule_list")||!!xt(this,t,!1)&&(this.loadData(),!0)}render(){return this.hass&&this.config?this.schedule_list&&this.schedule_list.length>0?X` -
-
${Vt("wiser.helpers.select_a_schedule")}
- ${this.supported_schedule_types.map(t=>this.renderScheduleItemsByType(t))} -
- ${this.renderAddScheduleButton()} - `:X` ${this._showWarning(Vt("wiser.common.no_schedules"))} `:X``}_showWarning(t){return X` ${t} `}renderScheduleItemsByType(t){var e,i,s=this.schedule_list.filter(e=>e.Type===t);return this.config?.hide_hw_schedule&&(s=s.filter(e=>1e3!=e.Id)),s.length>0?X` -
-
- ${t} -
- ${"list"==(null===(e=this.config)||void 0===e?void 0:e.view_type)?this.renderScheduleList(s):(null===(i=this.config)||void 0===i?void 0:i.show_schedule_id)?s.sort((t,e)=>t.Id-e.Id).map(t=>this.renderScheduleItem(t)):s.map(t=>this.renderScheduleItem(t))} -
-
-
- `:X``}renderScheduleList(t){return t.length>0?X` - - - - - - - - - - - ${t.sort((t,e)=>t.Id-e.Id).map(t=>this.renderScheduleListItem(t))} - -
ID${Vt("wiser.labels.name")}${Vt("wiser.labels.assigns")} 
- `:X``}renderScheduleItem(t){var e,i;const s=At[t.Type];return X` - this._scheduleClick(t.Type,t.Id)} - > - - ${(null===(e=this.config)||void 0===e?void 0:e.show_schedule_id)?t.Id+" - ":null}${t.Name} - ${(null===(i=this.config)||void 0===i?void 0:i.show_badges)?X`${t.Assignments}`:null} - - `}renderScheduleListItem(t){return X` - - ${t.Id} - ${t.Name} - ${t.Assignments} - - this._scheduleClick(t.Type,t.Id)} - > - ${Vt("wiser.actions.view")} - - - - `}renderAddScheduleButton(){if(ne(this.hass,this.config))return X` -
- ${Vt("wiser.actions.add_schedule")} - -
- `}async _addScheduleClick(){const t=new CustomEvent("addScheduleClick");this.dispatchEvent(t)}_scheduleClick(t,e){const i=new CustomEvent("scheduleClick",{detail:{schedule_type:t,schedule_id:e}});this.dispatchEvent(i)}};ce.styles=h` - ${jt} - div.info-text { - margin-bottom: 10px; - } - span.button-label { - padding-left: 5px; - text-transform: uppercase; - font-weight: 500; - } - div.wrapper { - white-space: nowrap; - transition: - width 0.2s cubic-bezier(0.17, 0.67, 0.83, 0.67), - margin 0.2s cubic-bezier(0.17, 0.67, 0.83, 0.67); - overflow: auto; - display: flex; - flex-wrap: wrap; - flex-direction: row; - justify-content: flex-start; - } - div.sub-heading { - display: block; - margin: 5px 0; - } - div.sub-heading fieldset { - border: 1px solid var(--divider-color, #e8e8e8); - border-radius: 5px; - font-size: small; - } - .schedule-id { - width: 30px; - text-align: right; - } - .schedule-name { - padding-left: 5px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - } - .schedule-assigns { - width: 15%; - text-align: center; - padding-left: 5px; - } - .schedule-action { - width: 75px; - text-align: center; - padding-left: 5px; - } - div.table-header { - display: flex; - font-weight: 500; - } - div.table-body-item { - display: flex; - align-items: center; - } - .schedule-table { - width: 100%; - font-size: 14px; - table-layout: fixed; - } - .view-button { - line-height: 32px; - cursor: pointer; - white-space: nowrap; - text-overflow: ellipsis; - margin: 3px 10px 3px 5px; - display: flex; - padding: 0px 15px 0px 10px; - color: var(--mdc-theme-primary, #6200ee); - background: var(--primary-color); - --mdc-theme-primary: var(--text-primary-color); - border-radius: 4px; - font-size: var(--material-button-font-size); - position: relative; - } - .schedule-item { - white-space: nowrap; - text-overflow: ellipsis; - padding: 5px 5px; - position: relative; - } - .badge { - font-size: 13px; - font-weight: 400; - position: absolute; - min-width: 20px; - box-sizing: border-box; - top: 0px; - right: 0px; - background-color: var(--accent-color); - border-radius: 50%; - line-height: 20px; - text-align: center; - padding: 0px 6px; - color: var(--text-accent-color, var(--text-primary-color)); - } - `,n([gt({attribute:!1})],ce.prototype,"config",void 0),n([gt({attribute:!1})],ce.prototype,"schedule_list",void 0),n([gt({attribute:!1})],ce.prototype,"component_loaded",void 0),ce=n([ut("wiser-schedule-list-card")],ce);let he=class extends ht{async showDialog(t){this._params=t,await this.updateComplete}async closeDialog(){this._params&&this._params.cancel(),this._params=void 0}render(){return this._params?X` +`;let Et=class extends le{localize(e,t="",i=""){return je(this.hass,e,t,i)}async showDialog(e){this._params=e,await this.updateComplete}async closeDialog(){const e=this._params;this._params=void 0,null==e||e.cancel()}render(){var e;return this._params?W`
- ${Vt("wiser.helpers.delete_schedule_confirm")+" "+this._params.name+"?"} -
Note : UI can take 5-10 seconds to reflect change
+ ${this.localize("wiser.helpers.delete_schedule_confirm")+" "+this._params.name+"?"} +
+
+ ${this.hass.localize("ui.common.cancel")} + ${this.hass.localize("ui.common.delete")}
- - - ${this.hass.localize("ui.common.cancel")} - - - ${this.hass.localize("ui.common.delete")} - -
- `:X``}confirmClick(){this._params.confirm()}cancelClick(){this._params.cancel()}static get styles(){return h` + `:W``}confirmClick(){const e=this._params;this._params=void 0,null==e||e.confirm()}cancelClick(){this.closeDialog()}static get styles(){return n` + .actions { + display: flex; + justify-content: flex-end; + gap: 8px; + padding-top: 16px; + } div.wrapper { color: var(--primary-text-color); } - div.notice { - margin-top: 12px; - font-size: 0.9em; - } - `}};n([gt({attribute:!1})],he.prototype,"hass",void 0),n([vt()],he.prototype,"_params",void 0),he=n([ut("wiser-dialog-delete-confirm")],he);var pe=Object.freeze({__proto__:null,get DialogDeleteConfirm(){return he}});function ue(t){if(t.match(/^([0-9:]+)$/)){const e=t.split(":").map(Number);return 3600*e[0]+60*e[1]+(e[2]||0)}const e=new Date(t);return 3600*e.getHours()+60*e.getMinutes()+e.getSeconds()}function me(t){const e=Math.floor(t/3600);t-=3600*e;const i=Math.floor(t/60);t-=60*i;const s=Math.round(t);return String(e%24).padStart(2,"0")+":"+String(i).padStart(2,"0")+":"+String(s).padStart(2,"0")}function fe(t){const e=Math.floor(t/3600);t-=3600*e;const i=Math.floor(t/60);return String(e%24).padStart(2,"0")+":"+String(i).padStart(2,"0")}function ge(t,e,i={wrapAround:!0}){let s=t>=0?Math.floor(t/3600):Math.ceil(t/3600),n=Math.floor((t-3600*s)/60);n%e!=0&&(n=Math.round(n/e)*e),n>=60?(s++,n-=60):n<0&&(s--,n+=60),i.wrapAround&&(s>=24?s-=24:s<0&&(s+=24));const r=3600*s+60*n;if(i.maxHours){if(r>3600*i.maxHours)return 3600*i.maxHours;if(r<3600*-i.maxHours)return 3600*-i.maxHours}return r}var ve=/d{1,4}|M{1,4}|YY(?:YY)?|S{1,3}|Do|ZZ|Z|([HhMsDm])\1?|[aA]|"[^"]*"|'[^']*'/g,_e=/\[([^]*?)\]/gm;function be(t,e){for(var i=[],s=0,n=t.length;s3?0:(t-t%10!=10?1:0)*t%10]}}),Ee=function(t,e){for(void 0===e&&(e=2),t=String(t);t.length0?"-":"+")+Ee(100*Math.floor(Math.abs(e)/60)+Math.abs(e)%60,4)},Z:function(t){var e=t.getTimezoneOffset();return(e>0?"-":"+")+Ee(Math.floor(Math.abs(e)/60),2)+":"+Ee(Math.abs(e)%60,2)}},Ce={default:"ddd MMM DD YYYY HH:mm:ss",shortDate:"M/D/YY",mediumDate:"MMM D, YYYY",longDate:"MMMM D, YYYY",fullDate:"dddd, MMMM D, YYYY",isoDate:"YYYY-MM-DD",isoDateTime:"YYYY-MM-DDTHH:mm:ssZ",shortTime:"HH:mm",mediumTime:"HH:mm:ss",longTime:"HH:mm:ss.SSS"},Te=function(t,e,i){if(void 0===e&&(e=Ce.default),void 0===i&&(i={}),"number"==typeof t&&(t=new Date(t)),"[object Date]"!==Object.prototype.toString.call(t)||isNaN(t.getTime()))throw new Error("Invalid Date pass to format");var s=[];e=(e=Ce[e]||e).replace(_e,function(t,e){return s.push(e),"@@@"});var n=ye(ye({},Ae),i);return(e=e.replace(ve,function(e){return Se[e](t,n)})).replace(/@@@/g,function(){return s.shift()})};const Ie=t=>{if(t.time_format===bt.language||t.time_format===bt.system){const e=t.time_format===bt.language?t.language:void 0,i=(new Date).toLocaleString(e);return i.includes("AM")||i.includes("PM")}return t.time_format===bt.am_pm};function Oe(t,e,i){return i===bt.am_pm||!i&&e.time_format===bt.am_pm?Te(t,"h:mm A"):i===bt.twenty_four||!i&&e.time_format===bt.twenty_four?Te(t,"shortTime"):(()=>{try{(new Date).toLocaleTimeString("i")}catch(t){return"RangeError"===t.name}return!1})()?t.toLocaleTimeString(e.language,{hour:"numeric",minute:"2-digit",hour12:Ie(e)}):Ie(e)?Oe(t,e,bt.am_pm):Oe(t,e,bt.twenty_four)}function ke(t){const e=new Date,i=(t||"").match(/^([0-9]{4})-([0-9]{2})-([0-9]{2})/);null!==i&&e.setFullYear(Number(i[1]),Number(i[2])-1,Number(i[3]));const s=(t||"").match(/([0-9]{2}):([0-9]{2})(:([0-9]{2}))?$/);return null!==s&&e.setHours(Number(s[1]),Number(s[2]),s.length>4?Number(s[4]):e.getSeconds()),e}let Re=class extends ht{constructor(){super(...arguments),this.min=0,this.max=255,this.step=1,this.scaleFactor=1,this.unit="",this.optional=!1,this.disabled=!1,this._displayedValue=0}set value(t){t=isNaN(t)?this.min:this._roundedValue(t/this.scaleFactor),this._displayedValue=t}render(){return X` + `}};e([pe({attribute:!1})],Et.prototype,"hass",void 0),e([ue()],Et.prototype,"_params",void 0),Et=e([t("wiser-dialog-delete-confirm")],Et);var At=Object.freeze({__proto__:null,get DialogDeleteConfirm(){return Et}});function zt(e){if(e.match(/^([0-9:]+)$/)){const t=e.split(":").map(Number);return 3600*t[0]+60*t[1]+(t[2]||0)}const t=new Date(e);return 3600*t.getHours()+60*t.getMinutes()+t.getSeconds()}function Dt(e){const t=Math.floor(e/3600);e-=3600*t;const i=Math.floor(e/60);e-=60*i;const s=Math.round(e);return String(t%24).padStart(2,"0")+":"+String(i).padStart(2,"0")+":"+String(s).padStart(2,"0")}function Tt(e){const t=Math.floor(e/3600);e-=3600*t;const i=Math.floor(e/60);return String(t%24).padStart(2,"0")+":"+String(i).padStart(2,"0")}function Mt(e,t,i={wrapAround:!0}){let s=e>=0?Math.floor(e/3600):Math.ceil(e/3600),o=Math.floor((e-3600*s)/60);o%t!=0&&(o=Math.round(o/t)*t),o>=60?(s++,o-=60):o<0&&(s--,o+=60),i.wrapAround&&(s>=24?s-=24:s<0&&(s+=24));const a=3600*s+60*o;if(i.maxHours){if(a>3600*i.maxHours)return 3600*i.maxHours;if(a<3600*-i.maxHours)return 3600*-i.maxHours}return a}var Nt=/d{1,4}|M{1,4}|YY(?:YY)?|S{1,3}|Do|ZZ|Z|([HhMsDm])\1?|[aA]|"[^"]*"|'[^']*'/g,Ot=/\[([^]*?)\]/gm;function It(e,t){for(var i=[],s=0,o=e.length;s3?0:(e-e%10!=10?1:0)*e%10]}}),Ut=function(e,t){for(void 0===t&&(t=2),e=String(e);e.length0?"-":"+")+Ut(100*Math.floor(Math.abs(t)/60)+Math.abs(t)%60,4)},Z:function(e){var t=e.getTimezoneOffset();return(t>0?"-":"+")+Ut(Math.floor(Math.abs(t)/60),2)+":"+Ut(Math.abs(t)%60,2)}},Bt={default:"ddd MMM DD YYYY HH:mm:ss",shortDate:"M/D/YY",mediumDate:"MMM D, YYYY",longDate:"MMMM D, YYYY",fullDate:"dddd, MMMM D, YYYY",isoDate:"YYYY-MM-DD",isoDateTime:"YYYY-MM-DDTHH:mm:ssZ",shortTime:"HH:mm",mediumTime:"HH:mm:ss",longTime:"HH:mm:ss.SSS"},Wt=function(e,t,i){if(void 0===t&&(t=Bt.default),void 0===i&&(i={}),"number"==typeof e&&(e=new Date(e)),"[object Date]"!==Object.prototype.toString.call(e)||isNaN(e.getTime()))throw new Error("Invalid Date pass to format");var s=[];t=(t=Bt[t]||t).replace(Ot,function(e,t){return s.push(t),"@@@"});var o=Lt(Lt({},jt),i);return(t=t.replace(Nt,function(t){return Vt[t](e,o)})).replace(/@@@/g,function(){return s.shift()})};const qt=e=>{if(e.time_format===ge.language||e.time_format===ge.system){const t=e.time_format===ge.language?e.language:void 0,i=(new Date).toLocaleString(t);return i.includes("AM")||i.includes("PM")}return e.time_format===ge.am_pm};function Ft(e,t,i){return i===ge.am_pm||!i&&t.time_format===ge.am_pm?Wt(e,"h:mm A"):i===ge.twenty_four||!i&&t.time_format===ge.twenty_four?Wt(e,"shortTime"):(()=>{try{(new Date).toLocaleTimeString("i")}catch(e){return"RangeError"===e.name}return!1})()?e.toLocaleTimeString(t.language,{hour:"numeric",minute:"2-digit",hour12:qt(t)}):qt(t)?Ft(e,t,ge.am_pm):Ft(e,t,ge.twenty_four)}function Yt(e){const t=new Date,i=(e||"").match(/^([0-9]{4})-([0-9]{2})-([0-9]{2})/);null!==i&&t.setFullYear(Number(i[1]),Number(i[2])-1,Number(i[3]));const s=(e||"").match(/([0-9]{2}):([0-9]{2})(:([0-9]{2}))?$/);return null!==s&&t.setHours(Number(s[1]),Number(s[2]),s.length>4?Number(s[4]):t.getSeconds()),t}let Jt=class extends le{constructor(){super(...arguments),this.min=0,this.max=255,this.step=1,this.scaleFactor=1,this.unit="",this.optional=!1,this.disabled=!1,this._displayedValue=0}set value(e){e=isNaN(e)?this.min:this._roundedValue(e/this.scaleFactor),this._displayedValue=e}render(){return W`
${this.getCheckbox()}
${this.getSlider()}
${this._displayedValue}${this.unit}
- `}getSlider(){return this.disabled?X` - - `:X` - - `}getCheckbox(){return this.optional?X` `:X``}_toggleChecked(t){const e=t.target.checked;this.disabled=!e;const i=this.disabled?null:this._scaledValue(this._displayedValue);yt(this,"value-changed",{value:i})}_updateValue(t){let e=Number(t.target.value);this._displayedValue=e,e=this._scaledValue(this._displayedValue),yt(this,"value-changed",{value:e})}_roundedValue(t){return t=Math.round(t/this.step)*this.step,(t=parseFloat(t.toPrecision(12)))>this.max?t=this.max:t`}getCheckbox(){return this.optional?W` + + `:W``}_toggleChecked(e){const t=e.target.checked;this.disabled=!t;const i=this.disabled?null:this._scaledValue(this._displayedValue);ve(this,"value-changed",{value:i})}_updateValue(e){let t=Number(e.target.value);this._displayedValue=t,t=this._scaledValue(this._displayedValue),ve(this,"value-changed",{value:t})}_roundedValue(e){return e=Math.round(e/this.step)*this.step,(e=parseFloat(e.toPrecision(12)))>this.max?e=this.max:e${this.renderTimes()} `}renderTimes(){if(this.hass){const t=parseFloat(getComputedStyle(this).getPropertyValue("width"))||460,e=[1,2,3,4,6,8,12],i=Ie(le(this.hass))?55:40;let s=Math.ceil(24/(t/i));for(;!e.includes(s);)s++;const n=[0,...Array.from(Array(24/s-1).keys()).map(t=>(t+1)*s),24];return n.map(t=>{const e=0==t||24==t,i=e?s/48*100:s/24*100;return X` -
- ${e?"":Oe(ke(me(3600*t)),le(this.hass))} + `,e([pe({type:Number})],Jt.prototype,"min",void 0),e([pe({type:Number})],Jt.prototype,"max",void 0),e([pe({type:Number})],Jt.prototype,"step",void 0),e([pe({type:Number})],Jt.prototype,"value",null),e([pe({type:Number})],Jt.prototype,"scaleFactor",void 0),e([pe({type:String})],Jt.prototype,"unit",void 0),e([pe({type:Boolean})],Jt.prototype,"optional",void 0),e([pe({type:Boolean})],Jt.prototype,"disabled",void 0),e([pe({type:Number})],Jt.prototype,"_displayedValue",void 0),Jt=e([t("wiser-variable-slider")],Jt);let Zt=class extends le{render(){return W`
${this.renderTimes()}
`}renderTimes(){if(this.hass){const e=parseFloat(getComputedStyle(this).getPropertyValue("width"))||460,t=[1,2,3,4,6,8,12],i=qt(bt(this.hass))?55:40;let s=Math.ceil(24/(e/i));for(;!t.includes(s);)s++;const o=[0,...Array.from(Array(24/s-1).keys()).map(e=>(e+1)*s),24];return o.map(e=>{const t=0==e||24==e,i=t?s/48*100:s/24*100;return W` +
+ ${t?"":Ft(Yt(Dt(3600*e)),bt(this.hass))}
- `})}return X``}static get styles(){return h` + `})}return W``}static get styles(){return n` :host { display: block; max-width: 100%; @@ -396,7 +964,7 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} position: relative; height: 25px; line-height: 25px; - font-size: 12px; + font-size: calc(12px + 1pt); text-align: center; align-content: center; align-items: center; @@ -421,9 +989,9 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} visibility: visible; } } - `}};n([gt({attribute:!1})],Pe.prototype,"hass",void 0),Pe=n([ut("wiser-time-bar")],Pe);let Le=class extends ht{constructor(){super(),this.editMode=!1,this._activeSlot=-99,this._activeDay="",this._show_short_days=!1,this.schedule_type=Tt[0],this.activeMarker=0,this.isDragging=!1,this.currentTime=0,this.timer=0,this.timeout=0,this.zoomFactor=1,this.rangeMin=0,this.rangeMax=wt,this.stepSize=5,this.initialise()}async initialise(){return this.schedule&&(this.schedule_type=this.schedule.Type),!0}shouldUpdate(){return this.editMode||(this._activeSlot=-99,this._activeDay=""),!0}render(){const t=parseFloat(getComputedStyle(this).getPropertyValue("width"));return this._show_short_days=t<500,this.hass&&this.config&&this.suntimes&&this.schedule?X` + `}};e([pe({attribute:!1})],Zt.prototype,"hass",void 0),Zt=e([t("wiser-time-bar")],Zt);let Gt=class extends le{localize(e,t="",i=""){return je(this.hass,e,t,i)}constructor(){super(),this.editMode=!1,this._activeSlot=-99,this._activeDay="",this._show_short_days=!1,this.schedule_type=xe[0],this.activeMarker=0,this.isDragging=!1,this.currentTime=0,this.timer=0,this.timeout=0,this.zoomFactor=1,this.rangeMin=0,this.rangeMax=_e,this.stepSize=5,this.initialise()}async initialise(){return this.schedule&&(this.schedule_type=this.schedule.Type),!0}shouldUpdate(){return this.editMode||(this._activeSlot=-99,this._activeDay=""),!0}render(){const e=parseFloat(getComputedStyle(this).getPropertyValue("width"));return this._show_short_days=e<500,this.hass&&this.config&&this.suntimes&&this.schedule?W`
- ${Pt.map(t=>this.renderDay(this.schedule.ScheduleData.filter(e=>e.day==t)[0]?this.schedule.ScheduleData.filter(e=>e.day==t)[0]:{day:t,slots:[]}))} + ${Ee.map(e=>this.renderDay(this.schedule.ScheduleData.filter(t=>t.day==e)[0]?this.schedule.ScheduleData.filter(t=>t.day==e)[0]:{day:e,slots:[]}))}
 
(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)}
- ${this.editMode&&It.includes(this.schedule_type)?this.renderSpecialTimeButtons():null} + ${this.editMode&&$e.includes(this.schedule_type)?this.renderSpecialTimeButtons():null} ${this.editMode?this.renderAddDeleteButtons():null} ${this.editMode?this.renderSetPointControl():null} ${this.editMode?this.renderCopyDay():null} - `:X``}renderDay(t){return X` + `:W``}renderDay(e){return W`
- ${this.computeDayLabel(t.day)} -
+ ${this.computeDayLabel(e.day)} +
- ${t.slots.length>0?t.slots.map((e,i)=>this.renderSlot(e,i,t)):this.renderEmptySlot({Time:"23:59",Setpoint:"0",SpecialTime:""},-1,t,!0)} + ${e.slots.length>0?e.slots.map((t,i)=>this.renderSlot(t,i,e)):this.renderEmptySlot({Time:"23:59",Setpoint:"0",SpecialTime:""},-1,e,!0)}
- `}renderEmptySlot(t,e,i,s=!1){const n="00:00",r=t.Time,o=oe(i,e,this.schedule),a=parseFloat(getComputedStyle(this).getPropertyValue("width")),l=this.config.theme_colors?"rgba(var(--rgb-primary-color), 0.7)":"rgba("+se(this,this.schedule_type,o)+")",d=(ae(r)-ae(n))/wt*100,c=Vt("wiser.labels.start")+" - "+n+"\n"+Vt("wiser.labels.end")+" - "+r+"\n"+Vt("wiser.labels.setting")+" - "+this.computeSetpointLabel(o),h=d/100*a<35?"setpoint rotate":"setpoint";return X` + `}renderEmptySlot(e,t,i,s=!1){const o="00:00",a=e.Time,r=_t(i,t,this.schedule),n=parseFloat(getComputedStyle(this).getPropertyValue("width")),l=this.config.theme_colors?"rgba(var(--rgb-primary-color), 0.7)":"rgba("+gt(this,this.schedule_type,r)+")",d=(ft(a)-ft(o))/_e*100,c=this.localize("wiser.labels.start")+" - "+o+"\n"+this.localize("wiser.labels.end")+" - "+a+"\n"+this.localize("wiser.labels.setting")+" - "+this.computeSetpointLabel(r),h=d/100*n<35?"setpoint rotate":"setpoint";return W` - `}renderSlot(t,e,i){const s=t.Time,n=re(i,e),r=t.Setpoint,o=(ae(n)-ae(s))/wt*100,a=this.config.theme_colors?"rgba(var(--rgb-primary-color), 0.7)":"rgba("+se(this,this.schedule_type,r)+")",l=o/100*parseFloat(getComputedStyle(this).getPropertyValue("width"))<35?"setpoint rotate":"setpoint",d=Vt("wiser.labels.start")+" - "+(t.SpecialTime?t.SpecialTime+" ("+s+")":s)+"\n"+Vt("wiser.labels.end")+" - "+n+"\n"+Vt("wiser.labels.setting")+" - "+this.computeSetpointLabel(r);return X` - ${0==e&&"00:00"!=s&&"0:00"!=s?this.renderEmptySlot(t,-1,i,!1):""} + `}renderSlot(e,t,i){const s=e.Time,o=yt(i,t),a=e.Setpoint,r=(ft(o)-ft(s))/_e*100,n=this.config.theme_colors?"rgba(var(--rgb-primary-color), 0.7)":"rgba("+gt(this,this.schedule_type,a)+")",l=r/100*parseFloat(getComputedStyle(this).getPropertyValue("width"))<35?"setpoint rotate":"setpoint",d=this.localize("wiser.labels.start")+" - "+(e.SpecialTime?e.SpecialTime+" ("+s+")":s)+"\n"+this.localize("wiser.labels.end")+" - "+o+"\n"+this.localize("wiser.labels.setting")+" - "+this.computeSetpointLabel(a);return W` + ${0==t&&"00:00"!=s&&"0:00"!=s?this.renderEmptySlot(e,-1,i,!1):""}
- ${this.computeSetpointLabel(r)} + ${this.computeSetpointLabel(a)}
- ${this._activeSlot==e&&this._activeDay==i.day?X` -
-
- - -
-
- `:""} - ${this._activeSlot==e&&this._activeDay==i.day?this.renderTooltip(i,e):""} + ${this._activeSlot==t&&this._activeDay==i.day?W` + ${zt(i.slots[t].Time)>0?this.renderBoundaryHandle(i,t,!1):""} + ${t - `}renderSpecialTimeButtons(){const t=this._activeDay?this.schedule.ScheduleData.filter(t=>t.day==this._activeDay)[0].slots[this._activeSlot]:null;return X` + `}renderBoundaryHandle(e,t,i){return W` +
+
+ e.stopPropagation()} + @mousedown=${this._handleTouchStart} + @touchstart=${this._handleTouchStart} + > +
+
+ ${this.renderTooltip(e,t,i)} + `}renderSpecialTimeButtons(){const e=this._activeDay?this.schedule.ScheduleData.filter(e=>e.day==this._activeDay)[0].slots[this._activeSlot]:null;return W`
 
Set Special Time
- + +
- `}renderAddDeleteButtons(){let t=0;return this.schedule.ScheduleData.filter(t=>t.day==this._activeDay).length>0&&(t=this._activeDay?this.schedule.ScheduleData.filter(t=>t.day==this._activeDay)[0].slots.length:0),X` + `}renderAddDeleteButtons(){let e=0;return this.schedule.ScheduleData.filter(e=>e.day==this._activeDay).length>0&&(e=this._activeDay?this.schedule.ScheduleData.filter(e=>e.day==this._activeDay)[0].slots.length:0),W`
 
- =24} + .disabled=${this._activeSlot<-1||e>=24} > - ${Vt("wiser.actions.add")} - - +
- `}renderSetPointControl(){let t={};return this.editMode?(this.schedule.ScheduleData.filter(t=>t.day==this._activeDay).length>0&&(t=this._activeDay?this.schedule.ScheduleData.filter(t=>t.day==this._activeDay)[0].slots:{}),"Heating"==this.schedule_type?X` -
-
 
-
+ `}renderSetPointControl(){let e={};return this.editMode?(this.schedule.ScheduleData.filter(e=>e.day==this._activeDay).length>0&&(e=this._activeDay?this.schedule.ScheduleData.filter(e=>e.day==this._activeDay)[0].slots:{}),"Heating"==this.schedule_type?W` +
+
${this._show_short_days?"Temp":"Temperature"}
-
-
- + =0?parseFloat(t[this._activeSlot].Setpoint):0} + value=${this._activeSlot>=0?parseFloat(e[this._activeSlot].Setpoint):0} unit="°C" .optional=${!1} .disabled=${this._activeSlot<0} - @value-changed=${t=>{this._updateSetPoint(Number(t.detail.value))}} + @value-changed=${e=>{this._updateSetPoint(Number(e.detail.value))}} >
- `:"OnOff"==this.schedule_type?X` + `:"OnOff"==this.schedule_type?W`
 
@@ -560,19 +1136,21 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)}
State
Off - =0&&"On"==t[this._activeSlot].Setpoint} + .checked=${this._activeSlot>=0&&"On"==e[this._activeSlot].Setpoint} .disabled=${this._activeSlot<0} - @change=${()=>"On"==t[this._activeSlot].Setpoint?this._updateSetPoint("Off"):this._updateSetPoint("On")} - > - + @change=${()=>"On"==e[this._activeSlot].Setpoint?this._updateSetPoint("Off"):this._updateSetPoint("On")} + /> On
- `:["Lighting","Shutters"].includes(this.schedule_type)?X` + `:["Lighting","Shutters"].includes(this.schedule_type)?W`
 
@@ -582,54 +1160,56 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} min="0" max="100" step="1" - value=${this._activeSlot>=0?parseFloat(t[this._activeSlot].Setpoint):0} + value=${this._activeSlot>=0?parseFloat(e[this._activeSlot].Setpoint):0} unit="%" .optional=${!1} .disabled=${this._activeSlot<0} - @value-changed=${t=>{this._updateSetPoint(Number(t.detail.value))}} + @value-changed=${e=>{this._updateSetPoint(Number(e.detail.value))}} >
- `:X``):X``}renderCopyDay(){return X` + `:W``):W``}renderCopyDay(){return W`
 
- ${this._activeDay?Vt("wiser.actions.copy")+" "+Vt("wiser.days."+this._activeDay.toLowerCase())+" "+Vt("wiser.labels.to"):Vt("wiser.actions.copy")+" "+Vt("wiser.labels.to")} + ${this._activeDay?this.localize("wiser.actions.copy")+" "+this.localize("wiser.days."+this._activeDay.toLowerCase())+" "+this.localize("wiser.labels.to"):this.localize("wiser.actions.copy")+" "+this.localize("wiser.labels.to")}
- ${Pt.concat(Ot).concat("All").map(t=>this.renderCopyToButton(t))} + ${Ee.concat(Se).concat("All").map(e=>this.renderCopyToButton(e))}
- `}renderCopyToButton(t){return X` - - ${Pt.includes(t)&&this._show_short_days?Vt("wiser.days.short."+t.toLowerCase()):Vt("wiser.days."+t.toLowerCase())} - - `}renderTooltip(t,e){const i=t.slots,s=Lt.includes(i[e].SpecialTime);return X` -
-
- ${s?X` - - ${i[e].SpecialTime} - `:Oe(ke(me(ue(i[e].Time))),le(this.hass))} + ${Ee.includes(e)&&this._show_short_days?this.localize("wiser.days.short."+e.toLowerCase()):this.localize("wiser.days."+e.toLowerCase())} + + `}renderTooltip(e,t,i=!1){const s=e.slots,o=Ae.includes(s[t].SpecialTime);return W` +
+
+ ${o?W` + + ${s[t].SpecialTime} + `:Ft(Yt(Dt(zt(s[t].Time))),bt(this.hass))}
- `}_slotClick(t){const e=t.target.parentElement.parentElement;if(e.id){const t=e.id.split("|")[0],i=e.id.split("|")[1];i!=this._activeSlot||t!=this._activeDay?(this._activeSlot=parseInt(i),this._activeDay=t):(this._activeSlot=-99,this._activeDay="");const s=new CustomEvent("slotClicked",{detail:{day:this._activeDay,slot:this._activeSlot}});this.dispatchEvent(s)}}_copyDay(t){const e=t.target,i=JSON.stringify(this.schedule.ScheduleData[Pt.indexOf(this._activeDay)].slots);Pt.includes(e.id)?this.schedule.ScheduleData[Pt.indexOf(e.id)].slots=JSON.parse(i):e.id==Ot[0]?kt.map(t=>{this.schedule.ScheduleData[Pt.indexOf(t)].slots=JSON.parse(i)}):e.id==Ot[1]?Rt.map(t=>{this.schedule.ScheduleData[Pt.indexOf(t)].slots=JSON.parse(i)}):"All"==e.id&&Pt.map(t=>{this.schedule.ScheduleData[Pt.indexOf(t)].slots=JSON.parse(i)}),this.requestUpdate()}_updateSetPoint(t){this.schedule.ScheduleData[Pt.indexOf(this._activeDay)].slots=Object.assign(this.schedule.ScheduleData[Pt.indexOf(this._activeDay)].slots,{[this._activeSlot]:Object.assign(Object.assign({},this.schedule.ScheduleData[Pt.indexOf(this._activeDay)].slots[this._activeSlot]),{Setpoint:t})});const e=new CustomEvent("scheduleChanged",{detail:{schedule:this.schedule}});this.dispatchEvent(e),this.requestUpdate()}getSunTime(t,e){return e==Lt[0]?this.suntimes.Sunrises[Pt.indexOf(t)].time:this.suntimes.Sunsets[Pt.indexOf(t)].time}convertScheduleDay(t){const e=t.slots.map(e=>Lt.includes(e.SpecialTime)?{Time:this.getSunTime(t.day,e.SpecialTime),Setpoint:e.Setpoint,SpecialTime:e.SpecialTime}:{Time:e.Time,Setpoint:e.Setpoint,SpecialTime:e.SpecialTime}).sort((t,e)=>parseInt(t.Time.replace(":",""))JSON.stringify(t))),s=Array.from(i).map(t=>JSON.parse(t));return{day:t.day,slots:s}}_setSpecialTime(t){const e=t.target.id.replace(/\w\S*/g,t=>t.charAt(0).toUpperCase()+t.substr(1).toLowerCase());this._activeDay&&this._activeSlot>=0&&(this.schedule.ScheduleData[Pt.indexOf(this._activeDay)].slots[this._activeSlot].SpecialTime!=e&&(this.schedule.ScheduleData[Pt.indexOf(this._activeDay)].slots=Object.assign(this.schedule.ScheduleData[Pt.indexOf(this._activeDay)].slots,{[this._activeSlot]:Object.assign(Object.assign({},this.schedule.ScheduleData[Pt.indexOf(this._activeDay)].slots[this._activeSlot]),{SpecialTime:e,Time:this.getSunTime(this._activeDay,e)})})),this.schedule.ScheduleData[Pt.indexOf(this._activeDay)]=this.convertScheduleDay(this.schedule.ScheduleData[Pt.indexOf(this._activeDay)]),this.schedule.ScheduleData[Pt.indexOf(this._activeDay)].slots.forEach((t,i)=>{t.SpecialTime==e&&(this._activeSlot=i)}),this.requestUpdate())}_addSlot(){if(this._activeSlot<-1)return;const t=Pt.indexOf(this._activeDay);if(this._activeSlot<0)this.schedule.ScheduleData[t].slots=[{Time:fe(ue("06:00")),Setpoint:St[this.schedule_type],SpecialTime:""}],this._activeSlot=0;else{const e=this.schedule.ScheduleData[t].slots[this._activeSlot];let i=ue(e.Time),s=ue(re(this.schedule.ScheduleData[t],this._activeSlot));st.day==this._activeDay)[0].slots;const s=t.target;let n=s;for(;!n.classList.contains("outer");)n=n.parentElement;const r=parseFloat(getComputedStyle(n).getPropertyValue("width")),o=wt/(this.rangeMax-this.rangeMin)*r,a=-(-this.rangeMin/(this.rangeMax-this.rangeMin)*r)/o*wt;let l=s;for(;!l.classList.contains("slot");)l=l.parentElement;const d=l,c=Number(d.getAttribute("slot")),h=c>0?ue(i[c-1].Time)+60*this.stepSize:0,p=c{let s;s="undefined"!=typeof TouchEvent&&t instanceof TouchEvent?t.changedTouches[0].pageX:t.pageX;let n=s-u.left;n>r-1&&(n=r-1),n<-18&&(n=-18);let l=Math.round(n/o*wt+a);lp&&(l=p),this.currentTime=l,l=Math.round(l)>=wt?wt:ge(l,this.stepSize);const d=fe(l);d!=re(this.schedule.ScheduleData[e],c)&&(i=Object.assign(i,{[c]:Object.assign(Object.assign({},i[c]),{Time:d,SpecialTime:""})}),this.requestUpdate())};const f=()=>{window.removeEventListener("mousemove",m),window.removeEventListener("touchmove",m),window.removeEventListener("mouseup",f),window.removeEventListener("touchend",f),window.removeEventListener("blur",f),m=()=>{},setTimeout(()=>{this.isDragging=!1},100),s.blur();const t=new CustomEvent("scheduleChanged",{detail:{schedule:this.schedule}});this.dispatchEvent(t)};window.addEventListener("mouseup",f),window.addEventListener("touchend",f),window.addEventListener("blur",f),window.addEventListener("mousemove",m),window.addEventListener("touchmove",m)}computeDayLabel(t){return X` + `}_slotClick(e){const t=e.currentTarget;if(t.id){const e=t.id.split("|")[0],i=t.id.split("|")[1];i!=this._activeSlot||e!=this._activeDay?(this._activeSlot=parseInt(i),this._activeDay=e):(this._activeSlot=-99,this._activeDay="");const s=new CustomEvent("slotClicked",{detail:{day:this._activeDay,slot:this._activeSlot}});this.dispatchEvent(s)}}_copyDay(e){const t=e.currentTarget,i=JSON.stringify(this.schedule.ScheduleData[Ee.indexOf(this._activeDay)].slots);Ee.includes(t.id)?this.schedule.ScheduleData[Ee.indexOf(t.id)].slots=JSON.parse(i):t.id==Se[0]?ke.map(e=>{this.schedule.ScheduleData[Ee.indexOf(e)].slots=JSON.parse(i)}):t.id==Se[1]?Ce.map(e=>{this.schedule.ScheduleData[Ee.indexOf(e)].slots=JSON.parse(i)}):"All"==t.id&&Ee.map(e=>{this.schedule.ScheduleData[Ee.indexOf(e)].slots=JSON.parse(i)}),this.requestUpdate()}_updateSetPoint(e){this.schedule.ScheduleData[Ee.indexOf(this._activeDay)].slots=Object.assign(this.schedule.ScheduleData[Ee.indexOf(this._activeDay)].slots,{[this._activeSlot]:Object.assign(Object.assign({},this.schedule.ScheduleData[Ee.indexOf(this._activeDay)].slots[this._activeSlot]),{Setpoint:e})});const t=new CustomEvent("scheduleChanged",{detail:{schedule:this.schedule}});this.dispatchEvent(t),this.requestUpdate()}getSunTime(e,t){return t==Ae[0]?this.suntimes.Sunrises[Ee.indexOf(e)].time:this.suntimes.Sunsets[Ee.indexOf(e)].time}convertScheduleDay(e){const t=e.slots.map(t=>Ae.includes(t.SpecialTime)?{Time:this.getSunTime(e.day,t.SpecialTime),Setpoint:t.Setpoint,SpecialTime:t.SpecialTime}:{Time:t.Time,Setpoint:t.Setpoint,SpecialTime:t.SpecialTime}).sort((e,t)=>parseInt(e.Time.replace(":",""))JSON.stringify(e))),s=Array.from(i).map(e=>JSON.parse(e));return{day:e.day,slots:s}}_setSpecialTime(e){const t=e.currentTarget.id.replace(/\w\S*/g,e=>e.charAt(0).toUpperCase()+e.substr(1).toLowerCase());this._activeDay&&this._activeSlot>=0&&(this.schedule.ScheduleData[Ee.indexOf(this._activeDay)].slots[this._activeSlot].SpecialTime!=t&&(this.schedule.ScheduleData[Ee.indexOf(this._activeDay)].slots=Object.assign(this.schedule.ScheduleData[Ee.indexOf(this._activeDay)].slots,{[this._activeSlot]:Object.assign(Object.assign({},this.schedule.ScheduleData[Ee.indexOf(this._activeDay)].slots[this._activeSlot]),{SpecialTime:t,Time:this.getSunTime(this._activeDay,t)})})),this.schedule.ScheduleData[Ee.indexOf(this._activeDay)]=this.convertScheduleDay(this.schedule.ScheduleData[Ee.indexOf(this._activeDay)]),this.schedule.ScheduleData[Ee.indexOf(this._activeDay)].slots.forEach((e,i)=>{e.SpecialTime==t&&(this._activeSlot=i)}),this.requestUpdate())}_addSlot(){if(this._activeSlot<-1)return;const e=Ee.indexOf(this._activeDay);if(this._activeSlot<0)this.schedule.ScheduleData[e].slots=[{Time:Tt(zt("06:00")),Setpoint:be[this.schedule_type],SpecialTime:""}],this._activeSlot=0;else{const t=this.schedule.ScheduleData[e].slots[this._activeSlot];let i=zt(t.Time),s=zt(yt(this.schedule.ScheduleData[e],this._activeSlot));se.day==this._activeDay)[0].slots;const s=e.currentTarget;let o=s;for(;!o.classList.contains("outer");)o=o.parentElement;const a=parseFloat(getComputedStyle(o).getPropertyValue("width")),r=_e/(this.rangeMax-this.rangeMin)*a,n=-(-this.rangeMin/(this.rangeMax-this.rangeMin)*a)/r*_e;let l=s;for(;!l.classList.contains("slot");)l=l.parentElement;const d=l,c=Number(s.dataset.boundary);if(!Number.isInteger(c)||c<0||c>=i.length)return;const h=c>0?zt(i[c-1].Time)+60*this.stepSize:0,p=c{let s;s="undefined"!=typeof TouchEvent&&e instanceof TouchEvent?e.changedTouches[0].pageX:e.pageX;let o=s-u.left;o>a-1&&(o=a-1),o<-18&&(o=-18);let l=Math.round(o/r*_e+n);lp&&(l=p),this.currentTime=l,l=Math.round(l)>=_e?_e:Mt(l,this.stepSize);const d=Tt(l);d!=yt(this.schedule.ScheduleData[t],c)&&(i=Object.assign(i,{[c]:Object.assign(Object.assign({},i[c]),{Time:d,SpecialTime:""})}),this.requestUpdate())};const g=()=>{window.removeEventListener("mousemove",m),window.removeEventListener("touchmove",m),window.removeEventListener("mouseup",g),window.removeEventListener("touchend",g),window.removeEventListener("blur",g),m=()=>{},setTimeout(()=>{this.isDragging=!1},100),s.blur();const e=new CustomEvent("scheduleChanged",{detail:{schedule:this.schedule}});this.dispatchEvent(e)};window.addEventListener("mouseup",g),window.addEventListener("touchend",g),window.addEventListener("blur",g),window.addEventListener("mousemove",m),window.addEventListener("touchmove",m)}computeDayLabel(e){return W`
- ${this._show_short_days?Vt("wiser.days.short."+t.toLowerCase()):Vt("wiser.days."+t.toLowerCase())} + ${this._show_short_days?this.localize("wiser.days.short."+e.toLowerCase()):this.localize("wiser.days."+e.toLowerCase())}
- `}computeSetpointLabel(t){return"Unknown"==t?t:"Heating"==this.schedule_type&&-20==t?"Off":t+Ct[this.schedule_type]}static get styles(){return h` + `}computeSetpointLabel(e){return"Unknown"==e?e:"Heating"==this.schedule_type&&-20==e?"Off":e+we[this.schedule_type]}static get styles(){return n` + ${kt} :host { display: block; max-width: 100%; @@ -656,13 +1236,37 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} line-height: 40px; padding: 0 5px; text-transform: uppercase; - font-size: small; + font-size: calc(13px + 1pt); + } + .temperature-row { + display: flex; + justify-content: center; + width: 100%; + padding-top: 10px; + } + .temperature-controls { + display: flex; + align-items: center; + justify-content: center; + flex-wrap: wrap; + gap: 8px; + width: min(100%, 540px); + } + .temperature-input { + display: flex; + align-items: center; + flex: 1 1 240px; + min-width: 0; + max-width: 400px; + } + .temperature-input wiser-variable-slider { + min-width: 0; } .section-header { - color: var(--material-body-text-color, #000); + color: var(--primary-text-color); text-transform: uppercase; font-weight: 500; - font-size: var(--material-small-font-size); + font-size: calc(var(--material-small-font-size, 12px) + 1pt); padding: 5px 10px; } .slot { @@ -674,7 +1278,7 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} position: relative; height: 40px; line-height: 40px; - font-size: 10px; + font-size: calc(10px + 1pt); text-align: center; } .slot:first-child { @@ -778,7 +1382,7 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} position: relative; height: 25px; line-height: 25px; - font-size: 12px; + font-size: calc(12px + 1pt); text-align: center; align-content: center; align-items: center; @@ -796,7 +1400,7 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} margin-top: 0px; } .slot span { - font-size: 10px; + font-size: calc(10px + 1pt); color: var(--text-primary-color); height: 100%; display: flex; @@ -810,36 +1414,61 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} line-height: 1em; } div.handle { - display: flex; + position: absolute; + top: 0; + left: 0; height: 100%; width: 36px; - margin-left: -19px; - margin-bottom: -60px; - align-content: center; - align-items: center; - justify-content: center; + transform: translateX(-50%); + display: grid; + place-items: center; + z-index: 5; + } + div.handle.end-handle { + left: 100%; + } + div.tooltip-container.end-time { + left: 100%; } div.button-holder { + line-height: 0; background: var(--card-background-color); + border: 1px solid var(--divider-color); border-radius: 50%; - width: 24px; - height: 24px; + width: 32px; + height: 32px; + display: grid; + place-items: center; + } + ha-icon-button.time-handle { display: flex; - visibility: hidden; - animation: 0.2s fadeIn; - animation-fill-mode: forwards; - z-index: 5; + align-items: center; + justify-content: center; + line-height: 0; + --ha-button-height: 32px; + --wa-form-control-height: 32px; + --ha-icon-button-padding-inline: 0px; + --mdc-icon-button-size: 32px; + --mdc-icon-size: 24px; + --ha-icon-button-size: 32px; + width: 32px; + height: 32px; + margin: 0; + padding: 0; + color: var(--primary-color); + cursor: ew-resize; + touch-action: none; } div.tooltip-container { position: absolute; - margin-top: -12px; - margin-left: -22px; - width: 40px; + margin-top: 0; + margin-left: -40px; + width: 80px; height: 0px; text-align: center; line-height: 35px; z-index: 3; - top: -26px; + top: -48px; } div.tooltip-container.visible { @@ -858,10 +1487,13 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} margin: 0px auto; border-radius: 5px; color: var(--text-primary-color); - font-size: 1em; - padding: 0px 5px; + font-size: calc(18px + 1pt); + font-weight: 600; + font-variant-numeric: tabular-nums; + white-space: nowrap; + padding: 4px 10px; text-align: center; - line-height: 20px; + line-height: 28px; z-index: 5; transition: all 0.1s ease-in; transform-origin: center bottom; @@ -885,7 +1517,7 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} border-right: 6px solid transparent; border-top: 10px solid var(--primary-color); position: absolute; - margin-top: 25px; + margin-top: 36px; margin-left: calc(50% - 6px); top: 0px; left: 0px; @@ -966,124 +1598,158 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} padding: 0px 10px 0px 10px; font-weight: 500; } - `}};n([gt({attribute:!1})],Le.prototype,"hass",void 0),n([gt({attribute:!1})],Le.prototype,"config",void 0),n([gt({attribute:!1})],Le.prototype,"schedule",void 0),n([gt({attribute:!1})],Le.prototype,"suntimes",void 0),n([gt({attribute:!1})],Le.prototype,"editMode",void 0),n([vt()],Le.prototype,"_activeSlot",void 0),n([vt()],Le.prototype,"_activeDay",void 0),n([vt()],Le.prototype,"_show_short_days",void 0),n([vt()],Le.prototype,"rangeMin",void 0),n([vt()],Le.prototype,"rangeMax",void 0),n([vt()],Le.prototype,"stepSize",void 0),n([function(t){return(e,i)=>{const s="function"==typeof e?e:e[i];Object.assign(s,t)}}({passive:!0})],Le.prototype,"_handleTouchStart",null),Le=n([ut("wiser-schedule-slot-editor")],Le);let Me=class extends ht{async showDialog(t){this._params=t,await this.updateComplete}async closeDialog(){this._params=void 0}render(){return this._params?X` + `}};e([pe({attribute:!1})],Gt.prototype,"hass",void 0),e([pe({attribute:!1})],Gt.prototype,"config",void 0),e([pe({attribute:!1})],Gt.prototype,"schedule",void 0),e([pe({attribute:!1})],Gt.prototype,"suntimes",void 0),e([pe({attribute:!1})],Gt.prototype,"editMode",void 0),e([ue()],Gt.prototype,"_activeSlot",void 0),e([ue()],Gt.prototype,"_activeDay",void 0),e([ue()],Gt.prototype,"_show_short_days",void 0),e([ue()],Gt.prototype,"rangeMin",void 0),e([ue()],Gt.prototype,"rangeMax",void 0),e([ue()],Gt.prototype,"stepSize",void 0),e([function(e){return(t,i)=>{const s="function"==typeof t?t:t[i];Object.assign(s,e)}}({passive:!0})],Gt.prototype,"_handleTouchStart",null),Gt=e([t("wiser-schedule-slot-editor")],Gt);let Kt=class extends le{async showDialog(e){this._params=e,await this.updateComplete}async closeDialog(){this._params=void 0}render(){var e;return this._params?W`
${this._params.error||""}
- - ${this.hass.localize("ui.dialogs.generic.ok")} - +
+ ${this.hass.localize("ui.dialogs.generic.ok")} +
- `:X``}static get styles(){return h` + `:W``}static get styles(){return n` + .actions { + display: flex; + justify-content: flex-end; + gap: 8px; + padding-top: 16px; + } div.wrapper { color: var(--primary-text-color); } - `}};n([gt({attribute:!1})],Me.prototype,"hass",void 0),n([vt()],Me.prototype,"_params",void 0),Me=n([ut("wiser-dialog-error")],Me);var Ne=Object.freeze({__proto__:null,get DialogError(){return Me}});let De=class extends(de(ht)){constructor(){var t;super(...arguments),this.schedule_id=0,this.use_heat_colors=!0,this.rooms=[],this.entities=[],this._activeSlot=null,this._activeDay=null,this.editMode=!1,this._current_user=null===(t=this.hass)||void 0===t?void 0:t.user,this._assigning_in_progress=0,this._save_in_progress=!1,this.stepSize=5}async initialise(){return await this._isComponentLoaded()&&(this.component_loaded=!0,await this.loadData()),!0}hassSubscribe(){return this.initialise(),[this.hass.connection.subscribeMessage(t=>this.handleUpdate(t),{type:"wiser_updated"})]}async handleUpdate(t){this.config.hub&&t.hub!=this.config.hub||"wiser_updated"!=t.event||await this.loadData()}async _isComponentLoaded(){for(;!this.hass&&!this.config&&!this.hass.config.components.includes("wiser");)await new Promise(t=>setTimeout(t,100));return!0}getSunTime(t,e){return e==Lt[0]?this.suntimes.Sunrises[Pt.indexOf(t)].time:this.suntimes.Sunsets[Pt.indexOf(t)].time}convertLoadedSchedule(t){const e=t.ScheduleData.map(t=>this.convertLoadedScheduleDay(t));return t.ScheduleData=e,t}convertLoadedScheduleDay(t){const e=t.slots.map(e=>Lt.includes(e.Time)?{Time:this.getSunTime(t.day,e.Time),Setpoint:e.Setpoint,SpecialTime:e.Time}:{Time:e.Time,Setpoint:e.Setpoint,SpecialTime:""}).sort((t,e)=>parseInt(t.Time.replace(":",""))JSON.stringify(t))),s=Array.from(i).map(t=>JSON.parse(t));return{day:t.day,slots:s}}convertScheduleForSaving(t){const e=t.ScheduleData.map(t=>this.convertScheduleDayForSaving(t));return t.ScheduleData=e,t}convertScheduleDayForSaving(t){const e=t.slots.map(t=>Lt.includes(t.SpecialTime)?{Time:t.SpecialTime,Setpoint:t.Setpoint,SpecialTime:t.SpecialTime}:{Time:t.Time,Setpoint:t.Setpoint,SpecialTime:""}).sort((t,e)=>t.Time.replace(":","")JSON.stringify(t))),s=Array.from(i).map(t=>JSON.parse(t));return{day:t.day,slots:s}}async loadData(){var t,e;this.error=void 0,this.schedule_type&&this.schedule_id&&!this.editMode&&(await(t=this.hass,e=this.config.hub,t.callWS({type:"wiser/suntimes",hub:e})).then(t=>{this.suntimes=t}).catch(t=>{this.error=t}),await Yt(this.hass,this.config.hub,this.schedule_type,this.schedule_id).then(t=>{this.schedule=this.convertLoadedSchedule(t)}).catch(t=>{this.schedule=void 0,this.error=t}),this.schedule&&await this.get_entity_list(this.hass,this.config.hub).then(t=>{this.entities=t}).catch(t=>{this.error=t}))}async get_entity_list(t,e){return"heating"==this.schedule.Type.toLowerCase()?await((t,e)=>t.callWS({type:"wiser/rooms",hub:e}))(t,e):await((t,e,i)=>t.callWS({type:"wiser/devices",device_type:i,hub:e}))(t,e,this.schedule.SubType)}shouldUpdate(t){return t.has("schedule_id")||t.has("editMode")?(this.loadData(),!0):!!(t.has("schedule")||t.has("entities")||t.has("editMode")||t.has("_assigning_in_progress")||t.has("_save_in_progress")||t.has("error")&&te(this.error))}render(){return this.hass&&this.config&&this.component_loaded?te(this.error)?X` ${this.error.message} `:this.schedule&&this.entities&&this.suntimes?X` -
-
- ${Vt("wiser.headings.schedule_type")}: ${this.schedule.SubType} -
-
- ${Vt("wiser.headings.schedule_id")}: ${this.schedule.Id} -
-
- ${Vt("wiser.headings.schedule_name")}: ${this.schedule.Name} -
-
${this.editMode?"Edit Mode":null}
-
-
-
- -
+ `}};e([pe({attribute:!1})],Kt.prototype,"hass",void 0),e([ue()],Kt.prototype,"_params",void 0),Kt=e([t("wiser-dialog-error")],Kt);var Xt=Object.freeze({__proto__:null,get DialogError(){return Kt}});let Qt=class extends(wt(le)){constructor(){var e;super(...arguments),this.schedule_id=0,this.use_heat_colors=!0,this.embedded=!1,this.assignmentSelection=[],this.assigningDevices=!1,this.rooms=[],this.entities=[],this._activeSlot=null,this._activeDay=null,this.editMode=!1,this._current_user=null===(e=this.hass)||void 0===e?void 0:e.user,this._assigning_in_progress=0,this._save_in_progress=!1,this.stepSize=5}localize(e,t="",i=""){return je(this.hass,e,t,i)}async initialise(){return await this._isComponentLoaded()&&(this.component_loaded=!0,await this.loadData()),!0}hassSubscribe(){return this.initialise(),[this.hass.connection.subscribeMessage(e=>this.handleUpdate(e),{type:"wiser_updated"})]}async handleUpdate(e){this.assigningDevices||this.config.hub&&e.hub!=this.config.hub||"wiser_updated"!=e.event||await this.loadData()}async _isComponentLoaded(){return Boolean(this.hass&&this.config&&this.hass.config.components.includes("wiser"))}getSunTime(e,t){return t==Ae[0]?this.suntimes.Sunrises[Ee.indexOf(e)].time:this.suntimes.Sunsets[Ee.indexOf(e)].time}convertLoadedSchedule(e){const t=e.ScheduleData.map(e=>this.convertLoadedScheduleDay(e));return e.ScheduleData=t,e}convertLoadedScheduleDay(e){const t=e.slots.map(t=>Ae.includes(t.Time)?{Time:this.getSunTime(e.day,t.Time),Setpoint:t.Setpoint,SpecialTime:t.Time}:{Time:t.Time,Setpoint:t.Setpoint,SpecialTime:""}).sort((e,t)=>parseInt(e.Time.replace(":",""))JSON.stringify(e))),s=Array.from(i).map(e=>JSON.parse(e));return{day:e.day,slots:s}}convertScheduleForSaving(e){const t=e.ScheduleData.map(e=>this.convertScheduleDayForSaving(e));return e.ScheduleData=t,e}convertScheduleDayForSaving(e){const t=e.slots.map(e=>Ae.includes(e.SpecialTime)?{Time:e.SpecialTime,Setpoint:e.Setpoint,SpecialTime:e.SpecialTime}:{Time:e.Time,Setpoint:e.Setpoint,SpecialTime:""}).sort((e,t)=>e.Time.replace(":","")JSON.stringify(e))),s=Array.from(i).map(e=>JSON.parse(e));return{day:e.day,slots:s}}async loadData(){this.error=void 0,this.embedded||await at(),this.schedule_type&&this.schedule_id&&!this.editMode&&(await We(this.hass,this.config.hub).then(e=>{this.suntimes=e}).catch(e=>{this.error=e}),await Fe(this.hass,this.config.hub,this.schedule_type,this.schedule_id).then(e=>{this.schedule=this.convertLoadedSchedule(e)}).catch(e=>{this.schedule=void 0,this.error=e}),this.schedule&&await this.get_entity_list(this.hass,this.config.hub).then(e=>{this.entities=e,this.assignmentSelection=e.filter(e=>this.isAssigned(e)).map(e=>String(e.Id))}).catch(e=>{this.error=e})),await xt(this)}async get_entity_list(e,t){return 1e3===this.schedule.Id?[]:"heating"==this.schedule.Type.toLowerCase()?await Ye(e,t):await Je(e,t,this.schedule.SubType||this.schedule.Type)}shouldUpdate(e){return!(!e.has("hass")&&!e.has("component_loaded"))||(e.has("schedule_id")||e.has("schedule_type")||e.has("config")||e.has("editMode")?(this.loadData(),!0):!!(e.has("schedule")||e.has("entities")||e.has("editMode")||e.has("_assigning_in_progress")||e.has("_save_in_progress")||e.has("assignmentSelection")||e.has("assigningDevices")||e.has("error")&&pt(this.error)))}updated(e){super.updated(e),this.embedded&&this.dispatchEvent(new CustomEvent("editor-state",{detail:{editing:this.editMode,saving:this._save_in_progress,ready:Boolean(this.schedule&&this.schedule.Id===this.schedule_id&&this.suntimes&&!this.error)}}))}render(){return this.hass&&this.config&&this.component_loaded?pt(this.error)?W`
${this.error.message}
`:this.schedule&&this.entities&&this.suntimes?W` +
+ ${this.embedded?"":this.renderToolbar()} + ${this.embedded||1e3===this.schedule.Id?"":this.renderScheduleAssignment(this.entities,this.schedule.Assignments)} +
+
+
+
- ${this.renderScheduleAssignment(this.entities,this.schedule.Assignments)} - ${this.renderScheduleActionButtonSection()} -
- ${this.renderCardActions()} - - `:X``:X``}renderScheduleAssignment(t,e){if(this.schedule&&!this.editMode)return ne(this.hass,this.config)?X` -
-
${Vt("wiser.headings.schedule_assignment")}
- ${t.length>0?t.map(t=>this.renderEntityButton(t,e.map(function(t){return t.name}).includes(t.Name))):X`
(No Assignable Devices)
`}
- `:X` -
-
${Vt("wiser.headings.schedule_assignment")}
- ${e.length>0?t.filter(t=>e.map(function(t){return t.name}).includes(t.Name)).map(t=>this.renderEntityLabel(t)):X`${Vt("wiser.headings.not_assigned")}`} -
- `}renderEntityButton(t,e){return X` - + `:W``:W``}isAssigned(e){var t;return Boolean(null===(t=this.schedule)||void 0===t?void 0:t.Assignments.some(t=>{var i,s;const o=t,a=null!==(i=o.id)&&void 0!==i?i:o.Id;return void 0!==a?String(a)===String(e.Id):(null!==(s=o.name)&&void 0!==s?s:o.Name)===e.Name}))}renderScheduleAssignment(e,t){if(this.schedule&&!this.editMode&&1e3!==this.schedule.Id)return vt(this.hass,this.config)?W`
+ ({value:String(e.Id),label:e.Name}))}}} + .value=${this.assignmentSelection} + .required=${!1} + .disabled=${this.assigningDevices||!e.length} + @value-changed=${t=>{var i;if(t.stopPropagation(),this.assigningDevices)return;const s=null!==(i=t.detail.value)&&void 0!==i?i:[];Array.isArray(s)&&s.every(t=>e.some(e=>String(e.Id)===t))&&(this.assignmentSelection=s)}} + > + ${e.length?"":W`

${this.localize("wiser.home.no_devices")}

`} +
`:W`

+ ${e.filter(e=>this.isAssigned(e)).map(e=>e.Name).join(", ")||this.localize("wiser.headings.not_assigned")} +

`}async applyDeviceAssignments(){if(!this.schedule||this.assigningDevices||this.editMode||1e3===this.schedule.Id||!vt(this.hass,this.config))return;const e=(this.entities||[]).filter(e=>this.isAssigned(e)!==this.assignmentSelection.includes(String(e.Id)));this.assigningDevices=!0;try{for(const t of e)await Ze(this.hass,this.config.hub,this.schedule.Type,this.schedule.Id,String(t.Id),!this.assignmentSelection.includes(String(t.Id)));await this.loadData()}catch(e){await this.loadData(),Ge(this,"Schedule assignment",e.message||this.localize("common.load_failed"))}finally{this.assigningDevices=!1}}renderEntityButton(e,t){return W` + + `}tool(e,t,i,s=!1){return W``}renderToolbar(){const e=vt(this.hass,this.config),t=this.assigningDevices||this._save_in_progress,i=1e3===this.schedule.Id,s=(this.entities||[]).some(e=>this.isAssigned(e)!==this.assignmentSelection.includes(String(e.Id)));return W` {var t;const i=e.target,s=null===(t=i.files)||void 0===t?void 0:t[0];i.value="",s&&this.importSchedule(s)}} + /> + + - `}renderBackButton(){return X` - ${this.hass.localize("ui.common.back")} - `}renderCancelButton(){return X` - ${this.hass.localize("ui.common.cancel")} - `}renderScheduleRenameButton(){return X` - - ${Vt("wiser.actions.rename")} - - `}renderDeleteScheduleButton(){return X` - - ${this.hass.localize("ui.common.delete")} - - `}renderCopyScheduleButton(){return X` - - ${Vt("wiser.actions.copy")} - - `}renderEditScheduleButton(){return X` - - ${this.hass.localize("ui.common.edit")} - - `}renderFilesScheduleButton(){return X` - - ${Vt("wiser.actions.files")} - - `}renderSaveScheduleButton(){if(ne(this.hass,this.config))return X` - - ${this._save_in_progress?X``:this.hass.localize("ui.common.save")} - - `}async entityAssignmentClick(t){const e=t.target;this._assigning_in_progress=parseInt(e.id),ne(this.hass,this.config)&&await((t,e,i,s,n,r=!1)=>t.callWS({type:"wiser/schedule/assign",hub:e,schedule_type:i,schedule_id:s,entity_id:n,remove:r}))(this.hass,this.config.hub,this.schedule_type,this.schedule_id,e.id,e.classList.contains("active")),this._assigning_in_progress=0}backClick(){const t=new CustomEvent("backClick");this.dispatchEvent(t)}editClick(){this._tempSchedule=this.schedule,this.editMode=!this.editMode}copyClick(){const t=new CustomEvent("copyClick");this.dispatchEvent(t)}filesClick(){const t=new CustomEvent("filesClick");this.dispatchEvent(t)}async renameScheduleClick(){const t=new CustomEvent("renameClick");this.dispatchEvent(t)}async deleteClick(t){const e=t.target;if(await new Promise(t=>{yt(e,"show-dialog",{dialogTag:"wiser-dialog-delete-confirm",dialogImport:()=>Promise.resolve().then(function(){return pe}),dialogParams:{cancel:()=>{t(!1)},confirm:()=>{t(!0)},name:this.schedule.Name}})})){this.schedule_id=0,await(i=this.hass,s=this.config.hub,n=this.schedule.Type,r=this.schedule.Id,i.callWS({type:"wiser/schedule/delete",hub:s,schedule_type:n,schedule_id:r}));const t=new CustomEvent("schedule-deleted",{bubbles:!0,composed:!0});this.dispatchEvent(t)}var i,s,n,r}cancelClick(){this.editMode=!1}validateSchedule(t){return t.ScheduleData.map(t=>t.slots).map(t=>t.length>0).includes(!0)}async saveClick(){if(this._save_in_progress=!0,this.validateSchedule(this._tempSchedule))It.includes(this.schedule_type)&&(this._tempSchedule=await this.convertScheduleForSaving(this._tempSchedule)),await(t=this.hass,e=this.config.hub,i=this.schedule_type,s=this.schedule_id,n=this._tempSchedule,t.callWS({type:"wiser/schedule/save",hub:e,schedule_type:i,schedule_id:s,schedule:n})),this.editMode=!1;else{const t=X`The schedule you are trying to save has no time slots.`;yt(this,"show-dialog",{dialogTag:"wiser-dialog-error",dialogImport:()=>Promise.resolve().then(function(){return Ne}),dialogParams:{title:"Error Saving Schedule",error:t}})}var t,e,i,s,n;this._save_in_progress=!1}scheduleChanged(t){this._tempSchedule=t.detail.schedule,this.render()}static get styles(){return h` + +

${this.schedule.Name}

`}async entityAssignmentClick(e){var t;const i=e.currentTarget;if(!this._assigning_in_progress&&!this.editMode&&1e3!==(null===(t=this.schedule)||void 0===t?void 0:t.Id)&&vt(this.hass,this.config)){this._assigning_in_progress=parseInt(i.id);try{await Ze(this.hass,this.config.hub,this.schedule_type,this.schedule_id,i.id,i.classList.contains("active")),await this.loadData()}catch(e){Ge(this,"Schedule assignment",e.message||this.localize("common.load_failed"))}finally{this._assigning_in_progress=0}}}backClick(){const e=new CustomEvent("backClick");this.dispatchEvent(e)}editClick(){this.schedule&&this.schedule.Id===this.schedule_id&&vt(this.hass,this.config)&&(this._tempSchedule=JSON.parse(JSON.stringify(this.schedule)),this.editMode=!this.editMode)}copyClick(){const e=new CustomEvent("copyClick");this.dispatchEvent(e)}exportSchedule(){if(!this.schedule)return;const e=this.convertScheduleForSaving(JSON.parse(JSON.stringify(this.schedule))),t={format:"wiser-schedule",version:1,schedule:{Name:e.Name,Type:e.Type,SubType:e.SubType,ScheduleData:e.ScheduleData}},i=URL.createObjectURL(new Blob([JSON.stringify(t,null,2)],{type:"application/json"})),s=document.createElement("a");s.href=i,s.download=`${e.Name.replace(/[^a-z0-9_-]/gi,"_")||"schedule"}.json`,s.click(),setTimeout(()=>URL.revokeObjectURL(i),1e3)}async importSchedule(e){if(this.schedule&&!this.editMode&&vt(this.hass,this.config))try{if(e.size>1048576)throw new Error("Schedule file is too large.");const t=function(e,t){var i;const s=JSON.parse(e);if("wiser-schedule"!==s.format||1!==s.version)throw new Error("Unsupported schedule file.");const o=s.schedule,a=(t.SubType||t.Type).toLowerCase();if(!o||(null===(i=o.SubType||o.Type)||void 0===i?void 0:i.toLowerCase())!==a)throw new Error("This file is for a different schedule type.");if(!Array.isArray(o.ScheduleData)||7!==o.ScheduleData.length)throw new Error("The file must contain all seven days.");const r=new Set;let n=0;const l=o.ScheduleData.map(e=>{if(!Ee.includes(e.day)||r.has(e.day)||!Array.isArray(e.slots)||e.slots.length>24)throw new Error("Invalid schedule days or slots.");r.add(e.day);const t=new Set;return{day:e.day,slots:e.slots.map(e=>{const i=Ae.includes(e.Time);if(!i&&!/^([01]\d|2[0-3]):[0-5]\d$/.test(e.Time)||i&&!["lighting","shutters"].includes(a)||t.has(e.Time))throw new Error("Invalid or duplicate slot time.");t.add(e.Time);const s=String(e.Setpoint),o=Number(s);if(!("heating"===a?Number.isFinite(o)&&(-20===o||o>=5&&o<=30):["lighting","shutters"].includes(a)?Number.isFinite(o)&&o>=0&&o<=100:["On","Off"].includes(s)))throw new Error("Invalid schedule setting.");return n++,{Time:e.Time,Setpoint:s,SpecialTime:i?e.Time:""}})}});if(!n)throw new Error("The schedule has no time slots.");return Object.assign(Object.assign({},t),{ScheduleData:l})}(await e.text(),this.schedule);this._tempSchedule=this.convertLoadedSchedule(t),this.editMode=!0}catch(e){Ge(this,"Import schedule",e.message)}}filesClick(){const e=new CustomEvent("filesClick");this.dispatchEvent(e)}async renameScheduleClick(){const e=new CustomEvent("renameClick");this.dispatchEvent(e)}async deleteClick(e){if(!vt(this.hass,this.config))return;const t=(null==e?void 0:e.target)||this;if(await new Promise(e=>{ve(t,"show-dialog",{dialogTag:"wiser-dialog-delete-confirm",dialogImport:()=>Promise.resolve().then(function(){return At}),dialogParams:{cancel:()=>{e(!1)},confirm:()=>{e(!0)},name:this.schedule.Name}})})){this.schedule_id=0,await(i=this.hass,s=this.config.hub,o=this.schedule.Type,a=this.schedule.Id,i.callWS({type:"wiser/schedule/delete",hub:s,schedule_type:o,schedule_id:a}));const e=new CustomEvent("scheduleDeleted");this.dispatchEvent(e)}var i,s,o,a}cancelClick(){this.editMode=!1}validateSchedule(e){return e.ScheduleData.map(e=>e.slots).map(e=>e.length>0).includes(!0)}async saveClick(){if(!this._save_in_progress&&this._tempSchedule&&vt(this.hass,this.config)){this._save_in_progress=!0;try{if(this.validateSchedule(this._tempSchedule)){const e=JSON.parse(JSON.stringify(this._tempSchedule)),t=$e.includes(this.schedule_type)?this.convertScheduleForSaving(e):e;await((e,t,i,s,o)=>e.callWS({type:"wiser/schedule/save",hub:t,schedule_type:i,schedule_id:s,schedule:o}))(this.hass,this.config.hub,this.schedule_type,this.schedule_id,t),this.editMode=!1}else Ge(this,"Error Saving Schedule","The schedule you are trying to save has no time slots.")}catch(e){Ge(this,"Error Saving Schedule",(null==e?void 0:e.message)||this.localize("common.load_failed"))}finally{this._save_in_progress=!1}}}scheduleChanged(e){this._tempSchedule=e.detail.schedule,this.render()}static get styles(){return n` + ${Ct} + .schedule-heading { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + gap: 12px; + } + .schedule-title { + margin: 16px 0 8px; + font-size: calc(22px + 1pt); + } + .tools { + display: flex; + flex-wrap: wrap; + gap: 6px; + margin-inline-start: auto; + } + .tool { + width: 44px; + height: 44px; + padding: 0; + display: grid; + place-items: center; + color: var(--secondary-text-color); + } + .tool:disabled { + color: var(--disabled-text-color); + opacity: 1; + } + .tool:not(:disabled):hover { + color: var(--primary-color); + } + + .device-assignment { + max-width: 420px; + margin: 20px 0; + display: grid; + gap: 8px; + } + .device-assignment button { + justify-self: start; + } :host { display: block; max-width: 100%; @@ -1124,7 +1790,7 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} color: var(--primary-color); text-transform: uppercase; font-weight: 500; - font-size: var(--material-small-font-size); + font-size: calc(var(--material-small-font-size, 12px) + 1pt); padding: 5px 10px; } .slot { @@ -1137,7 +1803,7 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} position: relative; height: 40px; line-height: 40px; - font-size: 10px; + font-size: calc(10px + 1pt); text-align: center; overflow: hidden; } @@ -1223,6 +1889,8 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} div.schedule-action-wrapper { display: flex; justify-content: center; + flex-wrap: wrap; + gap: 8px; } div.time-wrapper div { float: left; @@ -1230,11 +1898,13 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} position: relative; height: 25px; line-height: 25px; - font-size: 12px; + font-size: calc(12px + 1pt); text-align: center; align-content: center; align-items: center; justify-content: center; + flex-wrap: wrap; + gap: 8px; } div.time-wrapper div.time:before { content: ' '; @@ -1248,7 +1918,7 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} margin-top: 0px; } .slot span { - font-size: 10px; + font-size: calc(10px + 1pt); color: var(--text-primary-color); height: 100%; display: flex; @@ -1282,7 +1952,7 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} animation-fill-mode: forwards; } .schedule-action-button { - width: 20%; + flex: 1 1 100px; padding: 0 5px; } ha-icon-button { @@ -1316,46 +1986,63 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} div.schedule-info { margin: 3px 0; } - `}};n([gt({attribute:!1})],De.prototype,"config",void 0),n([gt({attribute:!1})],De.prototype,"schedule_id",void 0),n([gt({attribute:!1})],De.prototype,"schedule_type",void 0),n([gt({attribute:!1})],De.prototype,"use_heat_colors",void 0),n([vt()],De.prototype,"schedule",void 0),n([vt()],De.prototype,"rooms",void 0),n([vt()],De.prototype,"entities",void 0),n([vt()],De.prototype,"suntimes",void 0),n([vt()],De.prototype,"component_loaded",void 0),n([vt()],De.prototype,"_activeSlot",void 0),n([vt()],De.prototype,"_activeDay",void 0),n([vt()],De.prototype,"editMode",void 0),n([vt()],De.prototype,"_current_user",void 0),n([vt()],De.prototype,"_assigning_in_progress",void 0),n([vt()],De.prototype,"_save_in_progress",void 0),n([vt()],De.prototype,"error",void 0),De=n([ut("wiser-schedule-edit-card")],De);let He=class extends ht{constructor(){super(),this.component_loaded=!1,this._schedule_types=[],this._schedule_info={Name:"",Type:"Heating"},this.initialise()}async initialise(){return await this.isComponentLoaded()&&(this.component_loaded=!0,await this.loadData()),!0}async isComponentLoaded(){for(;!this.hass||!this.hass.config.components.includes("wiser");)await new Promise(t=>setTimeout(t,100));return!0}async loadData(){this._schedule_types=await Wt(this.hass,this.config.hub)}render(){return this.hass&&this.config?X` + ${Ue} + `}};e([pe({attribute:!1})],Qt.prototype,"config",void 0),e([pe({attribute:!1})],Qt.prototype,"schedule_id",void 0),e([pe({attribute:!1})],Qt.prototype,"schedule_type",void 0),e([pe({attribute:!1})],Qt.prototype,"use_heat_colors",void 0),e([pe({attribute:!1})],Qt.prototype,"embedded",void 0),e([ue()],Qt.prototype,"assignmentSelection",void 0),e([ue()],Qt.prototype,"assigningDevices",void 0),e([ue()],Qt.prototype,"schedule",void 0),e([ue()],Qt.prototype,"rooms",void 0),e([ue()],Qt.prototype,"entities",void 0),e([ue()],Qt.prototype,"suntimes",void 0),e([ue()],Qt.prototype,"component_loaded",void 0),e([ue()],Qt.prototype,"_activeSlot",void 0),e([ue()],Qt.prototype,"_activeDay",void 0),e([ue()],Qt.prototype,"editMode",void 0),e([ue()],Qt.prototype,"_current_user",void 0),e([ue()],Qt.prototype,"_assigning_in_progress",void 0),e([ue()],Qt.prototype,"_save_in_progress",void 0),e([ue()],Qt.prototype,"error",void 0),Qt=e([t("wiser-schedule-edit-card")],Qt);let ei=class extends le{constructor(){super(...arguments),this.component_loaded=!1,this._saving=!1,this._schedule_types=[],this._schedule_info={Name:"",Type:""},this._loadError=""}localize(e,t="",i=""){return je(this.hass,e,t,i)}firstUpdated(){this.loadData().then(()=>{this.component_loaded=!0}).catch(e=>{this._loadError=(null==e?void 0:e.message)||this.localize("common.load_failed")}).then(()=>xt(this))}async loadData(){const e=await(t=this.hass,i=this.config.hub,t.callWS({type:"wiser/schedules/types",hub:i}));var t,i;if(this._schedule_types=e.filter(e=>!this.allowed_types||this.allowed_types.some(t=>t.toLowerCase()===e.toLowerCase())),this._schedule_info={Name:"",Type:this._schedule_types[0]||""},!this._schedule_types.length)throw new Error(this.localize("wiser.helpers.no_supported_types"))}render(){var e,t,i;return this.hass&&this.config?this._loadError?W`
${this._loadError}`:this.component_loaded?W` + + +
-
${Vt("wiser.actions.add_schedule")}
-
${Vt("wiser.helpers.add_schedule")}
-
${this._schedule_types.map((t,e)=>this.renderScheduleTypeButtons(t,e))}
- - -
-
- - ${this.hass.localize("ui.common.save")} - - ${this.hass.localize("ui.common.cancel")} +
${this.localize("wiser.actions.add_schedule")}
+
+ ${this.localize(1===this._schedule_types.length?"wiser.helpers.add_schedule_name":"wiser.helpers.add_schedule")} +
+ ${this._schedule_types.length>1?W`
${this._schedule_types.map((e,t)=>this.renderScheduleTypeButtons(e,t))}
`:""} +
- `:X``}renderScheduleTypeButtons(t,e){return X` - ${this.localize("common.loading")}
`:W``}renderScheduleTypeButtons(e,t){return W` + + `}async confirmClick(){await this.createSchedule()}async createSchedule(){const e=this._schedule_info;if(this.hass&&this.config&&vt(this.hass,this.config)&&!this._saving&&(null==e?void 0:e.Name.trim())&&this._schedule_types.includes(e.Type)){this._saving=!0;try{const a=await qe(this.hass,this.config.hub,e.Type);await(t=this.hass,i=this.config.hub,s=e.Type,o=e.Name.trim(),t.callWS({type:"wiser/schedule/create",hub:i,schedule_type:s,name:o}));const r=(await qe(this.hass,this.config.hub,e.Type)).find(t=>t.Name===e.Name.trim()&&!a.some(e=>e.Id===t.Id&&e.Type===t.Type));r&&void 0!==this.assign_to&&await Ze(this.hass,this.config.hub,r.Type,r.Id,String(this.assign_to)),this.dispatchEvent(new CustomEvent("scheduleAdded",{detail:r}))}catch(e){this._loadError=(null==e?void 0:e.message)||this.localize("common.load_failed")}finally{this._saving=!1}var t,i,s,o}}cancelClick(){const e=new CustomEvent("backClick");this.dispatchEvent(e)}_valueChanged(e){const t=e.currentTarget;t.configValue&&(this._schedule_info=Object.assign(Object.assign({},this._schedule_info),{[t.configValue]:void 0!==t.checked?t.checked:t.value}))}static get styles(){return n` + ${Ct} + .header-actions { + display: flex; + flex-wrap: wrap; + justify-content: flex-end; + gap: 6px; + } div.wrapper { white-space: nowrap; transition: @@ -1371,9 +2058,28 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} margin: 20px 0 0 0; } .schedule-name { + max-width: 420px; + display: grid; + gap: 8px; + color: var(--primary-text-color); margin: 20px 0 0 0; width: 100%; } + input { + box-sizing: border-box; + width: 100%; + min-height: 44px; + padding: 10px 12px; + border: 1px solid var(--divider-color, #aaa); + border-radius: 10px; + background: var(--card-background-color, white); + color: var(--primary-text-color, #222); + font: inherit; + } + input:focus-visible { + outline: 2px solid var(--primary-color); + outline-offset: 2px; + } ha-icon-button { --mdc-icon-button-size: 36px; margin-top: -6px; @@ -1389,44 +2095,51 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} --mdc-theme-primary: var(--text-primary-color); border-radius: 4px; } - `}};n([gt({attribute:!1})],He.prototype,"hass",void 0),n([gt({attribute:!1})],He.prototype,"config",void 0),n([gt({attribute:!1})],He.prototype,"component_loaded",void 0),n([vt()],He.prototype,"_schedule_types",void 0),n([vt()],He.prototype,"_schedule_info",void 0),He=n([ut("wiser-schedule-add-card")],He);let Ue=class extends ht{constructor(){super(),this.schedule_id=0,this.component_loaded=!1,this._copy_in_progress=0,this._schedule_list=[],this.initialise()}async initialise(){return await this.isComponentLoaded()&&(this.component_loaded=!0,await this.loadData()),!0}async isComponentLoaded(){for(;!this.hass||!this.hass.config.components.includes("wiser");)await new Promise(t=>setTimeout(t,100));return!0}async loadData(){this.schedule=await Yt(this.hass,this.config.hub,this.schedule_type,this.schedule_id),this._schedule_list=await qt(this.hass,this.config.hub,this.schedule_type)}render(){return this.hass&&this.config&&this.schedule?X` -
-
${Vt("wiser.headings.copy_schedule")}
-
- ${Vt("wiser.headings.schedule_type")}: ${this.schedule.Type} -
-
- ${Vt("wiser.headings.schedule_id")}: ${this.schedule.Id} -
-
- ${Vt("wiser.headings.schedule_name")}: ${this.schedule.Name} -
-
${Vt("wiser.helpers.select_copy_schedule")}
-
- ${this._schedule_list.filter(t=>{var e;return t.Id!=(null===(e=this.schedule)||void 0===e?void 0:e.Id)}).map(t=>this.renderScheduleButtons(t))} -
-
-
- + `}};e([pe({attribute:!1})],ei.prototype,"hass",void 0),e([pe({attribute:!1})],ei.prototype,"config",void 0),e([pe({attribute:!1})],ei.prototype,"component_loaded",void 0),e([pe({attribute:!1})],ei.prototype,"allowed_types",void 0),e([pe({attribute:!1})],ei.prototype,"assign_to",void 0),e([ue()],ei.prototype,"_saving",void 0),e([ue()],ei.prototype,"_schedule_types",void 0),e([ue()],ei.prototype,"_schedule_info",void 0),e([ue()],ei.prototype,"_loadError",void 0),ei=e([t("wiser-schedule-add-card")],ei);let ti=class extends le{constructor(){super(...arguments),this.schedule_id=0,this.component_loaded=!1,this._copy_in_progress=0,this._schedule_list=[],this._loadError=""}localize(e,t="",i=""){return je(this.hass,e,t,i)}firstUpdated(){this.loadData().then(()=>{this.component_loaded=!0}).catch(e=>{this._loadError=(null==e?void 0:e.message)||this.localize("common.load_failed")}).then(()=>xt(this))}async loadData(){this.schedule=await Fe(this.hass,this.config.hub,this.schedule_type,this.schedule_id),this._schedule_list=await qe(this.hass,this.config.hub,this.schedule_type)}render(){return this.hass&&this.config?this._loadError?W`
${this._loadError}`:this.component_loaded&&this.schedule?W` + + + +
+
${this.localize("wiser.headings.copy_schedule")}
+
+ ${this.localize("wiser.headings.schedule_type")}: ${this.schedule.Type}
- - `:X``}renderScheduleButtons(t){return X` - + ${this.localize("wiser.headings.schedule_id")}: ${this.schedule.Id} +
+
+ ${this.localize("wiser.headings.schedule_name")}: ${this.schedule.Name} +
+
${this.localize("wiser.helpers.select_copy_schedule")}
+
+ ${this._schedule_list.filter(e=>{var t;return e.Id!=(null===(t=this.schedule)||void 0===t?void 0:t.Id)}).map(e=>this.renderScheduleButtons(e))} +
+
+ `:W`
${this.localize("common.loading")}
`:W``}renderScheduleButtons(e){return W` + + `}cancelClick(){const e=new CustomEvent("backClick",{detail:fe.ScheduleEdit});this.dispatchEvent(e)}async _copySchedule(e){const t=e.currentTarget;if(t.id){this._copy_in_progress=parseInt(t.id),await(i=this.hass,s=this.config.hub,o=this.schedule_type,a=this.schedule_id,r=parseInt(t.id),i.callWS({type:"wiser/schedule/copy",hub:s,schedule_type:o,schedule_id:a,to_schedule_id:r})),this._copy_in_progress=0;const e=new CustomEvent("scheduleCopied");this.dispatchEvent(e)}var i,s,o,a,r}static get styles(){return n` + ${Ct} + .header-actions { + display: flex; + flex-wrap: wrap; + justify-content: flex-end; + gap: 6px; + } div.wrapper { white-space: nowrap; transition: @@ -1466,36 +2179,45 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} div.schedule-info { margin: 3px 0; } - `}};n([gt({attribute:!1})],Ue.prototype,"hass",void 0),n([gt({attribute:!1})],Ue.prototype,"config",void 0),n([gt({attribute:!1})],Ue.prototype,"schedule_id",void 0),n([gt({attribute:!1})],Ue.prototype,"schedule_type",void 0),n([vt()],Ue.prototype,"schedule",void 0),n([vt()],Ue.prototype,"component_loaded",void 0),n([vt()],Ue.prototype,"_copy_in_progress",void 0),n([vt()],Ue.prototype,"_schedule_list",void 0),Ue=n([ut("wiser-schedule-copy-card")],Ue);let ze=class extends ht{constructor(){super(),this.component_loaded=!1,this._newScheduleName="",this._rename_in_progress=!1,this.initialise()}async initialise(){return await this.isComponentLoaded()&&(this.component_loaded=!0,await this.loadData()),!0}async isComponentLoaded(){for(;!this.hass||!this.hass.config.components.includes("wiser");)await new Promise(t=>setTimeout(t,100));return!0}async loadData(){this._schedule=await Yt(this.hass,this.config.hub,this.schedule_type,this.schedule_id)}render(){return this.hass&&this.config?X` + `}};e([pe({attribute:!1})],ti.prototype,"hass",void 0),e([pe({attribute:!1})],ti.prototype,"config",void 0),e([pe({attribute:!1})],ti.prototype,"schedule_id",void 0),e([pe({attribute:!1})],ti.prototype,"schedule_type",void 0),e([ue()],ti.prototype,"schedule",void 0),e([ue()],ti.prototype,"component_loaded",void 0),e([ue()],ti.prototype,"_copy_in_progress",void 0),e([ue()],ti.prototype,"_schedule_list",void 0),e([ue()],ti.prototype,"_loadError",void 0),ti=e([t("wiser-schedule-copy-card")],ti);let ii=class extends le{constructor(){super(...arguments),this.component_loaded=!1,this._newScheduleName="",this._rename_in_progress=!1,this._loadError=""}localize(e,t="",i=""){return je(this.hass,e,t,i)}firstUpdated(){this.loadData().then(()=>{this.component_loaded=!0}).catch(e=>{this._loadError=(null==e?void 0:e.message)||this.localize("common.load_failed")}).then(()=>xt(this))}async loadData(){this._schedule=await Fe(this.hass,this.config.hub,this.schedule_type,this.schedule_id),this._newScheduleName=this._schedule.Name}render(){var e;return this.hass&&this.config?this._loadError?W`
${this._loadError}`:this.component_loaded?W` + + +
-
${Vt("wiser.headings.rename_schedule")}
-
${Vt("wiser.helpers.enter_new_name")}
- - -
-
- - ${this._rename_in_progress?X``:this.hass.localize("ui.common.save")} - - - ${this.hass.localize("ui.common.cancel")} - +
${this.localize("wiser.headings.rename_schedule")}
+
${this.localize("wiser.helpers.enter_new_name")}
+
- `:X``}async confirmClick(){await this.renameSchedule()}async renameSchedule(){var t,e,i,s,n;this._rename_in_progress=!0,await(t=this.hass,e=this.config.hub,i=this.schedule_type,s=this.schedule_id,n=this._newScheduleName,t.callWS({type:"wiser/schedule/rename",hub:e,schedule_type:i,schedule_id:s,schedule_name:n}));const r=new CustomEvent("scheduleRenamed");this.dispatchEvent(r),this._rename_in_progress=!1}cancelClick(){const t=new CustomEvent("backClick",{detail:Et.ScheduleEdit});this.dispatchEvent(t)}_valueChanged(t){const e=t.target;e.configValue&&(this._newScheduleName=e.value)}static get styles(){return h` + `:W`
${this.localize("common.loading")}
`:W``}async confirmClick(){await this.renameSchedule()}async renameSchedule(){var e,t,i,s,o;this._rename_in_progress=!0,await(e=this.hass,t=this.config.hub,i=this.schedule_type,s=this.schedule_id,o=this._newScheduleName,e.callWS({type:"wiser/schedule/rename",hub:t,schedule_type:i,schedule_id:s,schedule_name:o}));const a=new CustomEvent("scheduleRenamed");this.dispatchEvent(a),this._rename_in_progress=!1}cancelClick(){const e=new CustomEvent("backClick",{detail:fe.ScheduleEdit});this.dispatchEvent(e)}static get styles(){return n` + ${Ct} + .header-actions { + display: flex; + flex-wrap: wrap; + justify-content: flex-end; + gap: 6px; + } div.wrapper { white-space: nowrap; transition: @@ -1514,6 +2236,7 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} margin: 20px 0 0 0; } .schedule-name { + max-width: 420px; margin: 20px 0 0 0; width: 100%; } @@ -1532,1761 +2255,178 @@ const ut=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)} --mdc-theme-primary: var(--text-primary-color); border-radius: 4px; } - `}};n([gt({attribute:!1})],ze.prototype,"hass",void 0),n([gt({attribute:!1})],ze.prototype,"config",void 0),n([gt({attribute:!1})],ze.prototype,"component_loaded",void 0),n([gt({attribute:!1})],ze.prototype,"schedule_type",void 0),n([gt({attribute:!1})],ze.prototype,"schedule_id",void 0),n([vt()],ze.prototype,"_newScheduleName",void 0),n([vt()],ze.prototype,"_schedule",void 0),n([vt()],ze.prototype,"_rename_in_progress",void 0),ze=n([ut("wiser-schedule-rename-card")],ze); -/** - * @license - * Copyright 2016 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -var Fe=function(){function t(t){void 0===t&&(t={}),this.adapter=t}return Object.defineProperty(t,"cssClasses",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"strings",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"numbers",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"defaultAdapter",{get:function(){return{}},enumerable:!1,configurable:!0}),t.prototype.init=function(){},t.prototype.destroy=function(){},t}(),Be={ROOT:"mdc-form-field"},Ve={LABEL_SELECTOR:".mdc-form-field > label"},je=function(t){function e(i){var n=t.call(this,s(s({},e.defaultAdapter),i))||this;return n.click=function(){n.handleClick()},n}return i(e,t),Object.defineProperty(e,"cssClasses",{get:function(){return Be},enumerable:!1,configurable:!0}),Object.defineProperty(e,"strings",{get:function(){return Ve},enumerable:!1,configurable:!0}),Object.defineProperty(e,"defaultAdapter",{get:function(){return{activateInputRipple:function(){},deactivateInputRipple:function(){},deregisterInteractionHandler:function(){},registerInteractionHandler:function(){}}},enumerable:!1,configurable:!0}),e.prototype.init=function(){this.adapter.registerInteractionHandler("click",this.click)},e.prototype.destroy=function(){this.adapter.deregisterInteractionHandler("click",this.click)},e.prototype.handleClick=function(){var t=this;this.adapter.activateInputRipple(),requestAnimationFrame(function(){t.adapter.deactivateInputRipple()})},e}(Fe); -/** - * @license - * Copyright 2017 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const We=window,qe=We.ShadowRoot&&(void 0===We.ShadyCSS||We.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,Ye=Symbol(),Xe=new WeakMap;let Ge=class{constructor(t,e,i){if(this._$cssResult$=!0,i!==Ye)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(qe&&void 0===t){const i=void 0!==e&&1===e.length;i&&(t=Xe.get(e)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&Xe.set(e,t))}return t}toString(){return this.cssText}};const Ke=qe?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new Ge("string"==typeof t?t:t+"",void 0,Ye))(e)})(t):t; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */var Je;const Ze=window,Qe=Ze.trustedTypes,ti=Qe?Qe.emptyScript:"",ei=Ze.reactiveElementPolyfillSupport,ii={toAttribute(t,e){switch(e){case Boolean:t=t?ti: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}},si=(t,e)=>e!==t&&(e==e||t==t),ni={attribute:!0,type:String,converter:ii,reflect:!1,hasChanged:si},ri="finalized";let oi=class extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(t){var e;this.finalize(),(null!==(e=this.h)&&void 0!==e?e:this.h=[]).push(t)}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach((e,i)=>{const s=this._$Ep(i,e);void 0!==s&&(this._$Ev.set(s,i),t.push(s))}),t}static createProperty(t,e=ni){if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){const i="symbol"==typeof t?Symbol():"__"+t,s=this.getPropertyDescriptor(t,i,e);void 0!==s&&Object.defineProperty(this.prototype,t,s)}}static getPropertyDescriptor(t,e,i){return{get(){return this[e]},set(s){const n=this[t];this[e]=s,this.requestUpdate(t,n,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||ni}static finalize(){if(this.hasOwnProperty(ri))return!1;this[ri]=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),void 0!==t.h&&(this.h=[...t.h]),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,e=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const i of e)this.createProperty(i,t[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}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(Ke(t))}else void 0!==t&&e.push(Ke(t));return e}static _$Ep(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}_$Eu(){var t;this._$E_=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach(t=>t(this))}addController(t){var e,i;(null!==(e=this._$ES)&&void 0!==e?e:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(i=t.hostConnected)||void 0===i||i.call(t))}removeController(t){var e;null===(e=this._$ES)||void 0===e||e.splice(this._$ES.indexOf(t)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach((t,e)=>{this.hasOwnProperty(e)&&(this._$Ei.set(e,this[e]),delete this[e])})}createRenderRoot(){var t;const e=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return((t,e)=>{qe?t.adoptedStyleSheets=e.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet):e.forEach(e=>{const i=document.createElement("style"),s=We.litNonce;void 0!==s&&i.setAttribute("nonce",s),i.textContent=e.cssText,t.appendChild(i)})})(e,this.constructor.elementStyles),e}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)})}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)})}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$EO(t,e,i=ni){var s;const n=this.constructor._$Ep(t,i);if(void 0!==n&&!0===i.reflect){const r=(void 0!==(null===(s=i.converter)||void 0===s?void 0:s.toAttribute)?i.converter:ii).toAttribute(e,i.type);this._$El=t,null==r?this.removeAttribute(n):this.setAttribute(n,r),this._$El=null}}_$AK(t,e){var i;const s=this.constructor,n=s._$Ev.get(t);if(void 0!==n&&this._$El!==n){const t=s.getPropertyOptions(n),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(i=t.converter)||void 0===i?void 0:i.fromAttribute)?t.converter:ii;this._$El=n,this[n]=r.fromAttribute(e,t.type),this._$El=null}}requestUpdate(t,e,i){let s=!0;void 0!==t&&(((i=i||this.constructor.getPropertyOptions(t)).hasChanged||si)(this[t],e)?(this._$AL.has(t)||this._$AL.set(t,e),!0===i.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,i))):s=!1),!this.isUpdatePending&&s&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach((t,e)=>this[e]=t),this._$Ei=void 0);let e=!1;const i=this._$AL;try{e=this.shouldUpdate(i),e?(this.willUpdate(i),null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)}),this.update(i)):this._$Ek()}catch(t){throw e=!1,this._$Ek(),t}e&&this._$AE(i)}willUpdate(t){}_$AE(t){var e;null===(e=this._$ES)||void 0===e||e.forEach(t=>{var e;return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)}),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return!0}update(t){void 0!==this._$EC&&(this._$EC.forEach((t,e)=>this._$EO(e,this[e],t)),this._$EC=void 0),this._$Ek()}updated(t){}firstUpdated(t){}}; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -var ai;oi[ri]=!0,oi.elementProperties=new Map,oi.elementStyles=[],oi.shadowRootOptions={mode:"open"},null==ei||ei({ReactiveElement:oi}),(null!==(Je=Ze.reactiveElementVersions)&&void 0!==Je?Je:Ze.reactiveElementVersions=[]).push("1.6.3");const li=window,di=li.trustedTypes,ci=di?di.createPolicy("lit-html",{createHTML:t=>t}):void 0,hi="$lit$",pi=`lit$${(Math.random()+"").slice(9)}$`,ui="?"+pi,mi=`<${ui}>`,fi=document,gi=()=>fi.createComment(""),vi=t=>null===t||"object"!=typeof t&&"function"!=typeof t,_i=Array.isArray,bi="[ \t\n\f\r]",yi=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,xi=/-->/g,$i=/>/g,wi=RegExp(`>|${bi}(?:([^\\s"'>=/]+)(${bi}*=${bi}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),Ai=/'/g,Ei=/"/g,Si=/^(?:script|style|textarea|title)$/i,Ci=Symbol.for("lit-noChange"),Ti=Symbol.for("lit-nothing"),Ii=new WeakMap,Oi=fi.createTreeWalker(fi,129,null,!1);function ki(t,e){if(!Array.isArray(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==ci?ci.createHTML(e):e}let Ri=class t{constructor({strings:e,_$litType$:i},s){let n;this.parts=[];let r=0,o=0;const a=e.length-1,l=this.parts,[d,c]=((t,e)=>{const i=t.length-1,s=[];let n,r=2===e?"":"",o=yi;for(let e=0;e"===l[0]?(o=null!=n?n:yi,d=-1):void 0===l[1]?d=-2:(d=o.lastIndex-l[2].length,a=l[1],o=void 0===l[3]?wi:'"'===l[3]?Ei:Ai):o===Ei||o===Ai?o=wi:o===xi||o===$i?o=yi:(o=wi,n=void 0);const h=o===wi&&t[e+1].startsWith("/>")?" ":"";r+=o===yi?i+mi:d>=0?(s.push(a),i.slice(0,d)+hi+i.slice(d)+pi+h):i+pi+(-2===d?(s.push(void 0),e):h)}return[ki(t,r+(t[i]||"")+(2===e?"":"")),s]})(e,i);if(this.el=t.createElement(d,s),Oi.currentNode=this.el.content,2===i){const t=this.el.content,e=t.firstChild;e.remove(),t.append(...e.childNodes)}for(;null!==(n=Oi.nextNode())&&l.length0){n.textContent=di?di.emptyScript:"";for(let i=0;i_i(t)||"function"==typeof(null==t?void 0: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!==Ti&&vi(this._$AH)?this._$AA.nextSibling.data=t:this.$(fi.createTextNode(t)),this._$AH=t}g(t){var e;const{values:i,_$litType$:s}=t,n="number"==typeof s?this._$AC(t):(void 0===s.el&&(s.el=Ri.createElement(ki(s.h,s.h[0]),this.options)),s);if((null===(e=this._$AH)||void 0===e?void 0:e._$AD)===n)this._$AH.v(i);else{const t=new Li(n,this),e=t.u(this.options);t.v(i),this.$(e),this._$AH=t}}_$AC(t){let e=Ii.get(t.strings);return void 0===e&&Ii.set(t.strings,e=new Ri(t)),e}T(e){_i(this._$AH)||(this._$AH=[],this._$AR());const i=this._$AH;let s,n=0;for(const r of e)n===i.length?i.push(s=new t(this.k(gi()),this.k(gi()),this,this.options)):s=i[n],s._$AI(r),n++;n2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=Ti}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(t,e=this,i,s){const n=this.strings;let r=!1;if(void 0===n)t=Pi(this,t,e,0),r=!vi(t)||t!==this._$AH&&t!==Ci,r&&(this._$AH=t);else{const s=t;let o,a;for(t=n[0],o=0;o{var s,n;const r=null!==(s=null==i?void 0:i.renderBefore)&&void 0!==s?s:e;let o=r._$litPart$;if(void 0===o){const t=null!==(n=null==i?void 0:i.renderBefore)&&void 0!==n?n:null;r._$litPart$=o=new Mi(e.insertBefore(gi(),t),t,void 0,null!=i?i:{})}return o._$AI(t),o})(e,this.renderRoot,this.renderOptions)}connectedCallback(){var t;super.connectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!0)}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!1)}render(){return Ci}};Wi.finalized=!0,Wi._$litElement$=!0,null===(Vi=globalThis.litElementHydrateSupport)||void 0===Vi||Vi.call(globalThis,{LitElement:Wi});const qi=globalThis.litElementPolyfillSupport;null==qi||qi({LitElement:Wi}),(null!==(ji=globalThis.litElementVersions)&&void 0!==ji?ji:globalThis.litElementVersions=[]).push("3.3.3"); -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -const Yi=t=>t.nodeType===Node.ELEMENT_NODE;function Xi(t){return{addClass:e=>{t.classList.add(e)},removeClass:e=>{t.classList.remove(e)},hasClass:e=>t.classList.contains(e)}}const Gi=()=>{},Ki={get passive(){return!1}};document.addEventListener("x",Gi,Ki),document.removeEventListener("x",Gi);const Ji=(t=window.document)=>{let e=t.activeElement;const i=[];if(!e)return i;for(;e&&(i.push(e),e.shadowRoot);)e=e.shadowRoot.activeElement;return i},Zi=t=>{const e=Ji();if(!e.length)return!1;const i=e[e.length-1],s=new Event("check-if-focused",{bubbles:!0,composed:!0});let n=[];const r=t=>{n=t.composedPath()};return document.body.addEventListener("check-if-focused",r),i.dispatchEvent(s),document.body.removeEventListener("check-if-focused",r),-1!==n.indexOf(t)}; -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -class Qi extends Wi{click(){if(this.mdcRoot)return this.mdcRoot.focus(),void this.mdcRoot.click();super.click()}createFoundation(){void 0!==this.mdcFoundation&&this.mdcFoundation.destroy(),this.mdcFoundationClass&&(this.mdcFoundation=new this.mdcFoundationClass(this.createAdapter()),this.mdcFoundation.init())}firstUpdated(){this.createFoundation()}} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */const ts=(t,e)=>"method"===e.kind&&e.descriptor&&!("value"in e.descriptor)?{...e,finisher(i){i.createProperty(e.key,t)}}:{kind:"field",key:Symbol(),placement:"own",descriptor:{},originalKey:e.key,initializer(){"function"==typeof e.initializer&&(this[e.key]=e.initializer.call(this))},finisher(i){i.createProperty(e.key,t)}}; -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -var es,is,ss;null===(es=window.HTMLSlotElement)||void 0===es||es.prototype.assignedElements;const ns=null!==(ss=null===(is=window.ShadyDOM)||void 0===is?void 0:is.inUse)&&void 0!==ss&&ss;class rs extends Qi{constructor(){super(...arguments),this.disabled=!1,this.containingForm=null,this.formDataListener=t=>{this.disabled||this.setFormData(t.formData)}}findFormElement(){if(!this.shadowRoot||ns)return null;const t=this.getRootNode().querySelectorAll("form");for(const e of Array.from(t))if(e.contains(this))return e;return null}connectedCallback(){var t;super.connectedCallback(),this.containingForm=this.findFormElement(),null===(t=this.containingForm)||void 0===t||t.addEventListener("formdata",this.formDataListener)}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this.containingForm)||void 0===t||t.removeEventListener("formdata",this.formDataListener),this.containingForm=null}click(){this.formElement&&!this.disabled&&(this.formElement.focus(),this.formElement.click())}firstUpdated(){super.firstUpdated(),this.shadowRoot&&this.mdcRoot.addEventListener("change",t=>{this.dispatchEvent(new Event("change",t))})}}rs.shadowRootOptions={mode:"open",delegatesFocus:!0},n([function(t){return(e,i)=>void 0!==i?((t,e,i)=>{e.constructor.createProperty(i,t)})(t,e,i):ts(t,e)}({type:Boolean})],rs.prototype,"disabled",void 0); -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -const os=t=>(e,i)=>{if(e.constructor._observers){if(!e.constructor.hasOwnProperty("_observers")){const t=e.constructor._observers;e.constructor._observers=new Map,t.forEach((t,i)=>e.constructor._observers.set(i,t))}}else{e.constructor._observers=new Map;const t=e.updated;e.updated=function(e){t.call(this,e),e.forEach((t,e)=>{const i=this.constructor._observers.get(e);void 0!==i&&i.call(this,this[e],t)})}}e.constructor._observers.set(i,t)},as=window,ls=as.ShadowRoot&&(void 0===as.ShadyCSS||as.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,ds=Symbol(),cs=new WeakMap; -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */let hs=class{constructor(t,e,i){if(this._$cssResult$=!0,i!==ds)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(ls&&void 0===t){const i=void 0!==e&&1===e.length;i&&(t=cs.get(e)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&cs.set(e,t))}return t}toString(){return this.cssText}};const ps=ls?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new hs("string"==typeof t?t:t+"",void 0,ds))(e)})(t):t; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */var us;const ms=window,fs=ms.trustedTypes,gs=fs?fs.emptyScript:"",vs=ms.reactiveElementPolyfillSupport,_s={toAttribute(t,e){switch(e){case Boolean:t=t?gs: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}},bs=(t,e)=>e!==t&&(e==e||t==t),ys={attribute:!0,type:String,converter:_s,reflect:!1,hasChanged:bs},xs="finalized";let $s=class extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(t){var e;this.finalize(),(null!==(e=this.h)&&void 0!==e?e:this.h=[]).push(t)}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach((e,i)=>{const s=this._$Ep(i,e);void 0!==s&&(this._$Ev.set(s,i),t.push(s))}),t}static createProperty(t,e=ys){if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){const i="symbol"==typeof t?Symbol():"__"+t,s=this.getPropertyDescriptor(t,i,e);void 0!==s&&Object.defineProperty(this.prototype,t,s)}}static getPropertyDescriptor(t,e,i){return{get(){return this[e]},set(s){const n=this[t];this[e]=s,this.requestUpdate(t,n,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||ys}static finalize(){if(this.hasOwnProperty(xs))return!1;this[xs]=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),void 0!==t.h&&(this.h=[...t.h]),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,e=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const i of e)this.createProperty(i,t[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}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(ps(t))}else void 0!==t&&e.push(ps(t));return e}static _$Ep(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}_$Eu(){var t;this._$E_=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach(t=>t(this))}addController(t){var e,i;(null!==(e=this._$ES)&&void 0!==e?e:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(i=t.hostConnected)||void 0===i||i.call(t))}removeController(t){var e;null===(e=this._$ES)||void 0===e||e.splice(this._$ES.indexOf(t)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach((t,e)=>{this.hasOwnProperty(e)&&(this._$Ei.set(e,this[e]),delete this[e])})}createRenderRoot(){var t;const e=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return((t,e)=>{ls?t.adoptedStyleSheets=e.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet):e.forEach(e=>{const i=document.createElement("style"),s=as.litNonce;void 0!==s&&i.setAttribute("nonce",s),i.textContent=e.cssText,t.appendChild(i)})})(e,this.constructor.elementStyles),e}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)})}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)})}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$EO(t,e,i=ys){var s;const n=this.constructor._$Ep(t,i);if(void 0!==n&&!0===i.reflect){const r=(void 0!==(null===(s=i.converter)||void 0===s?void 0:s.toAttribute)?i.converter:_s).toAttribute(e,i.type);this._$El=t,null==r?this.removeAttribute(n):this.setAttribute(n,r),this._$El=null}}_$AK(t,e){var i;const s=this.constructor,n=s._$Ev.get(t);if(void 0!==n&&this._$El!==n){const t=s.getPropertyOptions(n),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(i=t.converter)||void 0===i?void 0:i.fromAttribute)?t.converter:_s;this._$El=n,this[n]=r.fromAttribute(e,t.type),this._$El=null}}requestUpdate(t,e,i){let s=!0;void 0!==t&&(((i=i||this.constructor.getPropertyOptions(t)).hasChanged||bs)(this[t],e)?(this._$AL.has(t)||this._$AL.set(t,e),!0===i.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,i))):s=!1),!this.isUpdatePending&&s&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach((t,e)=>this[e]=t),this._$Ei=void 0);let e=!1;const i=this._$AL;try{e=this.shouldUpdate(i),e?(this.willUpdate(i),null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)}),this.update(i)):this._$Ek()}catch(t){throw e=!1,this._$Ek(),t}e&&this._$AE(i)}willUpdate(t){}_$AE(t){var e;null===(e=this._$ES)||void 0===e||e.forEach(t=>{var e;return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)}),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return!0}update(t){void 0!==this._$EC&&(this._$EC.forEach((t,e)=>this._$EO(e,this[e],t)),this._$EC=void 0),this._$Ek()}updated(t){}firstUpdated(t){}}; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -var ws;$s[xs]=!0,$s.elementProperties=new Map,$s.elementStyles=[],$s.shadowRootOptions={mode:"open"},null==vs||vs({ReactiveElement:$s}),(null!==(us=ms.reactiveElementVersions)&&void 0!==us?us:ms.reactiveElementVersions=[]).push("1.6.3");const As=window,Es=As.trustedTypes,Ss=Es?Es.createPolicy("lit-html",{createHTML:t=>t}):void 0,Cs="$lit$",Ts=`lit$${(Math.random()+"").slice(9)}$`,Is="?"+Ts,Os=`<${Is}>`,ks=document,Rs=()=>ks.createComment(""),Ps=t=>null===t||"object"!=typeof t&&"function"!=typeof t,Ls=Array.isArray,Ms="[ \t\n\f\r]",Ns=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Ds=/-->/g,Hs=/>/g,Us=RegExp(`>|${Ms}(?:([^\\s"'>=/]+)(${Ms}*=${Ms}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),zs=/'/g,Fs=/"/g,Bs=/^(?:script|style|textarea|title)$/i,Vs=(t=>(e,...i)=>({_$litType$:t,strings:e,values:i}))(1),js=Symbol.for("lit-noChange"),Ws=Symbol.for("lit-nothing"),qs=new WeakMap,Ys=ks.createTreeWalker(ks,129,null,!1);function Xs(t,e){if(!Array.isArray(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==Ss?Ss.createHTML(e):e}let Gs=class t{constructor({strings:e,_$litType$:i},s){let n;this.parts=[];let r=0,o=0;const a=e.length-1,l=this.parts,[d,c]=((t,e)=>{const i=t.length-1,s=[];let n,r=2===e?"":"",o=Ns;for(let e=0;e"===l[0]?(o=null!=n?n:Ns,d=-1):void 0===l[1]?d=-2:(d=o.lastIndex-l[2].length,a=l[1],o=void 0===l[3]?Us:'"'===l[3]?Fs:zs):o===Fs||o===zs?o=Us:o===Ds||o===Hs?o=Ns:(o=Us,n=void 0);const h=o===Us&&t[e+1].startsWith("/>")?" ":"";r+=o===Ns?i+Os:d>=0?(s.push(a),i.slice(0,d)+Cs+i.slice(d)+Ts+h):i+Ts+(-2===d?(s.push(void 0),e):h)}return[Xs(t,r+(t[i]||"")+(2===e?"":"")),s]})(e,i);if(this.el=t.createElement(d,s),Ys.currentNode=this.el.content,2===i){const t=this.el.content,e=t.firstChild;e.remove(),t.append(...e.childNodes)}for(;null!==(n=Ys.nextNode())&&l.length0){n.textContent=Es?Es.emptyScript:"";for(let i=0;iLs(t)||"function"==typeof(null==t?void 0: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!==Ws&&Ps(this._$AH)?this._$AA.nextSibling.data=t:this.$(ks.createTextNode(t)),this._$AH=t}g(t){var e;const{values:i,_$litType$:s}=t,n="number"==typeof s?this._$AC(t):(void 0===s.el&&(s.el=Gs.createElement(Xs(s.h,s.h[0]),this.options)),s);if((null===(e=this._$AH)||void 0===e?void 0:e._$AD)===n)this._$AH.v(i);else{const t=new Js(n,this),e=t.u(this.options);t.v(i),this.$(e),this._$AH=t}}_$AC(t){let e=qs.get(t.strings);return void 0===e&&qs.set(t.strings,e=new Gs(t)),e}T(e){Ls(this._$AH)||(this._$AH=[],this._$AR());const i=this._$AH;let s,n=0;for(const r of e)n===i.length?i.push(s=new t(this.k(Rs()),this.k(Rs()),this,this.options)):s=i[n],s._$AI(r),n++;n2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=Ws}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(t,e=this,i,s){const n=this.strings;let r=!1;if(void 0===n)t=Ks(this,t,e,0),r=!Ps(t)||t!==this._$AH&&t!==js,r&&(this._$AH=t);else{const s=t;let o,a;for(t=n[0],o=0;o{var s,n;const r=null!==(s=null==i?void 0:i.renderBefore)&&void 0!==s?s:e;let o=r._$litPart$;if(void 0===o){const t=null!==(n=null==i?void 0:i.renderBefore)&&void 0!==n?n:null;r._$litPart$=o=new Zs(e.insertBefore(Rs(),t),t,void 0,null!=i?i:{})}return o._$AI(t),o})(e,this.renderRoot,this.renderOptions)}connectedCallback(){var t;super.connectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!0)}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!1)}render(){return js}};dn.finalized=!0,dn._$litElement$=!0,null===(an=globalThis.litElementHydrateSupport)||void 0===an||an.call(globalThis,{LitElement:dn});const cn=globalThis.litElementPolyfillSupport;null==cn||cn({LitElement:dn}),(null!==(ln=globalThis.litElementVersions)&&void 0!==ln?ln:globalThis.litElementVersions=[]).push("3.3.3"); -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const hn=(t,e)=>"method"===e.kind&&e.descriptor&&!("value"in e.descriptor)?{...e,finisher(i){i.createProperty(e.key,t)}}:{kind:"field",key:Symbol(),placement:"own",descriptor:{},originalKey:e.key,initializer(){"function"==typeof e.initializer&&(this[e.key]=e.initializer.call(this))},finisher(i){i.createProperty(e.key,t)}};function pn(t){return(e,i)=>void 0!==i?((t,e,i)=>{e.constructor.createProperty(i,t)})(t,e,i):hn(t,e)} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */const un=({finisher:t,descriptor:e})=>(i,s)=>{var n;if(void 0===s){const s=null!==(n=i.originalKey)&&void 0!==n?n:i.key,r=null!=e?{kind:"method",placement:"prototype",key:s,descriptor:e(i.key)}:{...i,key:s};return null!=t&&(r.finisher=function(e){t(e,s)}),r}{const n=i.constructor;void 0!==e&&Object.defineProperty(i,s,e(s)),null==t||t(n,s)}}; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */function mn(t,e){return un({descriptor:e=>{const i={get(){var e,i;return null!==(i=null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(t))&&void 0!==i?i:null},enumerable:!0,configurable:!0};return i}})} -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */var fn;const gn=null!=(null===(fn=window.HTMLSlotElement)||void 0===fn?void 0:fn.prototype.assignedElements)?(t,e)=>t.assignedElements(e):(t,e)=>t.assignedNodes(e).filter(t=>t.nodeType===Node.ELEMENT_NODE); -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const vn=1;let _n=class{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 2018 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */const bn=(t=>(...e)=>({_$litDirective$:t,values:e}))(class extends _n{constructor(t){var e;if(super(t),t.type!==vn||"class"!==t.name||(null===(e=t.strings)||void 0===e?void 0:e.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]){var i,s;if(void 0===this.it){this.it=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]&&!(null===(i=this.nt)||void 0===i?void 0:i.has(t))&&this.it.add(t);return this.render(e)}const n=t.element.classList;this.it.forEach(t=>{t in e||(n.remove(t),this.it.delete(t))});for(const t in e){const i=!!e[t];i===this.it.has(t)||(null===(s=this.nt)||void 0===s?void 0:s.has(t))||(i?(n.add(t),this.it.add(t)):(n.remove(t),this.it.delete(t)))}return js}}); -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */class yn extends Qi{constructor(){super(...arguments),this.alignEnd=!1,this.spaceBetween=!1,this.nowrap=!1,this.label="",this.mdcFoundationClass=je}createAdapter(){return{registerInteractionHandler:(t,e)=>{this.labelEl.addEventListener(t,e)},deregisterInteractionHandler:(t,e)=>{this.labelEl.removeEventListener(t,e)},activateInputRipple:async()=>{const t=this.input;if(t instanceof rs){const e=await t.ripple;e&&e.startPress()}},deactivateInputRipple:async()=>{const t=this.input;if(t instanceof rs){const e=await t.ripple;e&&e.endPress()}}}}get input(){var t,e;return null!==(e=null===(t=this.slottedInputs)||void 0===t?void 0:t[0])&&void 0!==e?e:null}render(){const t={"mdc-form-field--align-end":this.alignEnd,"mdc-form-field--space-between":this.spaceBetween,"mdc-form-field--nowrap":this.nowrap};return Vs` -
- - -
`}click(){this._labelClick()}_labelClick(){const t=this.input;t&&(t.focus(),t.click())}}n([pn({type:Boolean})],yn.prototype,"alignEnd",void 0),n([pn({type:Boolean})],yn.prototype,"spaceBetween",void 0),n([pn({type:Boolean})],yn.prototype,"nowrap",void 0),n([pn({type:String}),os(async function(t){var e;null===(e=this.input)||void 0===e||e.setAttribute("aria-label",t)})],yn.prototype,"label",void 0),n([mn(".mdc-form-field")],yn.prototype,"mdcRoot",void 0),n([ -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -function(t,e,i){let s;return s={flatten:e},i?function(t){const{slot:e,selector:i}=null!=t?t:{};return un({descriptor:s=>({get(){var s;const n="slot"+(e?`[name=${e}]`:":not([name])"),r=null===(s=this.renderRoot)||void 0===s?void 0:s.querySelector(n),o=null!=r?gn(r,t):[];return i?o.filter(t=>t.matches(i)):o},enumerable:!0,configurable:!0})})}({slot:t,flatten:e,selector:i}):un({descriptor:t=>({get(){var t,e;const i=null===(t=this.renderRoot)||void 0===t?void 0:t.querySelector("slot:not([name])");return null!==(e=null==i?void 0:i.assignedNodes(s))&&void 0!==e?e:[]},enumerable:!0,configurable:!0})})}("",!0,"*")],yn.prototype,"slottedInputs",void 0),n([mn("label")],yn.prototype,"labelEl",void 0); -/** - * @license - * Copyright 2021 Google LLC - * SPDX-LIcense-Identifier: Apache-2.0 - */ -const xn=((t,...e)=>{const i=1===t.length?t[0]:e.reduce((e,i,s)=>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[s+1],t[0]);return new hs(i,t,ds)})`.mdc-form-field{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-body2-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:0.875rem;font-size:var(--mdc-typography-body2-font-size, 0.875rem);line-height:1.25rem;line-height:var(--mdc-typography-body2-line-height, 1.25rem);font-weight:400;font-weight:var(--mdc-typography-body2-font-weight, 400);letter-spacing:0.0178571429em;letter-spacing:var(--mdc-typography-body2-letter-spacing, 0.0178571429em);text-decoration:inherit;text-decoration:var(--mdc-typography-body2-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-body2-text-transform, inherit);color:rgba(0, 0, 0, 0.87);color:var(--mdc-theme-text-primary-on-background, rgba(0, 0, 0, 0.87));display:inline-flex;align-items:center;vertical-align:middle}.mdc-form-field>label{margin-left:0;margin-right:auto;padding-left:4px;padding-right:0;order:0}[dir=rtl] .mdc-form-field>label,.mdc-form-field>label[dir=rtl]{margin-left:auto;margin-right:0}[dir=rtl] .mdc-form-field>label,.mdc-form-field>label[dir=rtl]{padding-left:0;padding-right:4px}.mdc-form-field--nowrap>label{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.mdc-form-field--align-end>label{margin-left:auto;margin-right:0;padding-left:0;padding-right:4px;order:-1}[dir=rtl] .mdc-form-field--align-end>label,.mdc-form-field--align-end>label[dir=rtl]{margin-left:0;margin-right:auto}[dir=rtl] .mdc-form-field--align-end>label,.mdc-form-field--align-end>label[dir=rtl]{padding-left:4px;padding-right:0}.mdc-form-field--space-between{justify-content:space-between}.mdc-form-field--space-between>label{margin:0}[dir=rtl] .mdc-form-field--space-between>label,.mdc-form-field--space-between>label[dir=rtl]{margin:0}:host{display:inline-flex}.mdc-form-field{width:100%}::slotted(*){-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-body2-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:0.875rem;font-size:var(--mdc-typography-body2-font-size, 0.875rem);line-height:1.25rem;line-height:var(--mdc-typography-body2-line-height, 1.25rem);font-weight:400;font-weight:var(--mdc-typography-body2-font-weight, 400);letter-spacing:0.0178571429em;letter-spacing:var(--mdc-typography-body2-letter-spacing, 0.0178571429em);text-decoration:inherit;text-decoration:var(--mdc-typography-body2-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-body2-text-transform, inherit);color:rgba(0, 0, 0, 0.87);color:var(--mdc-theme-text-primary-on-background, rgba(0, 0, 0, 0.87))}::slotted(mwc-switch){margin-right:10px}[dir=rtl] ::slotted(mwc-switch),::slotted(mwc-switch[dir=rtl]){margin-left:10px}`,$n={"mwc-formfield":class extends yn{static get styles(){return xn}}}; -/** - * @license - * Copyright 2020 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -var wn="Unknown",An="Backspace",En="Enter",Sn="Spacebar",Cn="PageUp",Tn="PageDown",In="End",On="Home",kn="ArrowLeft",Rn="ArrowUp",Pn="ArrowRight",Ln="ArrowDown",Mn="Delete",Nn="Escape",Dn="Tab",Hn=new Set;Hn.add(An),Hn.add(En),Hn.add(Sn),Hn.add(Cn),Hn.add(Tn),Hn.add(In),Hn.add(On),Hn.add(kn),Hn.add(Rn),Hn.add(Pn),Hn.add(Ln),Hn.add(Mn),Hn.add(Nn),Hn.add(Dn);var Un=8,zn=13,Fn=32,Bn=33,Vn=34,jn=35,Wn=36,qn=37,Yn=38,Xn=39,Gn=40,Kn=46,Jn=27,Zn=9,Qn=new Map;Qn.set(Un,An),Qn.set(zn,En),Qn.set(Fn,Sn),Qn.set(Bn,Cn),Qn.set(Vn,Tn),Qn.set(jn,In),Qn.set(Wn,On),Qn.set(qn,kn),Qn.set(Yn,Rn),Qn.set(Xn,Pn),Qn.set(Gn,Ln),Qn.set(Kn,Mn),Qn.set(Jn,Nn),Qn.set(Zn,Dn);var tr=new Set;function er(t){var e=t.key;if(Hn.has(e))return e;var i=Qn.get(t.keyCode);return i||wn} -/** - * @license - * Copyright 2020 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */tr.add(Cn),tr.add(Tn),tr.add(In),tr.add(On),tr.add(kn),tr.add(Rn),tr.add(Pn),tr.add(Ln);var ir="Unknown",sr="Backspace",nr="Enter",rr="Spacebar",or="PageUp",ar="PageDown",lr="End",dr="Home",cr="ArrowLeft",hr="ArrowUp",pr="ArrowRight",ur="ArrowDown",mr="Delete",fr="Escape",gr="Tab",vr=new Set;vr.add(sr),vr.add(nr),vr.add(rr),vr.add(or),vr.add(ar),vr.add(lr),vr.add(dr),vr.add(cr),vr.add(hr),vr.add(pr),vr.add(ur),vr.add(mr),vr.add(fr),vr.add(gr);var _r=8,br=13,yr=32,xr=33,$r=34,wr=35,Ar=36,Er=37,Sr=38,Cr=39,Tr=40,Ir=46,Or=27,kr=9,Rr=new Map;Rr.set(_r,sr),Rr.set(br,nr),Rr.set(yr,rr),Rr.set(xr,or),Rr.set($r,ar),Rr.set(wr,lr),Rr.set(Ar,dr),Rr.set(Er,cr),Rr.set(Sr,hr),Rr.set(Cr,pr),Rr.set(Tr,ur),Rr.set(Ir,mr),Rr.set(Or,fr),Rr.set(kr,gr);var Pr,Lr,Mr=new Set;function Nr(t){var e=t.key;if(vr.has(e))return e;var i=Rr.get(t.keyCode);return i||ir} -/** - * @license - * Copyright 2018 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */Mr.add(or),Mr.add(ar),Mr.add(lr),Mr.add(dr),Mr.add(cr),Mr.add(hr),Mr.add(pr),Mr.add(ur);var Dr="mdc-list-item--activated",Hr="mdc-list-item",Ur="mdc-list-item--disabled",zr="mdc-list-item--selected",Fr="mdc-list-item__text",Br="mdc-list-item__primary-text",Vr="mdc-list";(Pr={})[""+Dr]="mdc-list-item--activated",Pr[""+Hr]="mdc-list-item",Pr[""+Ur]="mdc-list-item--disabled",Pr[""+zr]="mdc-list-item--selected",Pr[""+Br]="mdc-list-item__primary-text",Pr[""+Vr]="mdc-list";var jr=((Lr={})[""+Dr]="mdc-deprecated-list-item--activated",Lr[""+Hr]="mdc-deprecated-list-item",Lr[""+Ur]="mdc-deprecated-list-item--disabled",Lr[""+zr]="mdc-deprecated-list-item--selected",Lr[""+Fr]="mdc-deprecated-list-item__text",Lr[""+Br]="mdc-deprecated-list-item__primary-text",Lr[""+Vr]="mdc-deprecated-list",Lr),Wr={ACTION_EVENT:"MDCList:action",SELECTION_CHANGE_EVENT:"MDCList:selectionChange",ARIA_CHECKED:"aria-checked",ARIA_CHECKED_CHECKBOX_SELECTOR:'[role="checkbox"][aria-checked="true"]',ARIA_CHECKED_RADIO_SELECTOR:'[role="radio"][aria-checked="true"]',ARIA_CURRENT:"aria-current",ARIA_DISABLED:"aria-disabled",ARIA_ORIENTATION:"aria-orientation",ARIA_ORIENTATION_HORIZONTAL:"horizontal",ARIA_ROLE_CHECKBOX_SELECTOR:'[role="checkbox"]',ARIA_SELECTED:"aria-selected",ARIA_INTERACTIVE_ROLES_SELECTOR:'[role="listbox"], [role="menu"]',ARIA_MULTI_SELECTABLE_SELECTOR:'[aria-multiselectable="true"]',CHECKBOX_RADIO_SELECTOR:'input[type="checkbox"], input[type="radio"]',CHECKBOX_SELECTOR:'input[type="checkbox"]',CHILD_ELEMENTS_TO_TOGGLE_TABINDEX:"\n ."+Hr+" button:not(:disabled),\n ."+Hr+" a,\n ."+jr[Hr]+" button:not(:disabled),\n ."+jr[Hr]+" a\n ",DEPRECATED_SELECTOR:".mdc-deprecated-list",FOCUSABLE_CHILD_ELEMENTS:"\n ."+Hr+" button:not(:disabled),\n ."+Hr+" a,\n ."+Hr+' input[type="radio"]:not(:disabled),\n .'+Hr+' input[type="checkbox"]:not(:disabled),\n .'+jr[Hr]+" button:not(:disabled),\n ."+jr[Hr]+" a,\n ."+jr[Hr]+' input[type="radio"]:not(:disabled),\n .'+jr[Hr]+' input[type="checkbox"]:not(:disabled)\n ',RADIO_SELECTOR:'input[type="radio"]',SELECTED_ITEM_SELECTOR:'[aria-selected="true"], [aria-current="true"]'},qr={UNSET_INDEX:-1,TYPEAHEAD_BUFFER_CLEAR_TIMEOUT_MS:300},Yr=["input","button","textarea","select"],Xr=function(t){var e=t.target;if(e){var i=(""+e.tagName).toLowerCase();-1===Yr.indexOf(i)&&t.preventDefault()}};function Gr(t,e){for(var i=new Map,s=0;se&&!i(r[a].index)){l=a;break}if(-1!==l)return s.sortedIndexCursor=l,r[s.sortedIndexCursor].index;return-1}(r,o,l,e):function(t,e,i){var s=i.typeaheadBuffer[0],n=t.get(s);if(!n)return-1;var r=n[i.sortedIndexCursor];if(0===r.text.lastIndexOf(i.typeaheadBuffer,0)&&!e(r.index))return r.index;var o=(i.sortedIndexCursor+1)%n.length,a=-1;for(;o!==i.sortedIndexCursor;){var l=n[o],d=0===l.text.lastIndexOf(i.typeaheadBuffer,0),c=!e(l.index);if(d&&c){a=o;break}o=(o+1)%n.length}if(-1!==a)return i.sortedIndexCursor=a,n[i.sortedIndexCursor].index;return-1}(r,l,e),-1===i||a||n(i),i}function Jr(t){return t.typeaheadBuffer.length>0} -/** - * @license - * Copyright 2016 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -var Zr=function(){function t(t){void 0===t&&(t={}),this.adapter=t}return Object.defineProperty(t,"cssClasses",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"strings",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"numbers",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"defaultAdapter",{get:function(){return{}},enumerable:!1,configurable:!0}),t.prototype.init=function(){},t.prototype.destroy=function(){},t}(),Qr={LABEL_FLOAT_ABOVE:"mdc-floating-label--float-above",LABEL_REQUIRED:"mdc-floating-label--required",LABEL_SHAKE:"mdc-floating-label--shake",ROOT:"mdc-floating-label"},to=function(t){function e(i){var n=t.call(this,s(s({},e.defaultAdapter),i))||this;return n.shakeAnimationEndHandler=function(){n.handleShakeAnimationEnd()},n}return i(e,t),Object.defineProperty(e,"cssClasses",{get:function(){return Qr},enumerable:!1,configurable:!0}),Object.defineProperty(e,"defaultAdapter",{get:function(){return{addClass:function(){},removeClass:function(){},getWidth:function(){return 0},registerInteractionHandler:function(){},deregisterInteractionHandler:function(){}}},enumerable:!1,configurable:!0}),e.prototype.init=function(){this.adapter.registerInteractionHandler("animationend",this.shakeAnimationEndHandler)},e.prototype.destroy=function(){this.adapter.deregisterInteractionHandler("animationend",this.shakeAnimationEndHandler)},e.prototype.getWidth=function(){return this.adapter.getWidth()},e.prototype.shake=function(t){var i=e.cssClasses.LABEL_SHAKE;t?this.adapter.addClass(i):this.adapter.removeClass(i)},e.prototype.float=function(t){var i=e.cssClasses,s=i.LABEL_FLOAT_ABOVE,n=i.LABEL_SHAKE;t?this.adapter.addClass(s):(this.adapter.removeClass(s),this.adapter.removeClass(n))},e.prototype.setRequired=function(t){var i=e.cssClasses.LABEL_REQUIRED;t?this.adapter.addClass(i):this.adapter.removeClass(i)},e.prototype.handleShakeAnimationEnd=function(){var t=e.cssClasses.LABEL_SHAKE;this.adapter.removeClass(t)},e}(Zr); -/** - * @license - * Copyright 2016 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const eo=1,io=3;let so=class{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 2018 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */const no=(t=>(...e)=>({_$litDirective$:t,values:e}))(class extends so{constructor(t){switch(super(t),this.foundation=null,this.previousPart=null,t.type){case eo:case io:break;default:throw new Error("FloatingLabel directive only support attribute and property parts")}}update(t,[e]){if(t!==this.previousPart){this.foundation&&this.foundation.destroy(),this.previousPart=t;const e=t.element;e.classList.add("mdc-floating-label");const i=(t=>({addClass:e=>t.classList.add(e),removeClass:e=>t.classList.remove(e),getWidth:()=>t.scrollWidth,registerInteractionHandler:(e,i)=>{t.addEventListener(e,i)},deregisterInteractionHandler:(e,i)=>{t.removeEventListener(e,i)}}))(e);this.foundation=new to(i),this.foundation.init()}return this.render(e)}render(t){return this.foundation}}); -/** - * @license - * Copyright 2016 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */var ro=function(){function t(t){void 0===t&&(t={}),this.adapter=t}return Object.defineProperty(t,"cssClasses",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"strings",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"numbers",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"defaultAdapter",{get:function(){return{}},enumerable:!1,configurable:!0}),t.prototype.init=function(){},t.prototype.destroy=function(){},t}(),oo={LINE_RIPPLE_ACTIVE:"mdc-line-ripple--active",LINE_RIPPLE_DEACTIVATING:"mdc-line-ripple--deactivating"},ao=function(t){function e(i){var n=t.call(this,s(s({},e.defaultAdapter),i))||this;return n.transitionEndHandler=function(t){n.handleTransitionEnd(t)},n}return i(e,t),Object.defineProperty(e,"cssClasses",{get:function(){return oo},enumerable:!1,configurable:!0}),Object.defineProperty(e,"defaultAdapter",{get:function(){return{addClass:function(){},removeClass:function(){},hasClass:function(){return!1},setStyle:function(){},registerEventHandler:function(){},deregisterEventHandler:function(){}}},enumerable:!1,configurable:!0}),e.prototype.init=function(){this.adapter.registerEventHandler("transitionend",this.transitionEndHandler)},e.prototype.destroy=function(){this.adapter.deregisterEventHandler("transitionend",this.transitionEndHandler)},e.prototype.activate=function(){this.adapter.removeClass(oo.LINE_RIPPLE_DEACTIVATING),this.adapter.addClass(oo.LINE_RIPPLE_ACTIVE)},e.prototype.setRippleCenter=function(t){this.adapter.setStyle("transform-origin",t+"px center")},e.prototype.deactivate=function(){this.adapter.addClass(oo.LINE_RIPPLE_DEACTIVATING)},e.prototype.handleTransitionEnd=function(t){var e=this.adapter.hasClass(oo.LINE_RIPPLE_DEACTIVATING);"opacity"===t.propertyName&&e&&(this.adapter.removeClass(oo.LINE_RIPPLE_ACTIVE),this.adapter.removeClass(oo.LINE_RIPPLE_DEACTIVATING))},e}(ro); -/** - * @license - * Copyright 2018 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const lo=1,co=3;let ho=class{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 2019 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */const po=(t=>(...e)=>({_$litDirective$:t,values:e}))(class extends ho{constructor(t){switch(super(t),this.previousPart=null,this.foundation=null,t.type){case lo:case co:return;default:throw new Error("LineRipple only support attribute and property parts.")}}update(t,e){if(this.previousPart!==t){this.foundation&&this.foundation.destroy(),this.previousPart=t;const e=t.element;e.classList.add("mdc-line-ripple");const i=(t=>({addClass:e=>t.classList.add(e),removeClass:e=>t.classList.remove(e),hasClass:e=>t.classList.contains(e),setStyle:(e,i)=>t.style.setProperty(e,i),registerEventHandler:(e,i)=>{t.addEventListener(e,i)},deregisterEventHandler:(e,i)=>{t.removeEventListener(e,i)}}))(e);this.foundation=new ao(i),this.foundation.init()}return this.render()}render(){return this.foundation}}); -/** - * @license - * Copyright 2016 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */var uo=function(){function t(t){void 0===t&&(t={}),this.adapter=t}return Object.defineProperty(t,"cssClasses",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"strings",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"numbers",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"defaultAdapter",{get:function(){return{}},enumerable:!1,configurable:!0}),t.prototype.init=function(){},t.prototype.destroy=function(){},t}(),mo="Unknown",fo="Backspace",go="Enter",vo="Spacebar",_o="PageUp",bo="PageDown",yo="End",xo="Home",$o="ArrowLeft",wo="ArrowUp",Ao="ArrowRight",Eo="ArrowDown",So="Delete",Co="Escape",To="Tab",Io=new Set; -/** - * @license - * Copyright 2020 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */Io.add(fo),Io.add(go),Io.add(vo),Io.add(_o),Io.add(bo),Io.add(yo),Io.add(xo),Io.add($o),Io.add(wo),Io.add(Ao),Io.add(Eo),Io.add(So),Io.add(Co),Io.add(To);var Oo=8,ko=13,Ro=32,Po=33,Lo=34,Mo=35,No=36,Do=37,Ho=38,Uo=39,zo=40,Fo=46,Bo=27,Vo=9,jo=new Map;jo.set(Oo,fo),jo.set(ko,go),jo.set(Ro,vo),jo.set(Po,_o),jo.set(Lo,bo),jo.set(Mo,yo),jo.set(No,xo),jo.set(Do,$o),jo.set(Ho,wo),jo.set(Uo,Ao),jo.set(zo,Eo),jo.set(Fo,So),jo.set(Bo,Co),jo.set(Vo,To);var Wo=new Set;function qo(t){var e=t.key;if(Io.has(e))return e;var i=jo.get(t.keyCode);return i||mo} -/** - * @license - * Copyright 2018 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */Wo.add(_o),Wo.add(bo),Wo.add(yo),Wo.add(xo),Wo.add($o),Wo.add(wo),Wo.add(Ao),Wo.add(Eo);var Yo,Xo,Go={ANCHOR:"mdc-menu-surface--anchor",ANIMATING_CLOSED:"mdc-menu-surface--animating-closed",ANIMATING_OPEN:"mdc-menu-surface--animating-open",FIXED:"mdc-menu-surface--fixed",IS_OPEN_BELOW:"mdc-menu-surface--is-open-below",OPEN:"mdc-menu-surface--open",ROOT:"mdc-menu-surface"},Ko={CLOSED_EVENT:"MDCMenuSurface:closed",CLOSING_EVENT:"MDCMenuSurface:closing",OPENED_EVENT:"MDCMenuSurface:opened",OPENING_EVENT:"MDCMenuSurface:opening",FOCUSABLE_ELEMENTS:["button:not(:disabled)",'[href]:not([aria-disabled="true"])',"input:not(:disabled)","select:not(:disabled)","textarea:not(:disabled)",'[tabindex]:not([tabindex="-1"]):not([aria-disabled="true"])'].join(", ")},Jo={TRANSITION_OPEN_DURATION:120,TRANSITION_CLOSE_DURATION:75,MARGIN_TO_EDGE:32,ANCHOR_TO_MENU_SURFACE_WIDTH_RATIO:.67,TOUCH_EVENT_WAIT_MS:30};!function(t){t[t.BOTTOM=1]="BOTTOM",t[t.CENTER=2]="CENTER",t[t.RIGHT=4]="RIGHT",t[t.FLIP_RTL=8]="FLIP_RTL"}(Yo||(Yo={})),function(t){t[t.TOP_LEFT=0]="TOP_LEFT",t[t.TOP_RIGHT=4]="TOP_RIGHT",t[t.BOTTOM_LEFT=1]="BOTTOM_LEFT",t[t.BOTTOM_RIGHT=5]="BOTTOM_RIGHT",t[t.TOP_START=8]="TOP_START",t[t.TOP_END=12]="TOP_END",t[t.BOTTOM_START=9]="BOTTOM_START",t[t.BOTTOM_END=13]="BOTTOM_END"}(Xo||(Xo={})); -/** - * @license - * Copyright 2016 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -var Zo={ACTIVATED:"mdc-select--activated",DISABLED:"mdc-select--disabled",FOCUSED:"mdc-select--focused",INVALID:"mdc-select--invalid",MENU_INVALID:"mdc-select__menu--invalid",OUTLINED:"mdc-select--outlined",REQUIRED:"mdc-select--required",ROOT:"mdc-select",WITH_LEADING_ICON:"mdc-select--with-leading-icon"},Qo={ARIA_CONTROLS:"aria-controls",ARIA_DESCRIBEDBY:"aria-describedby",ARIA_SELECTED_ATTR:"aria-selected",CHANGE_EVENT:"MDCSelect:change",HIDDEN_INPUT_SELECTOR:'input[type="hidden"]',LABEL_SELECTOR:".mdc-floating-label",LEADING_ICON_SELECTOR:".mdc-select__icon",LINE_RIPPLE_SELECTOR:".mdc-line-ripple",MENU_SELECTOR:".mdc-select__menu",OUTLINE_SELECTOR:".mdc-notched-outline",SELECTED_TEXT_SELECTOR:".mdc-select__selected-text",SELECT_ANCHOR_SELECTOR:".mdc-select__anchor",VALUE_ATTR:"data-value"},ta={LABEL_SCALE:.75,UNSET_INDEX:-1,CLICK_DEBOUNCE_TIMEOUT_MS:330},ea=function(t){function e(i,n){void 0===n&&(n={});var r=t.call(this,s(s({},e.defaultAdapter),i))||this;return r.disabled=!1,r.isMenuOpen=!1,r.useDefaultValidation=!0,r.customValidity=!0,r.lastSelectedIndex=ta.UNSET_INDEX,r.clickDebounceTimeout=0,r.recentlyClicked=!1,r.leadingIcon=n.leadingIcon,r.helperText=n.helperText,r}return i(e,t),Object.defineProperty(e,"cssClasses",{get:function(){return Zo},enumerable:!1,configurable:!0}),Object.defineProperty(e,"numbers",{get:function(){return ta},enumerable:!1,configurable:!0}),Object.defineProperty(e,"strings",{get:function(){return Qo},enumerable:!1,configurable:!0}),Object.defineProperty(e,"defaultAdapter",{get:function(){return{addClass:function(){},removeClass:function(){},hasClass:function(){return!1},activateBottomLine:function(){},deactivateBottomLine:function(){},getSelectedIndex:function(){return-1},setSelectedIndex:function(){},hasLabel:function(){return!1},floatLabel:function(){},getLabelWidth:function(){return 0},setLabelRequired:function(){},hasOutline:function(){return!1},notchOutline:function(){},closeOutline:function(){},setRippleCenter:function(){},notifyChange:function(){},setSelectedText:function(){},isSelectAnchorFocused:function(){return!1},getSelectAnchorAttr:function(){return""},setSelectAnchorAttr:function(){},removeSelectAnchorAttr:function(){},addMenuClass:function(){},removeMenuClass:function(){},openMenu:function(){},closeMenu:function(){},getAnchorElement:function(){return null},setMenuAnchorElement:function(){},setMenuAnchorCorner:function(){},setMenuWrapFocus:function(){},focusMenuItemAtIndex:function(){},getMenuItemCount:function(){return 0},getMenuItemValues:function(){return[]},getMenuItemTextAtIndex:function(){return""},isTypeaheadInProgress:function(){return!1},typeaheadMatchItem:function(){return-1}}},enumerable:!1,configurable:!0}),e.prototype.getSelectedIndex=function(){return this.adapter.getSelectedIndex()},e.prototype.setSelectedIndex=function(t,e,i){void 0===e&&(e=!1),void 0===i&&(i=!1),t>=this.adapter.getMenuItemCount()||(t===ta.UNSET_INDEX?this.adapter.setSelectedText(""):this.adapter.setSelectedText(this.adapter.getMenuItemTextAtIndex(t).trim()),this.adapter.setSelectedIndex(t),e&&this.adapter.closeMenu(),i||this.lastSelectedIndex===t||this.handleChange(),this.lastSelectedIndex=t)},e.prototype.setValue=function(t,e){void 0===e&&(e=!1);var i=this.adapter.getMenuItemValues().indexOf(t);this.setSelectedIndex(i,!1,e)},e.prototype.getValue=function(){var t=this.adapter.getSelectedIndex(),e=this.adapter.getMenuItemValues();return t!==ta.UNSET_INDEX?e[t]:""},e.prototype.getDisabled=function(){return this.disabled},e.prototype.setDisabled=function(t){this.disabled=t,this.disabled?(this.adapter.addClass(Zo.DISABLED),this.adapter.closeMenu()):this.adapter.removeClass(Zo.DISABLED),this.leadingIcon&&this.leadingIcon.setDisabled(this.disabled),this.disabled?this.adapter.removeSelectAnchorAttr("tabindex"):this.adapter.setSelectAnchorAttr("tabindex","0"),this.adapter.setSelectAnchorAttr("aria-disabled",this.disabled.toString())},e.prototype.openMenu=function(){this.adapter.addClass(Zo.ACTIVATED),this.adapter.openMenu(),this.isMenuOpen=!0,this.adapter.setSelectAnchorAttr("aria-expanded","true")},e.prototype.setHelperTextContent=function(t){this.helperText&&this.helperText.setContent(t)},e.prototype.layout=function(){if(this.adapter.hasLabel()){var t=this.getValue().length>0,e=this.adapter.hasClass(Zo.FOCUSED),i=t||e,s=this.adapter.hasClass(Zo.REQUIRED);this.notchOutline(i),this.adapter.floatLabel(i),this.adapter.setLabelRequired(s)}},e.prototype.layoutOptions=function(){var t=this.adapter.getMenuItemValues().indexOf(this.getValue());this.setSelectedIndex(t,!1,!0)},e.prototype.handleMenuOpened=function(){if(0!==this.adapter.getMenuItemValues().length){var t=this.getSelectedIndex(),e=t>=0?t:0;this.adapter.focusMenuItemAtIndex(e)}},e.prototype.handleMenuClosing=function(){this.adapter.setSelectAnchorAttr("aria-expanded","false")},e.prototype.handleMenuClosed=function(){this.adapter.removeClass(Zo.ACTIVATED),this.isMenuOpen=!1,this.adapter.isSelectAnchorFocused()||this.blur()},e.prototype.handleChange=function(){this.layout(),this.adapter.notifyChange(this.getValue()),this.adapter.hasClass(Zo.REQUIRED)&&this.useDefaultValidation&&this.setValid(this.isValid())},e.prototype.handleMenuItemAction=function(t){this.setSelectedIndex(t,!0)},e.prototype.handleFocus=function(){this.adapter.addClass(Zo.FOCUSED),this.layout(),this.adapter.activateBottomLine()},e.prototype.handleBlur=function(){this.isMenuOpen||this.blur()},e.prototype.handleClick=function(t){this.disabled||this.recentlyClicked||(this.setClickDebounceTimeout(),this.isMenuOpen?this.adapter.closeMenu():(this.adapter.setRippleCenter(t),this.openMenu()))},e.prototype.handleKeydown=function(t){if(!this.isMenuOpen&&this.adapter.hasClass(Zo.FOCUSED)){var e=qo(t)===go,i=qo(t)===vo,s=qo(t)===wo,n=qo(t)===Eo;if(!(t.ctrlKey||t.metaKey)&&(!i&&t.key&&1===t.key.length||i&&this.adapter.isTypeaheadInProgress())){var r=i?" ":t.key,o=this.adapter.typeaheadMatchItem(r,this.getSelectedIndex());return o>=0&&this.setSelectedIndex(o),void t.preventDefault()}(e||i||s||n)&&(this.openMenu(),t.preventDefault())}},e.prototype.notchOutline=function(t){if(this.adapter.hasOutline()){var e=this.adapter.hasClass(Zo.FOCUSED);if(t){var i=ta.LABEL_SCALE,s=this.adapter.getLabelWidth()*i;this.adapter.notchOutline(s)}else e||this.adapter.closeOutline()}},e.prototype.setLeadingIconAriaLabel=function(t){this.leadingIcon&&this.leadingIcon.setAriaLabel(t)},e.prototype.setLeadingIconContent=function(t){this.leadingIcon&&this.leadingIcon.setContent(t)},e.prototype.getUseDefaultValidation=function(){return this.useDefaultValidation},e.prototype.setUseDefaultValidation=function(t){this.useDefaultValidation=t},e.prototype.setValid=function(t){this.useDefaultValidation||(this.customValidity=t),this.adapter.setSelectAnchorAttr("aria-invalid",(!t).toString()),t?(this.adapter.removeClass(Zo.INVALID),this.adapter.removeMenuClass(Zo.MENU_INVALID)):(this.adapter.addClass(Zo.INVALID),this.adapter.addMenuClass(Zo.MENU_INVALID)),this.syncHelperTextValidity(t)},e.prototype.isValid=function(){return this.useDefaultValidation&&this.adapter.hasClass(Zo.REQUIRED)&&!this.adapter.hasClass(Zo.DISABLED)?this.getSelectedIndex()!==ta.UNSET_INDEX&&(0!==this.getSelectedIndex()||Boolean(this.getValue())):this.customValidity},e.prototype.setRequired=function(t){t?this.adapter.addClass(Zo.REQUIRED):this.adapter.removeClass(Zo.REQUIRED),this.adapter.setSelectAnchorAttr("aria-required",t.toString()),this.adapter.setLabelRequired(t)},e.prototype.getRequired=function(){return"true"===this.adapter.getSelectAnchorAttr("aria-required")},e.prototype.init=function(){var t=this.adapter.getAnchorElement();t&&(this.adapter.setMenuAnchorElement(t),this.adapter.setMenuAnchorCorner(Xo.BOTTOM_START)),this.adapter.setMenuWrapFocus(!1),this.setDisabled(this.adapter.hasClass(Zo.DISABLED)),this.syncHelperTextValidity(!this.adapter.hasClass(Zo.INVALID)),this.layout(),this.layoutOptions()},e.prototype.blur=function(){this.adapter.removeClass(Zo.FOCUSED),this.layout(),this.adapter.deactivateBottomLine(),this.adapter.hasClass(Zo.REQUIRED)&&this.useDefaultValidation&&this.setValid(this.isValid())},e.prototype.syncHelperTextValidity=function(t){if(this.helperText){this.helperText.setValidity(t);var e=this.helperText.isVisible(),i=this.helperText.getId();e&&i?this.adapter.setSelectAnchorAttr(Qo.ARIA_DESCRIBEDBY,i):this.adapter.removeSelectAnchorAttr(Qo.ARIA_DESCRIBEDBY)}},e.prototype.setClickDebounceTimeout=function(){var t=this;clearTimeout(this.clickDebounceTimeout),this.clickDebounceTimeout=setTimeout(function(){t.recentlyClicked=!1},ta.CLICK_DEBOUNCE_TIMEOUT_MS),this.recentlyClicked=!0},e}(uo); -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const ia=window,sa=ia.ShadowRoot&&(void 0===ia.ShadyCSS||ia.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,na=Symbol(),ra=new WeakMap;let oa=class{constructor(t,e,i){if(this._$cssResult$=!0,i!==na)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(sa&&void 0===t){const i=void 0!==e&&1===e.length;i&&(t=ra.get(e)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&ra.set(e,t))}return t}toString(){return this.cssText}};const aa=sa?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new oa("string"==typeof t?t:t+"",void 0,na))(e)})(t):t; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */var la;const da=window,ca=da.trustedTypes,ha=ca?ca.emptyScript:"",pa=da.reactiveElementPolyfillSupport,ua={toAttribute(t,e){switch(e){case Boolean:t=t?ha: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}},ma=(t,e)=>e!==t&&(e==e||t==t),fa={attribute:!0,type:String,converter:ua,reflect:!1,hasChanged:ma},ga="finalized";let va=class extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(t){var e;this.finalize(),(null!==(e=this.h)&&void 0!==e?e:this.h=[]).push(t)}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach((e,i)=>{const s=this._$Ep(i,e);void 0!==s&&(this._$Ev.set(s,i),t.push(s))}),t}static createProperty(t,e=fa){if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){const i="symbol"==typeof t?Symbol():"__"+t,s=this.getPropertyDescriptor(t,i,e);void 0!==s&&Object.defineProperty(this.prototype,t,s)}}static getPropertyDescriptor(t,e,i){return{get(){return this[e]},set(s){const n=this[t];this[e]=s,this.requestUpdate(t,n,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||fa}static finalize(){if(this.hasOwnProperty(ga))return!1;this[ga]=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),void 0!==t.h&&(this.h=[...t.h]),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,e=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const i of e)this.createProperty(i,t[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}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(aa(t))}else void 0!==t&&e.push(aa(t));return e}static _$Ep(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}_$Eu(){var t;this._$E_=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach(t=>t(this))}addController(t){var e,i;(null!==(e=this._$ES)&&void 0!==e?e:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(i=t.hostConnected)||void 0===i||i.call(t))}removeController(t){var e;null===(e=this._$ES)||void 0===e||e.splice(this._$ES.indexOf(t)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach((t,e)=>{this.hasOwnProperty(e)&&(this._$Ei.set(e,this[e]),delete this[e])})}createRenderRoot(){var t;const e=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return((t,e)=>{sa?t.adoptedStyleSheets=e.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet):e.forEach(e=>{const i=document.createElement("style"),s=ia.litNonce;void 0!==s&&i.setAttribute("nonce",s),i.textContent=e.cssText,t.appendChild(i)})})(e,this.constructor.elementStyles),e}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)})}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)})}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$EO(t,e,i=fa){var s;const n=this.constructor._$Ep(t,i);if(void 0!==n&&!0===i.reflect){const r=(void 0!==(null===(s=i.converter)||void 0===s?void 0:s.toAttribute)?i.converter:ua).toAttribute(e,i.type);this._$El=t,null==r?this.removeAttribute(n):this.setAttribute(n,r),this._$El=null}}_$AK(t,e){var i;const s=this.constructor,n=s._$Ev.get(t);if(void 0!==n&&this._$El!==n){const t=s.getPropertyOptions(n),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(i=t.converter)||void 0===i?void 0:i.fromAttribute)?t.converter:ua;this._$El=n,this[n]=r.fromAttribute(e,t.type),this._$El=null}}requestUpdate(t,e,i){let s=!0;void 0!==t&&(((i=i||this.constructor.getPropertyOptions(t)).hasChanged||ma)(this[t],e)?(this._$AL.has(t)||this._$AL.set(t,e),!0===i.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,i))):s=!1),!this.isUpdatePending&&s&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach((t,e)=>this[e]=t),this._$Ei=void 0);let e=!1;const i=this._$AL;try{e=this.shouldUpdate(i),e?(this.willUpdate(i),null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)}),this.update(i)):this._$Ek()}catch(t){throw e=!1,this._$Ek(),t}e&&this._$AE(i)}willUpdate(t){}_$AE(t){var e;null===(e=this._$ES)||void 0===e||e.forEach(t=>{var e;return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)}),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return!0}update(t){void 0!==this._$EC&&(this._$EC.forEach((t,e)=>this._$EO(e,this[e],t)),this._$EC=void 0),this._$Ek()}updated(t){}firstUpdated(t){}}; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -var _a;va[ga]=!0,va.elementProperties=new Map,va.elementStyles=[],va.shadowRootOptions={mode:"open"},null==pa||pa({ReactiveElement:va}),(null!==(la=da.reactiveElementVersions)&&void 0!==la?la:da.reactiveElementVersions=[]).push("1.6.3");const ba=window,ya=ba.trustedTypes,xa=ya?ya.createPolicy("lit-html",{createHTML:t=>t}):void 0,$a="$lit$",wa=`lit$${(Math.random()+"").slice(9)}$`,Aa="?"+wa,Ea=`<${Aa}>`,Sa=document,Ca=()=>Sa.createComment(""),Ta=t=>null===t||"object"!=typeof t&&"function"!=typeof t,Ia=Array.isArray,Oa="[ \t\n\f\r]",ka=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Ra=/-->/g,Pa=/>/g,La=RegExp(`>|${Oa}(?:([^\\s"'>=/]+)(${Oa}*=${Oa}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),Ma=/'/g,Na=/"/g,Da=/^(?:script|style|textarea|title)$/i,Ha=(t=>(e,...i)=>({_$litType$:t,strings:e,values:i}))(1),Ua=Symbol.for("lit-noChange"),za=Symbol.for("lit-nothing"),Fa=new WeakMap,Ba=Sa.createTreeWalker(Sa,129,null,!1);function Va(t,e){if(!Array.isArray(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==xa?xa.createHTML(e):e}let ja=class t{constructor({strings:e,_$litType$:i},s){let n;this.parts=[];let r=0,o=0;const a=e.length-1,l=this.parts,[d,c]=((t,e)=>{const i=t.length-1,s=[];let n,r=2===e?"":"",o=ka;for(let e=0;e"===l[0]?(o=null!=n?n:ka,d=-1):void 0===l[1]?d=-2:(d=o.lastIndex-l[2].length,a=l[1],o=void 0===l[3]?La:'"'===l[3]?Na:Ma):o===Na||o===Ma?o=La:o===Ra||o===Pa?o=ka:(o=La,n=void 0);const h=o===La&&t[e+1].startsWith("/>")?" ":"";r+=o===ka?i+Ea:d>=0?(s.push(a),i.slice(0,d)+$a+i.slice(d)+wa+h):i+wa+(-2===d?(s.push(void 0),e):h)}return[Va(t,r+(t[i]||"")+(2===e?"":"")),s]})(e,i);if(this.el=t.createElement(d,s),Ba.currentNode=this.el.content,2===i){const t=this.el.content,e=t.firstChild;e.remove(),t.append(...e.childNodes)}for(;null!==(n=Ba.nextNode())&&l.length0){n.textContent=ya?ya.emptyScript:"";for(let i=0;iIa(t)||"function"==typeof(null==t?void 0: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!==za&&Ta(this._$AH)?this._$AA.nextSibling.data=t:this.$(Sa.createTextNode(t)),this._$AH=t}g(t){var e;const{values:i,_$litType$:s}=t,n="number"==typeof s?this._$AC(t):(void 0===s.el&&(s.el=ja.createElement(Va(s.h,s.h[0]),this.options)),s);if((null===(e=this._$AH)||void 0===e?void 0:e._$AD)===n)this._$AH.v(i);else{const t=new qa(n,this),e=t.u(this.options);t.v(i),this.$(e),this._$AH=t}}_$AC(t){let e=Fa.get(t.strings);return void 0===e&&Fa.set(t.strings,e=new ja(t)),e}T(e){Ia(this._$AH)||(this._$AH=[],this._$AR());const i=this._$AH;let s,n=0;for(const r of e)n===i.length?i.push(s=new t(this.k(Ca()),this.k(Ca()),this,this.options)):s=i[n],s._$AI(r),n++;n2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=za}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(t,e=this,i,s){const n=this.strings;let r=!1;if(void 0===n)t=Wa(this,t,e,0),r=!Ta(t)||t!==this._$AH&&t!==Ua,r&&(this._$AH=t);else{const s=t;let o,a;for(t=n[0],o=0;o{var s,n;const r=null!==(s=null==i?void 0:i.renderBefore)&&void 0!==s?s:e;let o=r._$litPart$;if(void 0===o){const t=null!==(n=null==i?void 0:i.renderBefore)&&void 0!==n?n:null;r._$litPart$=o=new Ya(e.insertBefore(Ca(),t),t,void 0,null!=i?i:{})}return o._$AI(t),o})(e,this.renderRoot,this.renderOptions)}connectedCallback(){var t;super.connectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!0)}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!1)}render(){return Ua}};sl.finalized=!0,sl._$litElement$=!0,null===(el=globalThis.litElementHydrateSupport)||void 0===el||el.call(globalThis,{LitElement:sl});const nl=globalThis.litElementPolyfillSupport;null==nl||nl({LitElement:sl}),(null!==(il=globalThis.litElementVersions)&&void 0!==il?il:globalThis.litElementVersions=[]).push("3.3.3"); -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const rl=(t,e)=>"method"===e.kind&&e.descriptor&&!("value"in e.descriptor)?{...e,finisher(i){i.createProperty(e.key,t)}}:{kind:"field",key:Symbol(),placement:"own",descriptor:{},originalKey:e.key,initializer(){"function"==typeof e.initializer&&(this[e.key]=e.initializer.call(this))},finisher(i){i.createProperty(e.key,t)}};function ol(t){return(e,i)=>void 0!==i?((t,e,i)=>{e.constructor.createProperty(i,t)})(t,e,i):rl(t,e)} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */function al(t){return ol({...t,state:!0})} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */const ll=({finisher:t,descriptor:e})=>(i,s)=>{var n;if(void 0===s){const s=null!==(n=i.originalKey)&&void 0!==n?n:i.key,r=null!=e?{kind:"method",placement:"prototype",key:s,descriptor:e(i.key)}:{...i,key:s};return null!=t&&(r.finisher=function(e){t(e,s)}),r}{const n=i.constructor;void 0!==e&&Object.defineProperty(i,s,e(s)),null==t||t(n,s)}}; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -function dl(t,e){return ll({descriptor:e=>{const i={get(){var e,i;return null!==(i=null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(t))&&void 0!==i?i:null},enumerable:!0,configurable:!0};return i}})} -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */var cl;null===(cl=window.HTMLSlotElement)||void 0===cl||cl.prototype.assignedElements; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const hl=1;let pl=class{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 2018 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */const ul=(t=>(...e)=>({_$litDirective$:t,values:e}))(class extends pl{constructor(t){var e;if(super(t),t.type!==hl||"class"!==t.name||(null===(e=t.strings)||void 0===e?void 0:e.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]){var i,s;if(void 0===this.it){this.it=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]&&!(null===(i=this.nt)||void 0===i?void 0:i.has(t))&&this.it.add(t);return this.render(e)}const n=t.element.classList;this.it.forEach(t=>{t in e||(n.remove(t),this.it.delete(t))});for(const t in e){const i=!!e[t];i===this.it.has(t)||(null===(s=this.nt)||void 0===s?void 0:s.has(t))||(i?(n.add(t),this.it.add(t)):(n.remove(t),this.it.delete(t)))}return Ua}}),ml=t=>null!=t?t:za,fl=(t={})=>{const e={};for(const i in t)e[i]=t[i];return Object.assign({badInput:!1,customError:!1,patternMismatch:!1,rangeOverflow:!1,rangeUnderflow:!1,stepMismatch:!1,tooLong:!1,tooShort:!1,typeMismatch:!1,valid:!0,valueMissing:!1},e)}; -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */class gl extends rs{constructor(){super(...arguments),this.mdcFoundationClass=ea,this.disabled=!1,this.outlined=!1,this.label="",this.outlineOpen=!1,this.outlineWidth=0,this.value="",this.name="",this.selectedText="",this.icon="",this.menuOpen=!1,this.helper="",this.validateOnInitialRender=!1,this.validationMessage="",this.required=!1,this.naturalMenuWidth=!1,this.isUiValid=!0,this.fixedMenuPosition=!1,this.typeaheadState={bufferClearTimeout:0,currentFirstChar:"",sortedIndexCursor:0,typeaheadBuffer:""},this.sortedIndexByFirstChar=new Map,this.menuElement_=null,this.listeners=[],this.onBodyClickBound=()=>{},this._menuUpdateComplete=null,this.valueSetDirectly=!1,this.validityTransform=null,this._validity=fl()}get items(){return this.menuElement_||(this.menuElement_=this.menuElement),this.menuElement_?this.menuElement_.items:[]}get selected(){const t=this.menuElement;return t?t.selected:null}get index(){const t=this.menuElement;return t?t.index:-1}get shouldRenderHelperText(){return!!this.helper||!!this.validationMessage}get validity(){return this._checkValidity(this.value),this._validity}render(){const t={"mdc-select--disabled":this.disabled,"mdc-select--no-label":!this.label,"mdc-select--filled":!this.outlined,"mdc-select--outlined":this.outlined,"mdc-select--with-leading-icon":!!this.icon,"mdc-select--required":this.required,"mdc-select--invalid":!this.isUiValid},e=this.label?"label":void 0,i=this.shouldRenderHelperText?"helper-text":void 0;return Ha` -
- - -
- ${this.renderRipple()} - ${this.outlined?this.renderOutline():this.renderLabel()} - ${this.renderLeadingIcon()} - - ${this.selectedText} - - - - - - - - - - ${this.renderLineRipple()} + `}};e([pe({attribute:!1})],ii.prototype,"hass",void 0),e([pe({attribute:!1})],ii.prototype,"config",void 0),e([pe({attribute:!1})],ii.prototype,"component_loaded",void 0),e([pe({attribute:!1})],ii.prototype,"schedule_type",void 0),e([pe({attribute:!1})],ii.prototype,"schedule_id",void 0),e([ue()],ii.prototype,"_newScheduleName",void 0),e([ue()],ii.prototype,"_schedule",void 0),e([ue()],ii.prototype,"_rename_in_progress",void 0),e([ue()],ii.prototype,"_loadError",void 0),ii=e([t("wiser-schedule-rename-card")],ii);let si=class extends le{constructor(){super(...arguments),this._hubs=[],this._error="",this._requestId=0}localize(e,t="",i=""){return je(this.hass,e,t,i)}setConfig(e){this._config=Object.assign({},e)}updated(e){var t;const i=e.get("_config");(e.has("hass")&&!e.get("hass")||e.has("_config")&&(!i||i.hub!==(null===(t=this._config)||void 0===t?void 0:t.hub)))&&this.loadData()}async loadData(){if(!this.hass||!this._config)return;const e=++this._requestId;this._error="";try{await at();const t=await Be(this.hass);if(e!==this._requestId)return;this._hubs=t}catch(t){e===this._requestId&&(this._error=(null==t?void 0:t.message)||"Unable to load schedules.")}}change(e,t){if(!this._config)return;const i=Object.assign({},this._config);""===t?delete i[e]:i[e]=t,"home_screen"===e&&delete i.selected_schedule,"hub"===e&&delete i.selected_schedule,this._config=i,ve(this,"config-changed",{config:i})}toggle(e,t,i=!1){var s;return W``}render(){if(!this._config)return W``;const e=this._config;return W` +
+
+ ${this.localize("wiser.home.screen")} + {e.stopPropagation(),["schedules","overview"].includes(e.detail.value)&&this.change("home_screen",e.detail.value)}} + >
- ${this.renderMenu()} + ${"overview"===e.home_screen||"devices"===e.home_screen?W` +
+ ${this.localize("wiser.home.overview_details")} + {e.stopPropagation(),["show","hide"].includes(e.detail.value)&&this.change("overview_details","show"===e.detail.value)}} + > +
+ `:""} + ${this._hubs.length>1?W``:""}
- ${this.renderHelperText()}`}renderMenu(){const t=this.getMenuClasses();return Ha` - - ${this.renderMenuContent()} - `}getMenuClasses(){return{"mdc-select__menu":!0,"mdc-menu":!0,"mdc-menu-surface":!0,"mdc-select__menu--invalid":!this.isUiValid}}renderMenuContent(){return Ha``}renderRipple(){return this.outlined?za:Ha` - - `}renderOutline(){return this.outlined?Ha` - - ${this.renderLabel()} - `:za}renderLabel(){return this.label?Ha` - ${this.label} - `:za}renderLeadingIcon(){return this.icon?Ha`
${this.icon}
`:za}renderLineRipple(){return this.outlined?za:Ha` - - `}renderHelperText(){if(!this.shouldRenderHelperText)return za;const t=this.validationMessage&&!this.isUiValid;return Ha` -

${t?this.validationMessage:this.helper}

`}createAdapter(){return Object.assign(Object.assign({},Xi(this.mdcRoot)),{activateBottomLine:()=>{this.lineRippleElement&&this.lineRippleElement.lineRippleFoundation.activate()},deactivateBottomLine:()=>{this.lineRippleElement&&this.lineRippleElement.lineRippleFoundation.deactivate()},hasLabel:()=>!!this.label,floatLabel:t=>{this.labelElement&&this.labelElement.floatingLabelFoundation.float(t)},getLabelWidth:()=>this.labelElement?this.labelElement.floatingLabelFoundation.getWidth():0,setLabelRequired:t=>{this.labelElement&&this.labelElement.floatingLabelFoundation.setRequired(t)},hasOutline:()=>this.outlined,notchOutline:t=>{this.outlineElement&&!this.outlineOpen&&(this.outlineWidth=t,this.outlineOpen=!0)},closeOutline:()=>{this.outlineElement&&(this.outlineOpen=!1)},setRippleCenter:t=>{if(this.lineRippleElement){this.lineRippleElement.lineRippleFoundation.setRippleCenter(t)}},notifyChange:async t=>{if(!this.valueSetDirectly&&t===this.value)return;this.valueSetDirectly=!1,this.value=t,await this.updateComplete;const e=new Event("change",{bubbles:!0});this.dispatchEvent(e)},setSelectedText:t=>this.selectedText=t,isSelectAnchorFocused:()=>{const t=this.anchorElement;if(!t)return!1;return t.getRootNode().activeElement===t},getSelectAnchorAttr:t=>{const e=this.anchorElement;return e?e.getAttribute(t):null},setSelectAnchorAttr:(t,e)=>{const i=this.anchorElement;i&&i.setAttribute(t,e)},removeSelectAnchorAttr:t=>{const e=this.anchorElement;e&&e.removeAttribute(t)},openMenu:()=>{this.menuOpen=!0},closeMenu:()=>{this.menuOpen=!1},addMenuClass:()=>{},removeMenuClass:()=>{},getAnchorElement:()=>this.anchorElement,setMenuAnchorElement:()=>{},setMenuAnchorCorner:()=>{const t=this.menuElement;t&&(t.corner="BOTTOM_START")},setMenuWrapFocus:t=>{const e=this.menuElement;e&&(e.wrapFocus=t)},focusMenuItemAtIndex:t=>{const e=this.menuElement;if(!e)return;const i=e.items[t];i&&i.focus()},getMenuItemCount:()=>{const t=this.menuElement;return t?t.items.length:0},getMenuItemValues:()=>{const t=this.menuElement;if(!t)return[];return t.items.map(t=>t.value)},getMenuItemTextAtIndex:t=>{const e=this.menuElement;if(!e)return"";const i=e.items[t];return i?i.text:""},getSelectedIndex:()=>this.index,setSelectedIndex:()=>{},isTypeaheadInProgress:()=>Jr(this.typeaheadState),typeaheadMatchItem:(t,e)=>{if(!this.menuElement)return-1;const i={focusItemAtIndex:t=>{this.menuElement.focusItemAtIndex(t)},focusedItemIndex:e||this.menuElement.getFocusedItemIndex(),nextChar:t,sortedIndexByFirstChar:this.sortedIndexByFirstChar,skipFocus:!1,isItemAtIndexDisabled:t=>this.items[t].disabled},s=Kr(i,this.typeaheadState);return-1!==s&&this.select(s),s}})}checkValidity(){const t=this._checkValidity(this.value);if(!t){const t=new Event("invalid",{bubbles:!1,cancelable:!0});this.dispatchEvent(t)}return t}reportValidity(){const t=this.checkValidity();return this.isUiValid=t,t}_checkValidity(t){const e=this.formElement.validity;let i=fl(e);if(this.validityTransform){const e=this.validityTransform(t,i);i=Object.assign(Object.assign({},i),e)}return this._validity=i,this._validity.valid}setCustomValidity(t){this.validationMessage=t,this.formElement.setCustomValidity(t)}async getUpdateComplete(){await this._menuUpdateComplete;return await super.getUpdateComplete()}async firstUpdated(){const t=this.menuElement;if(t&&(this._menuUpdateComplete=t.updateComplete,await this._menuUpdateComplete),super.firstUpdated(),this.mdcFoundation.isValid=()=>!0,this.mdcFoundation.setValid=()=>{},this.mdcFoundation.setDisabled(this.disabled),this.validateOnInitialRender&&this.reportValidity(),!this.selected){!this.items.length&&this.slotElement&&this.slotElement.assignedNodes({flatten:!0}).length&&(await new Promise(t=>requestAnimationFrame(t)),await this.layout());const t=this.items.length&&""===this.items[0].value;if(!this.value&&t)return void this.select(0);this.selectByValue(this.value)}this.sortedIndexByFirstChar=Gr(this.items.length,t=>this.items[t].text)}onItemsUpdated(){this.sortedIndexByFirstChar=Gr(this.items.length,t=>this.items[t].text)}select(t){const e=this.menuElement;e&&e.select(t)}selectByValue(t){let e=-1;for(let i=0;i0,n=i&&this.index{this.menuElement.focusItemAtIndex(t)},focusedItemIndex:e,isTargetListItem:!!i&&i.hasAttribute("mwc-list-item"),sortedIndexByFirstChar:this.sortedIndexByFirstChar,isItemAtIndexDisabled:t=>this.items[t].disabled},this.typeaheadState)}async onSelected(t){this.mdcFoundation||await this.updateComplete,this.mdcFoundation.handleMenuItemAction(t.detail.index);const e=this.items[t.detail.index];e&&(this.value=e.value)}onOpened(){this.mdcFoundation&&(this.menuOpen=!0,this.mdcFoundation.handleMenuOpened())}onClosed(){this.mdcFoundation&&(this.menuOpen=!1,this.mdcFoundation.handleMenuClosed())}setFormData(t){this.name&&null!==this.selected&&t.append(this.name,this.value)}async layout(t=!0){this.mdcFoundation&&this.mdcFoundation.layout(),await this.updateComplete;const e=this.menuElement;e&&e.layout(t);const i=this.labelElement;if(!i)return void(this.outlineOpen=!1);const s=!!this.label&&!!this.value;if(i.floatingLabelFoundation.float(s),!this.outlined)return;this.outlineOpen=s,await this.updateComplete;const n=i.floatingLabelFoundation.getWidth();this.outlineOpen&&(this.outlineWidth=n)}async layoutOptions(){this.mdcFoundation&&this.mdcFoundation.layoutOptions()}}n([dl(".mdc-select")],gl.prototype,"mdcRoot",void 0),n([dl(".formElement")],gl.prototype,"formElement",void 0),n([dl("slot")],gl.prototype,"slotElement",void 0),n([dl("select")],gl.prototype,"nativeSelectElement",void 0),n([dl("input")],gl.prototype,"nativeInputElement",void 0),n([dl(".mdc-line-ripple")],gl.prototype,"lineRippleElement",void 0),n([dl(".mdc-floating-label")],gl.prototype,"labelElement",void 0),n([dl("mwc-notched-outline")],gl.prototype,"outlineElement",void 0),n([dl(".mdc-menu")],gl.prototype,"menuElement",void 0),n([dl(".mdc-select__anchor")],gl.prototype,"anchorElement",void 0),n([ol({type:Boolean,attribute:"disabled",reflect:!0}),os(function(t){this.mdcFoundation&&this.mdcFoundation.setDisabled(t)})],gl.prototype,"disabled",void 0),n([ol({type:Boolean}),os(function(t,e){void 0!==e&&this.outlined!==e&&this.layout(!1)})],gl.prototype,"outlined",void 0),n([ol({type:String}),os(function(t,e){void 0!==e&&this.label!==e&&this.layout(!1)})],gl.prototype,"label",void 0),n([al()],gl.prototype,"outlineOpen",void 0),n([al()],gl.prototype,"outlineWidth",void 0),n([ol({type:String}),os(function(t){if(this.mdcFoundation){const e=null===this.selected&&!!t,i=this.selected&&this.selected.value!==t;(e||i)&&this.selectByValue(t),this.reportValidity()}})],gl.prototype,"value",void 0),n([ol()],gl.prototype,"name",void 0),n([al()],gl.prototype,"selectedText",void 0),n([ol({type:String})],gl.prototype,"icon",void 0),n([al()],gl.prototype,"menuOpen",void 0),n([ol({type:String})],gl.prototype,"helper",void 0),n([ol({type:Boolean})],gl.prototype,"validateOnInitialRender",void 0),n([ol({type:String})],gl.prototype,"validationMessage",void 0),n([ol({type:Boolean})],gl.prototype,"required",void 0),n([ol({type:Boolean})],gl.prototype,"naturalMenuWidth",void 0),n([al()],gl.prototype,"isUiValid",void 0),n([ol({type:Boolean})],gl.prototype,"fixedMenuPosition",void 0),n([function(t){return ll({finisher:(e,i)=>{Object.assign(e.prototype[i],t)}})}({capture:!0})],gl.prototype,"handleTypeahead",null); -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const vl=window,_l=vl.ShadowRoot&&(void 0===vl.ShadyCSS||vl.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,bl=Symbol(),yl=new WeakMap;let xl=class{constructor(t,e,i){if(this._$cssResult$=!0,i!==bl)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(_l&&void 0===t){const i=void 0!==e&&1===e.length;i&&(t=yl.get(e)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&yl.set(e,t))}return t}toString(){return this.cssText}};const $l=(t,...e)=>{const i=1===t.length?t[0]:e.reduce((e,i,s)=>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[s+1],t[0]);return new xl(i,t,bl)},wl=_l?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new xl("string"==typeof t?t:t+"",void 0,bl))(e)})(t):t; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */var Al;const El=window,Sl=El.trustedTypes,Cl=Sl?Sl.emptyScript:"",Tl=El.reactiveElementPolyfillSupport,Il={toAttribute(t,e){switch(e){case Boolean:t=t?Cl: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}},Ol=(t,e)=>e!==t&&(e==e||t==t),kl={attribute:!0,type:String,converter:Il,reflect:!1,hasChanged:Ol},Rl="finalized";let Pl=class extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(t){var e;this.finalize(),(null!==(e=this.h)&&void 0!==e?e:this.h=[]).push(t)}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach((e,i)=>{const s=this._$Ep(i,e);void 0!==s&&(this._$Ev.set(s,i),t.push(s))}),t}static createProperty(t,e=kl){if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){const i="symbol"==typeof t?Symbol():"__"+t,s=this.getPropertyDescriptor(t,i,e);void 0!==s&&Object.defineProperty(this.prototype,t,s)}}static getPropertyDescriptor(t,e,i){return{get(){return this[e]},set(s){const n=this[t];this[e]=s,this.requestUpdate(t,n,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||kl}static finalize(){if(this.hasOwnProperty(Rl))return!1;this[Rl]=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),void 0!==t.h&&(this.h=[...t.h]),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,e=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const i of e)this.createProperty(i,t[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}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(wl(t))}else void 0!==t&&e.push(wl(t));return e}static _$Ep(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}_$Eu(){var t;this._$E_=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach(t=>t(this))}addController(t){var e,i;(null!==(e=this._$ES)&&void 0!==e?e:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(i=t.hostConnected)||void 0===i||i.call(t))}removeController(t){var e;null===(e=this._$ES)||void 0===e||e.splice(this._$ES.indexOf(t)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach((t,e)=>{this.hasOwnProperty(e)&&(this._$Ei.set(e,this[e]),delete this[e])})}createRenderRoot(){var t;const e=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return((t,e)=>{_l?t.adoptedStyleSheets=e.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet):e.forEach(e=>{const i=document.createElement("style"),s=vl.litNonce;void 0!==s&&i.setAttribute("nonce",s),i.textContent=e.cssText,t.appendChild(i)})})(e,this.constructor.elementStyles),e}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)})}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)})}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$EO(t,e,i=kl){var s;const n=this.constructor._$Ep(t,i);if(void 0!==n&&!0===i.reflect){const r=(void 0!==(null===(s=i.converter)||void 0===s?void 0:s.toAttribute)?i.converter:Il).toAttribute(e,i.type);this._$El=t,null==r?this.removeAttribute(n):this.setAttribute(n,r),this._$El=null}}_$AK(t,e){var i;const s=this.constructor,n=s._$Ev.get(t);if(void 0!==n&&this._$El!==n){const t=s.getPropertyOptions(n),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(i=t.converter)||void 0===i?void 0:i.fromAttribute)?t.converter:Il;this._$El=n,this[n]=r.fromAttribute(e,t.type),this._$El=null}}requestUpdate(t,e,i){let s=!0;void 0!==t&&(((i=i||this.constructor.getPropertyOptions(t)).hasChanged||Ol)(this[t],e)?(this._$AL.has(t)||this._$AL.set(t,e),!0===i.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,i))):s=!1),!this.isUpdatePending&&s&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach((t,e)=>this[e]=t),this._$Ei=void 0);let e=!1;const i=this._$AL;try{e=this.shouldUpdate(i),e?(this.willUpdate(i),null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)}),this.update(i)):this._$Ek()}catch(t){throw e=!1,this._$Ek(),t}e&&this._$AE(i)}willUpdate(t){}_$AE(t){var e;null===(e=this._$ES)||void 0===e||e.forEach(t=>{var e;return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)}),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return!0}update(t){void 0!==this._$EC&&(this._$EC.forEach((t,e)=>this._$EO(e,this[e],t)),this._$EC=void 0),this._$Ek()}updated(t){}firstUpdated(t){}}; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -var Ll;Pl[Rl]=!0,Pl.elementProperties=new Map,Pl.elementStyles=[],Pl.shadowRootOptions={mode:"open"},null==Tl||Tl({ReactiveElement:Pl}),(null!==(Al=El.reactiveElementVersions)&&void 0!==Al?Al:El.reactiveElementVersions=[]).push("1.6.3");const Ml=window,Nl=Ml.trustedTypes,Dl=Nl?Nl.createPolicy("lit-html",{createHTML:t=>t}):void 0,Hl="$lit$",Ul=`lit$${(Math.random()+"").slice(9)}$`,zl="?"+Ul,Fl=`<${zl}>`,Bl=document,Vl=()=>Bl.createComment(""),jl=t=>null===t||"object"!=typeof t&&"function"!=typeof t,Wl=Array.isArray,ql="[ \t\n\f\r]",Yl=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Xl=/-->/g,Gl=/>/g,Kl=RegExp(`>|${ql}(?:([^\\s"'>=/]+)(${ql}*=${ql}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),Jl=/'/g,Zl=/"/g,Ql=/^(?:script|style|textarea|title)$/i,td=(t=>(e,...i)=>({_$litType$:t,strings:e,values:i}))(1),ed=Symbol.for("lit-noChange"),id=Symbol.for("lit-nothing"),sd=new WeakMap,nd=Bl.createTreeWalker(Bl,129,null,!1);function rd(t,e){if(!Array.isArray(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==Dl?Dl.createHTML(e):e}let od=class t{constructor({strings:e,_$litType$:i},s){let n;this.parts=[];let r=0,o=0;const a=e.length-1,l=this.parts,[d,c]=((t,e)=>{const i=t.length-1,s=[];let n,r=2===e?"":"",o=Yl;for(let e=0;e"===l[0]?(o=null!=n?n:Yl,d=-1):void 0===l[1]?d=-2:(d=o.lastIndex-l[2].length,a=l[1],o=void 0===l[3]?Kl:'"'===l[3]?Zl:Jl):o===Zl||o===Jl?o=Kl:o===Xl||o===Gl?o=Yl:(o=Kl,n=void 0);const h=o===Kl&&t[e+1].startsWith("/>")?" ":"";r+=o===Yl?i+Fl:d>=0?(s.push(a),i.slice(0,d)+Hl+i.slice(d)+Ul+h):i+Ul+(-2===d?(s.push(void 0),e):h)}return[rd(t,r+(t[i]||"")+(2===e?"":"")),s]})(e,i);if(this.el=t.createElement(d,s),nd.currentNode=this.el.content,2===i){const t=this.el.content,e=t.firstChild;e.remove(),t.append(...e.childNodes)}for(;null!==(n=nd.nextNode())&&l.length0){n.textContent=Nl?Nl.emptyScript:"";for(let i=0;iWl(t)||"function"==typeof(null==t?void 0: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!==id&&jl(this._$AH)?this._$AA.nextSibling.data=t:this.$(Bl.createTextNode(t)),this._$AH=t}g(t){var e;const{values:i,_$litType$:s}=t,n="number"==typeof s?this._$AC(t):(void 0===s.el&&(s.el=od.createElement(rd(s.h,s.h[0]),this.options)),s);if((null===(e=this._$AH)||void 0===e?void 0:e._$AD)===n)this._$AH.v(i);else{const t=new ld(n,this),e=t.u(this.options);t.v(i),this.$(e),this._$AH=t}}_$AC(t){let e=sd.get(t.strings);return void 0===e&&sd.set(t.strings,e=new od(t)),e}T(e){Wl(this._$AH)||(this._$AH=[],this._$AR());const i=this._$AH;let s,n=0;for(const r of e)n===i.length?i.push(s=new t(this.k(Vl()),this.k(Vl()),this,this.options)):s=i[n],s._$AI(r),n++;n2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=id}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(t,e=this,i,s){const n=this.strings;let r=!1;if(void 0===n)t=ad(this,t,e,0),r=!jl(t)||t!==this._$AH&&t!==ed,r&&(this._$AH=t);else{const s=t;let o,a;for(t=n[0],o=0;o{var s,n;const r=null!==(s=null==i?void 0:i.renderBefore)&&void 0!==s?s:e;let o=r._$litPart$;if(void 0===o){const t=null!==(n=null==i?void 0:i.renderBefore)&&void 0!==n?n:null;r._$litPart$=o=new dd(e.insertBefore(Vl(),t),t,void 0,null!=i?i:{})}return o._$AI(t),o})(e,this.renderRoot,this.renderOptions)}connectedCallback(){var t;super.connectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!0)}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!1)}render(){return ed}};bd.finalized=!0,bd._$litElement$=!0,null===(vd=globalThis.litElementHydrateSupport)||void 0===vd||vd.call(globalThis,{LitElement:bd});const yd=globalThis.litElementPolyfillSupport;null==yd||yd({LitElement:bd}),(null!==(_d=globalThis.litElementVersions)&&void 0!==_d?_d:globalThis.litElementVersions=[]).push("3.3.3"); -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const xd=(t,e)=>"method"===e.kind&&e.descriptor&&!("value"in e.descriptor)?{...e,finisher(i){i.createProperty(e.key,t)}}:{kind:"field",key:Symbol(),placement:"own",descriptor:{},originalKey:e.key,initializer(){"function"==typeof e.initializer&&(this[e.key]=e.initializer.call(this))},finisher(i){i.createProperty(e.key,t)}};function $d(t){return(e,i)=>void 0!==i?((t,e,i)=>{e.constructor.createProperty(i,t)})(t,e,i):xd(t,e)} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */function wd(t){return $d({...t,state:!0})} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */const Ad=({finisher:t,descriptor:e})=>(i,s)=>{var n;if(void 0===s){const s=null!==(n=i.originalKey)&&void 0!==n?n:i.key,r=null!=e?{kind:"method",placement:"prototype",key:s,descriptor:e(i.key)}:{...i,key:s};return null!=t&&(r.finisher=function(e){t(e,s)}),r}{const n=i.constructor;void 0!==e&&Object.defineProperty(i,s,e(s)),null==t||t(n,s)}}; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */function Ed(t,e){return Ad({descriptor:e=>{const i={get(){var e,i;return null!==(i=null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(t))&&void 0!==i?i:null},enumerable:!0,configurable:!0};return i}})} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -var Sd;const Cd=null!=(null===(Sd=window.HTMLSlotElement)||void 0===Sd?void 0:Sd.prototype.assignedElements)?(t,e)=>t.assignedElements(e):(t,e)=>t.assignedNodes(e).filter(t=>t.nodeType===Node.ELEMENT_NODE); -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -function Td(t,e,i){let s;return s={flatten:e},i?function(t){const{slot:e,selector:i}=null!=t?t:{};return Ad({descriptor:s=>({get(){var s;const n="slot"+(e?`[name=${e}]`:":not([name])"),r=null===(s=this.renderRoot)||void 0===s?void 0:s.querySelector(n),o=null!=r?Cd(r,t):[];return i?o.filter(t=>t.matches(i)):o},enumerable:!0,configurable:!0})})}({slot:t,flatten:e,selector:i}):Ad({descriptor:t=>({get(){var t,e;const i=null===(t=this.renderRoot)||void 0===t?void 0:t.querySelector("slot:not([name])");return null!==(e=null==i?void 0:i.assignedNodes(s))&&void 0!==e?e:[]},enumerable:!0,configurable:!0})})} -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */const Id=t=>null!=t?t:id; -/** - * @license - * Copyright 2016 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */var Od=function(){function t(t){void 0===t&&(t={}),this.adapter=t}return Object.defineProperty(t,"cssClasses",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"strings",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"numbers",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"defaultAdapter",{get:function(){return{}},enumerable:!1,configurable:!0}),t.prototype.init=function(){},t.prototype.destroy=function(){},t}(),kd="Unknown",Rd="Backspace",Pd="Enter",Ld="Spacebar",Md="PageUp",Nd="PageDown",Dd="End",Hd="Home",Ud="ArrowLeft",zd="ArrowUp",Fd="ArrowRight",Bd="ArrowDown",Vd="Delete",jd="Escape",Wd="Tab",qd=new Set; -/** - * @license - * Copyright 2020 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */qd.add(Rd),qd.add(Pd),qd.add(Ld),qd.add(Md),qd.add(Nd),qd.add(Dd),qd.add(Hd),qd.add(Ud),qd.add(zd),qd.add(Fd),qd.add(Bd),qd.add(Vd),qd.add(jd),qd.add(Wd);var Yd=8,Xd=13,Gd=32,Kd=33,Jd=34,Zd=35,Qd=36,tc=37,ec=38,ic=39,sc=40,nc=46,rc=27,oc=9,ac=new Map;ac.set(Yd,Rd),ac.set(Xd,Pd),ac.set(Gd,Ld),ac.set(Kd,Md),ac.set(Jd,Nd),ac.set(Zd,Dd),ac.set(Qd,Hd),ac.set(tc,Ud),ac.set(ec,zd),ac.set(ic,Fd),ac.set(sc,Bd),ac.set(nc,Vd),ac.set(rc,jd),ac.set(oc,Wd);var lc=new Set;function dc(t){var e=t.key;if(qd.has(e))return e;var i=ac.get(t.keyCode);return i||kd} -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */lc.add(Md),lc.add(Nd),lc.add(Dd),lc.add(Hd),lc.add(Ud),lc.add(zd),lc.add(Fd),lc.add(Bd);const cc=(t,e)=>t-e,hc=["input","button","textarea","select"];function pc(t){return t instanceof Set}const uc=t=>{const e=t===qr.UNSET_INDEX?new Set:t;return pc(e)?new Set(e):new Set([e])};class mc extends Od{constructor(t){super(Object.assign(Object.assign({},mc.defaultAdapter),t)),this.isMulti_=!1,this.wrapFocus_=!1,this.isVertical_=!0,this.selectedIndex_=qr.UNSET_INDEX,this.focusedItemIndex_=qr.UNSET_INDEX,this.useActivatedClass_=!1,this.ariaCurrentAttrValue_=null}static get strings(){return Wr}static get numbers(){return qr}static get defaultAdapter(){return{focusItemAtIndex:()=>{},getFocusedElementIndex:()=>0,getListItemCount:()=>0,isFocusInsideList:()=>!1,isRootFocused:()=>!1,notifyAction:()=>{},notifySelected:()=>{},getSelectedStateForElementIndex:()=>!1,setDisabledStateForElementIndex:()=>{},getDisabledStateForElementIndex:()=>!1,setSelectedStateForElementIndex:()=>{},setActivatedStateForElementIndex:()=>{},setTabIndexForElementIndex:()=>{},setAttributeForElementIndex:()=>{},getAttributeForElementIndex:()=>null}}setWrapFocus(t){this.wrapFocus_=t}setMulti(t){this.isMulti_=t;const e=this.selectedIndex_;if(t){if(!pc(e)){const t=e===qr.UNSET_INDEX;this.selectedIndex_=t?new Set:new Set([e])}}else if(pc(e))if(e.size){const t=Array.from(e).sort(cc);this.selectedIndex_=t[0]}else this.selectedIndex_=qr.UNSET_INDEX}setVerticalOrientation(t){this.isVertical_=t}setUseActivatedClass(t){this.useActivatedClass_=t}getSelectedIndex(){return this.selectedIndex_}setSelectedIndex(t){this.isIndexValid_(t)&&(this.isMulti_?this.setMultiSelectionAtIndex_(uc(t)):this.setSingleSelectionAtIndex_(t))}handleFocusIn(t,e){e>=0&&this.adapter.setTabIndexForElementIndex(e,0)}handleFocusOut(t,e){e>=0&&this.adapter.setTabIndexForElementIndex(e,-1),setTimeout(()=>{this.adapter.isFocusInsideList()||this.setTabindexToFirstSelectedItem_()},0)}handleKeydown(t,e,i){const s="ArrowLeft"===dc(t),n="ArrowUp"===dc(t),r="ArrowRight"===dc(t),o="ArrowDown"===dc(t),a="Home"===dc(t),l="End"===dc(t),d="Enter"===dc(t),c="Spacebar"===dc(t);if(this.adapter.isRootFocused())return void(n||l?(t.preventDefault(),this.focusLastElement()):(o||a)&&(t.preventDefault(),this.focusFirstElement()));let h,p=this.adapter.getFocusedElementIndex();if(!(-1===p&&(p=i,p<0))){if(this.isVertical_&&o||!this.isVertical_&&r)this.preventDefaultEvent(t),h=this.focusNextElement(p);else if(this.isVertical_&&n||!this.isVertical_&&s)this.preventDefaultEvent(t),h=this.focusPrevElement(p);else if(a)this.preventDefaultEvent(t),h=this.focusFirstElement();else if(l)this.preventDefaultEvent(t),h=this.focusLastElement();else if((d||c)&&e){const e=t.target;if(e&&"A"===e.tagName&&d)return;this.preventDefaultEvent(t),this.setSelectedIndexOnAction_(p,!0)}this.focusedItemIndex_=p,void 0!==h&&(this.setTabindexAtIndex_(h),this.focusedItemIndex_=h)}}handleSingleSelection(t,e,i){t!==qr.UNSET_INDEX&&(this.setSelectedIndexOnAction_(t,e,i),this.setTabindexAtIndex_(t),this.focusedItemIndex_=t)}focusNextElement(t){let e=t+1;if(e>=this.adapter.getListItemCount()){if(!this.wrapFocus_)return t;e=0}return this.adapter.focusItemAtIndex(e),e}focusPrevElement(t){let e=t-1;if(e<0){if(!this.wrapFocus_)return t;e=this.adapter.getListItemCount()-1}return this.adapter.focusItemAtIndex(e),e}focusFirstElement(){return this.adapter.focusItemAtIndex(0),0}focusLastElement(){const t=this.adapter.getListItemCount()-1;return this.adapter.focusItemAtIndex(t),t}setEnabled(t,e){this.isIndexValid_(t)&&this.adapter.setDisabledStateForElementIndex(t,!e)}preventDefaultEvent(t){const e=`${t.target.tagName}`.toLowerCase();-1===hc.indexOf(e)&&t.preventDefault()}setSingleSelectionAtIndex_(t,e=!0){this.selectedIndex_!==t&&(this.selectedIndex_!==qr.UNSET_INDEX&&(this.adapter.setSelectedStateForElementIndex(this.selectedIndex_,!1),this.useActivatedClass_&&this.adapter.setActivatedStateForElementIndex(this.selectedIndex_,!1)),e&&this.adapter.setSelectedStateForElementIndex(t,!0),this.useActivatedClass_&&this.adapter.setActivatedStateForElementIndex(t,!0),this.setAriaForSingleSelectionAtIndex_(t),this.selectedIndex_=t,this.adapter.notifySelected(t))}setMultiSelectionAtIndex_(t,e=!0){const i=((t,e)=>{const i=Array.from(t),s=Array.from(e),n={added:[],removed:[]},r=i.sort(cc),o=s.sort(cc);let a=0,l=0;for(;a=0&&this.focusedItemIndex_!==t&&this.adapter.setTabIndexForElementIndex(this.focusedItemIndex_,-1),this.adapter.setTabIndexForElementIndex(t,0)}setTabindexToFirstSelectedItem_(){let t=0;"number"==typeof this.selectedIndex_&&this.selectedIndex_!==qr.UNSET_INDEX?t=this.selectedIndex_:pc(this.selectedIndex_)&&this.selectedIndex_.size>0&&(t=Math.min(...this.selectedIndex_)),this.setTabindexAtIndex_(t)}isIndexValid_(t){if(t instanceof Set){if(!this.isMulti_)throw new Error("MDCListFoundation: Array of index is only supported for checkbox based list");if(0===t.size)return!0;{let e=!1;for(const i of t)if(e=this.isIndexInRange_(i),e)break;return e}}if("number"==typeof t){if(this.isMulti_)throw new Error("MDCListFoundation: Expected array of index for checkbox based list but got number: "+t);return t===qr.UNSET_INDEX||this.isIndexInRange_(t)}return!1}isIndexInRange_(t){const e=this.adapter.getListItemCount();return t>=0&&tt.hasAttribute("mwc-list-item");function gc(){const t=this.itemsReadyResolver;this.itemsReady=new Promise(t=>this.itemsReadyResolver=t),t()}class vc extends Qi{constructor(){super(),this.mdcAdapter=null,this.mdcFoundationClass=mc,this.activatable=!1,this.multi=!1,this.wrapFocus=!1,this.itemRoles=null,this.innerRole=null,this.innerAriaLabel=null,this.rootTabbable=!1,this.previousTabindex=null,this.noninteractive=!1,this.itemsReadyResolver=()=>{},this.itemsReady=Promise.resolve([]),this.items_=[];const t=function(t,e=50){let i;return function(s=!0){clearTimeout(i),i=setTimeout(()=>{t(s)},e)}}(this.layout.bind(this));this.debouncedLayout=(e=!0)=>{gc.call(this),t(e)}}async getUpdateComplete(){const t=await super.getUpdateComplete();return await this.itemsReady,t}get items(){return this.items_}updateItems(){var t;const e=null!==(t=this.assignedElements)&&void 0!==t?t:[],i=[];for(const t of e)fc(t)&&(i.push(t),t._managingList=this),t.hasAttribute("divider")&&!t.hasAttribute("role")&&t.setAttribute("role","separator");this.items_=i;const s=new Set;if(this.items_.forEach((t,e)=>{this.itemRoles?t.setAttribute("role",this.itemRoles):t.removeAttribute("role"),t.selected&&s.add(e)}),this.multi)this.select(s);else{const t=s.size?s.entries().next().value[1]:-1;this.select(t)}const n=new Event("items-updated",{bubbles:!0,composed:!0});this.dispatchEvent(n)}get selected(){const t=this.index;if(!pc(t))return-1===t?null:this.items[t];const e=[];for(const i of t)e.push(this.items[i]);return e}get index(){return this.mdcFoundation?this.mdcFoundation.getSelectedIndex():-1}render(){const t=null===this.innerRole?void 0:this.innerRole,e=null===this.innerAriaLabel?void 0:this.innerAriaLabel,i=this.rootTabbable?"0":"-1";return td` - -
    - - ${this.renderPlaceholder()} -
- `}renderPlaceholder(){var t;const e=null!==(t=this.assignedElements)&&void 0!==t?t:[];return void 0!==this.emptyMessage&&0===e.length?td` - ${this.emptyMessage} - `:null}firstUpdated(){super.firstUpdated(),this.items.length||(this.mdcFoundation.setMulti(this.multi),this.layout())}onFocusIn(t){if(this.mdcFoundation&&this.mdcRoot){const e=this.getIndexOfTarget(t);this.mdcFoundation.handleFocusIn(t,e)}}onFocusOut(t){if(this.mdcFoundation&&this.mdcRoot){const e=this.getIndexOfTarget(t);this.mdcFoundation.handleFocusOut(t,e)}}onKeydown(t){if(this.mdcFoundation&&this.mdcRoot){const e=this.getIndexOfTarget(t),i=t.target,s=fc(i);this.mdcFoundation.handleKeydown(t,s,e)}}onRequestSelected(t){if(this.mdcFoundation){let e=this.getIndexOfTarget(t);if(-1===e&&(this.layout(),e=this.getIndexOfTarget(t),-1===e))return;if(this.items[e].disabled)return;const i=t.detail.selected,s=t.detail.source;this.mdcFoundation.handleSingleSelection(e,"interaction"===s,i),t.stopPropagation()}}getIndexOfTarget(t){const e=this.items,i=t.composedPath();for(const t of i){let i=-1;if(Yi(t)&&fc(t)&&(i=e.indexOf(t)),-1!==i)return i}return-1}createAdapter(){return this.mdcAdapter={getListItemCount:()=>this.mdcRoot?this.items.length:0,getFocusedElementIndex:this.getFocusedItemIndex,getAttributeForElementIndex:(t,e)=>{if(!this.mdcRoot)return"";const i=this.items[t];return i?i.getAttribute(e):""},setAttributeForElementIndex:(t,e,i)=>{if(!this.mdcRoot)return;const s=this.items[t];s&&s.setAttribute(e,i)},focusItemAtIndex:t=>{const e=this.items[t];e&&e.focus()},setTabIndexForElementIndex:(t,e)=>{const i=this.items[t];i&&(i.tabindex=e)},notifyAction:t=>{const e={bubbles:!0,composed:!0};e.detail={index:t};const i=new CustomEvent("action",e);this.dispatchEvent(i)},notifySelected:(t,e)=>{const i={bubbles:!0,composed:!0};i.detail={index:t,diff:e};const s=new CustomEvent("selected",i);this.dispatchEvent(s)},isFocusInsideList:()=>Zi(this),isRootFocused:()=>{const t=this.mdcRoot;return t.getRootNode().activeElement===t},setDisabledStateForElementIndex:(t,e)=>{const i=this.items[t];i&&(i.disabled=e)},getDisabledStateForElementIndex:t=>{const e=this.items[t];return!!e&&e.disabled},setSelectedStateForElementIndex:(t,e)=>{const i=this.items[t];i&&(i.selected=e)},getSelectedStateForElementIndex:t=>{const e=this.items[t];return!!e&&e.selected},setActivatedStateForElementIndex:(t,e)=>{const i=this.items[t];i&&(i.activated=e)}},this.mdcAdapter}selectUi(t,e=!1){const i=this.items[t];i&&(i.selected=!0,i.activated=e)}deselectUi(t){const e=this.items[t];e&&(e.selected=!1,e.activated=!1)}select(t){this.mdcFoundation&&this.mdcFoundation.setSelectedIndex(t)}toggle(t,e){this.multi&&this.mdcFoundation.toggleMultiAtIndex(t,e)}onListItemConnected(t){const e=t.target;this.layout(-1===this.items.indexOf(e))}layout(t=!0){t&&this.updateItems();const e=this.items[0];for(const t of this.items)t.tabindex=-1;e&&(this.noninteractive?this.previousTabindex||(this.previousTabindex=e):e.tabindex=0),this.itemsReadyResolver()}getFocusedItemIndex(){if(!this.mdcRoot)return-1;if(!this.items.length)return-1;const t=Ji();if(!t.length)return-1;for(let e=t.length-1;e>=0;e--){const i=t[e];if(fc(i))return this.items.indexOf(i)}return-1}focusItemAtIndex(t){for(const t of this.items)if(0===t.tabindex){t.tabindex=-1;break}this.items[t].tabindex=0,this.items[t].focus()}focus(){const t=this.mdcRoot;t&&t.focus()}blur(){const t=this.mdcRoot;t&&t.blur()}}n([$d({type:String})],vc.prototype,"emptyMessage",void 0),n([Ed(".mdc-deprecated-list")],vc.prototype,"mdcRoot",void 0),n([Td("",!0,"*")],vc.prototype,"assignedElements",void 0),n([Td("",!0,'[tabindex="0"]')],vc.prototype,"tabbableElements",void 0),n([$d({type:Boolean}),os(function(t){this.mdcFoundation&&this.mdcFoundation.setUseActivatedClass(t)})],vc.prototype,"activatable",void 0),n([$d({type:Boolean}),os(function(t,e){this.mdcFoundation&&this.mdcFoundation.setMulti(t),void 0!==e&&this.layout()})],vc.prototype,"multi",void 0),n([$d({type:Boolean}),os(function(t){this.mdcFoundation&&this.mdcFoundation.setWrapFocus(t)})],vc.prototype,"wrapFocus",void 0),n([$d({type:String}),os(function(t,e){void 0!==e&&this.updateItems()})],vc.prototype,"itemRoles",void 0),n([$d({type:String})],vc.prototype,"innerRole",void 0),n([$d({type:String})],vc.prototype,"innerAriaLabel",void 0),n([$d({type:Boolean})],vc.prototype,"rootTabbable",void 0),n([$d({type:Boolean,reflect:!0}),os(function(t){var e,i;if(t){const t=null!==(i=null===(e=this.tabbableElements)||void 0===e?void 0:e[0])&&void 0!==i?i:null;this.previousTabindex=t,t&&t.setAttribute("tabindex","-1")}else!t&&this.previousTabindex&&(this.previousTabindex.setAttribute("tabindex","0"),this.previousTabindex=null)})],vc.prototype,"noninteractive",void 0); -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -class _c{constructor(t){this.startPress=e=>{t().then(t=>{t&&t.startPress(e)})},this.endPress=()=>{t().then(t=>{t&&t.endPress()})},this.startFocus=()=>{t().then(t=>{t&&t.startFocus()})},this.endFocus=()=>{t().then(t=>{t&&t.endFocus()})},this.startHover=()=>{t().then(t=>{t&&t.startHover()})},this.endHover=()=>{t().then(t=>{t&&t.endHover()})}}} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */const bc=1;let yc=class{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 2018 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */const xc=(t=>(...e)=>({_$litDirective$:t,values:e}))(class extends yc{constructor(t){var e;if(super(t),t.type!==bc||"class"!==t.name||(null===(e=t.strings)||void 0===e?void 0:e.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]){var i,s;if(void 0===this.it){this.it=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]&&!(null===(i=this.nt)||void 0===i?void 0:i.has(t))&&this.it.add(t);return this.render(e)}const n=t.element.classList;this.it.forEach(t=>{t in e||(n.remove(t),this.it.delete(t))});for(const t in e){const i=!!e[t];i===this.it.has(t)||(null===(s=this.nt)||void 0===s?void 0:s.has(t))||(i?(n.add(t),this.it.add(t)):(n.remove(t),this.it.delete(t)))}return ed}}); -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */class $c extends bd{constructor(){super(...arguments),this.value="",this.group=null,this.tabindex=-1,this.disabled=!1,this.twoline=!1,this.activated=!1,this.graphic=null,this.multipleGraphics=!1,this.hasMeta=!1,this.noninteractive=!1,this.selected=!1,this.shouldRenderRipple=!1,this._managingList=null,this.boundOnClick=this.onClick.bind(this),this._firstChanged=!0,this._skipPropRequest=!1,this.rippleHandlers=new _c(()=>(this.shouldRenderRipple=!0,this.ripple)),this.listeners=[{target:this,eventNames:["click"],cb:()=>{this.onClick()}},{target:this,eventNames:["mouseenter"],cb:this.rippleHandlers.startHover},{target:this,eventNames:["mouseleave"],cb:this.rippleHandlers.endHover},{target:this,eventNames:["focus"],cb:this.rippleHandlers.startFocus},{target:this,eventNames:["blur"],cb:this.rippleHandlers.endFocus},{target:this,eventNames:["mousedown","touchstart"],cb:t=>{const e=t.type;this.onDown("mousedown"===e?"mouseup":"touchend",t)}}]}get text(){const t=this.textContent;return t?t.trim():""}render(){const t=this.renderText(),e=this.graphic?this.renderGraphic():td``,i=this.hasMeta?this.renderMeta():td``;return td` - ${this.renderRipple()} - ${e} - ${t} - ${i}`}renderRipple(){return this.shouldRenderRipple?td` - - `:this.activated?td`
`:""}renderGraphic(){const t={multi:this.multipleGraphics};return td` - - - `}renderMeta(){return td` - - - `}renderText(){const t=this.twoline?this.renderTwoline():this.renderSingleLine();return td` - - ${t} - `}renderSingleLine(){return td``}renderTwoline(){return td` - - - - - - - `}onClick(){this.fireRequestSelected(!this.selected,"interaction")}onDown(t,e){const i=()=>{window.removeEventListener(t,i),this.rippleHandlers.endPress()};window.addEventListener(t,i),this.rippleHandlers.startPress(e)}fireRequestSelected(t,e){if(this.noninteractive)return;const i=new CustomEvent("request-selected",{bubbles:!0,composed:!0,detail:{source:e,selected:t}});this.dispatchEvent(i)}connectedCallback(){super.connectedCallback(),this.noninteractive||this.setAttribute("mwc-list-item","");for(const t of this.listeners)for(const e of t.eventNames)t.target.addEventListener(e,t.cb,{passive:!0})}disconnectedCallback(){super.disconnectedCallback();for(const t of this.listeners)for(const e of t.eventNames)t.target.removeEventListener(e,t.cb);this._managingList&&(this._managingList.debouncedLayout?this._managingList.debouncedLayout(!0):this._managingList.layout(!0))}firstUpdated(){const t=new Event("list-item-rendered",{bubbles:!0,composed:!0});this.dispatchEvent(t)}}n([Ed("slot")],$c.prototype,"slotElement",void 0),n([function(t){return Ad({descriptor:e=>({async get(){var e;return await this.updateComplete,null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(t)},enumerable:!0,configurable:!0})})}("mwc-ripple")],$c.prototype,"ripple",void 0),n([$d({type:String})],$c.prototype,"value",void 0),n([$d({type:String,reflect:!0})],$c.prototype,"group",void 0),n([$d({type:Number,reflect:!0})],$c.prototype,"tabindex",void 0),n([$d({type:Boolean,reflect:!0}),os(function(t){t?this.setAttribute("aria-disabled","true"):this.setAttribute("aria-disabled","false")})],$c.prototype,"disabled",void 0),n([$d({type:Boolean,reflect:!0})],$c.prototype,"twoline",void 0),n([$d({type:Boolean,reflect:!0})],$c.prototype,"activated",void 0),n([$d({type:String,reflect:!0})],$c.prototype,"graphic",void 0),n([$d({type:Boolean})],$c.prototype,"multipleGraphics",void 0),n([$d({type:Boolean})],$c.prototype,"hasMeta",void 0),n([$d({type:Boolean,reflect:!0}),os(function(t){t?(this.removeAttribute("aria-checked"),this.removeAttribute("mwc-list-item"),this.selected=!1,this.activated=!1,this.tabIndex=-1):this.setAttribute("mwc-list-item","")})],$c.prototype,"noninteractive",void 0),n([$d({type:Boolean,reflect:!0}),os(function(t){const e=this.getAttribute("role"),i="gridcell"===e||"option"===e||"row"===e||"tab"===e;i&&t?this.setAttribute("aria-selected","true"):i&&this.setAttribute("aria-selected","false"),this._firstChanged?this._firstChanged=!1:this._skipPropRequest||this.fireRequestSelected(t,"property")})],$c.prototype,"selected",void 0),n([wd()],$c.prototype,"shouldRenderRipple",void 0),n([wd()],$c.prototype,"_managingList",void 0); -/** - * @license - * Copyright 2018 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -var wc,Ac={MENU_SELECTED_LIST_ITEM:"mdc-menu-item--selected",MENU_SELECTION_GROUP:"mdc-menu__selection-group",ROOT:"mdc-menu"},Ec={ARIA_CHECKED_ATTR:"aria-checked",ARIA_DISABLED_ATTR:"aria-disabled",CHECKBOX_SELECTOR:'input[type="checkbox"]',LIST_SELECTOR:".mdc-list,.mdc-deprecated-list",SELECTED_EVENT:"MDCMenu:selected",SKIP_RESTORE_FOCUS:"data-menu-item-skip-restore-focus"},Sc={FOCUS_ROOT_INDEX:-1};!function(t){t[t.NONE=0]="NONE",t[t.LIST_ROOT=1]="LIST_ROOT",t[t.FIRST_ITEM=2]="FIRST_ITEM",t[t.LAST_ITEM=3]="LAST_ITEM"}(wc||(wc={})); -/** - * @license - * Copyright 2016 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -var Cc=function(){function t(t){void 0===t&&(t={}),this.adapter=t}return Object.defineProperty(t,"cssClasses",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"strings",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"numbers",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"defaultAdapter",{get:function(){return{}},enumerable:!1,configurable:!0}),t.prototype.init=function(){},t.prototype.destroy=function(){},t}(),Tc=function(){function t(t){void 0===t&&(t={}),this.adapter=t}return Object.defineProperty(t,"cssClasses",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"strings",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"numbers",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"defaultAdapter",{get:function(){return{}},enumerable:!1,configurable:!0}),t.prototype.init=function(){},t.prototype.destroy=function(){},t}(),Ic=function(t){function e(i){var n=t.call(this,s(s({},e.defaultAdapter),i))||this;return n.isSurfaceOpen=!1,n.isQuickOpen=!1,n.isHoistedElement=!1,n.isFixedPosition=!1,n.isHorizontallyCenteredOnViewport=!1,n.maxHeight=0,n.openBottomBias=0,n.openAnimationEndTimerId=0,n.closeAnimationEndTimerId=0,n.animationRequestId=0,n.anchorCorner=Xo.TOP_START,n.originCorner=Xo.TOP_START,n.anchorMargin={top:0,right:0,bottom:0,left:0},n.position={x:0,y:0},n}return i(e,t),Object.defineProperty(e,"cssClasses",{get:function(){return Go},enumerable:!1,configurable:!0}),Object.defineProperty(e,"strings",{get:function(){return Ko},enumerable:!1,configurable:!0}),Object.defineProperty(e,"numbers",{get:function(){return Jo},enumerable:!1,configurable:!0}),Object.defineProperty(e,"Corner",{get:function(){return Xo},enumerable:!1,configurable:!0}),Object.defineProperty(e,"defaultAdapter",{get:function(){return{addClass:function(){},removeClass:function(){},hasClass:function(){return!1},hasAnchor:function(){return!1},isElementInContainer:function(){return!1},isFocused:function(){return!1},isRtl:function(){return!1},getInnerDimensions:function(){return{height:0,width:0}},getAnchorDimensions:function(){return null},getWindowDimensions:function(){return{height:0,width:0}},getBodyDimensions:function(){return{height:0,width:0}},getWindowScroll:function(){return{x:0,y:0}},setPosition:function(){},setMaxHeight:function(){},setTransformOrigin:function(){},saveFocus:function(){},restoreFocus:function(){},notifyClose:function(){},notifyClosing:function(){},notifyOpen:function(){},notifyOpening:function(){}}},enumerable:!1,configurable:!0}),e.prototype.init=function(){var t=e.cssClasses,i=t.ROOT,s=t.OPEN;if(!this.adapter.hasClass(i))throw new Error(i+" class required in root element.");this.adapter.hasClass(s)&&(this.isSurfaceOpen=!0)},e.prototype.destroy=function(){clearTimeout(this.openAnimationEndTimerId),clearTimeout(this.closeAnimationEndTimerId),cancelAnimationFrame(this.animationRequestId)},e.prototype.setAnchorCorner=function(t){this.anchorCorner=t},e.prototype.flipCornerHorizontally=function(){this.originCorner=this.originCorner^Yo.RIGHT},e.prototype.setAnchorMargin=function(t){this.anchorMargin.top=t.top||0,this.anchorMargin.right=t.right||0,this.anchorMargin.bottom=t.bottom||0,this.anchorMargin.left=t.left||0},e.prototype.setIsHoisted=function(t){this.isHoistedElement=t},e.prototype.setFixedPosition=function(t){this.isFixedPosition=t},e.prototype.isFixed=function(){return this.isFixedPosition},e.prototype.setAbsolutePosition=function(t,e){this.position.x=this.isFinite(t)?t:0,this.position.y=this.isFinite(e)?e:0},e.prototype.setIsHorizontallyCenteredOnViewport=function(t){this.isHorizontallyCenteredOnViewport=t},e.prototype.setQuickOpen=function(t){this.isQuickOpen=t},e.prototype.setMaxHeight=function(t){this.maxHeight=t},e.prototype.setOpenBottomBias=function(t){this.openBottomBias=t},e.prototype.isOpen=function(){return this.isSurfaceOpen},e.prototype.open=function(){var t=this;this.isSurfaceOpen||(this.adapter.notifyOpening(),this.adapter.saveFocus(),this.isQuickOpen?(this.isSurfaceOpen=!0,this.adapter.addClass(e.cssClasses.OPEN),this.dimensions=this.adapter.getInnerDimensions(),this.autoposition(),this.adapter.notifyOpen()):(this.adapter.addClass(e.cssClasses.ANIMATING_OPEN),this.animationRequestId=requestAnimationFrame(function(){t.dimensions=t.adapter.getInnerDimensions(),t.autoposition(),t.adapter.addClass(e.cssClasses.OPEN),t.openAnimationEndTimerId=setTimeout(function(){t.openAnimationEndTimerId=0,t.adapter.removeClass(e.cssClasses.ANIMATING_OPEN),t.adapter.notifyOpen()},Jo.TRANSITION_OPEN_DURATION)}),this.isSurfaceOpen=!0))},e.prototype.close=function(t){var i=this;if(void 0===t&&(t=!1),this.isSurfaceOpen){if(this.adapter.notifyClosing(),this.isQuickOpen)return this.isSurfaceOpen=!1,t||this.maybeRestoreFocus(),this.adapter.removeClass(e.cssClasses.OPEN),this.adapter.removeClass(e.cssClasses.IS_OPEN_BELOW),void this.adapter.notifyClose();this.adapter.addClass(e.cssClasses.ANIMATING_CLOSED),requestAnimationFrame(function(){i.adapter.removeClass(e.cssClasses.OPEN),i.adapter.removeClass(e.cssClasses.IS_OPEN_BELOW),i.closeAnimationEndTimerId=setTimeout(function(){i.closeAnimationEndTimerId=0,i.adapter.removeClass(e.cssClasses.ANIMATING_CLOSED),i.adapter.notifyClose()},Jo.TRANSITION_CLOSE_DURATION)}),this.isSurfaceOpen=!1,t||this.maybeRestoreFocus()}},e.prototype.handleBodyClick=function(t){var e=t.target;this.adapter.isElementInContainer(e)||this.close()},e.prototype.handleKeydown=function(t){var e=t.keyCode;("Escape"===t.key||27===e)&&this.close()},e.prototype.autoposition=function(){var t;this.measurements=this.getAutoLayoutmeasurements();var i=this.getoriginCorner(),s=this.getMenuSurfaceMaxHeight(i),n=this.hasBit(i,Yo.BOTTOM)?"bottom":"top",r=this.hasBit(i,Yo.RIGHT)?"right":"left",o=this.getHorizontalOriginOffset(i),a=this.getVerticalOriginOffset(i),l=this.measurements,d=l.anchorSize,c=l.surfaceSize,h=((t={})[r]=o,t[n]=a,t);d.width/c.width>Jo.ANCHOR_TO_MENU_SURFACE_WIDTH_RATIO&&(r="center"),(this.isHoistedElement||this.isFixedPosition)&&this.adjustPositionForHoistedElement(h),this.adapter.setTransformOrigin(r+" "+n),this.adapter.setPosition(h),this.adapter.setMaxHeight(s?s+"px":""),this.hasBit(i,Yo.BOTTOM)||this.adapter.addClass(e.cssClasses.IS_OPEN_BELOW)},e.prototype.getAutoLayoutmeasurements=function(){var t=this.adapter.getAnchorDimensions(),e=this.adapter.getBodyDimensions(),i=this.adapter.getWindowDimensions(),s=this.adapter.getWindowScroll();return t||(t={top:this.position.y,right:this.position.x,bottom:this.position.y,left:this.position.x,width:0,height:0}),{anchorSize:t,bodySize:e,surfaceSize:this.dimensions,viewportDistance:{top:t.top,right:i.width-t.right,bottom:i.height-t.bottom,left:t.left},viewportSize:i,windowScroll:s}},e.prototype.getoriginCorner=function(){var t,i,s=this.originCorner,n=this.measurements,r=n.viewportDistance,o=n.anchorSize,a=n.surfaceSize,l=e.numbers.MARGIN_TO_EDGE;this.hasBit(this.anchorCorner,Yo.BOTTOM)?(t=r.top-l+this.anchorMargin.bottom,i=r.bottom-l-this.anchorMargin.bottom):(t=r.top-l+this.anchorMargin.top,i=r.bottom-l+o.height-this.anchorMargin.top),!(i-a.height>0)&&t>i+this.openBottomBias&&(s=this.setBit(s,Yo.BOTTOM));var d,c,h=this.adapter.isRtl(),p=this.hasBit(this.anchorCorner,Yo.FLIP_RTL),u=this.hasBit(this.anchorCorner,Yo.RIGHT)||this.hasBit(s,Yo.RIGHT),m=!1;(m=h&&p?!u:u)?(d=r.left+o.width+this.anchorMargin.right,c=r.right-this.anchorMargin.right):(d=r.left+this.anchorMargin.left,c=r.right+o.width-this.anchorMargin.left);var f=d-a.width>0,g=c-a.width>0,v=this.hasBit(s,Yo.FLIP_RTL)&&this.hasBit(s,Yo.RIGHT);return g&&v&&h||!f&&v?s=this.unsetBit(s,Yo.RIGHT):(f&&m&&h||f&&!m&&u||!g&&d>=c)&&(s=this.setBit(s,Yo.RIGHT)),s},e.prototype.getMenuSurfaceMaxHeight=function(t){if(this.maxHeight>0)return this.maxHeight;var i=this.measurements.viewportDistance,s=0,n=this.hasBit(t,Yo.BOTTOM),r=this.hasBit(this.anchorCorner,Yo.BOTTOM),o=e.numbers.MARGIN_TO_EDGE;return n?(s=i.top+this.anchorMargin.top-o,r||(s+=this.measurements.anchorSize.height)):(s=i.bottom-this.anchorMargin.bottom+this.measurements.anchorSize.height-o,r&&(s-=this.measurements.anchorSize.height)),s},e.prototype.getHorizontalOriginOffset=function(t){var e=this.measurements.anchorSize,i=this.hasBit(t,Yo.RIGHT),s=this.hasBit(this.anchorCorner,Yo.RIGHT);if(i){var n=s?e.width-this.anchorMargin.left:this.anchorMargin.right;return this.isHoistedElement||this.isFixedPosition?n-(this.measurements.viewportSize.width-this.measurements.bodySize.width):n}return s?e.width-this.anchorMargin.right:this.anchorMargin.left},e.prototype.getVerticalOriginOffset=function(t){var e=this.measurements.anchorSize,i=this.hasBit(t,Yo.BOTTOM),s=this.hasBit(this.anchorCorner,Yo.BOTTOM);return i?s?e.height-this.anchorMargin.top:-this.anchorMargin.bottom:s?e.height+this.anchorMargin.bottom:this.anchorMargin.top},e.prototype.adjustPositionForHoistedElement=function(t){var e,i,s=this.measurements,n=s.windowScroll,o=s.viewportDistance,a=s.surfaceSize,l=s.viewportSize,d=Object.keys(t);try{for(var c=r(d),h=c.next();!h.done;h=c.next()){var p=h.value,u=t[p]||0;!this.isHorizontallyCenteredOnViewport||"left"!==p&&"right"!==p?(u+=o[p],this.isFixedPosition||("top"===p?u+=n.y:"bottom"===p?u-=n.y:"left"===p?u+=n.x:u-=n.x),t[p]=u):t[p]=(l.width-a.width)/2}}catch(t){e={error:t}}finally{try{h&&!h.done&&(i=c.return)&&i.call(c)}finally{if(e)throw e.error}}},e.prototype.maybeRestoreFocus=function(){var t=this,e=this.adapter.isFocused(),i=this.adapter.getOwnerDocument?this.adapter.getOwnerDocument():document,s=i.activeElement&&this.adapter.isElementInContainer(i.activeElement);(e||s)&&setTimeout(function(){t.adapter.restoreFocus()},Jo.TOUCH_EVENT_WAIT_MS)},e.prototype.hasBit=function(t,e){return Boolean(t&e)},e.prototype.setBit=function(t,e){return t|e},e.prototype.unsetBit=function(t,e){return t^e},e.prototype.isFinite=function(t){return"number"==typeof t&&isFinite(t)},e}(Tc),Oc=function(t){function e(i){var n=t.call(this,s(s({},e.defaultAdapter),i))||this;return n.closeAnimationEndTimerId=0,n.defaultFocusState=wc.LIST_ROOT,n.selectedIndex=-1,n}return i(e,t),Object.defineProperty(e,"cssClasses",{get:function(){return Ac},enumerable:!1,configurable:!0}),Object.defineProperty(e,"strings",{get:function(){return Ec},enumerable:!1,configurable:!0}),Object.defineProperty(e,"numbers",{get:function(){return Sc},enumerable:!1,configurable:!0}),Object.defineProperty(e,"defaultAdapter",{get:function(){return{addClassToElementAtIndex:function(){},removeClassFromElementAtIndex:function(){},addAttributeToElementAtIndex:function(){},removeAttributeFromElementAtIndex:function(){},getAttributeFromElementAtIndex:function(){return null},elementContainsClass:function(){return!1},closeSurface:function(){},getElementIndex:function(){return-1},notifySelected:function(){},getMenuItemCount:function(){return 0},focusItemAtIndex:function(){},focusListRoot:function(){},getSelectedSiblingOfItemAtIndex:function(){return-1},isSelectableItemAtIndex:function(){return!1}}},enumerable:!1,configurable:!0}),e.prototype.destroy=function(){this.closeAnimationEndTimerId&&clearTimeout(this.closeAnimationEndTimerId),this.adapter.closeSurface()},e.prototype.handleKeydown=function(t){var e=t.key,i=t.keyCode;("Tab"===e||9===i)&&this.adapter.closeSurface(!0)},e.prototype.handleItemAction=function(t){var e=this,i=this.adapter.getElementIndex(t);if(!(i<0)){this.adapter.notifySelected({index:i});var s="true"===this.adapter.getAttributeFromElementAtIndex(i,Ec.SKIP_RESTORE_FOCUS);this.adapter.closeSurface(s),this.closeAnimationEndTimerId=setTimeout(function(){var i=e.adapter.getElementIndex(t);i>=0&&e.adapter.isSelectableItemAtIndex(i)&&e.setSelectedIndex(i)},Ic.numbers.TRANSITION_CLOSE_DURATION)}},e.prototype.handleMenuSurfaceOpened=function(){switch(this.defaultFocusState){case wc.FIRST_ITEM:this.adapter.focusItemAtIndex(0);break;case wc.LAST_ITEM:this.adapter.focusItemAtIndex(this.adapter.getMenuItemCount()-1);break;case wc.NONE:break;default:this.adapter.focusListRoot()}},e.prototype.setDefaultFocusState=function(t){this.defaultFocusState=t},e.prototype.getSelectedIndex=function(){return this.selectedIndex},e.prototype.setSelectedIndex=function(t){if(this.validatedIndex(t),!this.adapter.isSelectableItemAtIndex(t))throw new Error("MDCMenuFoundation: No selection group at specified index.");var e=this.adapter.getSelectedSiblingOfItemAtIndex(t);e>=0&&(this.adapter.removeAttributeFromElementAtIndex(e,Ec.ARIA_CHECKED_ATTR),this.adapter.removeClassFromElementAtIndex(e,Ac.MENU_SELECTED_LIST_ITEM)),this.adapter.addClassToElementAtIndex(t,Ac.MENU_SELECTED_LIST_ITEM),this.adapter.addAttributeToElementAtIndex(t,Ec.ARIA_CHECKED_ATTR,"true"),this.selectedIndex=t},e.prototype.setEnabled=function(t,e){this.validatedIndex(t),e?(this.adapter.removeClassFromElementAtIndex(t,Ur),this.adapter.addAttributeToElementAtIndex(t,Ec.ARIA_DISABLED_ATTR,"false")):(this.adapter.addClassToElementAtIndex(t,Ur),this.adapter.addAttributeToElementAtIndex(t,Ec.ARIA_DISABLED_ATTR,"true"))},e.prototype.validatedIndex=function(t){var e=this.adapter.getMenuItemCount();if(!(t>=0&&t{const i=1===t.length?t[0]:e.reduce((e,i,s)=>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[s+1],t[0]);return new Mc(i,t,Pc)},Dc=Rc?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new Mc("string"==typeof t?t:t+"",void 0,Pc))(e)})(t):t; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */var Hc;const Uc=window,zc=Uc.trustedTypes,Fc=zc?zc.emptyScript:"",Bc=Uc.reactiveElementPolyfillSupport,Vc={toAttribute(t,e){switch(e){case Boolean:t=t?Fc: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}},jc=(t,e)=>e!==t&&(e==e||t==t),Wc={attribute:!0,type:String,converter:Vc,reflect:!1,hasChanged:jc},qc="finalized";let Yc=class extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(t){var e;this.finalize(),(null!==(e=this.h)&&void 0!==e?e:this.h=[]).push(t)}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach((e,i)=>{const s=this._$Ep(i,e);void 0!==s&&(this._$Ev.set(s,i),t.push(s))}),t}static createProperty(t,e=Wc){if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){const i="symbol"==typeof t?Symbol():"__"+t,s=this.getPropertyDescriptor(t,i,e);void 0!==s&&Object.defineProperty(this.prototype,t,s)}}static getPropertyDescriptor(t,e,i){return{get(){return this[e]},set(s){const n=this[t];this[e]=s,this.requestUpdate(t,n,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||Wc}static finalize(){if(this.hasOwnProperty(qc))return!1;this[qc]=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),void 0!==t.h&&(this.h=[...t.h]),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,e=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const i of e)this.createProperty(i,t[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}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(Dc(t))}else void 0!==t&&e.push(Dc(t));return e}static _$Ep(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}_$Eu(){var t;this._$E_=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach(t=>t(this))}addController(t){var e,i;(null!==(e=this._$ES)&&void 0!==e?e:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(i=t.hostConnected)||void 0===i||i.call(t))}removeController(t){var e;null===(e=this._$ES)||void 0===e||e.splice(this._$ES.indexOf(t)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach((t,e)=>{this.hasOwnProperty(e)&&(this._$Ei.set(e,this[e]),delete this[e])})}createRenderRoot(){var t;const e=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return((t,e)=>{Rc?t.adoptedStyleSheets=e.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet):e.forEach(e=>{const i=document.createElement("style"),s=kc.litNonce;void 0!==s&&i.setAttribute("nonce",s),i.textContent=e.cssText,t.appendChild(i)})})(e,this.constructor.elementStyles),e}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)})}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)})}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$EO(t,e,i=Wc){var s;const n=this.constructor._$Ep(t,i);if(void 0!==n&&!0===i.reflect){const r=(void 0!==(null===(s=i.converter)||void 0===s?void 0:s.toAttribute)?i.converter:Vc).toAttribute(e,i.type);this._$El=t,null==r?this.removeAttribute(n):this.setAttribute(n,r),this._$El=null}}_$AK(t,e){var i;const s=this.constructor,n=s._$Ev.get(t);if(void 0!==n&&this._$El!==n){const t=s.getPropertyOptions(n),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(i=t.converter)||void 0===i?void 0:i.fromAttribute)?t.converter:Vc;this._$El=n,this[n]=r.fromAttribute(e,t.type),this._$El=null}}requestUpdate(t,e,i){let s=!0;void 0!==t&&(((i=i||this.constructor.getPropertyOptions(t)).hasChanged||jc)(this[t],e)?(this._$AL.has(t)||this._$AL.set(t,e),!0===i.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,i))):s=!1),!this.isUpdatePending&&s&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach((t,e)=>this[e]=t),this._$Ei=void 0);let e=!1;const i=this._$AL;try{e=this.shouldUpdate(i),e?(this.willUpdate(i),null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)}),this.update(i)):this._$Ek()}catch(t){throw e=!1,this._$Ek(),t}e&&this._$AE(i)}willUpdate(t){}_$AE(t){var e;null===(e=this._$ES)||void 0===e||e.forEach(t=>{var e;return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)}),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return!0}update(t){void 0!==this._$EC&&(this._$EC.forEach((t,e)=>this._$EO(e,this[e],t)),this._$EC=void 0),this._$Ek()}updated(t){}firstUpdated(t){}}; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -var Xc;Yc[qc]=!0,Yc.elementProperties=new Map,Yc.elementStyles=[],Yc.shadowRootOptions={mode:"open"},null==Bc||Bc({ReactiveElement:Yc}),(null!==(Hc=Uc.reactiveElementVersions)&&void 0!==Hc?Hc:Uc.reactiveElementVersions=[]).push("1.6.3");const Gc=window,Kc=Gc.trustedTypes,Jc=Kc?Kc.createPolicy("lit-html",{createHTML:t=>t}):void 0,Zc="$lit$",Qc=`lit$${(Math.random()+"").slice(9)}$`,th="?"+Qc,eh=`<${th}>`,ih=document,sh=()=>ih.createComment(""),nh=t=>null===t||"object"!=typeof t&&"function"!=typeof t,rh=Array.isArray,oh="[ \t\n\f\r]",ah=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,lh=/-->/g,dh=/>/g,ch=RegExp(`>|${oh}(?:([^\\s"'>=/]+)(${oh}*=${oh}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),hh=/'/g,ph=/"/g,uh=/^(?:script|style|textarea|title)$/i,mh=(t=>(e,...i)=>({_$litType$:t,strings:e,values:i}))(1),fh=Symbol.for("lit-noChange"),gh=Symbol.for("lit-nothing"),vh=new WeakMap,_h=ih.createTreeWalker(ih,129,null,!1);function bh(t,e){if(!Array.isArray(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==Jc?Jc.createHTML(e):e}let yh=class t{constructor({strings:e,_$litType$:i},s){let n;this.parts=[];let r=0,o=0;const a=e.length-1,l=this.parts,[d,c]=((t,e)=>{const i=t.length-1,s=[];let n,r=2===e?"":"",o=ah;for(let e=0;e"===l[0]?(o=null!=n?n:ah,d=-1):void 0===l[1]?d=-2:(d=o.lastIndex-l[2].length,a=l[1],o=void 0===l[3]?ch:'"'===l[3]?ph:hh):o===ph||o===hh?o=ch:o===lh||o===dh?o=ah:(o=ch,n=void 0);const h=o===ch&&t[e+1].startsWith("/>")?" ":"";r+=o===ah?i+eh:d>=0?(s.push(a),i.slice(0,d)+Zc+i.slice(d)+Qc+h):i+Qc+(-2===d?(s.push(void 0),e):h)}return[bh(t,r+(t[i]||"")+(2===e?"":"")),s]})(e,i);if(this.el=t.createElement(d,s),_h.currentNode=this.el.content,2===i){const t=this.el.content,e=t.firstChild;e.remove(),t.append(...e.childNodes)}for(;null!==(n=_h.nextNode())&&l.length0){n.textContent=Kc?Kc.emptyScript:"";for(let i=0;irh(t)||"function"==typeof(null==t?void 0: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!==gh&&nh(this._$AH)?this._$AA.nextSibling.data=t:this.$(ih.createTextNode(t)),this._$AH=t}g(t){var e;const{values:i,_$litType$:s}=t,n="number"==typeof s?this._$AC(t):(void 0===s.el&&(s.el=yh.createElement(bh(s.h,s.h[0]),this.options)),s);if((null===(e=this._$AH)||void 0===e?void 0:e._$AD)===n)this._$AH.v(i);else{const t=new $h(n,this),e=t.u(this.options);t.v(i),this.$(e),this._$AH=t}}_$AC(t){let e=vh.get(t.strings);return void 0===e&&vh.set(t.strings,e=new yh(t)),e}T(e){rh(this._$AH)||(this._$AH=[],this._$AR());const i=this._$AH;let s,n=0;for(const r of e)n===i.length?i.push(s=new t(this.k(sh()),this.k(sh()),this,this.options)):s=i[n],s._$AI(r),n++;n2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=gh}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(t,e=this,i,s){const n=this.strings;let r=!1;if(void 0===n)t=xh(this,t,e,0),r=!nh(t)||t!==this._$AH&&t!==fh,r&&(this._$AH=t);else{const s=t;let o,a;for(t=n[0],o=0;o{var s,n;const r=null!==(s=null==i?void 0:i.renderBefore)&&void 0!==s?s:e;let o=r._$litPart$;if(void 0===o){const t=null!==(n=null==i?void 0:i.renderBefore)&&void 0!==n?n:null;r._$litPart$=o=new wh(e.insertBefore(sh(),t),t,void 0,null!=i?i:{})}return o._$AI(t),o})(e,this.renderRoot,this.renderOptions)}connectedCallback(){var t;super.connectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!0)}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!1)}render(){return fh}};Ph.finalized=!0,Ph._$litElement$=!0,null===(kh=globalThis.litElementHydrateSupport)||void 0===kh||kh.call(globalThis,{LitElement:Ph});const Lh=globalThis.litElementPolyfillSupport;null==Lh||Lh({LitElement:Ph}),(null!==(Rh=globalThis.litElementVersions)&&void 0!==Rh?Rh:globalThis.litElementVersions=[]).push("3.3.3"); -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const Mh=(t,e)=>"method"===e.kind&&e.descriptor&&!("value"in e.descriptor)?{...e,finisher(i){i.createProperty(e.key,t)}}:{kind:"field",key:Symbol(),placement:"own",descriptor:{},originalKey:e.key,initializer(){"function"==typeof e.initializer&&(this[e.key]=e.initializer.call(this))},finisher(i){i.createProperty(e.key,t)}};function Nh(t){return(e,i)=>void 0!==i?((t,e,i)=>{e.constructor.createProperty(i,t)})(t,e,i):Mh(t,e)} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */function Dh(t){return Nh({...t,state:!0})} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -function Hh(t,e){return(({finisher:t,descriptor:e})=>(i,s)=>{var n;if(void 0===s){const s=null!==(n=i.originalKey)&&void 0!==n?n:i.key,r=null!=e?{kind:"method",placement:"prototype",key:s,descriptor:e(i.key)}:{...i,key:s};return null!=t&&(r.finisher=function(e){t(e,s)}),r}{const n=i.constructor;void 0!==e&&Object.defineProperty(i,s,e(s)),null==t||t(n,s)}})({descriptor:e=>{const i={get(){var e,i;return null!==(i=null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(t))&&void 0!==i?i:null},enumerable:!0,configurable:!0};return i}})} -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */var Uh;null===(Uh=window.HTMLSlotElement)||void 0===Uh||Uh.prototype.assignedElements; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const zh=1,Fh=t=>(...e)=>({_$litDirective$:t,values:e});let Bh=class{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 2018 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */const Vh=Fh(class extends Bh{constructor(t){var e;if(super(t),t.type!==zh||"class"!==t.name||(null===(e=t.strings)||void 0===e?void 0:e.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]){var i,s;if(void 0===this.it){this.it=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]&&!(null===(i=this.nt)||void 0===i?void 0:i.has(t))&&this.it.add(t);return this.render(e)}const n=t.element.classList;this.it.forEach(t=>{t in e||(n.remove(t),this.it.delete(t))});for(const t in e){const i=!!e[t];i===this.it.has(t)||(null===(s=this.nt)||void 0===s?void 0:s.has(t))||(i?(n.add(t),this.it.add(t)):(n.remove(t),this.it.delete(t)))}return fh}}); -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */class jh extends Qi{constructor(){super(...arguments),this.mdcFoundationClass=Oc,this.listElement_=null,this.anchor=null,this.open=!1,this.quick=!1,this.wrapFocus=!1,this.innerRole="menu",this.innerAriaLabel=null,this.corner="TOP_START",this.x=null,this.y=null,this.absolute=!1,this.multi=!1,this.activatable=!1,this.fixed=!1,this.forceGroupSelection=!1,this.fullwidth=!1,this.menuCorner="START",this.stayOpenOnBodyClick=!1,this.defaultFocus="LIST_ROOT",this._listUpdateComplete=null}get listElement(){return this.listElement_||(this.listElement_=this.renderRoot.querySelector("mwc-list")),this.listElement_}get items(){const t=this.listElement;return t?t.items:[]}get index(){const t=this.listElement;return t?t.index:-1}get selected(){const t=this.listElement;return t?t.selected:null}render(){return this.renderSurface()}renderSurface(){const t=this.getSurfaceClasses();return mh` - - ${this.renderList()} - `}getSurfaceClasses(){return{"mdc-menu":!0,"mdc-menu-surface":!0}}renderList(){const t="menu"===this.innerRole?"menuitem":"option",e=this.renderListClasses();return mh` - - - `}renderListClasses(){return{"mdc-deprecated-list":!0}}createAdapter(){return{addClassToElementAtIndex:(t,e)=>{const i=this.listElement;if(!i)return;const s=i.items[t];s&&("mdc-menu-item--selected"===e?this.forceGroupSelection&&!s.selected&&i.toggle(t,!0):s.classList.add(e))},removeClassFromElementAtIndex:(t,e)=>{const i=this.listElement;if(!i)return;const s=i.items[t];s&&("mdc-menu-item--selected"===e?s.selected&&i.toggle(t,!1):s.classList.remove(e))},addAttributeToElementAtIndex:(t,e,i)=>{const s=this.listElement;if(!s)return;const n=s.items[t];n&&n.setAttribute(e,i)},removeAttributeFromElementAtIndex:(t,e)=>{const i=this.listElement;if(!i)return;const s=i.items[t];s&&s.removeAttribute(e)},getAttributeFromElementAtIndex:(t,e)=>{const i=this.listElement;if(!i)return null;const s=i.items[t];return s?s.getAttribute(e):null},elementContainsClass:(t,e)=>t.classList.contains(e),closeSurface:()=>{this.open=!1},getElementIndex:t=>{const e=this.listElement;return e?e.items.indexOf(t):-1},notifySelected:()=>{},getMenuItemCount:()=>{const t=this.listElement;return t?t.items.length:0},focusItemAtIndex:t=>{const e=this.listElement;if(!e)return;const i=e.items[t];i&&i.focus()},focusListRoot:()=>{this.listElement&&this.listElement.focus()},getSelectedSiblingOfItemAtIndex:t=>{const e=this.listElement;if(!e)return-1;const i=e.items[t];if(!i||!i.group)return-1;for(let s=0;s{const e=this.listElement;if(!e)return!1;const i=e.items[t];return!!i&&i.hasAttribute("group")}}}onKeydown(t){this.mdcFoundation&&this.mdcFoundation.handleKeydown(t)}onAction(t){const e=this.listElement;if(this.mdcFoundation&&e){const i=t.detail.index,s=e.items[i];s&&this.mdcFoundation.handleItemAction(s)}}onOpened(){this.open=!0,this.mdcFoundation&&this.mdcFoundation.handleMenuSurfaceOpened()}onClosed(){this.open=!1}async getUpdateComplete(){await this._listUpdateComplete;return await super.getUpdateComplete()}async firstUpdated(){super.firstUpdated();const t=this.listElement;t&&(this._listUpdateComplete=t.updateComplete,await this._listUpdateComplete)}select(t){const e=this.listElement;e&&e.select(t)}close(){this.open=!1}show(){this.open=!0}getFocusedItemIndex(){const t=this.listElement;return t?t.getFocusedItemIndex():-1}focusItemAtIndex(t){const e=this.listElement;e&&e.focusItemAtIndex(t)}layout(t=!0){const e=this.listElement;e&&e.layout(t)}}n([Hh(".mdc-menu")],jh.prototype,"mdcRoot",void 0),n([Hh("slot")],jh.prototype,"slotElement",void 0),n([Nh({type:Object})],jh.prototype,"anchor",void 0),n([Nh({type:Boolean,reflect:!0})],jh.prototype,"open",void 0),n([Nh({type:Boolean})],jh.prototype,"quick",void 0),n([Nh({type:Boolean})],jh.prototype,"wrapFocus",void 0),n([Nh({type:String})],jh.prototype,"innerRole",void 0),n([Nh({type:String})],jh.prototype,"innerAriaLabel",void 0),n([Nh({type:String})],jh.prototype,"corner",void 0),n([Nh({type:Number})],jh.prototype,"x",void 0),n([Nh({type:Number})],jh.prototype,"y",void 0),n([Nh({type:Boolean})],jh.prototype,"absolute",void 0),n([Nh({type:Boolean})],jh.prototype,"multi",void 0),n([Nh({type:Boolean})],jh.prototype,"activatable",void 0),n([Nh({type:Boolean})],jh.prototype,"fixed",void 0),n([Nh({type:Boolean})],jh.prototype,"forceGroupSelection",void 0),n([Nh({type:Boolean})],jh.prototype,"fullwidth",void 0),n([Nh({type:String})],jh.prototype,"menuCorner",void 0),n([Nh({type:Boolean})],jh.prototype,"stayOpenOnBodyClick",void 0),n([Nh({type:String}),os(function(t){this.mdcFoundation&&this.mdcFoundation.setDefaultFocusState(wc[t])})],jh.prototype,"defaultFocus",void 0); -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const Wh="important",qh=" !"+Wh,Yh=Fh(class extends Bh{constructor(t){var e;if(super(t),t.type!==zh||"style"!==t.name||(null===(e=t.strings)||void 0===e?void 0:e.length)>2)throw Error("The `styleMap` directive must be used in the `style` attribute and must be the only part in the attribute.")}render(t){return Object.keys(t).reduce((e,i)=>{const s=t[i];return null==s?e:e+`${i=i.includes("-")?i:i.replace(/(?:^(webkit|moz|ms|o)|)(?=[A-Z])/g,"-$&").toLowerCase()}:${s};`},"")}update(t,[e]){const{style:i}=t.element;if(void 0===this.ht){this.ht=new Set;for(const t in e)this.ht.add(t);return this.render(e)}this.ht.forEach(t=>{null==e[t]&&(this.ht.delete(t),t.includes("-")?i.removeProperty(t):i[t]="")});for(const t in e){const s=e[t];if(null!=s){this.ht.add(t);const e="string"==typeof s&&s.endsWith(qh);t.includes("-")||e?i.setProperty(t,e?s.slice(0,-11):s,e?Wh:""):i[t]=s}}return fh}}),Xh={TOP_LEFT:Xo.TOP_LEFT,TOP_RIGHT:Xo.TOP_RIGHT,BOTTOM_LEFT:Xo.BOTTOM_LEFT,BOTTOM_RIGHT:Xo.BOTTOM_RIGHT,TOP_START:Xo.TOP_START,TOP_END:Xo.TOP_END,BOTTOM_START:Xo.BOTTOM_START,BOTTOM_END:Xo.BOTTOM_END}; -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */class Gh extends Qi{constructor(){super(...arguments),this.mdcFoundationClass=Ic,this.absolute=!1,this.fullwidth=!1,this.fixed=!1,this.x=null,this.y=null,this.quick=!1,this.open=!1,this.stayOpenOnBodyClick=!1,this.bitwiseCorner=Xo.TOP_START,this.previousMenuCorner=null,this.menuCorner="START",this.corner="TOP_START",this.styleTop="",this.styleLeft="",this.styleRight="",this.styleBottom="",this.styleMaxHeight="",this.styleTransformOrigin="",this.anchor=null,this.previouslyFocused=null,this.previousAnchor=null,this.onBodyClickBound=()=>{}}render(){return this.renderSurface()}renderSurface(){const t=this.getRootClasses(),e=this.getRootStyles();return mh` -
- ${this.renderContent()} -
`}getRootClasses(){return{"mdc-menu-surface":!0,"mdc-menu-surface--fixed":this.fixed,"mdc-menu-surface--fullwidth":this.fullwidth}}getRootStyles(){return{top:this.styleTop,left:this.styleLeft,right:this.styleRight,bottom:this.styleBottom,"max-height":this.styleMaxHeight,"transform-origin":this.styleTransformOrigin}}renderContent(){return mh``}createAdapter(){return Object.assign(Object.assign({},Xi(this.mdcRoot)),{hasAnchor:()=>!!this.anchor,notifyClose:()=>{const t=new CustomEvent("closed",{bubbles:!0,composed:!0});this.open=!1,this.mdcRoot.dispatchEvent(t)},notifyClosing:()=>{const t=new CustomEvent("closing",{bubbles:!0,composed:!0});this.mdcRoot.dispatchEvent(t)},notifyOpen:()=>{const t=new CustomEvent("opened",{bubbles:!0,composed:!0});this.open=!0,this.mdcRoot.dispatchEvent(t)},notifyOpening:()=>{const t=new CustomEvent("opening",{bubbles:!0,composed:!0});this.mdcRoot.dispatchEvent(t)},isElementInContainer:()=>!1,isRtl:()=>!!this.mdcRoot&&"rtl"===getComputedStyle(this.mdcRoot).direction,setTransformOrigin:t=>{this.mdcRoot&&(this.styleTransformOrigin=t)},isFocused:()=>Zi(this),saveFocus:()=>{const t=Ji(),e=t.length;e||(this.previouslyFocused=null),this.previouslyFocused=t[e-1]},restoreFocus:()=>{this.previouslyFocused&&"focus"in this.previouslyFocused&&this.previouslyFocused.focus()},getInnerDimensions:()=>{const t=this.mdcRoot;return t?{width:t.offsetWidth,height:t.offsetHeight}:{width:0,height:0}},getAnchorDimensions:()=>{const t=this.anchor;return t?t.getBoundingClientRect():null},getBodyDimensions:()=>({width:document.body.clientWidth,height:document.body.clientHeight}),getWindowDimensions:()=>({width:window.innerWidth,height:window.innerHeight}),getWindowScroll:()=>({x:window.pageXOffset,y:window.pageYOffset}),setPosition:t=>{this.mdcRoot&&(this.styleLeft="left"in t?`${t.left}px`:"",this.styleRight="right"in t?`${t.right}px`:"",this.styleTop="top"in t?`${t.top}px`:"",this.styleBottom="bottom"in t?`${t.bottom}px`:"")},setMaxHeight:async t=>{this.mdcRoot&&(this.styleMaxHeight=t,await this.updateComplete,this.styleMaxHeight=`var(--mdc-menu-max-height, ${t})`)}})}onKeydown(t){this.mdcFoundation&&this.mdcFoundation.handleKeydown(t)}onBodyClick(t){if(this.stayOpenOnBodyClick)return;-1===t.composedPath().indexOf(this)&&this.close()}registerBodyClick(){this.onBodyClickBound=this.onBodyClick.bind(this),document.body.addEventListener("click",this.onBodyClickBound,{passive:!0,capture:!0})}deregisterBodyClick(){document.body.removeEventListener("click",this.onBodyClickBound,{capture:!0})}onOpenChanged(t,e){this.mdcFoundation&&(t?this.mdcFoundation.open():void 0!==e&&this.mdcFoundation.close())}close(){this.open=!1}show(){this.open=!0}}n([Hh(".mdc-menu-surface")],Gh.prototype,"mdcRoot",void 0),n([Hh("slot")],Gh.prototype,"slotElement",void 0),n([Nh({type:Boolean}),os(function(t){this.mdcFoundation&&!this.fixed&&this.mdcFoundation.setIsHoisted(t)})],Gh.prototype,"absolute",void 0),n([Nh({type:Boolean})],Gh.prototype,"fullwidth",void 0),n([Nh({type:Boolean}),os(function(t){this.mdcFoundation&&!this.absolute&&this.mdcFoundation.setFixedPosition(t)})],Gh.prototype,"fixed",void 0),n([Nh({type:Number}),os(function(t){this.mdcFoundation&&null!==this.y&&null!==t&&(this.mdcFoundation.setAbsolutePosition(t,this.y),this.mdcFoundation.setAnchorMargin({left:t,top:this.y,right:-t,bottom:this.y}))})],Gh.prototype,"x",void 0),n([Nh({type:Number}),os(function(t){this.mdcFoundation&&null!==this.x&&null!==t&&(this.mdcFoundation.setAbsolutePosition(this.x,t),this.mdcFoundation.setAnchorMargin({left:this.x,top:t,right:-this.x,bottom:t}))})],Gh.prototype,"y",void 0),n([Nh({type:Boolean}),os(function(t){this.mdcFoundation&&this.mdcFoundation.setQuickOpen(t)})],Gh.prototype,"quick",void 0),n([Nh({type:Boolean,reflect:!0}),os(function(t,e){this.onOpenChanged(t,e)})],Gh.prototype,"open",void 0),n([Nh({type:Boolean})],Gh.prototype,"stayOpenOnBodyClick",void 0),n([Dh(),os(function(t){this.mdcFoundation&&this.mdcFoundation.setAnchorCorner(t)})],Gh.prototype,"bitwiseCorner",void 0),n([Nh({type:String}),os(function(t){if(this.mdcFoundation){const e="START"===t||"END"===t,i=null===this.previousMenuCorner,s=!i&&t!==this.previousMenuCorner;e&&(s||i&&"END"===t)&&(this.bitwiseCorner=this.bitwiseCorner^Yo.RIGHT,this.mdcFoundation.flipCornerHorizontally(),this.previousMenuCorner=t)}})],Gh.prototype,"menuCorner",void 0),n([Nh({type:String}),os(function(t){if(this.mdcFoundation&&t){let e=Xh[t];"END"===this.menuCorner&&(e^=Yo.RIGHT),this.bitwiseCorner=e}})],Gh.prototype,"corner",void 0),n([Dh()],Gh.prototype,"styleTop",void 0),n([Dh()],Gh.prototype,"styleLeft",void 0),n([Dh()],Gh.prototype,"styleRight",void 0),n([Dh()],Gh.prototype,"styleBottom",void 0),n([Dh()],Gh.prototype,"styleMaxHeight",void 0),n([Dh()],Gh.prototype,"styleTransformOrigin",void 0); -/** - * @license - * Copyright 2016 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -var Kh=function(){function t(t){void 0===t&&(t={}),this.adapter=t}return Object.defineProperty(t,"cssClasses",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"strings",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"numbers",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"defaultAdapter",{get:function(){return{}},enumerable:!1,configurable:!0}),t.prototype.init=function(){},t.prototype.destroy=function(){},t}(),Jh={BG_FOCUSED:"mdc-ripple-upgraded--background-focused",FG_ACTIVATION:"mdc-ripple-upgraded--foreground-activation",FG_DEACTIVATION:"mdc-ripple-upgraded--foreground-deactivation",ROOT:"mdc-ripple-upgraded",UNBOUNDED:"mdc-ripple-upgraded--unbounded"},Zh={VAR_FG_SCALE:"--mdc-ripple-fg-scale",VAR_FG_SIZE:"--mdc-ripple-fg-size",VAR_FG_TRANSLATE_END:"--mdc-ripple-fg-translate-end",VAR_FG_TRANSLATE_START:"--mdc-ripple-fg-translate-start",VAR_LEFT:"--mdc-ripple-left",VAR_TOP:"--mdc-ripple-top"},Qh={DEACTIVATION_TIMEOUT_MS:225,FG_DEACTIVATION_MS:150,INITIAL_ORIGIN_SCALE:.6,PADDING:10,TAP_DELAY_MS:300}; -/** - * @license - * Copyright 2016 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -/** - * @license - * Copyright 2016 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -var tp=["touchstart","pointerdown","mousedown","keydown"],ep=["touchend","pointerup","mouseup","contextmenu"],ip=[],sp=function(t){function e(i){var n=t.call(this,s(s({},e.defaultAdapter),i))||this;return n.activationAnimationHasEnded=!1,n.activationTimer=0,n.fgDeactivationRemovalTimer=0,n.fgScale="0",n.frame={width:0,height:0},n.initialSize=0,n.layoutFrame=0,n.maxRadius=0,n.unboundedCoords={left:0,top:0},n.activationState=n.defaultActivationState(),n.activationTimerCallback=function(){n.activationAnimationHasEnded=!0,n.runDeactivationUXLogicIfReady()},n.activateHandler=function(t){n.activateImpl(t)},n.deactivateHandler=function(){n.deactivateImpl()},n.focusHandler=function(){n.handleFocus()},n.blurHandler=function(){n.handleBlur()},n.resizeHandler=function(){n.layout()},n}return i(e,t),Object.defineProperty(e,"cssClasses",{get:function(){return Jh},enumerable:!1,configurable:!0}),Object.defineProperty(e,"strings",{get:function(){return Zh},enumerable:!1,configurable:!0}),Object.defineProperty(e,"numbers",{get:function(){return Qh},enumerable:!1,configurable:!0}),Object.defineProperty(e,"defaultAdapter",{get:function(){return{addClass:function(){},browserSupportsCssVars:function(){return!0},computeBoundingRect:function(){return{top:0,right:0,bottom:0,left:0,width:0,height:0}},containsEventTarget:function(){return!0},deregisterDocumentInteractionHandler:function(){},deregisterInteractionHandler:function(){},deregisterResizeHandler:function(){},getWindowPageOffset:function(){return{x:0,y:0}},isSurfaceActive:function(){return!0},isSurfaceDisabled:function(){return!0},isUnbounded:function(){return!0},registerDocumentInteractionHandler:function(){},registerInteractionHandler:function(){},registerResizeHandler:function(){},removeClass:function(){},updateCssVariable:function(){}}},enumerable:!1,configurable:!0}),e.prototype.init=function(){var t=this,i=this.supportsPressRipple();if(this.registerRootHandlers(i),i){var s=e.cssClasses,n=s.ROOT,r=s.UNBOUNDED;requestAnimationFrame(function(){t.adapter.addClass(n),t.adapter.isUnbounded()&&(t.adapter.addClass(r),t.layoutInternal())})}},e.prototype.destroy=function(){var t=this;if(this.supportsPressRipple()){this.activationTimer&&(clearTimeout(this.activationTimer),this.activationTimer=0,this.adapter.removeClass(e.cssClasses.FG_ACTIVATION)),this.fgDeactivationRemovalTimer&&(clearTimeout(this.fgDeactivationRemovalTimer),this.fgDeactivationRemovalTimer=0,this.adapter.removeClass(e.cssClasses.FG_DEACTIVATION));var i=e.cssClasses,s=i.ROOT,n=i.UNBOUNDED;requestAnimationFrame(function(){t.adapter.removeClass(s),t.adapter.removeClass(n),t.removeCssVars()})}this.deregisterRootHandlers(),this.deregisterDeactivationHandlers()},e.prototype.activate=function(t){this.activateImpl(t)},e.prototype.deactivate=function(){this.deactivateImpl()},e.prototype.layout=function(){var t=this;this.layoutFrame&&cancelAnimationFrame(this.layoutFrame),this.layoutFrame=requestAnimationFrame(function(){t.layoutInternal(),t.layoutFrame=0})},e.prototype.setUnbounded=function(t){var i=e.cssClasses.UNBOUNDED;t?this.adapter.addClass(i):this.adapter.removeClass(i)},e.prototype.handleFocus=function(){var t=this;requestAnimationFrame(function(){return t.adapter.addClass(e.cssClasses.BG_FOCUSED)})},e.prototype.handleBlur=function(){var t=this;requestAnimationFrame(function(){return t.adapter.removeClass(e.cssClasses.BG_FOCUSED)})},e.prototype.supportsPressRipple=function(){return this.adapter.browserSupportsCssVars()},e.prototype.defaultActivationState=function(){return{activationEvent:void 0,hasDeactivationUXRun:!1,isActivated:!1,isProgrammatic:!1,wasActivatedByPointer:!1,wasElementMadeActive:!1}},e.prototype.registerRootHandlers=function(t){var e,i;if(t){try{for(var s=r(tp),n=s.next();!n.done;n=s.next()){var o=n.value;this.adapter.registerInteractionHandler(o,this.activateHandler)}}catch(t){e={error:t}}finally{try{n&&!n.done&&(i=s.return)&&i.call(s)}finally{if(e)throw e.error}}this.adapter.isUnbounded()&&this.adapter.registerResizeHandler(this.resizeHandler)}this.adapter.registerInteractionHandler("focus",this.focusHandler),this.adapter.registerInteractionHandler("blur",this.blurHandler)},e.prototype.registerDeactivationHandlers=function(t){var e,i;if("keydown"===t.type)this.adapter.registerInteractionHandler("keyup",this.deactivateHandler);else try{for(var s=r(ep),n=s.next();!n.done;n=s.next()){var o=n.value;this.adapter.registerDocumentInteractionHandler(o,this.deactivateHandler)}}catch(t){e={error:t}}finally{try{n&&!n.done&&(i=s.return)&&i.call(s)}finally{if(e)throw e.error}}},e.prototype.deregisterRootHandlers=function(){var t,e;try{for(var i=r(tp),s=i.next();!s.done;s=i.next()){var n=s.value;this.adapter.deregisterInteractionHandler(n,this.activateHandler)}}catch(e){t={error:e}}finally{try{s&&!s.done&&(e=i.return)&&e.call(i)}finally{if(t)throw t.error}}this.adapter.deregisterInteractionHandler("focus",this.focusHandler),this.adapter.deregisterInteractionHandler("blur",this.blurHandler),this.adapter.isUnbounded()&&this.adapter.deregisterResizeHandler(this.resizeHandler)},e.prototype.deregisterDeactivationHandlers=function(){var t,e;this.adapter.deregisterInteractionHandler("keyup",this.deactivateHandler);try{for(var i=r(ep),s=i.next();!s.done;s=i.next()){var n=s.value;this.adapter.deregisterDocumentInteractionHandler(n,this.deactivateHandler)}}catch(e){t={error:e}}finally{try{s&&!s.done&&(e=i.return)&&e.call(i)}finally{if(t)throw t.error}}},e.prototype.removeCssVars=function(){var t=this,i=e.strings;Object.keys(i).forEach(function(e){0===e.indexOf("VAR_")&&t.adapter.updateCssVariable(i[e],null)})},e.prototype.activateImpl=function(t){var e=this;if(!this.adapter.isSurfaceDisabled()){var i=this.activationState;if(!i.isActivated){var s=this.previousActivationEvent;if(!(s&&void 0!==t&&s.type!==t.type))i.isActivated=!0,i.isProgrammatic=void 0===t,i.activationEvent=t,i.wasActivatedByPointer=!i.isProgrammatic&&(void 0!==t&&("mousedown"===t.type||"touchstart"===t.type||"pointerdown"===t.type)),void 0!==t&&ip.length>0&&ip.some(function(t){return e.adapter.containsEventTarget(t)})?this.resetActivationState():(void 0!==t&&(ip.push(t.target),this.registerDeactivationHandlers(t)),i.wasElementMadeActive=this.checkElementMadeActive(t),i.wasElementMadeActive&&this.animateActivation(),requestAnimationFrame(function(){ip=[],i.wasElementMadeActive||void 0===t||" "!==t.key&&32!==t.keyCode||(i.wasElementMadeActive=e.checkElementMadeActive(t),i.wasElementMadeActive&&e.animateActivation()),i.wasElementMadeActive||(e.activationState=e.defaultActivationState())}))}}},e.prototype.checkElementMadeActive=function(t){return void 0===t||"keydown"!==t.type||this.adapter.isSurfaceActive()},e.prototype.animateActivation=function(){var t=this,i=e.strings,s=i.VAR_FG_TRANSLATE_START,n=i.VAR_FG_TRANSLATE_END,r=e.cssClasses,o=r.FG_DEACTIVATION,a=r.FG_ACTIVATION,l=e.numbers.DEACTIVATION_TIMEOUT_MS;this.layoutInternal();var d="",c="";if(!this.adapter.isUnbounded()){var h=this.getFgTranslationCoordinates(),p=h.startPoint,u=h.endPoint;d=p.x+"px, "+p.y+"px",c=u.x+"px, "+u.y+"px"}this.adapter.updateCssVariable(s,d),this.adapter.updateCssVariable(n,c),clearTimeout(this.activationTimer),clearTimeout(this.fgDeactivationRemovalTimer),this.rmBoundedActivationClasses(),this.adapter.removeClass(o),this.adapter.computeBoundingRect(),this.adapter.addClass(a),this.activationTimer=setTimeout(function(){t.activationTimerCallback()},l)},e.prototype.getFgTranslationCoordinates=function(){var t,e=this.activationState,i=e.activationEvent;return t=e.wasActivatedByPointer?function(t,e,i){if(!t)return{x:0,y:0};var s,n,r=e.x,o=e.y,a=r+i.left,l=o+i.top;if("touchstart"===t.type){var d=t;s=d.changedTouches[0].pageX-a,n=d.changedTouches[0].pageY-l}else{var c=t;s=c.pageX-a,n=c.pageY-l}return{x:s,y:n}}(i,this.adapter.getWindowPageOffset(),this.adapter.computeBoundingRect()):{x:this.frame.width/2,y:this.frame.height/2},{startPoint:t={x:t.x-this.initialSize/2,y:t.y-this.initialSize/2},endPoint:{x:this.frame.width/2-this.initialSize/2,y:this.frame.height/2-this.initialSize/2}}},e.prototype.runDeactivationUXLogicIfReady=function(){var t=this,i=e.cssClasses.FG_DEACTIVATION,s=this.activationState,n=s.hasDeactivationUXRun,r=s.isActivated;(n||!r)&&this.activationAnimationHasEnded&&(this.rmBoundedActivationClasses(),this.adapter.addClass(i),this.fgDeactivationRemovalTimer=setTimeout(function(){t.adapter.removeClass(i)},Qh.FG_DEACTIVATION_MS))},e.prototype.rmBoundedActivationClasses=function(){var t=e.cssClasses.FG_ACTIVATION;this.adapter.removeClass(t),this.activationAnimationHasEnded=!1,this.adapter.computeBoundingRect()},e.prototype.resetActivationState=function(){var t=this;this.previousActivationEvent=this.activationState.activationEvent,this.activationState=this.defaultActivationState(),setTimeout(function(){return t.previousActivationEvent=void 0},e.numbers.TAP_DELAY_MS)},e.prototype.deactivateImpl=function(){var t=this,e=this.activationState;if(e.isActivated){var i=s({},e);e.isProgrammatic?(requestAnimationFrame(function(){t.animateDeactivation(i)}),this.resetActivationState()):(this.deregisterDeactivationHandlers(),requestAnimationFrame(function(){t.activationState.hasDeactivationUXRun=!0,t.animateDeactivation(i),t.resetActivationState()}))}},e.prototype.animateDeactivation=function(t){var e=t.wasActivatedByPointer,i=t.wasElementMadeActive;(e||i)&&this.runDeactivationUXLogicIfReady()},e.prototype.layoutInternal=function(){var t=this;this.frame=this.adapter.computeBoundingRect();var i=Math.max(this.frame.height,this.frame.width);this.maxRadius=this.adapter.isUnbounded()?i:Math.sqrt(Math.pow(t.frame.width,2)+Math.pow(t.frame.height,2))+e.numbers.PADDING;var s=Math.floor(i*e.numbers.INITIAL_ORIGIN_SCALE);this.adapter.isUnbounded()&&s%2!=0?this.initialSize=s-1:this.initialSize=s,this.fgScale=""+this.maxRadius/this.initialSize,this.updateLayoutCssVars()},e.prototype.updateLayoutCssVars=function(){var t=e.strings,i=t.VAR_FG_SIZE,s=t.VAR_LEFT,n=t.VAR_TOP,r=t.VAR_FG_SCALE;this.adapter.updateCssVariable(i,this.initialSize+"px"),this.adapter.updateCssVariable(r,this.fgScale),this.adapter.isUnbounded()&&(this.unboundedCoords={left:Math.round(this.frame.width/2-this.initialSize/2),top:Math.round(this.frame.height/2-this.initialSize/2)},this.adapter.updateCssVariable(s,this.unboundedCoords.left+"px"),this.adapter.updateCssVariable(n,this.unboundedCoords.top+"px"))},e}(Kh); -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const np=window,rp=np.ShadowRoot&&(void 0===np.ShadyCSS||np.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,op=Symbol(),ap=new WeakMap;let lp=class{constructor(t,e,i){if(this._$cssResult$=!0,i!==op)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(rp&&void 0===t){const i=void 0!==e&&1===e.length;i&&(t=ap.get(e)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&ap.set(e,t))}return t}toString(){return this.cssText}};const dp=rp?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new lp("string"==typeof t?t:t+"",void 0,op))(e)})(t):t; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */var cp;const hp=window,pp=hp.trustedTypes,up=pp?pp.emptyScript:"",mp=hp.reactiveElementPolyfillSupport,fp={toAttribute(t,e){switch(e){case Boolean:t=t?up: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}},gp=(t,e)=>e!==t&&(e==e||t==t),vp={attribute:!0,type:String,converter:fp,reflect:!1,hasChanged:gp},_p="finalized";let bp=class extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(t){var e;this.finalize(),(null!==(e=this.h)&&void 0!==e?e:this.h=[]).push(t)}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach((e,i)=>{const s=this._$Ep(i,e);void 0!==s&&(this._$Ev.set(s,i),t.push(s))}),t}static createProperty(t,e=vp){if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){const i="symbol"==typeof t?Symbol():"__"+t,s=this.getPropertyDescriptor(t,i,e);void 0!==s&&Object.defineProperty(this.prototype,t,s)}}static getPropertyDescriptor(t,e,i){return{get(){return this[e]},set(s){const n=this[t];this[e]=s,this.requestUpdate(t,n,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||vp}static finalize(){if(this.hasOwnProperty(_p))return!1;this[_p]=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),void 0!==t.h&&(this.h=[...t.h]),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,e=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const i of e)this.createProperty(i,t[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}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(dp(t))}else void 0!==t&&e.push(dp(t));return e}static _$Ep(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}_$Eu(){var t;this._$E_=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach(t=>t(this))}addController(t){var e,i;(null!==(e=this._$ES)&&void 0!==e?e:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(i=t.hostConnected)||void 0===i||i.call(t))}removeController(t){var e;null===(e=this._$ES)||void 0===e||e.splice(this._$ES.indexOf(t)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach((t,e)=>{this.hasOwnProperty(e)&&(this._$Ei.set(e,this[e]),delete this[e])})}createRenderRoot(){var t;const e=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return((t,e)=>{rp?t.adoptedStyleSheets=e.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet):e.forEach(e=>{const i=document.createElement("style"),s=np.litNonce;void 0!==s&&i.setAttribute("nonce",s),i.textContent=e.cssText,t.appendChild(i)})})(e,this.constructor.elementStyles),e}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)})}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)})}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$EO(t,e,i=vp){var s;const n=this.constructor._$Ep(t,i);if(void 0!==n&&!0===i.reflect){const r=(void 0!==(null===(s=i.converter)||void 0===s?void 0:s.toAttribute)?i.converter:fp).toAttribute(e,i.type);this._$El=t,null==r?this.removeAttribute(n):this.setAttribute(n,r),this._$El=null}}_$AK(t,e){var i;const s=this.constructor,n=s._$Ev.get(t);if(void 0!==n&&this._$El!==n){const t=s.getPropertyOptions(n),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(i=t.converter)||void 0===i?void 0:i.fromAttribute)?t.converter:fp;this._$El=n,this[n]=r.fromAttribute(e,t.type),this._$El=null}}requestUpdate(t,e,i){let s=!0;void 0!==t&&(((i=i||this.constructor.getPropertyOptions(t)).hasChanged||gp)(this[t],e)?(this._$AL.has(t)||this._$AL.set(t,e),!0===i.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,i))):s=!1),!this.isUpdatePending&&s&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach((t,e)=>this[e]=t),this._$Ei=void 0);let e=!1;const i=this._$AL;try{e=this.shouldUpdate(i),e?(this.willUpdate(i),null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)}),this.update(i)):this._$Ek()}catch(t){throw e=!1,this._$Ek(),t}e&&this._$AE(i)}willUpdate(t){}_$AE(t){var e;null===(e=this._$ES)||void 0===e||e.forEach(t=>{var e;return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)}),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return!0}update(t){void 0!==this._$EC&&(this._$EC.forEach((t,e)=>this._$EO(e,this[e],t)),this._$EC=void 0),this._$Ek()}updated(t){}firstUpdated(t){}}; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -var yp;bp[_p]=!0,bp.elementProperties=new Map,bp.elementStyles=[],bp.shadowRootOptions={mode:"open"},null==mp||mp({ReactiveElement:bp}),(null!==(cp=hp.reactiveElementVersions)&&void 0!==cp?cp:hp.reactiveElementVersions=[]).push("1.6.3");const xp=window,$p=xp.trustedTypes,wp=$p?$p.createPolicy("lit-html",{createHTML:t=>t}):void 0,Ap="$lit$",Ep=`lit$${(Math.random()+"").slice(9)}$`,Sp="?"+Ep,Cp=`<${Sp}>`,Tp=document,Ip=()=>Tp.createComment(""),Op=t=>null===t||"object"!=typeof t&&"function"!=typeof t,kp=Array.isArray,Rp="[ \t\n\f\r]",Pp=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Lp=/-->/g,Mp=/>/g,Np=RegExp(`>|${Rp}(?:([^\\s"'>=/]+)(${Rp}*=${Rp}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),Dp=/'/g,Hp=/"/g,Up=/^(?:script|style|textarea|title)$/i,zp=(t=>(e,...i)=>({_$litType$:t,strings:e,values:i}))(1),Fp=Symbol.for("lit-noChange"),Bp=Symbol.for("lit-nothing"),Vp=new WeakMap,jp=Tp.createTreeWalker(Tp,129,null,!1);function Wp(t,e){if(!Array.isArray(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==wp?wp.createHTML(e):e}let qp=class t{constructor({strings:e,_$litType$:i},s){let n;this.parts=[];let r=0,o=0;const a=e.length-1,l=this.parts,[d,c]=((t,e)=>{const i=t.length-1,s=[];let n,r=2===e?"":"",o=Pp;for(let e=0;e"===l[0]?(o=null!=n?n:Pp,d=-1):void 0===l[1]?d=-2:(d=o.lastIndex-l[2].length,a=l[1],o=void 0===l[3]?Np:'"'===l[3]?Hp:Dp):o===Hp||o===Dp?o=Np:o===Lp||o===Mp?o=Pp:(o=Np,n=void 0);const h=o===Np&&t[e+1].startsWith("/>")?" ":"";r+=o===Pp?i+Cp:d>=0?(s.push(a),i.slice(0,d)+Ap+i.slice(d)+Ep+h):i+Ep+(-2===d?(s.push(void 0),e):h)}return[Wp(t,r+(t[i]||"")+(2===e?"":"")),s]})(e,i);if(this.el=t.createElement(d,s),jp.currentNode=this.el.content,2===i){const t=this.el.content,e=t.firstChild;e.remove(),t.append(...e.childNodes)}for(;null!==(n=jp.nextNode())&&l.length0){n.textContent=$p?$p.emptyScript:"";for(let i=0;ikp(t)||"function"==typeof(null==t?void 0: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!==Bp&&Op(this._$AH)?this._$AA.nextSibling.data=t:this.$(Tp.createTextNode(t)),this._$AH=t}g(t){var e;const{values:i,_$litType$:s}=t,n="number"==typeof s?this._$AC(t):(void 0===s.el&&(s.el=qp.createElement(Wp(s.h,s.h[0]),this.options)),s);if((null===(e=this._$AH)||void 0===e?void 0:e._$AD)===n)this._$AH.v(i);else{const t=new Xp(n,this),e=t.u(this.options);t.v(i),this.$(e),this._$AH=t}}_$AC(t){let e=Vp.get(t.strings);return void 0===e&&Vp.set(t.strings,e=new qp(t)),e}T(e){kp(this._$AH)||(this._$AH=[],this._$AR());const i=this._$AH;let s,n=0;for(const r of e)n===i.length?i.push(s=new t(this.k(Ip()),this.k(Ip()),this,this.options)):s=i[n],s._$AI(r),n++;n2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=Bp}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(t,e=this,i,s){const n=this.strings;let r=!1;if(void 0===n)t=Yp(this,t,e,0),r=!Op(t)||t!==this._$AH&&t!==Fp,r&&(this._$AH=t);else{const s=t;let o,a;for(t=n[0],o=0;o{var s,n;const r=null!==(s=null==i?void 0:i.renderBefore)&&void 0!==s?s:e;let o=r._$litPart$;if(void 0===o){const t=null!==(n=null==i?void 0:i.renderBefore)&&void 0!==n?n:null;r._$litPart$=o=new Gp(e.insertBefore(Ip(),t),t,void 0,null!=i?i:{})}return o._$AI(t),o})(e,this.renderRoot,this.renderOptions)}connectedCallback(){var t;super.connectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!0)}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!1)}render(){return Fp}};ru.finalized=!0,ru._$litElement$=!0,null===(su=globalThis.litElementHydrateSupport)||void 0===su||su.call(globalThis,{LitElement:ru});const ou=globalThis.litElementPolyfillSupport;null==ou||ou({LitElement:ru}),(null!==(nu=globalThis.litElementVersions)&&void 0!==nu?nu:globalThis.litElementVersions=[]).push("3.3.3"); -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const au=(t,e)=>"method"===e.kind&&e.descriptor&&!("value"in e.descriptor)?{...e,finisher(i){i.createProperty(e.key,t)}}:{kind:"field",key:Symbol(),placement:"own",descriptor:{},originalKey:e.key,initializer(){"function"==typeof e.initializer&&(this[e.key]=e.initializer.call(this))},finisher(i){i.createProperty(e.key,t)}};function lu(t){return(e,i)=>void 0!==i?((t,e,i)=>{e.constructor.createProperty(i,t)})(t,e,i):au(t,e)} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */function du(t){return lu({...t,state:!0})} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -var cu;null===(cu=window.HTMLSlotElement)||void 0===cu||cu.prototype.assignedElements; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const hu=1,pu=t=>(...e)=>({_$litDirective$:t,values:e});let uu=class{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 2018 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */const mu=pu(class extends uu{constructor(t){var e;if(super(t),t.type!==hu||"class"!==t.name||(null===(e=t.strings)||void 0===e?void 0:e.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]){var i,s;if(void 0===this.it){this.it=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]&&!(null===(i=this.nt)||void 0===i?void 0:i.has(t))&&this.it.add(t);return this.render(e)}const n=t.element.classList;this.it.forEach(t=>{t in e||(n.remove(t),this.it.delete(t))});for(const t in e){const i=!!e[t];i===this.it.has(t)||(null===(s=this.nt)||void 0===s?void 0:s.has(t))||(i?(n.add(t),this.it.add(t)):(n.remove(t),this.it.delete(t)))}return Fp}}),fu="important",gu=" !"+fu,vu=pu(class extends uu{constructor(t){var e;if(super(t),t.type!==hu||"style"!==t.name||(null===(e=t.strings)||void 0===e?void 0:e.length)>2)throw Error("The `styleMap` directive must be used in the `style` attribute and must be the only part in the attribute.")}render(t){return Object.keys(t).reduce((e,i)=>{const s=t[i];return null==s?e:e+`${i=i.includes("-")?i:i.replace(/(?:^(webkit|moz|ms|o)|)(?=[A-Z])/g,"-$&").toLowerCase()}:${s};`},"")}update(t,[e]){const{style:i}=t.element;if(void 0===this.ht){this.ht=new Set;for(const t in e)this.ht.add(t);return this.render(e)}this.ht.forEach(t=>{null==e[t]&&(this.ht.delete(t),t.includes("-")?i.removeProperty(t):i[t]="")});for(const t in e){const s=e[t];if(null!=s){this.ht.add(t);const e="string"==typeof s&&s.endsWith(gu);t.includes("-")||e?i.setProperty(t,e?s.slice(0,-11):s,e?fu:""):i[t]=s}}return Fp}}); -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -class _u extends Qi{constructor(){super(...arguments),this.primary=!1,this.accent=!1,this.unbounded=!1,this.disabled=!1,this.activated=!1,this.selected=!1,this.internalUseStateLayerCustomProperties=!1,this.hovering=!1,this.bgFocused=!1,this.fgActivation=!1,this.fgDeactivation=!1,this.fgScale="",this.fgSize="",this.translateStart="",this.translateEnd="",this.leftPos="",this.topPos="",this.mdcFoundationClass=sp}get isActive(){return t=this.parentElement||this,e=":active",(t.matches||t.webkitMatchesSelector||t.msMatchesSelector).call(t,e); -/** - * @license - * Copyright 2018 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -var t,e}createAdapter(){return{browserSupportsCssVars:()=>!0,isUnbounded:()=>this.unbounded,isSurfaceActive:()=>this.isActive,isSurfaceDisabled:()=>this.disabled,addClass:t=>{switch(t){case"mdc-ripple-upgraded--background-focused":this.bgFocused=!0;break;case"mdc-ripple-upgraded--foreground-activation":this.fgActivation=!0;break;case"mdc-ripple-upgraded--foreground-deactivation":this.fgDeactivation=!0}},removeClass:t=>{switch(t){case"mdc-ripple-upgraded--background-focused":this.bgFocused=!1;break;case"mdc-ripple-upgraded--foreground-activation":this.fgActivation=!1;break;case"mdc-ripple-upgraded--foreground-deactivation":this.fgDeactivation=!1}},containsEventTarget:()=>!0,registerInteractionHandler:()=>{},deregisterInteractionHandler:()=>{},registerDocumentInteractionHandler:()=>{},deregisterDocumentInteractionHandler:()=>{},registerResizeHandler:()=>{},deregisterResizeHandler:()=>{},updateCssVariable:(t,e)=>{switch(t){case"--mdc-ripple-fg-scale":this.fgScale=e;break;case"--mdc-ripple-fg-size":this.fgSize=e;break;case"--mdc-ripple-fg-translate-end":this.translateEnd=e;break;case"--mdc-ripple-fg-translate-start":this.translateStart=e;break;case"--mdc-ripple-left":this.leftPos=e;break;case"--mdc-ripple-top":this.topPos=e}},computeBoundingRect:()=>(this.parentElement||this).getBoundingClientRect(),getWindowPageOffset:()=>({x:window.pageXOffset,y:window.pageYOffset})}}startPress(t){this.waitForFoundation(()=>{this.mdcFoundation.activate(t)})}endPress(){this.waitForFoundation(()=>{this.mdcFoundation.deactivate()})}startFocus(){this.waitForFoundation(()=>{this.mdcFoundation.handleFocus()})}endFocus(){this.waitForFoundation(()=>{this.mdcFoundation.handleBlur()})}startHover(){this.hovering=!0}endHover(){this.hovering=!1}waitForFoundation(t){this.mdcFoundation?t():this.updateComplete.then(t)}update(t){t.has("disabled")&&this.disabled&&this.endHover(),super.update(t)}render(){const t=this.activated&&(this.primary||!this.accent),e=this.selected&&(this.primary||!this.accent),i={"mdc-ripple-surface--accent":this.accent,"mdc-ripple-surface--primary--activated":t,"mdc-ripple-surface--accent--activated":this.accent&&this.activated,"mdc-ripple-surface--primary--selected":e,"mdc-ripple-surface--accent--selected":this.accent&&this.selected,"mdc-ripple-surface--disabled":this.disabled,"mdc-ripple-surface--hover":this.hovering,"mdc-ripple-surface--primary":this.primary,"mdc-ripple-surface--selected":this.selected,"mdc-ripple-upgraded--background-focused":this.bgFocused,"mdc-ripple-upgraded--foreground-activation":this.fgActivation,"mdc-ripple-upgraded--foreground-deactivation":this.fgDeactivation,"mdc-ripple-upgraded--unbounded":this.unbounded,"mdc-ripple-surface--internal-use-state-layer-custom-properties":this.internalUseStateLayerCustomProperties};return zp` -
`}}n([ -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -function(t){return(({finisher:t,descriptor:e})=>(i,s)=>{var n;if(void 0===s){const s=null!==(n=i.originalKey)&&void 0!==n?n:i.key,r=null!=e?{kind:"method",placement:"prototype",key:s,descriptor:e(i.key)}:{...i,key:s};return null!=t&&(r.finisher=function(e){t(e,s)}),r}{const n=i.constructor;void 0!==e&&Object.defineProperty(i,s,e(s)),null==t||t(n,s)}})({descriptor:e=>{const i={get(){var e,i;return null!==(i=null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(t))&&void 0!==i?i:null},enumerable:!0,configurable:!0};return i}})}(".mdc-ripple-surface")],_u.prototype,"mdcRoot",void 0),n([lu({type:Boolean})],_u.prototype,"primary",void 0),n([lu({type:Boolean})],_u.prototype,"accent",void 0),n([lu({type:Boolean})],_u.prototype,"unbounded",void 0),n([lu({type:Boolean})],_u.prototype,"disabled",void 0),n([lu({type:Boolean})],_u.prototype,"activated",void 0),n([lu({type:Boolean})],_u.prototype,"selected",void 0),n([lu({type:Boolean})],_u.prototype,"internalUseStateLayerCustomProperties",void 0),n([du()],_u.prototype,"hovering",void 0),n([du()],_u.prototype,"bgFocused",void 0),n([du()],_u.prototype,"fgActivation",void 0),n([du()],_u.prototype,"fgDeactivation",void 0),n([du()],_u.prototype,"fgScale",void 0),n([du()],_u.prototype,"fgSize",void 0),n([du()],_u.prototype,"translateStart",void 0),n([du()],_u.prototype,"translateEnd",void 0),n([du()],_u.prototype,"leftPos",void 0),n([du()],_u.prototype,"topPos",void 0); -/** - * @license - * Copyright 2016 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -var bu=function(){function t(t){void 0===t&&(t={}),this.adapter=t}return Object.defineProperty(t,"cssClasses",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"strings",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"numbers",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"defaultAdapter",{get:function(){return{}},enumerable:!1,configurable:!0}),t.prototype.init=function(){},t.prototype.destroy=function(){},t}(),yu={NOTCH_ELEMENT_SELECTOR:".mdc-notched-outline__notch"},xu={NOTCH_ELEMENT_PADDING:8},$u={NO_LABEL:"mdc-notched-outline--no-label",OUTLINE_NOTCHED:"mdc-notched-outline--notched",OUTLINE_UPGRADED:"mdc-notched-outline--upgraded"},wu=function(t){function e(i){return t.call(this,s(s({},e.defaultAdapter),i))||this}return i(e,t),Object.defineProperty(e,"strings",{get:function(){return yu},enumerable:!1,configurable:!0}),Object.defineProperty(e,"cssClasses",{get:function(){return $u},enumerable:!1,configurable:!0}),Object.defineProperty(e,"numbers",{get:function(){return xu},enumerable:!1,configurable:!0}),Object.defineProperty(e,"defaultAdapter",{get:function(){return{addClass:function(){},removeClass:function(){},setNotchWidthProperty:function(){},removeNotchWidthProperty:function(){}}},enumerable:!1,configurable:!0}),e.prototype.notch=function(t){var i=e.cssClasses.OUTLINE_NOTCHED;t>0&&(t+=xu.NOTCH_ELEMENT_PADDING),this.adapter.setNotchWidthProperty(t),this.adapter.addClass(i)},e.prototype.closeNotch=function(){var t=e.cssClasses.OUTLINE_NOTCHED;this.adapter.removeClass(t),this.adapter.removeNotchWidthProperty()},e}(bu); -/** - * @license - * Copyright 2018 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const Au=window,Eu=Au.ShadowRoot&&(void 0===Au.ShadyCSS||Au.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,Su=Symbol(),Cu=new WeakMap;let Tu=class{constructor(t,e,i){if(this._$cssResult$=!0,i!==Su)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(Eu&&void 0===t){const i=void 0!==e&&1===e.length;i&&(t=Cu.get(e)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&Cu.set(e,t))}return t}toString(){return this.cssText}};const Iu=Eu?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new Tu("string"==typeof t?t:t+"",void 0,Su))(e)})(t):t; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */var Ou;const ku=window,Ru=ku.trustedTypes,Pu=Ru?Ru.emptyScript:"",Lu=ku.reactiveElementPolyfillSupport,Mu={toAttribute(t,e){switch(e){case Boolean:t=t?Pu: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}},Nu=(t,e)=>e!==t&&(e==e||t==t),Du={attribute:!0,type:String,converter:Mu,reflect:!1,hasChanged:Nu},Hu="finalized";let Uu=class extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(t){var e;this.finalize(),(null!==(e=this.h)&&void 0!==e?e:this.h=[]).push(t)}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach((e,i)=>{const s=this._$Ep(i,e);void 0!==s&&(this._$Ev.set(s,i),t.push(s))}),t}static createProperty(t,e=Du){if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){const i="symbol"==typeof t?Symbol():"__"+t,s=this.getPropertyDescriptor(t,i,e);void 0!==s&&Object.defineProperty(this.prototype,t,s)}}static getPropertyDescriptor(t,e,i){return{get(){return this[e]},set(s){const n=this[t];this[e]=s,this.requestUpdate(t,n,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||Du}static finalize(){if(this.hasOwnProperty(Hu))return!1;this[Hu]=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),void 0!==t.h&&(this.h=[...t.h]),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,e=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const i of e)this.createProperty(i,t[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}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(Iu(t))}else void 0!==t&&e.push(Iu(t));return e}static _$Ep(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}_$Eu(){var t;this._$E_=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach(t=>t(this))}addController(t){var e,i;(null!==(e=this._$ES)&&void 0!==e?e:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(i=t.hostConnected)||void 0===i||i.call(t))}removeController(t){var e;null===(e=this._$ES)||void 0===e||e.splice(this._$ES.indexOf(t)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach((t,e)=>{this.hasOwnProperty(e)&&(this._$Ei.set(e,this[e]),delete this[e])})}createRenderRoot(){var t;const e=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return((t,e)=>{Eu?t.adoptedStyleSheets=e.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet):e.forEach(e=>{const i=document.createElement("style"),s=Au.litNonce;void 0!==s&&i.setAttribute("nonce",s),i.textContent=e.cssText,t.appendChild(i)})})(e,this.constructor.elementStyles),e}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)})}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)})}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$EO(t,e,i=Du){var s;const n=this.constructor._$Ep(t,i);if(void 0!==n&&!0===i.reflect){const r=(void 0!==(null===(s=i.converter)||void 0===s?void 0:s.toAttribute)?i.converter:Mu).toAttribute(e,i.type);this._$El=t,null==r?this.removeAttribute(n):this.setAttribute(n,r),this._$El=null}}_$AK(t,e){var i;const s=this.constructor,n=s._$Ev.get(t);if(void 0!==n&&this._$El!==n){const t=s.getPropertyOptions(n),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(i=t.converter)||void 0===i?void 0:i.fromAttribute)?t.converter:Mu;this._$El=n,this[n]=r.fromAttribute(e,t.type),this._$El=null}}requestUpdate(t,e,i){let s=!0;void 0!==t&&(((i=i||this.constructor.getPropertyOptions(t)).hasChanged||Nu)(this[t],e)?(this._$AL.has(t)||this._$AL.set(t,e),!0===i.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,i))):s=!1),!this.isUpdatePending&&s&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach((t,e)=>this[e]=t),this._$Ei=void 0);let e=!1;const i=this._$AL;try{e=this.shouldUpdate(i),e?(this.willUpdate(i),null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)}),this.update(i)):this._$Ek()}catch(t){throw e=!1,this._$Ek(),t}e&&this._$AE(i)}willUpdate(t){}_$AE(t){var e;null===(e=this._$ES)||void 0===e||e.forEach(t=>{var e;return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)}),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return!0}update(t){void 0!==this._$EC&&(this._$EC.forEach((t,e)=>this._$EO(e,this[e],t)),this._$EC=void 0),this._$Ek()}updated(t){}firstUpdated(t){}}; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -var zu;Uu[Hu]=!0,Uu.elementProperties=new Map,Uu.elementStyles=[],Uu.shadowRootOptions={mode:"open"},null==Lu||Lu({ReactiveElement:Uu}),(null!==(Ou=ku.reactiveElementVersions)&&void 0!==Ou?Ou:ku.reactiveElementVersions=[]).push("1.6.3");const Fu=window,Bu=Fu.trustedTypes,Vu=Bu?Bu.createPolicy("lit-html",{createHTML:t=>t}):void 0,ju="$lit$",Wu=`lit$${(Math.random()+"").slice(9)}$`,qu="?"+Wu,Yu=`<${qu}>`,Xu=document,Gu=()=>Xu.createComment(""),Ku=t=>null===t||"object"!=typeof t&&"function"!=typeof t,Ju=Array.isArray,Zu="[ \t\n\f\r]",Qu=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,tm=/-->/g,em=/>/g,im=RegExp(`>|${Zu}(?:([^\\s"'>=/]+)(${Zu}*=${Zu}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),sm=/'/g,nm=/"/g,rm=/^(?:script|style|textarea|title)$/i,om=(t=>(e,...i)=>({_$litType$:t,strings:e,values:i}))(1),am=Symbol.for("lit-noChange"),lm=Symbol.for("lit-nothing"),dm=new WeakMap,cm=Xu.createTreeWalker(Xu,129,null,!1);function hm(t,e){if(!Array.isArray(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==Vu?Vu.createHTML(e):e}let pm=class t{constructor({strings:e,_$litType$:i},s){let n;this.parts=[];let r=0,o=0;const a=e.length-1,l=this.parts,[d,c]=((t,e)=>{const i=t.length-1,s=[];let n,r=2===e?"":"",o=Qu;for(let e=0;e"===l[0]?(o=null!=n?n:Qu,d=-1):void 0===l[1]?d=-2:(d=o.lastIndex-l[2].length,a=l[1],o=void 0===l[3]?im:'"'===l[3]?nm:sm):o===nm||o===sm?o=im:o===tm||o===em?o=Qu:(o=im,n=void 0);const h=o===im&&t[e+1].startsWith("/>")?" ":"";r+=o===Qu?i+Yu:d>=0?(s.push(a),i.slice(0,d)+ju+i.slice(d)+Wu+h):i+Wu+(-2===d?(s.push(void 0),e):h)}return[hm(t,r+(t[i]||"")+(2===e?"":"")),s]})(e,i);if(this.el=t.createElement(d,s),cm.currentNode=this.el.content,2===i){const t=this.el.content,e=t.firstChild;e.remove(),t.append(...e.childNodes)}for(;null!==(n=cm.nextNode())&&l.length0){n.textContent=Bu?Bu.emptyScript:"";for(let i=0;iJu(t)||"function"==typeof(null==t?void 0: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!==lm&&Ku(this._$AH)?this._$AA.nextSibling.data=t:this.$(Xu.createTextNode(t)),this._$AH=t}g(t){var e;const{values:i,_$litType$:s}=t,n="number"==typeof s?this._$AC(t):(void 0===s.el&&(s.el=pm.createElement(hm(s.h,s.h[0]),this.options)),s);if((null===(e=this._$AH)||void 0===e?void 0:e._$AD)===n)this._$AH.v(i);else{const t=new mm(n,this),e=t.u(this.options);t.v(i),this.$(e),this._$AH=t}}_$AC(t){let e=dm.get(t.strings);return void 0===e&&dm.set(t.strings,e=new pm(t)),e}T(e){Ju(this._$AH)||(this._$AH=[],this._$AR());const i=this._$AH;let s,n=0;for(const r of e)n===i.length?i.push(s=new t(this.k(Gu()),this.k(Gu()),this,this.options)):s=i[n],s._$AI(r),n++;n2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=lm}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(t,e=this,i,s){const n=this.strings;let r=!1;if(void 0===n)t=um(this,t,e,0),r=!Ku(t)||t!==this._$AH&&t!==am,r&&(this._$AH=t);else{const s=t;let o,a;for(t=n[0],o=0;o{var s,n;const r=null!==(s=null==i?void 0:i.renderBefore)&&void 0!==s?s:e;let o=r._$litPart$;if(void 0===o){const t=null!==(n=null==i?void 0:i.renderBefore)&&void 0!==n?n:null;r._$litPart$=o=new fm(e.insertBefore(Gu(),t),t,void 0,null!=i?i:{})}return o._$AI(t),o})(e,this.renderRoot,this.renderOptions)}connectedCallback(){var t;super.connectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!0)}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!1)}render(){return am}};Em.finalized=!0,Em._$litElement$=!0,null===(wm=globalThis.litElementHydrateSupport)||void 0===wm||wm.call(globalThis,{LitElement:Em});const Sm=globalThis.litElementPolyfillSupport;null==Sm||Sm({LitElement:Em}),(null!==(Am=globalThis.litElementVersions)&&void 0!==Am?Am:globalThis.litElementVersions=[]).push("3.3.3"); -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const Cm=(t,e)=>"method"===e.kind&&e.descriptor&&!("value"in e.descriptor)?{...e,finisher(i){i.createProperty(e.key,t)}}:{kind:"field",key:Symbol(),placement:"own",descriptor:{},originalKey:e.key,initializer(){"function"==typeof e.initializer&&(this[e.key]=e.initializer.call(this))},finisher(i){i.createProperty(e.key,t)}};function Tm(t){return(e,i)=>void 0!==i?((t,e,i)=>{e.constructor.createProperty(i,t)})(t,e,i):Cm(t,e)} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -function Im(t,e){return(({finisher:t,descriptor:e})=>(i,s)=>{var n;if(void 0===s){const s=null!==(n=i.originalKey)&&void 0!==n?n:i.key,r=null!=e?{kind:"method",placement:"prototype",key:s,descriptor:e(i.key)}:{...i,key:s};return null!=t&&(r.finisher=function(e){t(e,s)}),r}{const n=i.constructor;void 0!==e&&Object.defineProperty(i,s,e(s)),null==t||t(n,s)}})({descriptor:e=>{const i={get(){var e,i;return null!==(i=null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(t))&&void 0!==i?i:null},enumerable:!0,configurable:!0};return i}})} -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */var Om;null===(Om=window.HTMLSlotElement)||void 0===Om||Om.prototype.assignedElements; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const km=1;let Rm=class{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 2018 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */const Pm=(t=>(...e)=>({_$litDirective$:t,values:e}))(class extends Rm{constructor(t){var e;if(super(t),t.type!==km||"class"!==t.name||(null===(e=t.strings)||void 0===e?void 0:e.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]){var i,s;if(void 0===this.it){this.it=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]&&!(null===(i=this.nt)||void 0===i?void 0:i.has(t))&&this.it.add(t);return this.render(e)}const n=t.element.classList;this.it.forEach(t=>{t in e||(n.remove(t),this.it.delete(t))});for(const t in e){const i=!!e[t];i===this.it.has(t)||(null===(s=this.nt)||void 0===s?void 0:s.has(t))||(i?(n.add(t),this.it.add(t)):(n.remove(t),this.it.delete(t)))}return am}}); -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */class Lm extends Qi{constructor(){super(...arguments),this.mdcFoundationClass=wu,this.width=0,this.open=!1,this.lastOpen=this.open}createAdapter(){return{addClass:t=>this.mdcRoot.classList.add(t),removeClass:t=>this.mdcRoot.classList.remove(t),setNotchWidthProperty:t=>this.notchElement.style.setProperty("width",`${t}px`),removeNotchWidthProperty:()=>this.notchElement.style.removeProperty("width")}}openOrClose(t,e){this.mdcFoundation&&(t&&void 0!==e?this.mdcFoundation.notch(e):this.mdcFoundation.closeNotch())}render(){this.openOrClose(this.open,this.width);const t=Pm({"mdc-notched-outline--notched":this.open});return om` - - - - - - - `}}n([Im(".mdc-notched-outline")],Lm.prototype,"mdcRoot",void 0),n([Tm({type:Number})],Lm.prototype,"width",void 0),n([Tm({type:Boolean,reflect:!0})],Lm.prototype,"open",void 0),n([Im(".mdc-notched-outline__notch")],Lm.prototype,"notchElement",void 0); -/** - * @license - * Copyright 2021 Google LLC - * SPDX-LIcense-Identifier: Apache-2.0 - */ -const Mm=((t,...e)=>{const i=1===t.length?t[0]:e.reduce((e,i,s)=>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[s+1],t[0]);return new oa(i,t,na)})`.mdc-floating-label{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-subtitle1-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:1rem;font-size:var(--mdc-typography-subtitle1-font-size, 1rem);font-weight:400;font-weight:var(--mdc-typography-subtitle1-font-weight, 400);letter-spacing:0.009375em;letter-spacing:var(--mdc-typography-subtitle1-letter-spacing, 0.009375em);text-decoration:inherit;text-decoration:var(--mdc-typography-subtitle1-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-subtitle1-text-transform, inherit);position:absolute;left:0;-webkit-transform-origin:left top;transform-origin:left top;line-height:1.15rem;text-align:left;text-overflow:ellipsis;white-space:nowrap;cursor:text;overflow:hidden;will-change:transform;transition:transform 150ms cubic-bezier(0.4, 0, 0.2, 1),color 150ms cubic-bezier(0.4, 0, 0.2, 1)}[dir=rtl] .mdc-floating-label,.mdc-floating-label[dir=rtl]{right:0;left:auto;-webkit-transform-origin:right top;transform-origin:right top;text-align:right}.mdc-floating-label--float-above{cursor:auto}.mdc-floating-label--required::after{margin-left:1px;margin-right:0px;content:"*"}[dir=rtl] .mdc-floating-label--required::after,.mdc-floating-label--required[dir=rtl]::after{margin-left:0;margin-right:1px}.mdc-floating-label--float-above{transform:translateY(-106%) scale(0.75)}.mdc-floating-label--shake{animation:mdc-floating-label-shake-float-above-standard 250ms 1}@keyframes mdc-floating-label-shake-float-above-standard{0%{transform:translateX(calc(0 - 0%)) translateY(-106%) scale(0.75)}33%{animation-timing-function:cubic-bezier(0.5, 0, 0.701732, 0.495819);transform:translateX(calc(4% - 0%)) translateY(-106%) scale(0.75)}66%{animation-timing-function:cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);transform:translateX(calc(-4% - 0%)) translateY(-106%) scale(0.75)}100%{transform:translateX(calc(0 - 0%)) translateY(-106%) scale(0.75)}}@keyframes mdc-ripple-fg-radius-in{from{animation-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transform:translate(var(--mdc-ripple-fg-translate-start, 0)) scale(1)}to{transform:translate(var(--mdc-ripple-fg-translate-end, 0)) scale(var(--mdc-ripple-fg-scale, 1))}}@keyframes mdc-ripple-fg-opacity-in{from{animation-timing-function:linear;opacity:0}to{opacity:var(--mdc-ripple-fg-opacity, 0)}}@keyframes mdc-ripple-fg-opacity-out{from{animation-timing-function:linear;opacity:var(--mdc-ripple-fg-opacity, 0)}to{opacity:0}}.mdc-line-ripple::before,.mdc-line-ripple::after{position:absolute;bottom:0;left:0;width:100%;border-bottom-style:solid;content:""}.mdc-line-ripple::before{border-bottom-width:1px}.mdc-line-ripple::before{z-index:1}.mdc-line-ripple::after{transform:scaleX(0);border-bottom-width:2px;opacity:0;z-index:2}.mdc-line-ripple::after{transition:transform 180ms cubic-bezier(0.4, 0, 0.2, 1),opacity 180ms cubic-bezier(0.4, 0, 0.2, 1)}.mdc-line-ripple--active::after{transform:scaleX(1);opacity:1}.mdc-line-ripple--deactivating::after{opacity:0}.mdc-notched-outline{display:flex;position:absolute;top:0;right:0;left:0;box-sizing:border-box;width:100%;max-width:100%;height:100%;text-align:left;pointer-events:none}[dir=rtl] .mdc-notched-outline,.mdc-notched-outline[dir=rtl]{text-align:right}.mdc-notched-outline__leading,.mdc-notched-outline__notch,.mdc-notched-outline__trailing{box-sizing:border-box;height:100%;border-top:1px solid;border-bottom:1px solid;pointer-events:none}.mdc-notched-outline__leading{border-left:1px solid;border-right:none;width:12px}[dir=rtl] .mdc-notched-outline__leading,.mdc-notched-outline__leading[dir=rtl]{border-left:none;border-right:1px solid}.mdc-notched-outline__trailing{border-left:none;border-right:1px solid;flex-grow:1}[dir=rtl] .mdc-notched-outline__trailing,.mdc-notched-outline__trailing[dir=rtl]{border-left:1px solid;border-right:none}.mdc-notched-outline__notch{flex:0 0 auto;width:auto;max-width:calc(100% - 12px * 2)}.mdc-notched-outline .mdc-floating-label{display:inline-block;position:relative;max-width:100%}.mdc-notched-outline .mdc-floating-label--float-above{text-overflow:clip}.mdc-notched-outline--upgraded .mdc-floating-label--float-above{max-width:calc(100% / 0.75)}.mdc-notched-outline--notched .mdc-notched-outline__notch{padding-left:0;padding-right:8px;border-top:none}[dir=rtl] .mdc-notched-outline--notched .mdc-notched-outline__notch,.mdc-notched-outline--notched .mdc-notched-outline__notch[dir=rtl]{padding-left:8px;padding-right:0}.mdc-notched-outline--no-label .mdc-notched-outline__notch{display:none}.mdc-select{display:inline-flex;position:relative}.mdc-select:not(.mdc-select--disabled) .mdc-select__selected-text{color:rgba(0, 0, 0, 0.87)}.mdc-select.mdc-select--disabled .mdc-select__selected-text{color:rgba(0, 0, 0, 0.38)}.mdc-select:not(.mdc-select--disabled) .mdc-floating-label{color:rgba(0, 0, 0, 0.6)}.mdc-select:not(.mdc-select--disabled).mdc-select--focused .mdc-floating-label{color:rgba(98, 0, 238, 0.87)}.mdc-select.mdc-select--disabled .mdc-floating-label{color:rgba(0, 0, 0, 0.38)}.mdc-select:not(.mdc-select--disabled) .mdc-select__dropdown-icon{fill:rgba(0, 0, 0, 0.54)}.mdc-select:not(.mdc-select--disabled).mdc-select--focused .mdc-select__dropdown-icon{fill:#6200ee;fill:var(--mdc-theme-primary, #6200ee)}.mdc-select.mdc-select--disabled .mdc-select__dropdown-icon{fill:rgba(0, 0, 0, 0.38)}.mdc-select:not(.mdc-select--disabled)+.mdc-select-helper-text{color:rgba(0, 0, 0, 0.6)}.mdc-select.mdc-select--disabled+.mdc-select-helper-text{color:rgba(0, 0, 0, 0.38)}.mdc-select:not(.mdc-select--disabled) .mdc-select__icon{color:rgba(0, 0, 0, 0.54)}.mdc-select.mdc-select--disabled .mdc-select__icon{color:rgba(0, 0, 0, 0.38)}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-select.mdc-select--disabled .mdc-select__selected-text{color:GrayText}.mdc-select.mdc-select--disabled .mdc-select__dropdown-icon{fill:red}.mdc-select.mdc-select--disabled .mdc-floating-label{color:GrayText}.mdc-select.mdc-select--disabled .mdc-line-ripple::before{border-bottom-color:GrayText}.mdc-select.mdc-select--disabled .mdc-notched-outline__leading,.mdc-select.mdc-select--disabled .mdc-notched-outline__notch,.mdc-select.mdc-select--disabled .mdc-notched-outline__trailing{border-color:GrayText}.mdc-select.mdc-select--disabled .mdc-select__icon{color:GrayText}.mdc-select.mdc-select--disabled+.mdc-select-helper-text{color:GrayText}}.mdc-select .mdc-floating-label{top:50%;transform:translateY(-50%);pointer-events:none}.mdc-select .mdc-select__anchor{padding-left:16px;padding-right:0}[dir=rtl] .mdc-select .mdc-select__anchor,.mdc-select .mdc-select__anchor[dir=rtl]{padding-left:0;padding-right:16px}.mdc-select.mdc-select--with-leading-icon .mdc-select__anchor{padding-left:0;padding-right:0}[dir=rtl] .mdc-select.mdc-select--with-leading-icon .mdc-select__anchor,.mdc-select.mdc-select--with-leading-icon .mdc-select__anchor[dir=rtl]{padding-left:0;padding-right:0}.mdc-select .mdc-select__icon{width:24px;height:24px;font-size:24px}.mdc-select .mdc-select__dropdown-icon{width:24px;height:24px}.mdc-select .mdc-select__menu .mdc-deprecated-list-item{padding-left:16px;padding-right:16px}[dir=rtl] .mdc-select .mdc-select__menu .mdc-deprecated-list-item,.mdc-select .mdc-select__menu .mdc-deprecated-list-item[dir=rtl]{padding-left:16px;padding-right:16px}.mdc-select .mdc-select__menu .mdc-deprecated-list-item__graphic{margin-left:0;margin-right:12px}[dir=rtl] .mdc-select .mdc-select__menu .mdc-deprecated-list-item__graphic,.mdc-select .mdc-select__menu .mdc-deprecated-list-item__graphic[dir=rtl]{margin-left:12px;margin-right:0}.mdc-select__dropdown-icon{margin-left:12px;margin-right:12px;display:inline-flex;position:relative;align-self:center;align-items:center;justify-content:center;flex-shrink:0;pointer-events:none}.mdc-select__dropdown-icon .mdc-select__dropdown-icon-active,.mdc-select__dropdown-icon .mdc-select__dropdown-icon-inactive{position:absolute;top:0;left:0}.mdc-select__dropdown-icon .mdc-select__dropdown-icon-graphic{width:41.6666666667%;height:20.8333333333%}.mdc-select__dropdown-icon .mdc-select__dropdown-icon-inactive{opacity:1;transition:opacity 75ms linear 75ms}.mdc-select__dropdown-icon .mdc-select__dropdown-icon-active{opacity:0;transition:opacity 75ms linear}[dir=rtl] .mdc-select__dropdown-icon,.mdc-select__dropdown-icon[dir=rtl]{margin-left:12px;margin-right:12px}.mdc-select--activated .mdc-select__dropdown-icon .mdc-select__dropdown-icon-inactive{opacity:0;transition:opacity 49.5ms linear}.mdc-select--activated .mdc-select__dropdown-icon .mdc-select__dropdown-icon-active{opacity:1;transition:opacity 100.5ms linear 49.5ms}.mdc-select__anchor{width:200px;min-width:0;flex:1 1 auto;position:relative;box-sizing:border-box;overflow:hidden;outline:none;cursor:pointer}.mdc-select__anchor .mdc-floating-label--float-above{transform:translateY(-106%) scale(0.75)}.mdc-select__selected-text-container{display:flex;appearance:none;pointer-events:none;box-sizing:border-box;width:auto;min-width:0;flex-grow:1;height:28px;border:none;outline:none;padding:0;background-color:transparent;color:inherit}.mdc-select__selected-text{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-subtitle1-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:1rem;font-size:var(--mdc-typography-subtitle1-font-size, 1rem);line-height:1.75rem;line-height:var(--mdc-typography-subtitle1-line-height, 1.75rem);font-weight:400;font-weight:var(--mdc-typography-subtitle1-font-weight, 400);letter-spacing:0.009375em;letter-spacing:var(--mdc-typography-subtitle1-letter-spacing, 0.009375em);text-decoration:inherit;text-decoration:var(--mdc-typography-subtitle1-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-subtitle1-text-transform, inherit);text-overflow:ellipsis;white-space:nowrap;overflow:hidden;display:block;width:100%;text-align:left}[dir=rtl] .mdc-select__selected-text,.mdc-select__selected-text[dir=rtl]{text-align:right}.mdc-select--invalid:not(.mdc-select--disabled) .mdc-floating-label{color:#b00020;color:var(--mdc-theme-error, #b00020)}.mdc-select--invalid:not(.mdc-select--disabled).mdc-select--focused .mdc-floating-label{color:#b00020;color:var(--mdc-theme-error, #b00020)}.mdc-select--invalid:not(.mdc-select--disabled).mdc-select--invalid+.mdc-select-helper-text--validation-msg{color:#b00020;color:var(--mdc-theme-error, #b00020)}.mdc-select--invalid:not(.mdc-select--disabled) .mdc-select__dropdown-icon{fill:#b00020;fill:var(--mdc-theme-error, #b00020)}.mdc-select--invalid:not(.mdc-select--disabled).mdc-select--focused .mdc-select__dropdown-icon{fill:#b00020;fill:var(--mdc-theme-error, #b00020)}.mdc-select--disabled{cursor:default;pointer-events:none}.mdc-select--with-leading-icon .mdc-select__menu .mdc-deprecated-list-item{padding-left:12px;padding-right:12px}[dir=rtl] .mdc-select--with-leading-icon .mdc-select__menu .mdc-deprecated-list-item,.mdc-select--with-leading-icon .mdc-select__menu .mdc-deprecated-list-item[dir=rtl]{padding-left:12px;padding-right:12px}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-select__menu::before{position:absolute;box-sizing:border-box;width:100%;height:100%;top:0;left:0;border:1px solid transparent;border-radius:inherit;content:"";pointer-events:none}}@media screen and (forced-colors: active)and (forced-colors: active),screen and (-ms-high-contrast: active)and (forced-colors: active){.mdc-select__menu::before{border-color:CanvasText}}.mdc-select__menu .mdc-deprecated-list .mdc-select__icon,.mdc-select__menu .mdc-list .mdc-select__icon{margin-left:0;margin-right:0}[dir=rtl] .mdc-select__menu .mdc-deprecated-list .mdc-select__icon,[dir=rtl] .mdc-select__menu .mdc-list .mdc-select__icon,.mdc-select__menu .mdc-deprecated-list .mdc-select__icon[dir=rtl],.mdc-select__menu .mdc-list .mdc-select__icon[dir=rtl]{margin-left:0;margin-right:0}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected,.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--activated,.mdc-select__menu .mdc-list .mdc-deprecated-list-item--selected,.mdc-select__menu .mdc-list .mdc-deprecated-list-item--activated{color:#000;color:var(--mdc-theme-on-surface, #000)}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected .mdc-deprecated-list-item__graphic,.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--activated .mdc-deprecated-list-item__graphic,.mdc-select__menu .mdc-list .mdc-deprecated-list-item--selected .mdc-deprecated-list-item__graphic,.mdc-select__menu .mdc-list .mdc-deprecated-list-item--activated .mdc-deprecated-list-item__graphic{color:#000;color:var(--mdc-theme-on-surface, #000)}.mdc-select__menu .mdc-list-item__start{display:inline-flex;align-items:center}.mdc-select__option{padding-left:16px;padding-right:16px}[dir=rtl] .mdc-select__option,.mdc-select__option[dir=rtl]{padding-left:16px;padding-right:16px}.mdc-select__one-line-option.mdc-list-item--with-one-line{height:48px}.mdc-select__two-line-option.mdc-list-item--with-two-lines{height:64px}.mdc-select__two-line-option.mdc-list-item--with-two-lines .mdc-list-item__start{margin-top:20px}.mdc-select__two-line-option.mdc-list-item--with-two-lines .mdc-list-item__primary-text{display:block;margin-top:0;line-height:normal;margin-bottom:-20px}.mdc-select__two-line-option.mdc-list-item--with-two-lines .mdc-list-item__primary-text::before{display:inline-block;width:0;height:28px;content:"";vertical-align:0}.mdc-select__two-line-option.mdc-list-item--with-two-lines .mdc-list-item__primary-text::after{display:inline-block;width:0;height:20px;content:"";vertical-align:-20px}.mdc-select__two-line-option.mdc-list-item--with-two-lines.mdc-list-item--with-trailing-meta .mdc-list-item__end{display:block;margin-top:0;line-height:normal}.mdc-select__two-line-option.mdc-list-item--with-two-lines.mdc-list-item--with-trailing-meta .mdc-list-item__end::before{display:inline-block;width:0;height:36px;content:"";vertical-align:0}.mdc-select__option-with-leading-content{padding-left:0;padding-right:12px}.mdc-select__option-with-leading-content.mdc-list-item{padding-left:0;padding-right:auto}[dir=rtl] .mdc-select__option-with-leading-content.mdc-list-item,.mdc-select__option-with-leading-content.mdc-list-item[dir=rtl]{padding-left:auto;padding-right:0}.mdc-select__option-with-leading-content .mdc-list-item__start{margin-left:12px;margin-right:0}[dir=rtl] .mdc-select__option-with-leading-content .mdc-list-item__start,.mdc-select__option-with-leading-content .mdc-list-item__start[dir=rtl]{margin-left:0;margin-right:12px}.mdc-select__option-with-leading-content .mdc-list-item__start{width:36px;height:24px}[dir=rtl] .mdc-select__option-with-leading-content,.mdc-select__option-with-leading-content[dir=rtl]{padding-left:12px;padding-right:0}.mdc-select__option-with-meta.mdc-list-item{padding-left:auto;padding-right:0}[dir=rtl] .mdc-select__option-with-meta.mdc-list-item,.mdc-select__option-with-meta.mdc-list-item[dir=rtl]{padding-left:0;padding-right:auto}.mdc-select__option-with-meta .mdc-list-item__end{margin-left:12px;margin-right:12px}[dir=rtl] .mdc-select__option-with-meta .mdc-list-item__end,.mdc-select__option-with-meta .mdc-list-item__end[dir=rtl]{margin-left:12px;margin-right:12px}.mdc-select--filled .mdc-select__anchor{height:56px;display:flex;align-items:baseline}.mdc-select--filled .mdc-select__anchor::before{display:inline-block;width:0;height:40px;content:"";vertical-align:0}.mdc-select--filled.mdc-select--no-label .mdc-select__anchor .mdc-select__selected-text::before{content:"​"}.mdc-select--filled.mdc-select--no-label .mdc-select__anchor .mdc-select__selected-text-container{height:100%;display:inline-flex;align-items:center}.mdc-select--filled.mdc-select--no-label .mdc-select__anchor::before{display:none}.mdc-select--filled .mdc-select__anchor{border-top-left-radius:4px;border-top-left-radius:var(--mdc-shape-small, 4px);border-top-right-radius:4px;border-top-right-radius:var(--mdc-shape-small, 4px);border-bottom-right-radius:0;border-bottom-left-radius:0}.mdc-select--filled:not(.mdc-select--disabled) .mdc-select__anchor{background-color:whitesmoke}.mdc-select--filled.mdc-select--disabled .mdc-select__anchor{background-color:#fafafa}.mdc-select--filled:not(.mdc-select--disabled) .mdc-line-ripple::before{border-bottom-color:rgba(0, 0, 0, 0.42)}.mdc-select--filled:not(.mdc-select--disabled):hover .mdc-line-ripple::before{border-bottom-color:rgba(0, 0, 0, 0.87)}.mdc-select--filled:not(.mdc-select--disabled) .mdc-line-ripple::after{border-bottom-color:#6200ee;border-bottom-color:var(--mdc-theme-primary, #6200ee)}.mdc-select--filled.mdc-select--disabled .mdc-line-ripple::before{border-bottom-color:rgba(0, 0, 0, 0.06)}.mdc-select--filled .mdc-floating-label{max-width:calc(100% - 64px)}.mdc-select--filled .mdc-floating-label--float-above{max-width:calc(100% / 0.75 - 64px / 0.75)}.mdc-select--filled .mdc-menu-surface--is-open-below{border-top-left-radius:0px;border-top-right-radius:0px}.mdc-select--filled.mdc-select--focused.mdc-line-ripple::after{transform:scale(1, 2);opacity:1}.mdc-select--filled .mdc-floating-label{left:16px;right:initial}[dir=rtl] .mdc-select--filled .mdc-floating-label,.mdc-select--filled .mdc-floating-label[dir=rtl]{left:initial;right:16px}.mdc-select--filled.mdc-select--with-leading-icon .mdc-floating-label{left:48px;right:initial}[dir=rtl] .mdc-select--filled.mdc-select--with-leading-icon .mdc-floating-label,.mdc-select--filled.mdc-select--with-leading-icon .mdc-floating-label[dir=rtl]{left:initial;right:48px}.mdc-select--filled.mdc-select--with-leading-icon .mdc-floating-label{max-width:calc(100% - 96px)}.mdc-select--filled.mdc-select--with-leading-icon .mdc-floating-label--float-above{max-width:calc(100% / 0.75 - 96px / 0.75)}.mdc-select--invalid:not(.mdc-select--disabled) .mdc-line-ripple::before{border-bottom-color:#b00020;border-bottom-color:var(--mdc-theme-error, #b00020)}.mdc-select--invalid:not(.mdc-select--disabled):hover .mdc-line-ripple::before{border-bottom-color:#b00020;border-bottom-color:var(--mdc-theme-error, #b00020)}.mdc-select--invalid:not(.mdc-select--disabled) .mdc-line-ripple::after{border-bottom-color:#b00020;border-bottom-color:var(--mdc-theme-error, #b00020)}.mdc-select--outlined{border:none}.mdc-select--outlined .mdc-select__anchor{height:56px}.mdc-select--outlined .mdc-select__anchor .mdc-floating-label--float-above{transform:translateY(-37.25px) scale(1)}.mdc-select--outlined .mdc-select__anchor .mdc-floating-label--float-above{font-size:.75rem}.mdc-select--outlined .mdc-select__anchor.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-select--outlined .mdc-select__anchor .mdc-notched-outline--upgraded .mdc-floating-label--float-above{transform:translateY(-34.75px) scale(0.75)}.mdc-select--outlined .mdc-select__anchor.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-select--outlined .mdc-select__anchor .mdc-notched-outline--upgraded .mdc-floating-label--float-above{font-size:1rem}.mdc-select--outlined .mdc-select__anchor .mdc-floating-label--shake{animation:mdc-floating-label-shake-float-above-select-outlined-56px 250ms 1}@keyframes mdc-floating-label-shake-float-above-select-outlined-56px{0%{transform:translateX(calc(0 - 0%)) translateY(-34.75px) scale(0.75)}33%{animation-timing-function:cubic-bezier(0.5, 0, 0.701732, 0.495819);transform:translateX(calc(4% - 0%)) translateY(-34.75px) scale(0.75)}66%{animation-timing-function:cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);transform:translateX(calc(-4% - 0%)) translateY(-34.75px) scale(0.75)}100%{transform:translateX(calc(0 - 0%)) translateY(-34.75px) scale(0.75)}}.mdc-select--outlined .mdc-notched-outline .mdc-notched-outline__leading{border-top-left-radius:4px;border-top-left-radius:var(--mdc-shape-small, 4px);border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:4px;border-bottom-left-radius:var(--mdc-shape-small, 4px)}[dir=rtl] .mdc-select--outlined .mdc-notched-outline .mdc-notched-outline__leading,.mdc-select--outlined .mdc-notched-outline .mdc-notched-outline__leading[dir=rtl]{border-top-left-radius:0;border-top-right-radius:4px;border-top-right-radius:var(--mdc-shape-small, 4px);border-bottom-right-radius:4px;border-bottom-right-radius:var(--mdc-shape-small, 4px);border-bottom-left-radius:0}@supports(top: max(0%)){.mdc-select--outlined .mdc-notched-outline .mdc-notched-outline__leading{width:max(12px, var(--mdc-shape-small, 4px))}}@supports(top: max(0%)){.mdc-select--outlined .mdc-notched-outline .mdc-notched-outline__notch{max-width:calc(100% - max(12px, var(--mdc-shape-small, 4px)) * 2)}}.mdc-select--outlined .mdc-notched-outline .mdc-notched-outline__trailing{border-top-left-radius:0;border-top-right-radius:4px;border-top-right-radius:var(--mdc-shape-small, 4px);border-bottom-right-radius:4px;border-bottom-right-radius:var(--mdc-shape-small, 4px);border-bottom-left-radius:0}[dir=rtl] .mdc-select--outlined .mdc-notched-outline .mdc-notched-outline__trailing,.mdc-select--outlined .mdc-notched-outline .mdc-notched-outline__trailing[dir=rtl]{border-top-left-radius:4px;border-top-left-radius:var(--mdc-shape-small, 4px);border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:4px;border-bottom-left-radius:var(--mdc-shape-small, 4px)}@supports(top: max(0%)){.mdc-select--outlined .mdc-select__anchor{padding-left:max(16px, calc(var(--mdc-shape-small, 4px) + 4px))}}[dir=rtl] .mdc-select--outlined .mdc-select__anchor,.mdc-select--outlined .mdc-select__anchor[dir=rtl]{padding-left:0}@supports(top: max(0%)){[dir=rtl] .mdc-select--outlined .mdc-select__anchor,.mdc-select--outlined .mdc-select__anchor[dir=rtl]{padding-right:max(16px, calc(var(--mdc-shape-small, 4px) + 4px))}}@supports(top: max(0%)){.mdc-select--outlined+.mdc-select-helper-text{margin-left:max(16px, calc(var(--mdc-shape-small, 4px) + 4px))}}[dir=rtl] .mdc-select--outlined+.mdc-select-helper-text,.mdc-select--outlined+.mdc-select-helper-text[dir=rtl]{margin-left:0}@supports(top: max(0%)){[dir=rtl] .mdc-select--outlined+.mdc-select-helper-text,.mdc-select--outlined+.mdc-select-helper-text[dir=rtl]{margin-right:max(16px, calc(var(--mdc-shape-small, 4px) + 4px))}}.mdc-select--outlined:not(.mdc-select--disabled) .mdc-select__anchor{background-color:transparent}.mdc-select--outlined.mdc-select--disabled .mdc-select__anchor{background-color:transparent}.mdc-select--outlined:not(.mdc-select--disabled) .mdc-notched-outline__leading,.mdc-select--outlined:not(.mdc-select--disabled) .mdc-notched-outline__notch,.mdc-select--outlined:not(.mdc-select--disabled) .mdc-notched-outline__trailing{border-color:rgba(0, 0, 0, 0.38)}.mdc-select--outlined:not(.mdc-select--disabled):not(.mdc-select--focused) .mdc-select__anchor:hover .mdc-notched-outline .mdc-notched-outline__leading,.mdc-select--outlined:not(.mdc-select--disabled):not(.mdc-select--focused) .mdc-select__anchor:hover .mdc-notched-outline .mdc-notched-outline__notch,.mdc-select--outlined:not(.mdc-select--disabled):not(.mdc-select--focused) .mdc-select__anchor:hover .mdc-notched-outline .mdc-notched-outline__trailing{border-color:rgba(0, 0, 0, 0.87)}.mdc-select--outlined:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__leading,.mdc-select--outlined:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__notch,.mdc-select--outlined:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__trailing{border-width:2px}.mdc-select--outlined:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__leading,.mdc-select--outlined:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__notch,.mdc-select--outlined:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__trailing{border-color:#6200ee;border-color:var(--mdc-theme-primary, #6200ee)}.mdc-select--outlined.mdc-select--disabled .mdc-notched-outline__leading,.mdc-select--outlined.mdc-select--disabled .mdc-notched-outline__notch,.mdc-select--outlined.mdc-select--disabled .mdc-notched-outline__trailing{border-color:rgba(0, 0, 0, 0.06)}.mdc-select--outlined .mdc-select__anchor :not(.mdc-notched-outline--notched) .mdc-notched-outline__notch{max-width:calc(100% - 60px)}.mdc-select--outlined .mdc-select__anchor{display:flex;align-items:baseline;overflow:visible}.mdc-select--outlined .mdc-select__anchor .mdc-floating-label--shake{animation:mdc-floating-label-shake-float-above-select-outlined 250ms 1}.mdc-select--outlined .mdc-select__anchor .mdc-floating-label--float-above{transform:translateY(-37.25px) scale(1)}.mdc-select--outlined .mdc-select__anchor .mdc-floating-label--float-above{font-size:.75rem}.mdc-select--outlined .mdc-select__anchor.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-select--outlined .mdc-select__anchor .mdc-notched-outline--upgraded .mdc-floating-label--float-above{transform:translateY(-34.75px) scale(0.75)}.mdc-select--outlined .mdc-select__anchor.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-select--outlined .mdc-select__anchor .mdc-notched-outline--upgraded .mdc-floating-label--float-above{font-size:1rem}.mdc-select--outlined .mdc-select__anchor .mdc-notched-outline--notched .mdc-notched-outline__notch{padding-top:1px}.mdc-select--outlined .mdc-select__anchor .mdc-select__selected-text::before{content:"​"}.mdc-select--outlined .mdc-select__anchor .mdc-select__selected-text-container{height:100%;display:inline-flex;align-items:center}.mdc-select--outlined .mdc-select__anchor::before{display:none}.mdc-select--outlined .mdc-select__selected-text-container{display:flex;border:none;z-index:1;background-color:transparent}.mdc-select--outlined .mdc-select__icon{z-index:2}.mdc-select--outlined .mdc-floating-label{line-height:1.15rem;left:4px;right:initial}[dir=rtl] .mdc-select--outlined .mdc-floating-label,.mdc-select--outlined .mdc-floating-label[dir=rtl]{left:initial;right:4px}.mdc-select--outlined.mdc-select--focused .mdc-notched-outline--notched .mdc-notched-outline__notch{padding-top:2px}.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled) .mdc-notched-outline__leading,.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled) .mdc-notched-outline__notch,.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled) .mdc-notched-outline__trailing{border-color:#b00020;border-color:var(--mdc-theme-error, #b00020)}.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled):not(.mdc-select--focused) .mdc-select__anchor:hover .mdc-notched-outline .mdc-notched-outline__leading,.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled):not(.mdc-select--focused) .mdc-select__anchor:hover .mdc-notched-outline .mdc-notched-outline__notch,.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled):not(.mdc-select--focused) .mdc-select__anchor:hover .mdc-notched-outline .mdc-notched-outline__trailing{border-color:#b00020;border-color:var(--mdc-theme-error, #b00020)}.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__leading,.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__notch,.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__trailing{border-width:2px}.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__leading,.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__notch,.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__trailing{border-color:#b00020;border-color:var(--mdc-theme-error, #b00020)}.mdc-select--outlined.mdc-select--with-leading-icon .mdc-floating-label{left:36px;right:initial}[dir=rtl] .mdc-select--outlined.mdc-select--with-leading-icon .mdc-floating-label,.mdc-select--outlined.mdc-select--with-leading-icon .mdc-floating-label[dir=rtl]{left:initial;right:36px}.mdc-select--outlined.mdc-select--with-leading-icon .mdc-floating-label--float-above{transform:translateY(-37.25px) translateX(-32px) scale(1)}[dir=rtl] .mdc-select--outlined.mdc-select--with-leading-icon .mdc-floating-label--float-above,.mdc-select--outlined.mdc-select--with-leading-icon .mdc-floating-label--float-above[dir=rtl]{transform:translateY(-37.25px) translateX(32px) scale(1)}.mdc-select--outlined.mdc-select--with-leading-icon .mdc-floating-label--float-above{font-size:.75rem}.mdc-select--outlined.mdc-select--with-leading-icon.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-select--outlined.mdc-select--with-leading-icon .mdc-notched-outline--upgraded .mdc-floating-label--float-above{transform:translateY(-34.75px) translateX(-32px) scale(0.75)}[dir=rtl] .mdc-select--outlined.mdc-select--with-leading-icon.mdc-notched-outline--upgraded .mdc-floating-label--float-above,[dir=rtl] .mdc-select--outlined.mdc-select--with-leading-icon .mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-select--outlined.mdc-select--with-leading-icon.mdc-notched-outline--upgraded .mdc-floating-label--float-above[dir=rtl],.mdc-select--outlined.mdc-select--with-leading-icon .mdc-notched-outline--upgraded .mdc-floating-label--float-above[dir=rtl]{transform:translateY(-34.75px) translateX(32px) scale(0.75)}.mdc-select--outlined.mdc-select--with-leading-icon.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-select--outlined.mdc-select--with-leading-icon .mdc-notched-outline--upgraded .mdc-floating-label--float-above{font-size:1rem}.mdc-select--outlined.mdc-select--with-leading-icon .mdc-floating-label--shake{animation:mdc-floating-label-shake-float-above-select-outlined-leading-icon-56px 250ms 1}@keyframes mdc-floating-label-shake-float-above-select-outlined-leading-icon-56px{0%{transform:translateX(calc(0 - 32px)) translateY(-34.75px) scale(0.75)}33%{animation-timing-function:cubic-bezier(0.5, 0, 0.701732, 0.495819);transform:translateX(calc(4% - 32px)) translateY(-34.75px) scale(0.75)}66%{animation-timing-function:cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);transform:translateX(calc(-4% - 32px)) translateY(-34.75px) scale(0.75)}100%{transform:translateX(calc(0 - 32px)) translateY(-34.75px) scale(0.75)}}[dir=rtl] .mdc-select--outlined.mdc-select--with-leading-icon .mdc-floating-label--shake,.mdc-select--outlined.mdc-select--with-leading-icon[dir=rtl] .mdc-floating-label--shake{animation:mdc-floating-label-shake-float-above-select-outlined-leading-icon-56px 250ms 1}@keyframes mdc-floating-label-shake-float-above-select-outlined-leading-icon-56px-rtl{0%{transform:translateX(calc(0 - -32px)) translateY(-34.75px) scale(0.75)}33%{animation-timing-function:cubic-bezier(0.5, 0, 0.701732, 0.495819);transform:translateX(calc(4% - -32px)) translateY(-34.75px) scale(0.75)}66%{animation-timing-function:cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);transform:translateX(calc(-4% - -32px)) translateY(-34.75px) scale(0.75)}100%{transform:translateX(calc(0 - -32px)) translateY(-34.75px) scale(0.75)}}.mdc-select--outlined.mdc-select--with-leading-icon .mdc-select__anchor :not(.mdc-notched-outline--notched) .mdc-notched-outline__notch{max-width:calc(100% - 96px)}.mdc-select--outlined .mdc-menu-surface{margin-bottom:8px}.mdc-select--outlined.mdc-select--no-label .mdc-menu-surface,.mdc-select--outlined .mdc-menu-surface--is-open-below{margin-bottom:0}.mdc-select__anchor{--mdc-ripple-fg-size: 0;--mdc-ripple-left: 0;--mdc-ripple-top: 0;--mdc-ripple-fg-scale: 1;--mdc-ripple-fg-translate-end: 0;--mdc-ripple-fg-translate-start: 0;-webkit-tap-highlight-color:rgba(0,0,0,0);will-change:transform,opacity}.mdc-select__anchor .mdc-select__ripple::before,.mdc-select__anchor .mdc-select__ripple::after{position:absolute;border-radius:50%;opacity:0;pointer-events:none;content:""}.mdc-select__anchor .mdc-select__ripple::before{transition:opacity 15ms linear,background-color 15ms linear;z-index:1;z-index:var(--mdc-ripple-z-index, 1)}.mdc-select__anchor .mdc-select__ripple::after{z-index:0;z-index:var(--mdc-ripple-z-index, 0)}.mdc-select__anchor.mdc-ripple-upgraded .mdc-select__ripple::before{transform:scale(var(--mdc-ripple-fg-scale, 1))}.mdc-select__anchor.mdc-ripple-upgraded .mdc-select__ripple::after{top:0;left:0;transform:scale(0);transform-origin:center center}.mdc-select__anchor.mdc-ripple-upgraded--unbounded .mdc-select__ripple::after{top:var(--mdc-ripple-top, 0);left:var(--mdc-ripple-left, 0)}.mdc-select__anchor.mdc-ripple-upgraded--foreground-activation .mdc-select__ripple::after{animation:mdc-ripple-fg-radius-in 225ms forwards,mdc-ripple-fg-opacity-in 75ms forwards}.mdc-select__anchor.mdc-ripple-upgraded--foreground-deactivation .mdc-select__ripple::after{animation:mdc-ripple-fg-opacity-out 150ms;transform:translate(var(--mdc-ripple-fg-translate-end, 0)) scale(var(--mdc-ripple-fg-scale, 1))}.mdc-select__anchor .mdc-select__ripple::before,.mdc-select__anchor .mdc-select__ripple::after{top:calc(50% - 100%);left:calc(50% - 100%);width:200%;height:200%}.mdc-select__anchor.mdc-ripple-upgraded .mdc-select__ripple::after{width:var(--mdc-ripple-fg-size, 100%);height:var(--mdc-ripple-fg-size, 100%)}.mdc-select__anchor .mdc-select__ripple::before,.mdc-select__anchor .mdc-select__ripple::after{background-color:rgba(0, 0, 0, 0.87);background-color:var(--mdc-ripple-color, rgba(0, 0, 0, 0.87))}.mdc-select__anchor:hover .mdc-select__ripple::before,.mdc-select__anchor.mdc-ripple-surface--hover .mdc-select__ripple::before{opacity:0.04;opacity:var(--mdc-ripple-hover-opacity, 0.04)}.mdc-select__anchor.mdc-ripple-upgraded--background-focused .mdc-select__ripple::before,.mdc-select__anchor:not(.mdc-ripple-upgraded):focus .mdc-select__ripple::before{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-focus-opacity, 0.12)}.mdc-select__anchor .mdc-select__ripple{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected .mdc-deprecated-list-item__ripple::before,.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected .mdc-deprecated-list-item__ripple::after{background-color:#000;background-color:var(--mdc-ripple-color, var(--mdc-theme-on-surface, #000))}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected:hover .mdc-deprecated-list-item__ripple::before,.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected.mdc-ripple-surface--hover .mdc-deprecated-list-item__ripple::before{opacity:0.04;opacity:var(--mdc-ripple-hover-opacity, 0.04)}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected.mdc-ripple-upgraded--background-focused .mdc-deprecated-list-item__ripple::before,.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected:not(.mdc-ripple-upgraded):focus .mdc-deprecated-list-item__ripple::before{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-focus-opacity, 0.12)}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected:not(.mdc-ripple-upgraded) .mdc-deprecated-list-item__ripple::after{transition:opacity 150ms linear}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected:not(.mdc-ripple-upgraded):active .mdc-deprecated-list-item__ripple::after{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-press-opacity, 0.12)}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected.mdc-ripple-upgraded{--mdc-ripple-fg-opacity:var(--mdc-ripple-press-opacity, 0.12)}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected .mdc-list-item__ripple::before,.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected .mdc-list-item__ripple::after{background-color:#000;background-color:var(--mdc-ripple-color, var(--mdc-theme-on-surface, #000))}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected:hover .mdc-list-item__ripple::before,.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected.mdc-ripple-surface--hover .mdc-list-item__ripple::before{opacity:0.04;opacity:var(--mdc-ripple-hover-opacity, 0.04)}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected.mdc-ripple-upgraded--background-focused .mdc-list-item__ripple::before,.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected:not(.mdc-ripple-upgraded):focus .mdc-list-item__ripple::before{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-focus-opacity, 0.12)}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected:not(.mdc-ripple-upgraded) .mdc-list-item__ripple::after{transition:opacity 150ms linear}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected:not(.mdc-ripple-upgraded):active .mdc-list-item__ripple::after{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-press-opacity, 0.12)}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected.mdc-ripple-upgraded{--mdc-ripple-fg-opacity:var(--mdc-ripple-press-opacity, 0.12)}.mdc-select-helper-text{margin:0;margin-left:16px;margin-right:16px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-caption-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:0.75rem;font-size:var(--mdc-typography-caption-font-size, 0.75rem);line-height:1.25rem;line-height:var(--mdc-typography-caption-line-height, 1.25rem);font-weight:400;font-weight:var(--mdc-typography-caption-font-weight, 400);letter-spacing:0.0333333333em;letter-spacing:var(--mdc-typography-caption-letter-spacing, 0.0333333333em);text-decoration:inherit;text-decoration:var(--mdc-typography-caption-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-caption-text-transform, inherit);display:block;margin-top:0;line-height:normal}[dir=rtl] .mdc-select-helper-text,.mdc-select-helper-text[dir=rtl]{margin-left:16px;margin-right:16px}.mdc-select-helper-text::before{display:inline-block;width:0;height:16px;content:"";vertical-align:0}.mdc-select-helper-text--validation-msg{opacity:0;transition:opacity 180ms cubic-bezier(0.4, 0, 0.2, 1)}.mdc-select--invalid+.mdc-select-helper-text--validation-msg,.mdc-select-helper-text--validation-msg-persistent{opacity:1}.mdc-select--with-leading-icon .mdc-select__icon{display:inline-block;box-sizing:border-box;border:none;text-decoration:none;cursor:pointer;user-select:none;flex-shrink:0;align-self:center;background-color:transparent;fill:currentColor}.mdc-select--with-leading-icon .mdc-select__icon{margin-left:12px;margin-right:12px}[dir=rtl] .mdc-select--with-leading-icon .mdc-select__icon,.mdc-select--with-leading-icon .mdc-select__icon[dir=rtl]{margin-left:12px;margin-right:12px}.mdc-select__icon:not([tabindex]),.mdc-select__icon[tabindex="-1"]{cursor:default;pointer-events:none}.material-icons{font-family:var(--mdc-icon-font, "Material Icons");font-weight:normal;font-style:normal;font-size:var(--mdc-icon-size, 24px);line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;-moz-osx-font-smoothing:grayscale;font-feature-settings:"liga"}:host{display:inline-block;vertical-align:top;outline:none}.mdc-select{width:100%}[hidden]{display:none}.mdc-select__icon{z-index:2}.mdc-select--with-leading-icon{--mdc-list-item-graphic-margin: calc( 48px - var(--mdc-list-item-graphic-size, 24px) - var(--mdc-list-side-padding, 16px) )}.mdc-select .mdc-select__anchor .mdc-select__selected-text{overflow:hidden}.mdc-select .mdc-select__anchor *{display:inline-flex}.mdc-select .mdc-select__anchor .mdc-floating-label{display:inline-block}mwc-notched-outline{--mdc-notched-outline-border-color: var( --mdc-select-outlined-idle-border-color, rgba(0, 0, 0, 0.38) );--mdc-notched-outline-notch-offset: 1px}:host(:not([disabled]):hover) .mdc-select:not(.mdc-select--invalid):not(.mdc-select--focused) mwc-notched-outline{--mdc-notched-outline-border-color: var( --mdc-select-outlined-hover-border-color, rgba(0, 0, 0, 0.87) )}:host(:not([disabled])) .mdc-select:not(.mdc-select--disabled) .mdc-select__selected-text{color:rgba(0, 0, 0, 0.87);color:var(--mdc-select-ink-color, rgba(0, 0, 0, 0.87))}:host(:not([disabled])) .mdc-select:not(.mdc-select--disabled) .mdc-line-ripple::before{border-bottom-color:rgba(0, 0, 0, 0.42);border-bottom-color:var(--mdc-select-idle-line-color, rgba(0, 0, 0, 0.42))}:host(:not([disabled])) .mdc-select:not(.mdc-select--disabled):hover .mdc-line-ripple::before{border-bottom-color:rgba(0, 0, 0, 0.87);border-bottom-color:var(--mdc-select-hover-line-color, rgba(0, 0, 0, 0.87))}:host(:not([disabled])) .mdc-select:not(.mdc-select--outlined):not(.mdc-select--disabled) .mdc-select__anchor{background-color:whitesmoke;background-color:var(--mdc-select-fill-color, whitesmoke)}:host(:not([disabled])) .mdc-select.mdc-select--invalid .mdc-select__dropdown-icon{fill:var(--mdc-select-error-dropdown-icon-color, var(--mdc-select-error-color, var(--mdc-theme-error, #b00020)))}:host(:not([disabled])) .mdc-select.mdc-select--invalid .mdc-floating-label,:host(:not([disabled])) .mdc-select.mdc-select--invalid .mdc-floating-label::after{color:var(--mdc-select-error-color, var(--mdc-theme-error, #b00020))}:host(:not([disabled])) .mdc-select.mdc-select--invalid mwc-notched-outline{--mdc-notched-outline-border-color: var(--mdc-select-error-color, var(--mdc-theme-error, #b00020))}.mdc-select__menu--invalid{--mdc-theme-primary: var(--mdc-select-error-color, var(--mdc-theme-error, #b00020))}:host(:not([disabled])) .mdc-select:not(.mdc-select--invalid):not(.mdc-select--focused) .mdc-floating-label,:host(:not([disabled])) .mdc-select:not(.mdc-select--invalid):not(.mdc-select--focused) .mdc-floating-label::after{color:rgba(0, 0, 0, 0.6);color:var(--mdc-select-label-ink-color, rgba(0, 0, 0, 0.6))}:host(:not([disabled])) .mdc-select:not(.mdc-select--invalid):not(.mdc-select--focused) .mdc-select__dropdown-icon{fill:rgba(0, 0, 0, 0.54);fill:var(--mdc-select-dropdown-icon-color, rgba(0, 0, 0, 0.54))}:host(:not([disabled])) .mdc-select.mdc-select--focused mwc-notched-outline{--mdc-notched-outline-stroke-width: 2px;--mdc-notched-outline-notch-offset: 2px}:host(:not([disabled])) .mdc-select.mdc-select--focused:not(.mdc-select--invalid) mwc-notched-outline{--mdc-notched-outline-border-color: var( --mdc-select-focused-label-color, var(--mdc-theme-primary, rgba(98, 0, 238, 0.87)) )}:host(:not([disabled])) .mdc-select.mdc-select--focused:not(.mdc-select--invalid) .mdc-select__dropdown-icon{fill:rgba(98,0,238,.87);fill:var(--mdc-select-focused-dropdown-icon-color, var(--mdc-theme-primary, rgba(98, 0, 238, 0.87)))}:host(:not([disabled])) .mdc-select.mdc-select--focused:not(.mdc-select--invalid) .mdc-floating-label{color:#6200ee;color:var(--mdc-theme-primary, #6200ee)}:host(:not([disabled])) .mdc-select.mdc-select--focused:not(.mdc-select--invalid) .mdc-floating-label::after{color:#6200ee;color:var(--mdc-theme-primary, #6200ee)}:host(:not([disabled])) .mdc-select-helper-text:not(.mdc-select-helper-text--validation-msg){color:var(--mdc-select-label-ink-color, rgba(0, 0, 0, 0.6))}:host([disabled]){pointer-events:none}:host([disabled]) .mdc-select:not(.mdc-select--outlined).mdc-select--disabled .mdc-select__anchor{background-color:#fafafa;background-color:var(--mdc-select-disabled-fill-color, #fafafa)}:host([disabled]) .mdc-select.mdc-select--outlined mwc-notched-outline{--mdc-notched-outline-border-color: var( --mdc-select-outlined-disabled-border-color, rgba(0, 0, 0, 0.06) )}:host([disabled]) .mdc-select .mdc-select__dropdown-icon{fill:rgba(0, 0, 0, 0.38);fill:var(--mdc-select-disabled-dropdown-icon-color, rgba(0, 0, 0, 0.38))}:host([disabled]) .mdc-select:not(.mdc-select--invalid):not(.mdc-select--focused) .mdc-floating-label,:host([disabled]) .mdc-select:not(.mdc-select--invalid):not(.mdc-select--focused) .mdc-floating-label::after{color:rgba(0, 0, 0, 0.38);color:var(--mdc-select-disabled-ink-color, rgba(0, 0, 0, 0.38))}:host([disabled]) .mdc-select-helper-text{color:rgba(0, 0, 0, 0.38);color:var(--mdc-select-disabled-ink-color, rgba(0, 0, 0, 0.38))}:host([disabled]) .mdc-select__selected-text{color:rgba(0, 0, 0, 0.38);color:var(--mdc-select-disabled-ink-color, rgba(0, 0, 0, 0.38))}` -/** - * @license - * Copyright 2021 Google LLC - * SPDX-LIcense-Identifier: Apache-2.0 - */,Nm=$l`@keyframes mdc-ripple-fg-radius-in{from{animation-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transform:translate(var(--mdc-ripple-fg-translate-start, 0)) scale(1)}to{transform:translate(var(--mdc-ripple-fg-translate-end, 0)) scale(var(--mdc-ripple-fg-scale, 1))}}@keyframes mdc-ripple-fg-opacity-in{from{animation-timing-function:linear;opacity:0}to{opacity:var(--mdc-ripple-fg-opacity, 0)}}@keyframes mdc-ripple-fg-opacity-out{from{animation-timing-function:linear;opacity:var(--mdc-ripple-fg-opacity, 0)}to{opacity:0}}:host{display:block}.mdc-deprecated-list{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-subtitle1-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:1rem;font-size:var(--mdc-typography-subtitle1-font-size, 1rem);line-height:1.75rem;line-height:var(--mdc-typography-subtitle1-line-height, 1.75rem);font-weight:400;font-weight:var(--mdc-typography-subtitle1-font-weight, 400);letter-spacing:0.009375em;letter-spacing:var(--mdc-typography-subtitle1-letter-spacing, 0.009375em);text-decoration:inherit;text-decoration:var(--mdc-typography-subtitle1-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-subtitle1-text-transform, inherit);line-height:1.5rem;margin:0;padding:8px 0;list-style-type:none;color:rgba(0, 0, 0, 0.87);color:var(--mdc-theme-text-primary-on-background, rgba(0, 0, 0, 0.87));padding:var(--mdc-list-vertical-padding, 8px) 0}.mdc-deprecated-list:focus{outline:none}.mdc-deprecated-list-item{height:48px}.mdc-deprecated-list--dense{padding-top:4px;padding-bottom:4px;font-size:.812rem}.mdc-deprecated-list ::slotted([divider]){height:0;margin:0;border:none;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgba(0, 0, 0, 0.12)}.mdc-deprecated-list ::slotted([divider][padded]){margin:0 var(--mdc-list-side-padding, 16px)}.mdc-deprecated-list ::slotted([divider][inset]){margin-left:var(--mdc-list-inset-margin, 72px);margin-right:0;width:calc( 100% - var(--mdc-list-inset-margin, 72px) )}[dir=rtl] .mdc-deprecated-list ::slotted([divider][inset]),.mdc-deprecated-list ::slotted([divider][inset][dir=rtl]){margin-left:0;margin-right:var(--mdc-list-inset-margin, 72px)}.mdc-deprecated-list ::slotted([divider][inset][padded]){width:calc( 100% - var(--mdc-list-inset-margin, 72px) - var(--mdc-list-side-padding, 16px) )}.mdc-deprecated-list--dense ::slotted([mwc-list-item]){height:40px}.mdc-deprecated-list--dense ::slotted([mwc-list]){--mdc-list-item-graphic-size: 20px}.mdc-deprecated-list--two-line.mdc-deprecated-list--dense ::slotted([mwc-list-item]),.mdc-deprecated-list--avatar-list.mdc-deprecated-list--dense ::slotted([mwc-list-item]){height:60px}.mdc-deprecated-list--avatar-list.mdc-deprecated-list--dense ::slotted([mwc-list]){--mdc-list-item-graphic-size: 36px}:host([noninteractive]){pointer-events:none;cursor:default}.mdc-deprecated-list--dense ::slotted(.mdc-deprecated-list-item__primary-text){display:block;margin-top:0;line-height:normal;margin-bottom:-20px}.mdc-deprecated-list--dense ::slotted(.mdc-deprecated-list-item__primary-text)::before{display:inline-block;width:0;height:24px;content:"";vertical-align:0}.mdc-deprecated-list--dense ::slotted(.mdc-deprecated-list-item__primary-text)::after{display:inline-block;width:0;height:20px;content:"";vertical-align:-20px}` -/** - * @license - * Copyright 2021 Google LLC - * SPDX-LIcense-Identifier: Apache-2.0 - */,Dm=$l`:host{cursor:pointer;user-select:none;-webkit-tap-highlight-color:transparent;height:48px;display:flex;position:relative;align-items:center;justify-content:flex-start;overflow:hidden;padding:0;padding-left:var(--mdc-list-side-padding, 16px);padding-right:var(--mdc-list-side-padding, 16px);outline:none;height:48px;color:rgba(0,0,0,.87);color:var(--mdc-theme-text-primary-on-background, rgba(0, 0, 0, 0.87))}:host:focus{outline:none}:host([activated]){color:#6200ee;color:var(--mdc-theme-primary, #6200ee);--mdc-ripple-color: var( --mdc-theme-primary, #6200ee )}:host([activated]) .mdc-deprecated-list-item__graphic{color:#6200ee;color:var(--mdc-theme-primary, #6200ee)}:host([activated]) .fake-activated-ripple::before{position:absolute;display:block;top:0;bottom:0;left:0;right:0;width:100%;height:100%;pointer-events:none;z-index:1;content:"";opacity:0.12;opacity:var(--mdc-ripple-activated-opacity, 0.12);background-color:#6200ee;background-color:var(--mdc-ripple-color, var(--mdc-theme-primary, #6200ee))}.mdc-deprecated-list-item__graphic{flex-shrink:0;align-items:center;justify-content:center;fill:currentColor;display:inline-flex}.mdc-deprecated-list-item__graphic ::slotted(*){flex-shrink:0;align-items:center;justify-content:center;fill:currentColor;width:100%;height:100%;text-align:center}.mdc-deprecated-list-item__meta{width:var(--mdc-list-item-meta-size, 24px);height:var(--mdc-list-item-meta-size, 24px);margin-left:auto;margin-right:0;color:rgba(0, 0, 0, 0.38);color:var(--mdc-theme-text-hint-on-background, rgba(0, 0, 0, 0.38))}.mdc-deprecated-list-item__meta.multi{width:auto}.mdc-deprecated-list-item__meta ::slotted(*){width:var(--mdc-list-item-meta-size, 24px);line-height:var(--mdc-list-item-meta-size, 24px)}.mdc-deprecated-list-item__meta ::slotted(.material-icons),.mdc-deprecated-list-item__meta ::slotted(mwc-icon){line-height:var(--mdc-list-item-meta-size, 24px) !important}.mdc-deprecated-list-item__meta ::slotted(:not(.material-icons):not(mwc-icon)){-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-caption-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:0.75rem;font-size:var(--mdc-typography-caption-font-size, 0.75rem);line-height:1.25rem;line-height:var(--mdc-typography-caption-line-height, 1.25rem);font-weight:400;font-weight:var(--mdc-typography-caption-font-weight, 400);letter-spacing:0.0333333333em;letter-spacing:var(--mdc-typography-caption-letter-spacing, 0.0333333333em);text-decoration:inherit;text-decoration:var(--mdc-typography-caption-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-caption-text-transform, inherit)}[dir=rtl] .mdc-deprecated-list-item__meta,.mdc-deprecated-list-item__meta[dir=rtl]{margin-left:0;margin-right:auto}.mdc-deprecated-list-item__meta ::slotted(*){width:100%;height:100%}.mdc-deprecated-list-item__text{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.mdc-deprecated-list-item__text ::slotted([for]),.mdc-deprecated-list-item__text[for]{pointer-events:none}.mdc-deprecated-list-item__primary-text{text-overflow:ellipsis;white-space:nowrap;overflow:hidden;display:block;margin-top:0;line-height:normal;margin-bottom:-20px;display:block}.mdc-deprecated-list-item__primary-text::before{display:inline-block;width:0;height:32px;content:"";vertical-align:0}.mdc-deprecated-list-item__primary-text::after{display:inline-block;width:0;height:20px;content:"";vertical-align:-20px}.mdc-deprecated-list-item__secondary-text{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-body2-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:0.875rem;font-size:var(--mdc-typography-body2-font-size, 0.875rem);line-height:1.25rem;line-height:var(--mdc-typography-body2-line-height, 1.25rem);font-weight:400;font-weight:var(--mdc-typography-body2-font-weight, 400);letter-spacing:0.0178571429em;letter-spacing:var(--mdc-typography-body2-letter-spacing, 0.0178571429em);text-decoration:inherit;text-decoration:var(--mdc-typography-body2-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-body2-text-transform, inherit);text-overflow:ellipsis;white-space:nowrap;overflow:hidden;display:block;margin-top:0;line-height:normal;display:block}.mdc-deprecated-list-item__secondary-text::before{display:inline-block;width:0;height:20px;content:"";vertical-align:0}.mdc-deprecated-list--dense .mdc-deprecated-list-item__secondary-text{font-size:inherit}* ::slotted(a),a{color:inherit;text-decoration:none}:host([twoline]){height:72px}:host([twoline]) .mdc-deprecated-list-item__text{align-self:flex-start}:host([disabled]),:host([noninteractive]){cursor:default;pointer-events:none}:host([disabled]) .mdc-deprecated-list-item__text ::slotted(*){opacity:.38}:host([disabled]) .mdc-deprecated-list-item__text ::slotted(*),:host([disabled]) .mdc-deprecated-list-item__primary-text ::slotted(*),:host([disabled]) .mdc-deprecated-list-item__secondary-text ::slotted(*){color:#000;color:var(--mdc-theme-on-surface, #000)}.mdc-deprecated-list-item__secondary-text ::slotted(*){color:rgba(0, 0, 0, 0.54);color:var(--mdc-theme-text-secondary-on-background, rgba(0, 0, 0, 0.54))}.mdc-deprecated-list-item__graphic ::slotted(*){background-color:transparent;color:rgba(0, 0, 0, 0.38);color:var(--mdc-theme-text-icon-on-background, rgba(0, 0, 0, 0.38))}.mdc-deprecated-list-group__subheader ::slotted(*){color:rgba(0, 0, 0, 0.87);color:var(--mdc-theme-text-primary-on-background, rgba(0, 0, 0, 0.87))}:host([graphic=avatar]) .mdc-deprecated-list-item__graphic{width:var(--mdc-list-item-graphic-size, 40px);height:var(--mdc-list-item-graphic-size, 40px)}:host([graphic=avatar]) .mdc-deprecated-list-item__graphic.multi{width:auto}:host([graphic=avatar]) .mdc-deprecated-list-item__graphic ::slotted(*){width:var(--mdc-list-item-graphic-size, 40px);line-height:var(--mdc-list-item-graphic-size, 40px)}:host([graphic=avatar]) .mdc-deprecated-list-item__graphic ::slotted(.material-icons),:host([graphic=avatar]) .mdc-deprecated-list-item__graphic ::slotted(mwc-icon){line-height:var(--mdc-list-item-graphic-size, 40px) !important}:host([graphic=avatar]) .mdc-deprecated-list-item__graphic ::slotted(*){border-radius:50%}:host([graphic=avatar]) .mdc-deprecated-list-item__graphic,:host([graphic=medium]) .mdc-deprecated-list-item__graphic,:host([graphic=large]) .mdc-deprecated-list-item__graphic,:host([graphic=control]) .mdc-deprecated-list-item__graphic{margin-left:0;margin-right:var(--mdc-list-item-graphic-margin, 16px)}[dir=rtl] :host([graphic=avatar]) .mdc-deprecated-list-item__graphic,[dir=rtl] :host([graphic=medium]) .mdc-deprecated-list-item__graphic,[dir=rtl] :host([graphic=large]) .mdc-deprecated-list-item__graphic,[dir=rtl] :host([graphic=control]) .mdc-deprecated-list-item__graphic,:host([graphic=avatar]) .mdc-deprecated-list-item__graphic[dir=rtl],:host([graphic=medium]) .mdc-deprecated-list-item__graphic[dir=rtl],:host([graphic=large]) .mdc-deprecated-list-item__graphic[dir=rtl],:host([graphic=control]) .mdc-deprecated-list-item__graphic[dir=rtl]{margin-left:var(--mdc-list-item-graphic-margin, 16px);margin-right:0}:host([graphic=icon]) .mdc-deprecated-list-item__graphic{width:var(--mdc-list-item-graphic-size, 24px);height:var(--mdc-list-item-graphic-size, 24px);margin-left:0;margin-right:var(--mdc-list-item-graphic-margin, 32px)}:host([graphic=icon]) .mdc-deprecated-list-item__graphic.multi{width:auto}:host([graphic=icon]) .mdc-deprecated-list-item__graphic ::slotted(*){width:var(--mdc-list-item-graphic-size, 24px);line-height:var(--mdc-list-item-graphic-size, 24px)}:host([graphic=icon]) .mdc-deprecated-list-item__graphic ::slotted(.material-icons),:host([graphic=icon]) .mdc-deprecated-list-item__graphic ::slotted(mwc-icon){line-height:var(--mdc-list-item-graphic-size, 24px) !important}[dir=rtl] :host([graphic=icon]) .mdc-deprecated-list-item__graphic,:host([graphic=icon]) .mdc-deprecated-list-item__graphic[dir=rtl]{margin-left:var(--mdc-list-item-graphic-margin, 32px);margin-right:0}:host([graphic=avatar]:not([twoLine])),:host([graphic=icon]:not([twoLine])){height:56px}:host([graphic=medium]:not([twoLine])),:host([graphic=large]:not([twoLine])){height:72px}:host([graphic=medium]) .mdc-deprecated-list-item__graphic,:host([graphic=large]) .mdc-deprecated-list-item__graphic{width:var(--mdc-list-item-graphic-size, 56px);height:var(--mdc-list-item-graphic-size, 56px)}:host([graphic=medium]) .mdc-deprecated-list-item__graphic.multi,:host([graphic=large]) .mdc-deprecated-list-item__graphic.multi{width:auto}:host([graphic=medium]) .mdc-deprecated-list-item__graphic ::slotted(*),:host([graphic=large]) .mdc-deprecated-list-item__graphic ::slotted(*){width:var(--mdc-list-item-graphic-size, 56px);line-height:var(--mdc-list-item-graphic-size, 56px)}:host([graphic=medium]) .mdc-deprecated-list-item__graphic ::slotted(.material-icons),:host([graphic=medium]) .mdc-deprecated-list-item__graphic ::slotted(mwc-icon),:host([graphic=large]) .mdc-deprecated-list-item__graphic ::slotted(.material-icons),:host([graphic=large]) .mdc-deprecated-list-item__graphic ::slotted(mwc-icon){line-height:var(--mdc-list-item-graphic-size, 56px) !important}:host([graphic=large]){padding-left:0px}` -/** - * @license - * Copyright 2021 Google LLC - * SPDX-LIcense-Identifier: Apache-2.0 - */,Hm=((t,...e)=>{const i=1===t.length?t[0]:e.reduce((e,i,s)=>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[s+1],t[0]);return new lp(i,t,op)})`.mdc-ripple-surface{--mdc-ripple-fg-size: 0;--mdc-ripple-left: 0;--mdc-ripple-top: 0;--mdc-ripple-fg-scale: 1;--mdc-ripple-fg-translate-end: 0;--mdc-ripple-fg-translate-start: 0;-webkit-tap-highlight-color:rgba(0,0,0,0);will-change:transform,opacity;position:relative;outline:none;overflow:hidden}.mdc-ripple-surface::before,.mdc-ripple-surface::after{position:absolute;border-radius:50%;opacity:0;pointer-events:none;content:""}.mdc-ripple-surface::before{transition:opacity 15ms linear,background-color 15ms linear;z-index:1;z-index:var(--mdc-ripple-z-index, 1)}.mdc-ripple-surface::after{z-index:0;z-index:var(--mdc-ripple-z-index, 0)}.mdc-ripple-surface.mdc-ripple-upgraded::before{transform:scale(var(--mdc-ripple-fg-scale, 1))}.mdc-ripple-surface.mdc-ripple-upgraded::after{top:0;left:0;transform:scale(0);transform-origin:center center}.mdc-ripple-surface.mdc-ripple-upgraded--unbounded::after{top:var(--mdc-ripple-top, 0);left:var(--mdc-ripple-left, 0)}.mdc-ripple-surface.mdc-ripple-upgraded--foreground-activation::after{animation:mdc-ripple-fg-radius-in 225ms forwards,mdc-ripple-fg-opacity-in 75ms forwards}.mdc-ripple-surface.mdc-ripple-upgraded--foreground-deactivation::after{animation:mdc-ripple-fg-opacity-out 150ms;transform:translate(var(--mdc-ripple-fg-translate-end, 0)) scale(var(--mdc-ripple-fg-scale, 1))}.mdc-ripple-surface::before,.mdc-ripple-surface::after{top:calc(50% - 100%);left:calc(50% - 100%);width:200%;height:200%}.mdc-ripple-surface.mdc-ripple-upgraded::after{width:var(--mdc-ripple-fg-size, 100%);height:var(--mdc-ripple-fg-size, 100%)}.mdc-ripple-surface[data-mdc-ripple-is-unbounded],.mdc-ripple-upgraded--unbounded{overflow:visible}.mdc-ripple-surface[data-mdc-ripple-is-unbounded]::before,.mdc-ripple-surface[data-mdc-ripple-is-unbounded]::after,.mdc-ripple-upgraded--unbounded::before,.mdc-ripple-upgraded--unbounded::after{top:calc(50% - 50%);left:calc(50% - 50%);width:100%;height:100%}.mdc-ripple-surface[data-mdc-ripple-is-unbounded].mdc-ripple-upgraded::before,.mdc-ripple-surface[data-mdc-ripple-is-unbounded].mdc-ripple-upgraded::after,.mdc-ripple-upgraded--unbounded.mdc-ripple-upgraded::before,.mdc-ripple-upgraded--unbounded.mdc-ripple-upgraded::after{top:var(--mdc-ripple-top, calc(50% - 50%));left:var(--mdc-ripple-left, calc(50% - 50%));width:var(--mdc-ripple-fg-size, 100%);height:var(--mdc-ripple-fg-size, 100%)}.mdc-ripple-surface[data-mdc-ripple-is-unbounded].mdc-ripple-upgraded::after,.mdc-ripple-upgraded--unbounded.mdc-ripple-upgraded::after{width:var(--mdc-ripple-fg-size, 100%);height:var(--mdc-ripple-fg-size, 100%)}.mdc-ripple-surface::before,.mdc-ripple-surface::after{background-color:#000;background-color:var(--mdc-ripple-color, #000)}.mdc-ripple-surface:hover::before,.mdc-ripple-surface.mdc-ripple-surface--hover::before{opacity:0.04;opacity:var(--mdc-ripple-hover-opacity, 0.04)}.mdc-ripple-surface.mdc-ripple-upgraded--background-focused::before,.mdc-ripple-surface:not(.mdc-ripple-upgraded):focus::before{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-focus-opacity, 0.12)}.mdc-ripple-surface:not(.mdc-ripple-upgraded)::after{transition:opacity 150ms linear}.mdc-ripple-surface:not(.mdc-ripple-upgraded):active::after{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-press-opacity, 0.12)}.mdc-ripple-surface.mdc-ripple-upgraded{--mdc-ripple-fg-opacity:var(--mdc-ripple-press-opacity, 0.12)}@keyframes mdc-ripple-fg-radius-in{from{animation-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transform:translate(var(--mdc-ripple-fg-translate-start, 0)) scale(1)}to{transform:translate(var(--mdc-ripple-fg-translate-end, 0)) scale(var(--mdc-ripple-fg-scale, 1))}}@keyframes mdc-ripple-fg-opacity-in{from{animation-timing-function:linear;opacity:0}to{opacity:var(--mdc-ripple-fg-opacity, 0)}}@keyframes mdc-ripple-fg-opacity-out{from{animation-timing-function:linear;opacity:var(--mdc-ripple-fg-opacity, 0)}to{opacity:0}}:host{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;display:block}:host .mdc-ripple-surface{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;will-change:unset}.mdc-ripple-surface--primary::before,.mdc-ripple-surface--primary::after{background-color:#6200ee;background-color:var(--mdc-ripple-color, var(--mdc-theme-primary, #6200ee))}.mdc-ripple-surface--primary:hover::before,.mdc-ripple-surface--primary.mdc-ripple-surface--hover::before{opacity:0.04;opacity:var(--mdc-ripple-hover-opacity, 0.04)}.mdc-ripple-surface--primary.mdc-ripple-upgraded--background-focused::before,.mdc-ripple-surface--primary:not(.mdc-ripple-upgraded):focus::before{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-focus-opacity, 0.12)}.mdc-ripple-surface--primary:not(.mdc-ripple-upgraded)::after{transition:opacity 150ms linear}.mdc-ripple-surface--primary:not(.mdc-ripple-upgraded):active::after{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-press-opacity, 0.12)}.mdc-ripple-surface--primary.mdc-ripple-upgraded{--mdc-ripple-fg-opacity:var(--mdc-ripple-press-opacity, 0.12)}.mdc-ripple-surface--primary--activated::before{opacity:0.12;opacity:var(--mdc-ripple-activated-opacity, 0.12)}.mdc-ripple-surface--primary--activated::before,.mdc-ripple-surface--primary--activated::after{background-color:#6200ee;background-color:var(--mdc-ripple-color, var(--mdc-theme-primary, #6200ee))}.mdc-ripple-surface--primary--activated:hover::before,.mdc-ripple-surface--primary--activated.mdc-ripple-surface--hover::before{opacity:0.16;opacity:var(--mdc-ripple-hover-opacity, 0.16)}.mdc-ripple-surface--primary--activated.mdc-ripple-upgraded--background-focused::before,.mdc-ripple-surface--primary--activated:not(.mdc-ripple-upgraded):focus::before{transition-duration:75ms;opacity:0.24;opacity:var(--mdc-ripple-focus-opacity, 0.24)}.mdc-ripple-surface--primary--activated:not(.mdc-ripple-upgraded)::after{transition:opacity 150ms linear}.mdc-ripple-surface--primary--activated:not(.mdc-ripple-upgraded):active::after{transition-duration:75ms;opacity:0.24;opacity:var(--mdc-ripple-press-opacity, 0.24)}.mdc-ripple-surface--primary--activated.mdc-ripple-upgraded{--mdc-ripple-fg-opacity:var(--mdc-ripple-press-opacity, 0.24)}.mdc-ripple-surface--primary--selected::before{opacity:0.08;opacity:var(--mdc-ripple-selected-opacity, 0.08)}.mdc-ripple-surface--primary--selected::before,.mdc-ripple-surface--primary--selected::after{background-color:#6200ee;background-color:var(--mdc-ripple-color, var(--mdc-theme-primary, #6200ee))}.mdc-ripple-surface--primary--selected:hover::before,.mdc-ripple-surface--primary--selected.mdc-ripple-surface--hover::before{opacity:0.12;opacity:var(--mdc-ripple-hover-opacity, 0.12)}.mdc-ripple-surface--primary--selected.mdc-ripple-upgraded--background-focused::before,.mdc-ripple-surface--primary--selected:not(.mdc-ripple-upgraded):focus::before{transition-duration:75ms;opacity:0.2;opacity:var(--mdc-ripple-focus-opacity, 0.2)}.mdc-ripple-surface--primary--selected:not(.mdc-ripple-upgraded)::after{transition:opacity 150ms linear}.mdc-ripple-surface--primary--selected:not(.mdc-ripple-upgraded):active::after{transition-duration:75ms;opacity:0.2;opacity:var(--mdc-ripple-press-opacity, 0.2)}.mdc-ripple-surface--primary--selected.mdc-ripple-upgraded{--mdc-ripple-fg-opacity:var(--mdc-ripple-press-opacity, 0.2)}.mdc-ripple-surface--accent::before,.mdc-ripple-surface--accent::after{background-color:#018786;background-color:var(--mdc-ripple-color, var(--mdc-theme-secondary, #018786))}.mdc-ripple-surface--accent:hover::before,.mdc-ripple-surface--accent.mdc-ripple-surface--hover::before{opacity:0.04;opacity:var(--mdc-ripple-hover-opacity, 0.04)}.mdc-ripple-surface--accent.mdc-ripple-upgraded--background-focused::before,.mdc-ripple-surface--accent:not(.mdc-ripple-upgraded):focus::before{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-focus-opacity, 0.12)}.mdc-ripple-surface--accent:not(.mdc-ripple-upgraded)::after{transition:opacity 150ms linear}.mdc-ripple-surface--accent:not(.mdc-ripple-upgraded):active::after{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-press-opacity, 0.12)}.mdc-ripple-surface--accent.mdc-ripple-upgraded{--mdc-ripple-fg-opacity:var(--mdc-ripple-press-opacity, 0.12)}.mdc-ripple-surface--accent--activated::before{opacity:0.12;opacity:var(--mdc-ripple-activated-opacity, 0.12)}.mdc-ripple-surface--accent--activated::before,.mdc-ripple-surface--accent--activated::after{background-color:#018786;background-color:var(--mdc-ripple-color, var(--mdc-theme-secondary, #018786))}.mdc-ripple-surface--accent--activated:hover::before,.mdc-ripple-surface--accent--activated.mdc-ripple-surface--hover::before{opacity:0.16;opacity:var(--mdc-ripple-hover-opacity, 0.16)}.mdc-ripple-surface--accent--activated.mdc-ripple-upgraded--background-focused::before,.mdc-ripple-surface--accent--activated:not(.mdc-ripple-upgraded):focus::before{transition-duration:75ms;opacity:0.24;opacity:var(--mdc-ripple-focus-opacity, 0.24)}.mdc-ripple-surface--accent--activated:not(.mdc-ripple-upgraded)::after{transition:opacity 150ms linear}.mdc-ripple-surface--accent--activated:not(.mdc-ripple-upgraded):active::after{transition-duration:75ms;opacity:0.24;opacity:var(--mdc-ripple-press-opacity, 0.24)}.mdc-ripple-surface--accent--activated.mdc-ripple-upgraded{--mdc-ripple-fg-opacity:var(--mdc-ripple-press-opacity, 0.24)}.mdc-ripple-surface--accent--selected::before{opacity:0.08;opacity:var(--mdc-ripple-selected-opacity, 0.08)}.mdc-ripple-surface--accent--selected::before,.mdc-ripple-surface--accent--selected::after{background-color:#018786;background-color:var(--mdc-ripple-color, var(--mdc-theme-secondary, #018786))}.mdc-ripple-surface--accent--selected:hover::before,.mdc-ripple-surface--accent--selected.mdc-ripple-surface--hover::before{opacity:0.12;opacity:var(--mdc-ripple-hover-opacity, 0.12)}.mdc-ripple-surface--accent--selected.mdc-ripple-upgraded--background-focused::before,.mdc-ripple-surface--accent--selected:not(.mdc-ripple-upgraded):focus::before{transition-duration:75ms;opacity:0.2;opacity:var(--mdc-ripple-focus-opacity, 0.2)}.mdc-ripple-surface--accent--selected:not(.mdc-ripple-upgraded)::after{transition:opacity 150ms linear}.mdc-ripple-surface--accent--selected:not(.mdc-ripple-upgraded):active::after{transition-duration:75ms;opacity:0.2;opacity:var(--mdc-ripple-press-opacity, 0.2)}.mdc-ripple-surface--accent--selected.mdc-ripple-upgraded{--mdc-ripple-fg-opacity:var(--mdc-ripple-press-opacity, 0.2)}.mdc-ripple-surface--disabled{opacity:0}.mdc-ripple-surface--internal-use-state-layer-custom-properties::before,.mdc-ripple-surface--internal-use-state-layer-custom-properties::after{background-color:#000;background-color:var(--mdc-ripple-hover-state-layer-color, #000)}.mdc-ripple-surface--internal-use-state-layer-custom-properties:hover::before,.mdc-ripple-surface--internal-use-state-layer-custom-properties.mdc-ripple-surface--hover::before{opacity:0.04;opacity:var(--mdc-ripple-hover-state-layer-opacity, 0.04)}.mdc-ripple-surface--internal-use-state-layer-custom-properties.mdc-ripple-upgraded--background-focused::before,.mdc-ripple-surface--internal-use-state-layer-custom-properties:not(.mdc-ripple-upgraded):focus::before{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-focus-state-layer-opacity, 0.12)}.mdc-ripple-surface--internal-use-state-layer-custom-properties:not(.mdc-ripple-upgraded)::after{transition:opacity 150ms linear}.mdc-ripple-surface--internal-use-state-layer-custom-properties:not(.mdc-ripple-upgraded):active::after{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-pressed-state-layer-opacity, 0.12)}.mdc-ripple-surface--internal-use-state-layer-custom-properties.mdc-ripple-upgraded{--mdc-ripple-fg-opacity:var(--mdc-ripple-pressed-state-layer-opacity, 0.12)}` -/** - * @license - * Copyright 2021 Google LLC - * SPDX-LIcense-Identifier: Apache-2.0 - */,Um=Nc`mwc-list ::slotted([mwc-list-item]:not([twoline])),mwc-list ::slotted([noninteractive]:not([twoline])){height:var(--mdc-menu-item-height, 48px)}` -/** - * @license - * Copyright 2021 Google LLC - * SPDX-LIcense-Identifier: Apache-2.0 - */,zm=Nc`.mdc-menu-surface{display:none;position:absolute;box-sizing:border-box;max-width:calc(100vw - 32px);max-width:var(--mdc-menu-max-width, calc(100vw - 32px));max-height:calc(100vh - 32px);max-height:var(--mdc-menu-max-height, calc(100vh - 32px));margin:0;padding:0;transform:scale(1);transform-origin:top left;opacity:0;overflow:auto;will-change:transform,opacity;z-index:8;transition:opacity .03s linear,transform .12s cubic-bezier(0, 0, 0.2, 1),height 250ms cubic-bezier(0, 0, 0.2, 1);box-shadow:0px 5px 5px -3px rgba(0, 0, 0, 0.2),0px 8px 10px 1px rgba(0, 0, 0, 0.14),0px 3px 14px 2px rgba(0,0,0,.12);background-color:#fff;background-color:var(--mdc-theme-surface, #fff);color:#000;color:var(--mdc-theme-on-surface, #000);border-radius:4px;border-radius:var(--mdc-shape-medium, 4px);transform-origin-left:top left;transform-origin-right:top right}.mdc-menu-surface:focus{outline:none}.mdc-menu-surface--animating-open{display:inline-block;transform:scale(0.8);opacity:0}.mdc-menu-surface--open{display:inline-block;transform:scale(1);opacity:1}.mdc-menu-surface--animating-closed{display:inline-block;opacity:0;transition:opacity .075s linear}[dir=rtl] .mdc-menu-surface,.mdc-menu-surface[dir=rtl]{transform-origin-left:top right;transform-origin-right:top left}.mdc-menu-surface--anchor{position:relative;overflow:visible}.mdc-menu-surface--fixed{position:fixed}.mdc-menu-surface--fullwidth{width:100%}:host(:not([open])){display:none}.mdc-menu-surface{z-index:8;z-index:var(--mdc-menu-z-index, 8);min-width:112px;min-width:var(--mdc-menu-min-width, 112px)}` -/** - * @license - * Copyright 2021 Google LLC - * SPDX-LIcense-Identifier: Apache-2.0 - */,Fm=((t,...e)=>{const i=1===t.length?t[0]:e.reduce((e,i,s)=>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[s+1],t[0]);return new Tu(i,t,Su)})`.mdc-notched-outline{display:flex;position:absolute;top:0;right:0;left:0;box-sizing:border-box;width:100%;max-width:100%;height:100%;text-align:left;pointer-events:none}[dir=rtl] .mdc-notched-outline,.mdc-notched-outline[dir=rtl]{text-align:right}.mdc-notched-outline__leading,.mdc-notched-outline__notch,.mdc-notched-outline__trailing{box-sizing:border-box;height:100%;border-top:1px solid;border-bottom:1px solid;pointer-events:none}.mdc-notched-outline__leading{border-left:1px solid;border-right:none;width:12px}[dir=rtl] .mdc-notched-outline__leading,.mdc-notched-outline__leading[dir=rtl]{border-left:none;border-right:1px solid}.mdc-notched-outline__trailing{border-left:none;border-right:1px solid;flex-grow:1}[dir=rtl] .mdc-notched-outline__trailing,.mdc-notched-outline__trailing[dir=rtl]{border-left:1px solid;border-right:none}.mdc-notched-outline__notch{flex:0 0 auto;width:auto;max-width:calc(100% - 12px * 2)}.mdc-notched-outline .mdc-floating-label{display:inline-block;position:relative;max-width:100%}.mdc-notched-outline .mdc-floating-label--float-above{text-overflow:clip}.mdc-notched-outline--upgraded .mdc-floating-label--float-above{max-width:calc(100% / 0.75)}.mdc-notched-outline--notched .mdc-notched-outline__notch{padding-left:0;padding-right:8px;border-top:none}[dir=rtl] .mdc-notched-outline--notched .mdc-notched-outline__notch,.mdc-notched-outline--notched .mdc-notched-outline__notch[dir=rtl]{padding-left:8px;padding-right:0}.mdc-notched-outline--no-label .mdc-notched-outline__notch{display:none}:host{display:block;position:absolute;right:0;left:0;box-sizing:border-box;width:100%;max-width:100%;height:100%;text-align:left;pointer-events:none}[dir=rtl] :host,:host([dir=rtl]){text-align:right}::slotted(.mdc-floating-label){display:inline-block;position:relative;top:17px;bottom:auto;max-width:100%}::slotted(.mdc-floating-label--float-above){text-overflow:clip}.mdc-notched-outline--upgraded ::slotted(.mdc-floating-label--float-above){max-width:calc(100% / 0.75)}.mdc-notched-outline .mdc-notched-outline__leading{border-top-left-radius:4px;border-top-left-radius:var(--mdc-shape-small, 4px);border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:4px;border-bottom-left-radius:var(--mdc-shape-small, 4px)}[dir=rtl] .mdc-notched-outline .mdc-notched-outline__leading,.mdc-notched-outline .mdc-notched-outline__leading[dir=rtl]{border-top-left-radius:0;border-top-right-radius:4px;border-top-right-radius:var(--mdc-shape-small, 4px);border-bottom-right-radius:4px;border-bottom-right-radius:var(--mdc-shape-small, 4px);border-bottom-left-radius:0}@supports(top: max(0%)){.mdc-notched-outline .mdc-notched-outline__leading{width:max(12px, var(--mdc-shape-small, 4px))}}@supports(top: max(0%)){.mdc-notched-outline .mdc-notched-outline__notch{max-width:calc(100% - max(12px, var(--mdc-shape-small, 4px)) * 2)}}.mdc-notched-outline .mdc-notched-outline__trailing{border-top-left-radius:0;border-top-right-radius:4px;border-top-right-radius:var(--mdc-shape-small, 4px);border-bottom-right-radius:4px;border-bottom-right-radius:var(--mdc-shape-small, 4px);border-bottom-left-radius:0}[dir=rtl] .mdc-notched-outline .mdc-notched-outline__trailing,.mdc-notched-outline .mdc-notched-outline__trailing[dir=rtl]{border-top-left-radius:4px;border-top-left-radius:var(--mdc-shape-small, 4px);border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:4px;border-bottom-left-radius:var(--mdc-shape-small, 4px)}.mdc-notched-outline__leading,.mdc-notched-outline__notch,.mdc-notched-outline__trailing{border-color:var(--mdc-notched-outline-border-color, var(--mdc-theme-primary, #6200ee));border-width:1px;border-width:var(--mdc-notched-outline-stroke-width, 1px)}.mdc-notched-outline--notched .mdc-notched-outline__notch{padding-top:0;padding-top:var(--mdc-notched-outline-notch-offset, 0)}`,Bm={"mwc-select":class extends gl{static get styles(){return Mm}},"mwc-list":class extends vc{static get styles(){return Nm}},"mwc-list-item":class extends $c{static get styles(){return Dm}},"mwc-ripple":class extends _u{static get styles(){return Hm}},"mwc-menu":class extends jh{static get styles(){return Um}},"mwc-menu-surface":class extends Gh{static get styles(){return zm}},"mwc-notched-outline":class extends Lm{static get styles(){return Fm}}};function Vm(t,e,i){if(void 0!==e) -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -return function(t,e,i){const s=t.constructor;if(!i){const t=`__${e}`;if(!(i=s.getPropertyDescriptor(e,t)))throw new Error("@ariaProperty must be used after a @property decorator")}const n=i;let r="";if(!n.set)throw new Error(`@ariaProperty requires a setter for ${e}`);if(t.dispatchWizEvent)return i;const o={configurable:!0,enumerable:!0,set(t){if(""===r){const t=s.getPropertyOptions(e);r="string"==typeof t.attribute?t.attribute:e}this.hasAttribute(r)&&this.removeAttribute(r),n.set.call(this,t)}};return n.get&&(o.get=function(){return n.get.call(this)}),o}(t,e,i);throw new Error("@ariaProperty only supports TypeScript Decorators")} -/** - * @license - * Copyright 2016 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */var jm=function(){function t(t){void 0===t&&(t={}),this.adapter=t}return Object.defineProperty(t,"cssClasses",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"strings",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"numbers",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"defaultAdapter",{get:function(){return{}},enumerable:!1,configurable:!0}),t.prototype.init=function(){},t.prototype.destroy=function(){},t}(),Wm={CHECKED:"mdc-switch--checked",DISABLED:"mdc-switch--disabled"},qm={ARIA_CHECKED_ATTR:"aria-checked",NATIVE_CONTROL_SELECTOR:".mdc-switch__native-control",RIPPLE_SURFACE_SELECTOR:".mdc-switch__thumb-underlay"},Ym=function(t){function e(i){return t.call(this,s(s({},e.defaultAdapter),i))||this}return i(e,t),Object.defineProperty(e,"strings",{get:function(){return qm},enumerable:!1,configurable:!0}),Object.defineProperty(e,"cssClasses",{get:function(){return Wm},enumerable:!1,configurable:!0}),Object.defineProperty(e,"defaultAdapter",{get:function(){return{addClass:function(){},removeClass:function(){},setNativeControlChecked:function(){},setNativeControlDisabled:function(){},setNativeControlAttr:function(){}}},enumerable:!1,configurable:!0}),e.prototype.setChecked=function(t){this.adapter.setNativeControlChecked(t),this.updateAriaChecked(t),this.updateCheckedStyling(t)},e.prototype.setDisabled=function(t){this.adapter.setNativeControlDisabled(t),t?this.adapter.addClass(Wm.DISABLED):this.adapter.removeClass(Wm.DISABLED)},e.prototype.handleChange=function(t){var e=t.target;this.updateAriaChecked(e.checked),this.updateCheckedStyling(e.checked)},e.prototype.updateCheckedStyling=function(t){t?this.adapter.addClass(Wm.CHECKED):this.adapter.removeClass(Wm.CHECKED)},e.prototype.updateAriaChecked=function(t){this.adapter.setNativeControlAttr(qm.ARIA_CHECKED_ATTR,""+!!t)},e}(jm); -/** - * @license - * Copyright 2018 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const Xm=window,Gm=Xm.ShadowRoot&&(void 0===Xm.ShadyCSS||Xm.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,Km=Symbol(),Jm=new WeakMap;let Zm=class{constructor(t,e,i){if(this._$cssResult$=!0,i!==Km)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(Gm&&void 0===t){const i=void 0!==e&&1===e.length;i&&(t=Jm.get(e)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&Jm.set(e,t))}return t}toString(){return this.cssText}};const Qm=Gm?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new Zm("string"==typeof t?t:t+"",void 0,Km))(e)})(t):t; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */var tf;const ef=window,sf=ef.trustedTypes,nf=sf?sf.emptyScript:"",rf=ef.reactiveElementPolyfillSupport,of={toAttribute(t,e){switch(e){case Boolean:t=t?nf: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}},af=(t,e)=>e!==t&&(e==e||t==t),lf={attribute:!0,type:String,converter:of,reflect:!1,hasChanged:af},df="finalized";let cf=class extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(t){var e;this.finalize(),(null!==(e=this.h)&&void 0!==e?e:this.h=[]).push(t)}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach((e,i)=>{const s=this._$Ep(i,e);void 0!==s&&(this._$Ev.set(s,i),t.push(s))}),t}static createProperty(t,e=lf){if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){const i="symbol"==typeof t?Symbol():"__"+t,s=this.getPropertyDescriptor(t,i,e);void 0!==s&&Object.defineProperty(this.prototype,t,s)}}static getPropertyDescriptor(t,e,i){return{get(){return this[e]},set(s){const n=this[t];this[e]=s,this.requestUpdate(t,n,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||lf}static finalize(){if(this.hasOwnProperty(df))return!1;this[df]=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),void 0!==t.h&&(this.h=[...t.h]),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,e=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const i of e)this.createProperty(i,t[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}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(Qm(t))}else void 0!==t&&e.push(Qm(t));return e}static _$Ep(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}_$Eu(){var t;this._$E_=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach(t=>t(this))}addController(t){var e,i;(null!==(e=this._$ES)&&void 0!==e?e:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(i=t.hostConnected)||void 0===i||i.call(t))}removeController(t){var e;null===(e=this._$ES)||void 0===e||e.splice(this._$ES.indexOf(t)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach((t,e)=>{this.hasOwnProperty(e)&&(this._$Ei.set(e,this[e]),delete this[e])})}createRenderRoot(){var t;const e=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return((t,e)=>{Gm?t.adoptedStyleSheets=e.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet):e.forEach(e=>{const i=document.createElement("style"),s=Xm.litNonce;void 0!==s&&i.setAttribute("nonce",s),i.textContent=e.cssText,t.appendChild(i)})})(e,this.constructor.elementStyles),e}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)})}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)})}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$EO(t,e,i=lf){var s;const n=this.constructor._$Ep(t,i);if(void 0!==n&&!0===i.reflect){const r=(void 0!==(null===(s=i.converter)||void 0===s?void 0:s.toAttribute)?i.converter:of).toAttribute(e,i.type);this._$El=t,null==r?this.removeAttribute(n):this.setAttribute(n,r),this._$El=null}}_$AK(t,e){var i;const s=this.constructor,n=s._$Ev.get(t);if(void 0!==n&&this._$El!==n){const t=s.getPropertyOptions(n),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(i=t.converter)||void 0===i?void 0:i.fromAttribute)?t.converter:of;this._$El=n,this[n]=r.fromAttribute(e,t.type),this._$El=null}}requestUpdate(t,e,i){let s=!0;void 0!==t&&(((i=i||this.constructor.getPropertyOptions(t)).hasChanged||af)(this[t],e)?(this._$AL.has(t)||this._$AL.set(t,e),!0===i.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,i))):s=!1),!this.isUpdatePending&&s&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach((t,e)=>this[e]=t),this._$Ei=void 0);let e=!1;const i=this._$AL;try{e=this.shouldUpdate(i),e?(this.willUpdate(i),null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)}),this.update(i)):this._$Ek()}catch(t){throw e=!1,this._$Ek(),t}e&&this._$AE(i)}willUpdate(t){}_$AE(t){var e;null===(e=this._$ES)||void 0===e||e.forEach(t=>{var e;return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)}),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return!0}update(t){void 0!==this._$EC&&(this._$EC.forEach((t,e)=>this._$EO(e,this[e],t)),this._$EC=void 0),this._$Ek()}updated(t){}firstUpdated(t){}}; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -var hf;cf[df]=!0,cf.elementProperties=new Map,cf.elementStyles=[],cf.shadowRootOptions={mode:"open"},null==rf||rf({ReactiveElement:cf}),(null!==(tf=ef.reactiveElementVersions)&&void 0!==tf?tf:ef.reactiveElementVersions=[]).push("1.6.3");const pf=window,uf=pf.trustedTypes,mf=uf?uf.createPolicy("lit-html",{createHTML:t=>t}):void 0,ff="$lit$",gf=`lit$${(Math.random()+"").slice(9)}$`,vf="?"+gf,_f=`<${vf}>`,bf=document,yf=()=>bf.createComment(""),xf=t=>null===t||"object"!=typeof t&&"function"!=typeof t,$f=Array.isArray,wf="[ \t\n\f\r]",Af=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Ef=/-->/g,Sf=/>/g,Cf=RegExp(`>|${wf}(?:([^\\s"'>=/]+)(${wf}*=${wf}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),Tf=/'/g,If=/"/g,Of=/^(?:script|style|textarea|title)$/i,kf=(t=>(e,...i)=>({_$litType$:t,strings:e,values:i}))(1),Rf=Symbol.for("lit-noChange"),Pf=Symbol.for("lit-nothing"),Lf=new WeakMap,Mf=bf.createTreeWalker(bf,129,null,!1);function Nf(t,e){if(!Array.isArray(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==mf?mf.createHTML(e):e}let Df=class t{constructor({strings:e,_$litType$:i},s){let n;this.parts=[];let r=0,o=0;const a=e.length-1,l=this.parts,[d,c]=((t,e)=>{const i=t.length-1,s=[];let n,r=2===e?"":"",o=Af;for(let e=0;e"===l[0]?(o=null!=n?n:Af,d=-1):void 0===l[1]?d=-2:(d=o.lastIndex-l[2].length,a=l[1],o=void 0===l[3]?Cf:'"'===l[3]?If:Tf):o===If||o===Tf?o=Cf:o===Ef||o===Sf?o=Af:(o=Cf,n=void 0);const h=o===Cf&&t[e+1].startsWith("/>")?" ":"";r+=o===Af?i+_f:d>=0?(s.push(a),i.slice(0,d)+ff+i.slice(d)+gf+h):i+gf+(-2===d?(s.push(void 0),e):h)}return[Nf(t,r+(t[i]||"")+(2===e?"":"")),s]})(e,i);if(this.el=t.createElement(d,s),Mf.currentNode=this.el.content,2===i){const t=this.el.content,e=t.firstChild;e.remove(),t.append(...e.childNodes)}for(;null!==(n=Mf.nextNode())&&l.length0){n.textContent=uf?uf.emptyScript:"";for(let i=0;i$f(t)||"function"==typeof(null==t?void 0: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!==Pf&&xf(this._$AH)?this._$AA.nextSibling.data=t:this.$(bf.createTextNode(t)),this._$AH=t}g(t){var e;const{values:i,_$litType$:s}=t,n="number"==typeof s?this._$AC(t):(void 0===s.el&&(s.el=Df.createElement(Nf(s.h,s.h[0]),this.options)),s);if((null===(e=this._$AH)||void 0===e?void 0:e._$AD)===n)this._$AH.v(i);else{const t=new Uf(n,this),e=t.u(this.options);t.v(i),this.$(e),this._$AH=t}}_$AC(t){let e=Lf.get(t.strings);return void 0===e&&Lf.set(t.strings,e=new Df(t)),e}T(e){$f(this._$AH)||(this._$AH=[],this._$AR());const i=this._$AH;let s,n=0;for(const r of e)n===i.length?i.push(s=new t(this.k(yf()),this.k(yf()),this,this.options)):s=i[n],s._$AI(r),n++;n2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=Pf}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(t,e=this,i,s){const n=this.strings;let r=!1;if(void 0===n)t=Hf(this,t,e,0),r=!xf(t)||t!==this._$AH&&t!==Rf,r&&(this._$AH=t);else{const s=t;let o,a;for(t=n[0],o=0;o{var s,n;const r=null!==(s=null==i?void 0:i.renderBefore)&&void 0!==s?s:e;let o=r._$litPart$;if(void 0===o){const t=null!==(n=null==i?void 0:i.renderBefore)&&void 0!==n?n:null;r._$litPart$=o=new zf(e.insertBefore(yf(),t),t,void 0,null!=i?i:{})}return o._$AI(t),o})(e,this.renderRoot,this.renderOptions)}connectedCallback(){var t;super.connectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!0)}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!1)}render(){return Rf}};Kf.finalized=!0,Kf._$litElement$=!0,null===(Xf=globalThis.litElementHydrateSupport)||void 0===Xf||Xf.call(globalThis,{LitElement:Kf});const Jf=globalThis.litElementPolyfillSupport;null==Jf||Jf({LitElement:Kf}),(null!==(Gf=globalThis.litElementVersions)&&void 0!==Gf?Gf:globalThis.litElementVersions=[]).push("3.3.3"); -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const Zf=(t,e)=>"method"===e.kind&&e.descriptor&&!("value"in e.descriptor)?{...e,finisher(i){i.createProperty(e.key,t)}}:{kind:"field",key:Symbol(),placement:"own",descriptor:{},originalKey:e.key,initializer(){"function"==typeof e.initializer&&(this[e.key]=e.initializer.call(this))},finisher(i){i.createProperty(e.key,t)}};function Qf(t){return(e,i)=>void 0!==i?((t,e,i)=>{e.constructor.createProperty(i,t)})(t,e,i):Zf(t,e)} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const tg=({finisher:t,descriptor:e})=>(i,s)=>{var n;if(void 0===s){const s=null!==(n=i.originalKey)&&void 0!==n?n:i.key,r=null!=e?{kind:"method",placement:"prototype",key:s,descriptor:e(i.key)}:{...i,key:s};return null!=t&&(r.finisher=function(e){t(e,s)}),r}{const n=i.constructor;void 0!==e&&Object.defineProperty(i,s,e(s)),null==t||t(n,s)}}; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */function eg(t){return tg({finisher:(e,i)=>{Object.assign(e.prototype[i],t)}})} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */function ig(t,e){return tg({descriptor:e=>{const i={get(){var e,i;return null!==(i=null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(t))&&void 0!==i?i:null},enumerable:!0,configurable:!0};return i}})} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -var sg;null===(sg=window.HTMLSlotElement)||void 0===sg||sg.prototype.assignedElements; -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const ng=t=>null!=t?t:Pf; -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */class rg extends Qi{constructor(){super(...arguments),this.checked=!1,this.disabled=!1,this.shouldRenderRipple=!1,this.mdcFoundationClass=Ym,this.rippleHandlers=new _c(()=>(this.shouldRenderRipple=!0,this.ripple))}changeHandler(t){this.mdcFoundation.handleChange(t),this.checked=this.formElement.checked}createAdapter(){return Object.assign(Object.assign({},Xi(this.mdcRoot)),{setNativeControlChecked:t=>{this.formElement.checked=t},setNativeControlDisabled:t=>{this.formElement.disabled=t},setNativeControlAttr:(t,e)=>{this.formElement.setAttribute(t,e)}})}renderRipple(){return this.shouldRenderRipple?kf` - - `:""}focus(){const t=this.formElement;t&&(this.rippleHandlers.startFocus(),t.focus())}blur(){const t=this.formElement;t&&(this.rippleHandlers.endFocus(),t.blur())}click(){this.formElement&&!this.disabled&&(this.formElement.focus(),this.formElement.click())}firstUpdated(){super.firstUpdated(),this.shadowRoot&&this.mdcRoot.addEventListener("change",t=>{this.dispatchEvent(new Event("change",t))})}render(){return kf` -
-
-
- ${this.renderRipple()} -
- -
-
-
`}handleRippleMouseDown(t){const e=()=>{window.removeEventListener("mouseup",e),this.handleRippleDeactivate()};window.addEventListener("mouseup",e),this.rippleHandlers.startPress(t)}handleRippleTouchStart(t){this.rippleHandlers.startPress(t)}handleRippleDeactivate(){this.rippleHandlers.endPress()}handleRippleMouseEnter(){this.rippleHandlers.startHover()}handleRippleMouseLeave(){this.rippleHandlers.endHover()}handleRippleFocus(){this.rippleHandlers.startFocus()}handleRippleBlur(){this.rippleHandlers.endFocus()}}n([Qf({type:Boolean}),os(function(t){this.mdcFoundation.setChecked(t)})],rg.prototype,"checked",void 0),n([Qf({type:Boolean}),os(function(t){this.mdcFoundation.setDisabled(t)})],rg.prototype,"disabled",void 0),n([Vm,Qf({attribute:"aria-label"})],rg.prototype,"ariaLabel",void 0),n([Vm,Qf({attribute:"aria-labelledby"})],rg.prototype,"ariaLabelledBy",void 0),n([ig(".mdc-switch")],rg.prototype,"mdcRoot",void 0),n([ig("input")],rg.prototype,"formElement",void 0),n([function(t){return tg({descriptor:e=>({async get(){var e;return await this.updateComplete,null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(t)},enumerable:!0,configurable:!0})})}("mwc-ripple")],rg.prototype,"ripple",void 0),n([function(t){return Qf({...t,state:!0})}()],rg.prototype,"shouldRenderRipple",void 0),n([eg({passive:!0})],rg.prototype,"handleRippleMouseDown",null),n([eg({passive:!0})],rg.prototype,"handleRippleTouchStart",null); -/** - * @license - * Copyright 2021 Google LLC - * SPDX-LIcense-Identifier: Apache-2.0 - */ -const og=((t,...e)=>{const i=1===t.length?t[0]:e.reduce((e,i,s)=>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[s+1],t[0]);return new Zm(i,t,Km)})`.mdc-switch__thumb-underlay{left:-14px;right:initial;top:-17px;width:48px;height:48px}[dir=rtl] .mdc-switch__thumb-underlay,.mdc-switch__thumb-underlay[dir=rtl]{left:initial;right:-14px}.mdc-switch__native-control{width:64px;height:48px}.mdc-switch{display:inline-block;position:relative;outline:none;user-select:none}.mdc-switch.mdc-switch--checked .mdc-switch__track{background-color:#018786;background-color:var(--mdc-theme-secondary, #018786)}.mdc-switch.mdc-switch--checked .mdc-switch__thumb{background-color:#018786;background-color:var(--mdc-theme-secondary, #018786);border-color:#018786;border-color:var(--mdc-theme-secondary, #018786)}.mdc-switch:not(.mdc-switch--checked) .mdc-switch__track{background-color:#000;background-color:var(--mdc-theme-on-surface, #000)}.mdc-switch:not(.mdc-switch--checked) .mdc-switch__thumb{background-color:#fff;background-color:var(--mdc-theme-surface, #fff);border-color:#fff;border-color:var(--mdc-theme-surface, #fff)}.mdc-switch__native-control{left:0;right:initial;position:absolute;top:0;margin:0;opacity:0;cursor:pointer;pointer-events:auto;transition:transform 90ms cubic-bezier(0.4, 0, 0.2, 1)}[dir=rtl] .mdc-switch__native-control,.mdc-switch__native-control[dir=rtl]{left:initial;right:0}.mdc-switch__track{box-sizing:border-box;width:36px;height:14px;border:1px solid transparent;border-radius:7px;opacity:.38;transition:opacity 90ms cubic-bezier(0.4, 0, 0.2, 1),background-color 90ms cubic-bezier(0.4, 0, 0.2, 1),border-color 90ms cubic-bezier(0.4, 0, 0.2, 1)}.mdc-switch__thumb-underlay{display:flex;position:absolute;align-items:center;justify-content:center;transform:translateX(0);transition:transform 90ms cubic-bezier(0.4, 0, 0.2, 1),background-color 90ms cubic-bezier(0.4, 0, 0.2, 1),border-color 90ms cubic-bezier(0.4, 0, 0.2, 1)}.mdc-switch__thumb{box-shadow:0px 3px 1px -2px rgba(0, 0, 0, 0.2),0px 2px 2px 0px rgba(0, 0, 0, 0.14),0px 1px 5px 0px rgba(0,0,0,.12);box-sizing:border-box;width:20px;height:20px;border:10px solid;border-radius:50%;pointer-events:none;z-index:1}.mdc-switch--checked .mdc-switch__track{opacity:.54}.mdc-switch--checked .mdc-switch__thumb-underlay{transform:translateX(16px)}[dir=rtl] .mdc-switch--checked .mdc-switch__thumb-underlay,.mdc-switch--checked .mdc-switch__thumb-underlay[dir=rtl]{transform:translateX(-16px)}.mdc-switch--checked .mdc-switch__native-control{transform:translateX(-16px)}[dir=rtl] .mdc-switch--checked .mdc-switch__native-control,.mdc-switch--checked .mdc-switch__native-control[dir=rtl]{transform:translateX(16px)}.mdc-switch--disabled{opacity:.38;pointer-events:none}.mdc-switch--disabled .mdc-switch__thumb{border-width:1px}.mdc-switch--disabled .mdc-switch__native-control{cursor:default;pointer-events:none}:host{display:inline-flex;outline:none;-webkit-tap-highlight-color:transparent}`,ag={"mwc-switch":class extends rg{static get styles(){return og}},"mwc-ripple":class extends _u{static get styles(){return Hm}}}; -/** - * @license - * Copyright 2016 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -var lg=function(){function t(t){void 0===t&&(t={}),this.adapter=t}return Object.defineProperty(t,"cssClasses",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"strings",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"numbers",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"defaultAdapter",{get:function(){return{}},enumerable:!1,configurable:!0}),t.prototype.init=function(){},t.prototype.destroy=function(){},t}(),dg={ARIA_CONTROLS:"aria-controls",ARIA_DESCRIBEDBY:"aria-describedby",INPUT_SELECTOR:".mdc-text-field__input",LABEL_SELECTOR:".mdc-floating-label",LEADING_ICON_SELECTOR:".mdc-text-field__icon--leading",LINE_RIPPLE_SELECTOR:".mdc-line-ripple",OUTLINE_SELECTOR:".mdc-notched-outline",PREFIX_SELECTOR:".mdc-text-field__affix--prefix",SUFFIX_SELECTOR:".mdc-text-field__affix--suffix",TRAILING_ICON_SELECTOR:".mdc-text-field__icon--trailing"},cg={DISABLED:"mdc-text-field--disabled",FOCUSED:"mdc-text-field--focused",HELPER_LINE:"mdc-text-field-helper-line",INVALID:"mdc-text-field--invalid",LABEL_FLOATING:"mdc-text-field--label-floating",NO_LABEL:"mdc-text-field--no-label",OUTLINED:"mdc-text-field--outlined",ROOT:"mdc-text-field",TEXTAREA:"mdc-text-field--textarea",WITH_LEADING_ICON:"mdc-text-field--with-leading-icon",WITH_TRAILING_ICON:"mdc-text-field--with-trailing-icon",WITH_INTERNAL_COUNTER:"mdc-text-field--with-internal-counter"},hg={LABEL_SCALE:.75},pg=["pattern","min","max","required","step","minlength","maxlength"],ug=["color","date","datetime-local","month","range","time","week"],mg=["mousedown","touchstart"],fg=["click","keydown"],gg=function(t){function e(i,n){void 0===n&&(n={});var r=t.call(this,s(s({},e.defaultAdapter),i))||this;return r.isFocused=!1,r.receivedUserInput=!1,r.valid=!0,r.useNativeValidation=!0,r.validateOnValueChange=!0,r.helperText=n.helperText,r.characterCounter=n.characterCounter,r.leadingIcon=n.leadingIcon,r.trailingIcon=n.trailingIcon,r.inputFocusHandler=function(){r.activateFocus()},r.inputBlurHandler=function(){r.deactivateFocus()},r.inputInputHandler=function(){r.handleInput()},r.setPointerXOffset=function(t){r.setTransformOrigin(t)},r.textFieldInteractionHandler=function(){r.handleTextFieldInteraction()},r.validationAttributeChangeHandler=function(t){r.handleValidationAttributeChange(t)},r}return i(e,t),Object.defineProperty(e,"cssClasses",{get:function(){return cg},enumerable:!1,configurable:!0}),Object.defineProperty(e,"strings",{get:function(){return dg},enumerable:!1,configurable:!0}),Object.defineProperty(e,"numbers",{get:function(){return hg},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"shouldAlwaysFloat",{get:function(){var t=this.getNativeInput().type;return ug.indexOf(t)>=0},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"shouldFloat",{get:function(){return this.shouldAlwaysFloat||this.isFocused||!!this.getValue()||this.isBadInput()},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"shouldShake",{get:function(){return!this.isFocused&&!this.isValid()&&!!this.getValue()},enumerable:!1,configurable:!0}),Object.defineProperty(e,"defaultAdapter",{get:function(){return{addClass:function(){},removeClass:function(){},hasClass:function(){return!0},setInputAttr:function(){},removeInputAttr:function(){},registerTextFieldInteractionHandler:function(){},deregisterTextFieldInteractionHandler:function(){},registerInputInteractionHandler:function(){},deregisterInputInteractionHandler:function(){},registerValidationAttributeChangeHandler:function(){return new MutationObserver(function(){})},deregisterValidationAttributeChangeHandler:function(){},getNativeInput:function(){return null},isFocused:function(){return!1},activateLineRipple:function(){},deactivateLineRipple:function(){},setLineRippleTransformOrigin:function(){},shakeLabel:function(){},floatLabel:function(){},setLabelRequired:function(){},hasLabel:function(){return!1},getLabelWidth:function(){return 0},hasOutline:function(){return!1},notchOutline:function(){},closeOutline:function(){}}},enumerable:!1,configurable:!0}),e.prototype.init=function(){var t,e,i,s;this.adapter.hasLabel()&&this.getNativeInput().required&&this.adapter.setLabelRequired(!0),this.adapter.isFocused()?this.inputFocusHandler():this.adapter.hasLabel()&&this.shouldFloat&&(this.notchOutline(!0),this.adapter.floatLabel(!0),this.styleFloating(!0)),this.adapter.registerInputInteractionHandler("focus",this.inputFocusHandler),this.adapter.registerInputInteractionHandler("blur",this.inputBlurHandler),this.adapter.registerInputInteractionHandler("input",this.inputInputHandler);try{for(var n=r(mg),o=n.next();!o.done;o=n.next()){var a=o.value;this.adapter.registerInputInteractionHandler(a,this.setPointerXOffset)}}catch(e){t={error:e}}finally{try{o&&!o.done&&(e=n.return)&&e.call(n)}finally{if(t)throw t.error}}try{for(var l=r(fg),d=l.next();!d.done;d=l.next()){a=d.value;this.adapter.registerTextFieldInteractionHandler(a,this.textFieldInteractionHandler)}}catch(t){i={error:t}}finally{try{d&&!d.done&&(s=l.return)&&s.call(l)}finally{if(i)throw i.error}}this.validationObserver=this.adapter.registerValidationAttributeChangeHandler(this.validationAttributeChangeHandler),this.setcharacterCounter(this.getValue().length)},e.prototype.destroy=function(){var t,e,i,s;this.adapter.deregisterInputInteractionHandler("focus",this.inputFocusHandler),this.adapter.deregisterInputInteractionHandler("blur",this.inputBlurHandler),this.adapter.deregisterInputInteractionHandler("input",this.inputInputHandler);try{for(var n=r(mg),o=n.next();!o.done;o=n.next()){var a=o.value;this.adapter.deregisterInputInteractionHandler(a,this.setPointerXOffset)}}catch(e){t={error:e}}finally{try{o&&!o.done&&(e=n.return)&&e.call(n)}finally{if(t)throw t.error}}try{for(var l=r(fg),d=l.next();!d.done;d=l.next()){a=d.value;this.adapter.deregisterTextFieldInteractionHandler(a,this.textFieldInteractionHandler)}}catch(t){i={error:t}}finally{try{d&&!d.done&&(s=l.return)&&s.call(l)}finally{if(i)throw i.error}}this.adapter.deregisterValidationAttributeChangeHandler(this.validationObserver)},e.prototype.handleTextFieldInteraction=function(){var t=this.adapter.getNativeInput();t&&t.disabled||(this.receivedUserInput=!0)},e.prototype.handleValidationAttributeChange=function(t){var e=this;t.some(function(t){return pg.indexOf(t)>-1&&(e.styleValidity(!0),e.adapter.setLabelRequired(e.getNativeInput().required),!0)}),t.indexOf("maxlength")>-1&&this.setcharacterCounter(this.getValue().length)},e.prototype.notchOutline=function(t){if(this.adapter.hasOutline()&&this.adapter.hasLabel())if(t){var e=this.adapter.getLabelWidth()*hg.LABEL_SCALE;this.adapter.notchOutline(e)}else this.adapter.closeOutline()},e.prototype.activateFocus=function(){this.isFocused=!0,this.styleFocused(this.isFocused),this.adapter.activateLineRipple(),this.adapter.hasLabel()&&(this.notchOutline(this.shouldFloat),this.adapter.floatLabel(this.shouldFloat),this.styleFloating(this.shouldFloat),this.adapter.shakeLabel(this.shouldShake)),!this.helperText||!this.helperText.isPersistent()&&this.helperText.isValidation()&&this.valid||this.helperText.showToScreenReader()},e.prototype.setTransformOrigin=function(t){if(!this.isDisabled()&&!this.adapter.hasOutline()){var e=t.touches,i=e?e[0]:t,s=i.target.getBoundingClientRect(),n=i.clientX-s.left;this.adapter.setLineRippleTransformOrigin(n)}},e.prototype.handleInput=function(){this.autoCompleteFocus(),this.setcharacterCounter(this.getValue().length)},e.prototype.autoCompleteFocus=function(){this.receivedUserInput||this.activateFocus()},e.prototype.deactivateFocus=function(){this.isFocused=!1,this.adapter.deactivateLineRipple();var t=this.isValid();this.styleValidity(t),this.styleFocused(this.isFocused),this.adapter.hasLabel()&&(this.notchOutline(this.shouldFloat),this.adapter.floatLabel(this.shouldFloat),this.styleFloating(this.shouldFloat),this.adapter.shakeLabel(this.shouldShake)),this.shouldFloat||(this.receivedUserInput=!1)},e.prototype.getValue=function(){return this.getNativeInput().value},e.prototype.setValue=function(t){if(this.getValue()!==t&&(this.getNativeInput().value=t),this.setcharacterCounter(t.length),this.validateOnValueChange){var e=this.isValid();this.styleValidity(e)}this.adapter.hasLabel()&&(this.notchOutline(this.shouldFloat),this.adapter.floatLabel(this.shouldFloat),this.styleFloating(this.shouldFloat),this.validateOnValueChange&&this.adapter.shakeLabel(this.shouldShake))},e.prototype.isValid=function(){return this.useNativeValidation?this.isNativeInputValid():this.valid},e.prototype.setValid=function(t){this.valid=t,this.styleValidity(t);var e=!t&&!this.isFocused&&!!this.getValue();this.adapter.hasLabel()&&this.adapter.shakeLabel(e)},e.prototype.setValidateOnValueChange=function(t){this.validateOnValueChange=t},e.prototype.getValidateOnValueChange=function(){return this.validateOnValueChange},e.prototype.setUseNativeValidation=function(t){this.useNativeValidation=t},e.prototype.isDisabled=function(){return this.getNativeInput().disabled},e.prototype.setDisabled=function(t){this.getNativeInput().disabled=t,this.styleDisabled(t)},e.prototype.setHelperTextContent=function(t){this.helperText&&this.helperText.setContent(t)},e.prototype.setLeadingIconAriaLabel=function(t){this.leadingIcon&&this.leadingIcon.setAriaLabel(t)},e.prototype.setLeadingIconContent=function(t){this.leadingIcon&&this.leadingIcon.setContent(t)},e.prototype.setTrailingIconAriaLabel=function(t){this.trailingIcon&&this.trailingIcon.setAriaLabel(t)},e.prototype.setTrailingIconContent=function(t){this.trailingIcon&&this.trailingIcon.setContent(t)},e.prototype.setcharacterCounter=function(t){if(this.characterCounter){var e=this.getNativeInput().maxLength;if(-1===e)throw new Error("MDCTextFieldFoundation: Expected maxlength html property on text input or textarea.");this.characterCounter.setCounterValue(t,e)}},e.prototype.isBadInput=function(){return this.getNativeInput().validity.badInput||!1},e.prototype.isNativeInputValid=function(){return this.getNativeInput().validity.valid},e.prototype.styleValidity=function(t){var i=e.cssClasses.INVALID;if(t?this.adapter.removeClass(i):this.adapter.addClass(i),this.helperText){if(this.helperText.setValidity(t),!this.helperText.isValidation())return;var s=this.helperText.isVisible(),n=this.helperText.getId();s&&n?this.adapter.setInputAttr(dg.ARIA_DESCRIBEDBY,n):this.adapter.removeInputAttr(dg.ARIA_DESCRIBEDBY)}},e.prototype.styleFocused=function(t){var i=e.cssClasses.FOCUSED;t?this.adapter.addClass(i):this.adapter.removeClass(i)},e.prototype.styleDisabled=function(t){var i=e.cssClasses,s=i.DISABLED,n=i.INVALID;t?(this.adapter.addClass(s),this.adapter.removeClass(n)):this.adapter.removeClass(s),this.leadingIcon&&this.leadingIcon.setDisabled(t),this.trailingIcon&&this.trailingIcon.setDisabled(t)},e.prototype.styleFloating=function(t){var i=e.cssClasses.LABEL_FLOATING;t?this.adapter.addClass(i):this.adapter.removeClass(i)},e.prototype.getNativeInput=function(){return(this.adapter?this.adapter.getNativeInput():null)||{disabled:!1,maxLength:-1,required:!1,type:"input",validity:{badInput:!1,valid:!0},value:""}},e}(lg); -/** - * @license - * Copyright 2016 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const vg=window,_g=vg.ShadowRoot&&(void 0===vg.ShadyCSS||vg.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,bg=Symbol(),yg=new WeakMap;let xg=class{constructor(t,e,i){if(this._$cssResult$=!0,i!==bg)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(_g&&void 0===t){const i=void 0!==e&&1===e.length;i&&(t=yg.get(e)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&yg.set(e,t))}return t}toString(){return this.cssText}};const $g=_g?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new xg("string"==typeof t?t:t+"",void 0,bg))(e)})(t):t; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */var wg;const Ag=window,Eg=Ag.trustedTypes,Sg=Eg?Eg.emptyScript:"",Cg=Ag.reactiveElementPolyfillSupport,Tg={toAttribute(t,e){switch(e){case Boolean:t=t?Sg: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}},Ig=(t,e)=>e!==t&&(e==e||t==t),Og={attribute:!0,type:String,converter:Tg,reflect:!1,hasChanged:Ig},kg="finalized";let Rg=class extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(t){var e;this.finalize(),(null!==(e=this.h)&&void 0!==e?e:this.h=[]).push(t)}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach((e,i)=>{const s=this._$Ep(i,e);void 0!==s&&(this._$Ev.set(s,i),t.push(s))}),t}static createProperty(t,e=Og){if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){const i="symbol"==typeof t?Symbol():"__"+t,s=this.getPropertyDescriptor(t,i,e);void 0!==s&&Object.defineProperty(this.prototype,t,s)}}static getPropertyDescriptor(t,e,i){return{get(){return this[e]},set(s){const n=this[t];this[e]=s,this.requestUpdate(t,n,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||Og}static finalize(){if(this.hasOwnProperty(kg))return!1;this[kg]=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),void 0!==t.h&&(this.h=[...t.h]),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,e=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const i of e)this.createProperty(i,t[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}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($g(t))}else void 0!==t&&e.push($g(t));return e}static _$Ep(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}_$Eu(){var t;this._$E_=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach(t=>t(this))}addController(t){var e,i;(null!==(e=this._$ES)&&void 0!==e?e:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(i=t.hostConnected)||void 0===i||i.call(t))}removeController(t){var e;null===(e=this._$ES)||void 0===e||e.splice(this._$ES.indexOf(t)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach((t,e)=>{this.hasOwnProperty(e)&&(this._$Ei.set(e,this[e]),delete this[e])})}createRenderRoot(){var t;const e=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return((t,e)=>{_g?t.adoptedStyleSheets=e.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet):e.forEach(e=>{const i=document.createElement("style"),s=vg.litNonce;void 0!==s&&i.setAttribute("nonce",s),i.textContent=e.cssText,t.appendChild(i)})})(e,this.constructor.elementStyles),e}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)})}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)})}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$EO(t,e,i=Og){var s;const n=this.constructor._$Ep(t,i);if(void 0!==n&&!0===i.reflect){const r=(void 0!==(null===(s=i.converter)||void 0===s?void 0:s.toAttribute)?i.converter:Tg).toAttribute(e,i.type);this._$El=t,null==r?this.removeAttribute(n):this.setAttribute(n,r),this._$El=null}}_$AK(t,e){var i;const s=this.constructor,n=s._$Ev.get(t);if(void 0!==n&&this._$El!==n){const t=s.getPropertyOptions(n),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(i=t.converter)||void 0===i?void 0:i.fromAttribute)?t.converter:Tg;this._$El=n,this[n]=r.fromAttribute(e,t.type),this._$El=null}}requestUpdate(t,e,i){let s=!0;void 0!==t&&(((i=i||this.constructor.getPropertyOptions(t)).hasChanged||Ig)(this[t],e)?(this._$AL.has(t)||this._$AL.set(t,e),!0===i.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,i))):s=!1),!this.isUpdatePending&&s&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach((t,e)=>this[e]=t),this._$Ei=void 0);let e=!1;const i=this._$AL;try{e=this.shouldUpdate(i),e?(this.willUpdate(i),null===(t=this._$ES)||void 0===t||t.forEach(t=>{var e;return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)}),this.update(i)):this._$Ek()}catch(t){throw e=!1,this._$Ek(),t}e&&this._$AE(i)}willUpdate(t){}_$AE(t){var e;null===(e=this._$ES)||void 0===e||e.forEach(t=>{var e;return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)}),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return!0}update(t){void 0!==this._$EC&&(this._$EC.forEach((t,e)=>this._$EO(e,this[e],t)),this._$EC=void 0),this._$Ek()}updated(t){}firstUpdated(t){}}; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -var Pg;Rg[kg]=!0,Rg.elementProperties=new Map,Rg.elementStyles=[],Rg.shadowRootOptions={mode:"open"},null==Cg||Cg({ReactiveElement:Rg}),(null!==(wg=Ag.reactiveElementVersions)&&void 0!==wg?wg:Ag.reactiveElementVersions=[]).push("1.6.3");const Lg=window,Mg=Lg.trustedTypes,Ng=Mg?Mg.createPolicy("lit-html",{createHTML:t=>t}):void 0,Dg="$lit$",Hg=`lit$${(Math.random()+"").slice(9)}$`,Ug="?"+Hg,zg=`<${Ug}>`,Fg=document,Bg=()=>Fg.createComment(""),Vg=t=>null===t||"object"!=typeof t&&"function"!=typeof t,jg=Array.isArray,Wg="[ \t\n\f\r]",qg=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Yg=/-->/g,Xg=/>/g,Gg=RegExp(`>|${Wg}(?:([^\\s"'>=/]+)(${Wg}*=${Wg}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),Kg=/'/g,Jg=/"/g,Zg=/^(?:script|style|textarea|title)$/i,Qg=(t=>(e,...i)=>({_$litType$:t,strings:e,values:i}))(1),tv=Symbol.for("lit-noChange"),ev=Symbol.for("lit-nothing"),iv=new WeakMap,sv=Fg.createTreeWalker(Fg,129,null,!1);function nv(t,e){if(!Array.isArray(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==Ng?Ng.createHTML(e):e}const rv=(t,e)=>{const i=t.length-1,s=[];let n,r=2===e?"":"",o=qg;for(let e=0;e"===l[0]?(o=null!=n?n:qg,d=-1):void 0===l[1]?d=-2:(d=o.lastIndex-l[2].length,a=l[1],o=void 0===l[3]?Gg:'"'===l[3]?Jg:Kg):o===Jg||o===Kg?o=Gg:o===Yg||o===Xg?o=qg:(o=Gg,n=void 0);const h=o===Gg&&t[e+1].startsWith("/>")?" ":"";r+=o===qg?i+zg:d>=0?(s.push(a),i.slice(0,d)+Dg+i.slice(d)+Hg+h):i+Hg+(-2===d?(s.push(void 0),e):h)}return[nv(t,r+(t[i]||"")+(2===e?"":"")),s]};class ov{constructor({strings:t,_$litType$:e},i){let s;this.parts=[];let n=0,r=0;const o=t.length-1,a=this.parts,[l,d]=rv(t,e);if(this.el=ov.createElement(l,i),sv.currentNode=this.el.content,2===e){const t=this.el.content,e=t.firstChild;e.remove(),t.append(...e.childNodes)}for(;null!==(s=sv.nextNode())&&a.length0){s.textContent=Mg?Mg.emptyScript:"";for(let i=0;ijg(t)||"function"==typeof(null==t?void 0: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!==ev&&Vg(this._$AH)?this._$AA.nextSibling.data=t:this.$(Fg.createTextNode(t)),this._$AH=t}g(t){var e;const{values:i,_$litType$:s}=t,n="number"==typeof s?this._$AC(t):(void 0===s.el&&(s.el=ov.createElement(nv(s.h,s.h[0]),this.options)),s);if((null===(e=this._$AH)||void 0===e?void 0:e._$AD)===n)this._$AH.v(i);else{const t=new lv(n,this),e=t.u(this.options);t.v(i),this.$(e),this._$AH=t}}_$AC(t){let e=iv.get(t.strings);return void 0===e&&iv.set(t.strings,e=new ov(t)),e}T(t){jg(this._$AH)||(this._$AH=[],this._$AR());const e=this._$AH;let i,s=0;for(const n of t)s===e.length?e.push(i=new dv(this.k(Bg()),this.k(Bg()),this,this.options)):i=e[s],i._$AI(n),s++;s2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=ev}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(t,e=this,i,s){const n=this.strings;let r=!1;if(void 0===n)t=av(this,t,e,0),r=!Vg(t)||t!==this._$AH&&t!==tv,r&&(this._$AH=t);else{const s=t;let o,a;for(t=n[0],o=0;o{var s,n;const r=null!==(s=null==i?void 0:i.renderBefore)&&void 0!==s?s:e;let o=r._$litPart$;if(void 0===o){const t=null!==(n=null==i?void 0:i.renderBefore)&&void 0!==n?n:null;r._$litPart$=o=new dv(e.insertBefore(Bg(),t),t,void 0,null!=i?i:{})}return o._$AI(t),o})(e,this.renderRoot,this.renderOptions)}connectedCallback(){var t;super.connectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!0)}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!1)}render(){return tv}};bv.finalized=!0,bv._$litElement$=!0,null===(vv=globalThis.litElementHydrateSupport)||void 0===vv||vv.call(globalThis,{LitElement:bv});const yv=globalThis.litElementPolyfillSupport;null==yv||yv({LitElement:bv}),(null!==(_v=globalThis.litElementVersions)&&void 0!==_v?_v:globalThis.litElementVersions=[]).push("3.3.3"); -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const xv=(t,e)=>"method"===e.kind&&e.descriptor&&!("value"in e.descriptor)?{...e,finisher(i){i.createProperty(e.key,t)}}:{kind:"field",key:Symbol(),placement:"own",descriptor:{},originalKey:e.key,initializer(){"function"==typeof e.initializer&&(this[e.key]=e.initializer.call(this))},finisher(i){i.createProperty(e.key,t)}};function $v(t){return(e,i)=>void 0!==i?((t,e,i)=>{e.constructor.createProperty(i,t)})(t,e,i):xv(t,e)} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */function wv(t){return $v({...t,state:!0})} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */const Av=({finisher:t,descriptor:e})=>(i,s)=>{var n;if(void 0===s){const s=null!==(n=i.originalKey)&&void 0!==n?n:i.key,r=null!=e?{kind:"method",placement:"prototype",key:s,descriptor:e(i.key)}:{...i,key:s};return null!=t&&(r.finisher=function(e){t(e,s)}),r}{const n=i.constructor;void 0!==e&&Object.defineProperty(i,s,e(s)),null==t||t(n,s)}}; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -function Ev(t,e){return Av({descriptor:e=>{const i={get(){var e,i;return null!==(i=null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(t))&&void 0!==i?i:null},enumerable:!0,configurable:!0};return i}})} -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */var Sv;null===(Sv=window.HTMLSlotElement)||void 0===Sv||Sv.prototype.assignedElements; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const Cv=1,Tv=3,Iv=4,Ov=t=>(...e)=>({_$litDirective$:t,values:e});class kv{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 2018 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */const Rv=Ov(class extends kv{constructor(t){var e;if(super(t),t.type!==Cv||"class"!==t.name||(null===(e=t.strings)||void 0===e?void 0:e.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]){var i,s;if(void 0===this.it){this.it=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]&&!(null===(i=this.nt)||void 0===i?void 0:i.has(t))&&this.it.add(t);return this.render(e)}const n=t.element.classList;this.it.forEach(t=>{t in e||(n.remove(t),this.it.delete(t))});for(const t in e){const i=!!e[t];i===this.it.has(t)||(null===(s=this.nt)||void 0===s?void 0:s.has(t))||(i?(n.add(t),this.it.add(t)):(n.remove(t),this.it.delete(t)))}return tv}}),Pv=t=>null!=t?t:ev,Lv={},Mv=Ov(class extends kv{constructor(t){if(super(t),t.type!==Tv&&t.type!==Cv&&t.type!==Iv)throw Error("The `live` directive is not allowed on child or event bindings");if(!(t=>void 0===t.strings)(t))throw Error("`live` bindings can only contain a single expression")}render(t){return t}update(t,[e]){if(e===tv||e===ev)return e;const i=t.element,s=t.name;if(t.type===Tv){if(e===i[s])return tv}else if(t.type===Iv){if(!!e===i.hasAttribute(s))return tv}else if(t.type===Cv&&i.getAttribute(s)===e+"")return tv;return((t,e=Lv)=>{t._$AH=e; -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */})(t),e}}),Nv=["touchstart","touchmove","scroll","mousewheel"],Dv=(t={})=>{const e={};for(const i in t)e[i]=t[i];return Object.assign({badInput:!1,customError:!1,patternMismatch:!1,rangeOverflow:!1,rangeUnderflow:!1,stepMismatch:!1,tooLong:!1,tooShort:!1,typeMismatch:!1,valid:!0,valueMissing:!1},e)}; -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */class Hv extends rs{constructor(){super(...arguments),this.mdcFoundationClass=gg,this.value="",this.type="text",this.placeholder="",this.label="",this.icon="",this.iconTrailing="",this.disabled=!1,this.required=!1,this.minLength=-1,this.maxLength=-1,this.outlined=!1,this.helper="",this.validateOnInitialRender=!1,this.validationMessage="",this.autoValidate=!1,this.pattern="",this.min="",this.max="",this.step=null,this.size=null,this.helperPersistent=!1,this.charCounter=!1,this.endAligned=!1,this.prefix="",this.suffix="",this.name="",this.readOnly=!1,this.autocapitalize="",this.outlineOpen=!1,this.outlineWidth=0,this.isUiValid=!0,this.focused=!1,this._validity=Dv(),this.validityTransform=null}get validity(){return this._checkValidity(this.value),this._validity}get willValidate(){return this.formElement.willValidate}get selectionStart(){return this.formElement.selectionStart}get selectionEnd(){return this.formElement.selectionEnd}focus(){const t=new CustomEvent("focus");this.formElement.dispatchEvent(t),this.formElement.focus()}blur(){const t=new CustomEvent("blur");this.formElement.dispatchEvent(t),this.formElement.blur()}select(){this.formElement.select()}setSelectionRange(t,e,i){this.formElement.setSelectionRange(t,e,i)}update(t){t.has("autoValidate")&&this.mdcFoundation&&this.mdcFoundation.setValidateOnValueChange(this.autoValidate),t.has("value")&&"string"!=typeof this.value&&(this.value=`${this.value}`),super.update(t)}setFormData(t){this.name&&t.append(this.name,this.value)}render(){const t=this.charCounter&&-1!==this.maxLength,e=!!this.helper||!!this.validationMessage||t,i={"mdc-text-field--disabled":this.disabled,"mdc-text-field--no-label":!this.label,"mdc-text-field--filled":!this.outlined,"mdc-text-field--outlined":this.outlined,"mdc-text-field--with-leading-icon":this.icon,"mdc-text-field--with-trailing-icon":this.iconTrailing,"mdc-text-field--end-aligned":this.endAligned};return Qg` - - ${this.renderHelperText(e,t)} - `}updated(t){t.has("value")&&void 0!==t.get("value")&&(this.mdcFoundation.setValue(this.value),this.autoValidate&&this.reportValidity())}renderRipple(){return this.outlined?"":Qg` - - `}renderOutline(){return this.outlined?Qg` - - ${this.renderLabel()} - `:""}renderLabel(){return this.label?Qg` - ${this.label} - `:""}renderLeadingIcon(){return this.icon?this.renderIcon(this.icon):""}renderTrailingIcon(){return this.iconTrailing?this.renderIcon(this.iconTrailing,!0):""}renderIcon(t,e=!1){return Qg`${t}`}renderPrefix(){return this.prefix?this.renderAffix(this.prefix):""}renderSuffix(){return this.suffix?this.renderAffix(this.suffix,!0):""}renderAffix(t,e=!1){return Qg` - ${t}`}renderInput(t){const e=-1===this.minLength?void 0:this.minLength,i=-1===this.maxLength?void 0:this.maxLength,s=this.autocapitalize?this.autocapitalize:void 0,n=this.validationMessage&&!this.isUiValid,r=this.label?"label":void 0,o=t?"helper-text":void 0,a=this.focused||this.helperPersistent||n?"helper-text":void 0;return Qg` - `}renderLineRipple(){return this.outlined?"":Qg` - - `}renderHelperText(t,e){const i=this.validationMessage&&!this.isUiValid,s={"mdc-text-field-helper-text--persistent":this.helperPersistent,"mdc-text-field-helper-text--validation-msg":i},n=this.focused||this.helperPersistent||i?void 0:"true",r=i?this.validationMessage:this.helper;return t?Qg` -
-
${r}
- ${this.renderCharCounter(e)} -
`:""}renderCharCounter(t){const e=Math.min(this.value.length,this.maxLength);return t?Qg` - ${e} / ${this.maxLength}`:""}onInputFocus(){this.focused=!0}onInputBlur(){this.focused=!1,this.reportValidity()}checkValidity(){const t=this._checkValidity(this.value);if(!t){const t=new Event("invalid",{bubbles:!1,cancelable:!0});this.dispatchEvent(t)}return t}reportValidity(){const t=this.checkValidity();return this.mdcFoundation.setValid(t),this.isUiValid=t,t}_checkValidity(t){const e=this.formElement.validity;let i=Dv(e);if(this.validityTransform){const e=this.validityTransform(t,i);i=Object.assign(Object.assign({},i),e),this.mdcFoundation.setUseNativeValidation(!1)}else this.mdcFoundation.setUseNativeValidation(!0);return this._validity=i,this._validity.valid}setCustomValidity(t){this.validationMessage=t,this.formElement.setCustomValidity(t)}handleInputChange(){this.value=this.formElement.value}createAdapter(){return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},this.getRootAdapterMethods()),this.getInputAdapterMethods()),this.getLabelAdapterMethods()),this.getLineRippleAdapterMethods()),this.getOutlineAdapterMethods())}getRootAdapterMethods(){return Object.assign({registerTextFieldInteractionHandler:(t,e)=>this.addEventListener(t,e),deregisterTextFieldInteractionHandler:(t,e)=>this.removeEventListener(t,e),registerValidationAttributeChangeHandler:t=>{const e=new MutationObserver(e=>{t((t=>t.map(t=>t.attributeName).filter(t=>t))(e))});return e.observe(this.formElement,{attributes:!0}),e},deregisterValidationAttributeChangeHandler:t=>t.disconnect()},Xi(this.mdcRoot))}getInputAdapterMethods(){return{getNativeInput:()=>this.formElement,setInputAttr:()=>{},removeInputAttr:()=>{},isFocused:()=>!!this.shadowRoot&&this.shadowRoot.activeElement===this.formElement,registerInputInteractionHandler:(t,e)=>this.formElement.addEventListener(t,e,{passive:t in Nv}),deregisterInputInteractionHandler:(t,e)=>this.formElement.removeEventListener(t,e)}}getLabelAdapterMethods(){return{floatLabel:t=>this.labelElement&&this.labelElement.floatingLabelFoundation.float(t),getLabelWidth:()=>this.labelElement?this.labelElement.floatingLabelFoundation.getWidth():0,hasLabel:()=>Boolean(this.labelElement),shakeLabel:t=>this.labelElement&&this.labelElement.floatingLabelFoundation.shake(t),setLabelRequired:t=>{this.labelElement&&this.labelElement.floatingLabelFoundation.setRequired(t)}}}getLineRippleAdapterMethods(){return{activateLineRipple:()=>{this.lineRippleElement&&this.lineRippleElement.lineRippleFoundation.activate()},deactivateLineRipple:()=>{this.lineRippleElement&&this.lineRippleElement.lineRippleFoundation.deactivate()},setLineRippleTransformOrigin:t=>{this.lineRippleElement&&this.lineRippleElement.lineRippleFoundation.setRippleCenter(t)}}}async getUpdateComplete(){var t;const e=await super.getUpdateComplete();return await(null===(t=this.outlineElement)||void 0===t?void 0:t.updateComplete),e}firstUpdated(){var t;super.firstUpdated(),this.mdcFoundation.setValidateOnValueChange(this.autoValidate),this.validateOnInitialRender&&this.reportValidity(),null===(t=this.outlineElement)||void 0===t||t.updateComplete.then(()=>{var t;this.outlineWidth=(null===(t=this.labelElement)||void 0===t?void 0:t.floatingLabelFoundation.getWidth())||0})}getOutlineAdapterMethods(){return{closeOutline:()=>this.outlineElement&&(this.outlineOpen=!1),hasOutline:()=>Boolean(this.outlineElement),notchOutline:t=>{this.outlineElement&&!this.outlineOpen&&(this.outlineWidth=t,this.outlineOpen=!0)}}}async layout(){await this.updateComplete;const t=this.labelElement;if(!t)return void(this.outlineOpen=!1);const e=!!this.label&&!!this.value;if(t.floatingLabelFoundation.float(e),!this.outlined)return;this.outlineOpen=e,await this.updateComplete;const i=t.floatingLabelFoundation.getWidth();this.outlineOpen&&(this.outlineWidth=i,await this.updateComplete)}}n([Ev(".mdc-text-field")],Hv.prototype,"mdcRoot",void 0),n([Ev("input")],Hv.prototype,"formElement",void 0),n([Ev(".mdc-floating-label")],Hv.prototype,"labelElement",void 0),n([Ev(".mdc-line-ripple")],Hv.prototype,"lineRippleElement",void 0),n([Ev("mwc-notched-outline")],Hv.prototype,"outlineElement",void 0),n([Ev(".mdc-notched-outline__notch")],Hv.prototype,"notchElement",void 0),n([$v({type:String})],Hv.prototype,"value",void 0),n([$v({type:String})],Hv.prototype,"type",void 0),n([$v({type:String})],Hv.prototype,"placeholder",void 0),n([$v({type:String}),os(function(t,e){void 0!==e&&this.label!==e&&this.layout()})],Hv.prototype,"label",void 0),n([$v({type:String})],Hv.prototype,"icon",void 0),n([$v({type:String})],Hv.prototype,"iconTrailing",void 0),n([$v({type:Boolean,reflect:!0})],Hv.prototype,"disabled",void 0),n([$v({type:Boolean})],Hv.prototype,"required",void 0),n([$v({type:Number})],Hv.prototype,"minLength",void 0),n([$v({type:Number})],Hv.prototype,"maxLength",void 0),n([$v({type:Boolean,reflect:!0}),os(function(t,e){void 0!==e&&this.outlined!==e&&this.layout()})],Hv.prototype,"outlined",void 0),n([$v({type:String})],Hv.prototype,"helper",void 0),n([$v({type:Boolean})],Hv.prototype,"validateOnInitialRender",void 0),n([$v({type:String})],Hv.prototype,"validationMessage",void 0),n([$v({type:Boolean})],Hv.prototype,"autoValidate",void 0),n([$v({type:String})],Hv.prototype,"pattern",void 0),n([$v({type:String})],Hv.prototype,"min",void 0),n([$v({type:String})],Hv.prototype,"max",void 0),n([$v({type:String})],Hv.prototype,"step",void 0),n([$v({type:Number})],Hv.prototype,"size",void 0),n([$v({type:Boolean})],Hv.prototype,"helperPersistent",void 0),n([$v({type:Boolean})],Hv.prototype,"charCounter",void 0),n([$v({type:Boolean})],Hv.prototype,"endAligned",void 0),n([$v({type:String})],Hv.prototype,"prefix",void 0),n([$v({type:String})],Hv.prototype,"suffix",void 0),n([$v({type:String})],Hv.prototype,"name",void 0),n([$v({type:String})],Hv.prototype,"inputMode",void 0),n([$v({type:Boolean})],Hv.prototype,"readOnly",void 0),n([$v({type:String})],Hv.prototype,"autocapitalize",void 0),n([wv()],Hv.prototype,"outlineOpen",void 0),n([wv()],Hv.prototype,"outlineWidth",void 0),n([wv()],Hv.prototype,"isUiValid",void 0),n([wv()],Hv.prototype,"focused",void 0),n([function(t){return Av({finisher:(e,i)=>{Object.assign(e.prototype[i],t)}})}({passive:!0})],Hv.prototype,"handleInputChange",null); -/** - * @license - * Copyright 2021 Google LLC - * SPDX-LIcense-Identifier: Apache-2.0 - */ -const Uv=((t,...e)=>{const i=1===t.length?t[0]:e.reduce((e,i,s)=>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[s+1],t[0]);return new xg(i,t,bg)})`.mdc-floating-label{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-subtitle1-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:1rem;font-size:var(--mdc-typography-subtitle1-font-size, 1rem);font-weight:400;font-weight:var(--mdc-typography-subtitle1-font-weight, 400);letter-spacing:0.009375em;letter-spacing:var(--mdc-typography-subtitle1-letter-spacing, 0.009375em);text-decoration:inherit;text-decoration:var(--mdc-typography-subtitle1-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-subtitle1-text-transform, inherit);position:absolute;left:0;-webkit-transform-origin:left top;transform-origin:left top;line-height:1.15rem;text-align:left;text-overflow:ellipsis;white-space:nowrap;cursor:text;overflow:hidden;will-change:transform;transition:transform 150ms cubic-bezier(0.4, 0, 0.2, 1),color 150ms cubic-bezier(0.4, 0, 0.2, 1)}[dir=rtl] .mdc-floating-label,.mdc-floating-label[dir=rtl]{right:0;left:auto;-webkit-transform-origin:right top;transform-origin:right top;text-align:right}.mdc-floating-label--float-above{cursor:auto}.mdc-floating-label--required::after{margin-left:1px;margin-right:0px;content:"*"}[dir=rtl] .mdc-floating-label--required::after,.mdc-floating-label--required[dir=rtl]::after{margin-left:0;margin-right:1px}.mdc-floating-label--float-above{transform:translateY(-106%) scale(0.75)}.mdc-floating-label--shake{animation:mdc-floating-label-shake-float-above-standard 250ms 1}@keyframes mdc-floating-label-shake-float-above-standard{0%{transform:translateX(calc(0 - 0%)) translateY(-106%) scale(0.75)}33%{animation-timing-function:cubic-bezier(0.5, 0, 0.701732, 0.495819);transform:translateX(calc(4% - 0%)) translateY(-106%) scale(0.75)}66%{animation-timing-function:cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);transform:translateX(calc(-4% - 0%)) translateY(-106%) scale(0.75)}100%{transform:translateX(calc(0 - 0%)) translateY(-106%) scale(0.75)}}.mdc-line-ripple::before,.mdc-line-ripple::after{position:absolute;bottom:0;left:0;width:100%;border-bottom-style:solid;content:""}.mdc-line-ripple::before{border-bottom-width:1px}.mdc-line-ripple::before{z-index:1}.mdc-line-ripple::after{transform:scaleX(0);border-bottom-width:2px;opacity:0;z-index:2}.mdc-line-ripple::after{transition:transform 180ms cubic-bezier(0.4, 0, 0.2, 1),opacity 180ms cubic-bezier(0.4, 0, 0.2, 1)}.mdc-line-ripple--active::after{transform:scaleX(1);opacity:1}.mdc-line-ripple--deactivating::after{opacity:0}.mdc-notched-outline{display:flex;position:absolute;top:0;right:0;left:0;box-sizing:border-box;width:100%;max-width:100%;height:100%;text-align:left;pointer-events:none}[dir=rtl] .mdc-notched-outline,.mdc-notched-outline[dir=rtl]{text-align:right}.mdc-notched-outline__leading,.mdc-notched-outline__notch,.mdc-notched-outline__trailing{box-sizing:border-box;height:100%;border-top:1px solid;border-bottom:1px solid;pointer-events:none}.mdc-notched-outline__leading{border-left:1px solid;border-right:none;width:12px}[dir=rtl] .mdc-notched-outline__leading,.mdc-notched-outline__leading[dir=rtl]{border-left:none;border-right:1px solid}.mdc-notched-outline__trailing{border-left:none;border-right:1px solid;flex-grow:1}[dir=rtl] .mdc-notched-outline__trailing,.mdc-notched-outline__trailing[dir=rtl]{border-left:1px solid;border-right:none}.mdc-notched-outline__notch{flex:0 0 auto;width:auto;max-width:calc(100% - 12px * 2)}.mdc-notched-outline .mdc-floating-label{display:inline-block;position:relative;max-width:100%}.mdc-notched-outline .mdc-floating-label--float-above{text-overflow:clip}.mdc-notched-outline--upgraded .mdc-floating-label--float-above{max-width:calc(100% / 0.75)}.mdc-notched-outline--notched .mdc-notched-outline__notch{padding-left:0;padding-right:8px;border-top:none}[dir=rtl] .mdc-notched-outline--notched .mdc-notched-outline__notch,.mdc-notched-outline--notched .mdc-notched-outline__notch[dir=rtl]{padding-left:8px;padding-right:0}.mdc-notched-outline--no-label .mdc-notched-outline__notch{display:none}@keyframes mdc-ripple-fg-radius-in{from{animation-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transform:translate(var(--mdc-ripple-fg-translate-start, 0)) scale(1)}to{transform:translate(var(--mdc-ripple-fg-translate-end, 0)) scale(var(--mdc-ripple-fg-scale, 1))}}@keyframes mdc-ripple-fg-opacity-in{from{animation-timing-function:linear;opacity:0}to{opacity:var(--mdc-ripple-fg-opacity, 0)}}@keyframes mdc-ripple-fg-opacity-out{from{animation-timing-function:linear;opacity:var(--mdc-ripple-fg-opacity, 0)}to{opacity:0}}.mdc-text-field--filled{--mdc-ripple-fg-size: 0;--mdc-ripple-left: 0;--mdc-ripple-top: 0;--mdc-ripple-fg-scale: 1;--mdc-ripple-fg-translate-end: 0;--mdc-ripple-fg-translate-start: 0;-webkit-tap-highlight-color:rgba(0,0,0,0);will-change:transform,opacity}.mdc-text-field--filled .mdc-text-field__ripple::before,.mdc-text-field--filled .mdc-text-field__ripple::after{position:absolute;border-radius:50%;opacity:0;pointer-events:none;content:""}.mdc-text-field--filled .mdc-text-field__ripple::before{transition:opacity 15ms linear,background-color 15ms linear;z-index:1;z-index:var(--mdc-ripple-z-index, 1)}.mdc-text-field--filled .mdc-text-field__ripple::after{z-index:0;z-index:var(--mdc-ripple-z-index, 0)}.mdc-text-field--filled.mdc-ripple-upgraded .mdc-text-field__ripple::before{transform:scale(var(--mdc-ripple-fg-scale, 1))}.mdc-text-field--filled.mdc-ripple-upgraded .mdc-text-field__ripple::after{top:0;left:0;transform:scale(0);transform-origin:center center}.mdc-text-field--filled.mdc-ripple-upgraded--unbounded .mdc-text-field__ripple::after{top:var(--mdc-ripple-top, 0);left:var(--mdc-ripple-left, 0)}.mdc-text-field--filled.mdc-ripple-upgraded--foreground-activation .mdc-text-field__ripple::after{animation:mdc-ripple-fg-radius-in 225ms forwards,mdc-ripple-fg-opacity-in 75ms forwards}.mdc-text-field--filled.mdc-ripple-upgraded--foreground-deactivation .mdc-text-field__ripple::after{animation:mdc-ripple-fg-opacity-out 150ms;transform:translate(var(--mdc-ripple-fg-translate-end, 0)) scale(var(--mdc-ripple-fg-scale, 1))}.mdc-text-field--filled .mdc-text-field__ripple::before,.mdc-text-field--filled .mdc-text-field__ripple::after{top:calc(50% - 100%);left:calc(50% - 100%);width:200%;height:200%}.mdc-text-field--filled.mdc-ripple-upgraded .mdc-text-field__ripple::after{width:var(--mdc-ripple-fg-size, 100%);height:var(--mdc-ripple-fg-size, 100%)}.mdc-text-field__ripple{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none}.mdc-text-field{border-top-left-radius:4px;border-top-left-radius:var(--mdc-shape-small, 4px);border-top-right-radius:4px;border-top-right-radius:var(--mdc-shape-small, 4px);border-bottom-right-radius:0;border-bottom-left-radius:0;display:inline-flex;align-items:baseline;padding:0 16px;position:relative;box-sizing:border-box;overflow:hidden;will-change:opacity,transform,color}.mdc-text-field:not(.mdc-text-field--disabled) .mdc-floating-label{color:rgba(0, 0, 0, 0.6)}.mdc-text-field:not(.mdc-text-field--disabled) .mdc-text-field__input{color:rgba(0, 0, 0, 0.87)}@media all{.mdc-text-field:not(.mdc-text-field--disabled) .mdc-text-field__input::placeholder{color:rgba(0, 0, 0, 0.54)}}@media all{.mdc-text-field:not(.mdc-text-field--disabled) .mdc-text-field__input:-ms-input-placeholder{color:rgba(0, 0, 0, 0.54)}}.mdc-text-field .mdc-text-field__input{caret-color:#6200ee;caret-color:var(--mdc-theme-primary, #6200ee)}.mdc-text-field:not(.mdc-text-field--disabled)+.mdc-text-field-helper-line .mdc-text-field-helper-text{color:rgba(0, 0, 0, 0.6)}.mdc-text-field:not(.mdc-text-field--disabled) .mdc-text-field-character-counter,.mdc-text-field:not(.mdc-text-field--disabled)+.mdc-text-field-helper-line .mdc-text-field-character-counter{color:rgba(0, 0, 0, 0.6)}.mdc-text-field:not(.mdc-text-field--disabled) .mdc-text-field__icon--leading{color:rgba(0, 0, 0, 0.54)}.mdc-text-field:not(.mdc-text-field--disabled) .mdc-text-field__icon--trailing{color:rgba(0, 0, 0, 0.54)}.mdc-text-field:not(.mdc-text-field--disabled) .mdc-text-field__affix--prefix{color:rgba(0, 0, 0, 0.6)}.mdc-text-field:not(.mdc-text-field--disabled) .mdc-text-field__affix--suffix{color:rgba(0, 0, 0, 0.6)}.mdc-text-field .mdc-floating-label{top:50%;transform:translateY(-50%);pointer-events:none}.mdc-text-field__input{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-subtitle1-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:1rem;font-size:var(--mdc-typography-subtitle1-font-size, 1rem);font-weight:400;font-weight:var(--mdc-typography-subtitle1-font-weight, 400);letter-spacing:0.009375em;letter-spacing:var(--mdc-typography-subtitle1-letter-spacing, 0.009375em);text-decoration:inherit;text-decoration:var(--mdc-typography-subtitle1-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-subtitle1-text-transform, inherit);height:28px;transition:opacity 150ms 0ms cubic-bezier(0.4, 0, 0.2, 1);width:100%;min-width:0;border:none;border-radius:0;background:none;appearance:none;padding:0}.mdc-text-field__input::-ms-clear{display:none}.mdc-text-field__input::-webkit-calendar-picker-indicator{display:none}.mdc-text-field__input:focus{outline:none}.mdc-text-field__input:invalid{box-shadow:none}@media all{.mdc-text-field__input::placeholder{transition:opacity 67ms 0ms cubic-bezier(0.4, 0, 0.2, 1);opacity:0}}@media all{.mdc-text-field__input:-ms-input-placeholder{transition:opacity 67ms 0ms cubic-bezier(0.4, 0, 0.2, 1);opacity:0}}@media all{.mdc-text-field--no-label .mdc-text-field__input::placeholder,.mdc-text-field--focused .mdc-text-field__input::placeholder{transition-delay:40ms;transition-duration:110ms;opacity:1}}@media all{.mdc-text-field--no-label .mdc-text-field__input:-ms-input-placeholder,.mdc-text-field--focused .mdc-text-field__input:-ms-input-placeholder{transition-delay:40ms;transition-duration:110ms;opacity:1}}.mdc-text-field__affix{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-subtitle1-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:1rem;font-size:var(--mdc-typography-subtitle1-font-size, 1rem);font-weight:400;font-weight:var(--mdc-typography-subtitle1-font-weight, 400);letter-spacing:0.009375em;letter-spacing:var(--mdc-typography-subtitle1-letter-spacing, 0.009375em);text-decoration:inherit;text-decoration:var(--mdc-typography-subtitle1-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-subtitle1-text-transform, inherit);height:28px;transition:opacity 150ms 0ms cubic-bezier(0.4, 0, 0.2, 1);opacity:0;white-space:nowrap}.mdc-text-field--label-floating .mdc-text-field__affix,.mdc-text-field--no-label .mdc-text-field__affix{opacity:1}@supports(-webkit-hyphens: none){.mdc-text-field--outlined .mdc-text-field__affix{align-items:center;align-self:center;display:inline-flex;height:100%}}.mdc-text-field__affix--prefix{padding-left:0;padding-right:2px}[dir=rtl] .mdc-text-field__affix--prefix,.mdc-text-field__affix--prefix[dir=rtl]{padding-left:2px;padding-right:0}.mdc-text-field--end-aligned .mdc-text-field__affix--prefix{padding-left:0;padding-right:12px}[dir=rtl] .mdc-text-field--end-aligned .mdc-text-field__affix--prefix,.mdc-text-field--end-aligned .mdc-text-field__affix--prefix[dir=rtl]{padding-left:12px;padding-right:0}.mdc-text-field__affix--suffix{padding-left:12px;padding-right:0}[dir=rtl] .mdc-text-field__affix--suffix,.mdc-text-field__affix--suffix[dir=rtl]{padding-left:0;padding-right:12px}.mdc-text-field--end-aligned .mdc-text-field__affix--suffix{padding-left:2px;padding-right:0}[dir=rtl] .mdc-text-field--end-aligned .mdc-text-field__affix--suffix,.mdc-text-field--end-aligned .mdc-text-field__affix--suffix[dir=rtl]{padding-left:0;padding-right:2px}.mdc-text-field--filled{height:56px}.mdc-text-field--filled .mdc-text-field__ripple::before,.mdc-text-field--filled .mdc-text-field__ripple::after{background-color:rgba(0, 0, 0, 0.87);background-color:var(--mdc-ripple-color, rgba(0, 0, 0, 0.87))}.mdc-text-field--filled:hover .mdc-text-field__ripple::before,.mdc-text-field--filled.mdc-ripple-surface--hover .mdc-text-field__ripple::before{opacity:0.04;opacity:var(--mdc-ripple-hover-opacity, 0.04)}.mdc-text-field--filled.mdc-ripple-upgraded--background-focused .mdc-text-field__ripple::before,.mdc-text-field--filled:not(.mdc-ripple-upgraded):focus .mdc-text-field__ripple::before{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-focus-opacity, 0.12)}.mdc-text-field--filled::before{display:inline-block;width:0;height:40px;content:"";vertical-align:0}.mdc-text-field--filled:not(.mdc-text-field--disabled){background-color:whitesmoke}.mdc-text-field--filled:not(.mdc-text-field--disabled) .mdc-line-ripple::before{border-bottom-color:rgba(0, 0, 0, 0.42)}.mdc-text-field--filled:not(.mdc-text-field--disabled):hover .mdc-line-ripple::before{border-bottom-color:rgba(0, 0, 0, 0.87)}.mdc-text-field--filled .mdc-line-ripple::after{border-bottom-color:#6200ee;border-bottom-color:var(--mdc-theme-primary, #6200ee)}.mdc-text-field--filled .mdc-floating-label{left:16px;right:initial}[dir=rtl] .mdc-text-field--filled .mdc-floating-label,.mdc-text-field--filled .mdc-floating-label[dir=rtl]{left:initial;right:16px}.mdc-text-field--filled .mdc-floating-label--float-above{transform:translateY(-106%) scale(0.75)}.mdc-text-field--filled.mdc-text-field--no-label .mdc-text-field__input{height:100%}.mdc-text-field--filled.mdc-text-field--no-label .mdc-floating-label{display:none}.mdc-text-field--filled.mdc-text-field--no-label::before{display:none}@supports(-webkit-hyphens: none){.mdc-text-field--filled.mdc-text-field--no-label .mdc-text-field__affix{align-items:center;align-self:center;display:inline-flex;height:100%}}.mdc-text-field--outlined{height:56px;overflow:visible}.mdc-text-field--outlined .mdc-floating-label--float-above{transform:translateY(-37.25px) scale(1)}.mdc-text-field--outlined .mdc-floating-label--float-above{font-size:.75rem}.mdc-text-field--outlined.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{transform:translateY(-34.75px) scale(0.75)}.mdc-text-field--outlined.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{font-size:1rem}.mdc-text-field--outlined .mdc-floating-label--shake{animation:mdc-floating-label-shake-float-above-text-field-outlined 250ms 1}@keyframes mdc-floating-label-shake-float-above-text-field-outlined{0%{transform:translateX(calc(0 - 0%)) translateY(-34.75px) scale(0.75)}33%{animation-timing-function:cubic-bezier(0.5, 0, 0.701732, 0.495819);transform:translateX(calc(4% - 0%)) translateY(-34.75px) scale(0.75)}66%{animation-timing-function:cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);transform:translateX(calc(-4% - 0%)) translateY(-34.75px) scale(0.75)}100%{transform:translateX(calc(0 - 0%)) translateY(-34.75px) scale(0.75)}}.mdc-text-field--outlined .mdc-text-field__input{height:100%}.mdc-text-field--outlined:not(.mdc-text-field--disabled) .mdc-notched-outline__leading,.mdc-text-field--outlined:not(.mdc-text-field--disabled) .mdc-notched-outline__notch,.mdc-text-field--outlined:not(.mdc-text-field--disabled) .mdc-notched-outline__trailing{border-color:rgba(0, 0, 0, 0.38)}.mdc-text-field--outlined:not(.mdc-text-field--disabled):not(.mdc-text-field--focused):hover .mdc-notched-outline .mdc-notched-outline__leading,.mdc-text-field--outlined:not(.mdc-text-field--disabled):not(.mdc-text-field--focused):hover .mdc-notched-outline .mdc-notched-outline__notch,.mdc-text-field--outlined:not(.mdc-text-field--disabled):not(.mdc-text-field--focused):hover .mdc-notched-outline .mdc-notched-outline__trailing{border-color:rgba(0, 0, 0, 0.87)}.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-notched-outline__leading,.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-notched-outline__notch,.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-notched-outline__trailing{border-color:#6200ee;border-color:var(--mdc-theme-primary, #6200ee)}.mdc-text-field--outlined .mdc-notched-outline .mdc-notched-outline__leading{border-top-left-radius:4px;border-top-left-radius:var(--mdc-shape-small, 4px);border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:4px;border-bottom-left-radius:var(--mdc-shape-small, 4px)}[dir=rtl] .mdc-text-field--outlined .mdc-notched-outline .mdc-notched-outline__leading,.mdc-text-field--outlined .mdc-notched-outline .mdc-notched-outline__leading[dir=rtl]{border-top-left-radius:0;border-top-right-radius:4px;border-top-right-radius:var(--mdc-shape-small, 4px);border-bottom-right-radius:4px;border-bottom-right-radius:var(--mdc-shape-small, 4px);border-bottom-left-radius:0}@supports(top: max(0%)){.mdc-text-field--outlined .mdc-notched-outline .mdc-notched-outline__leading{width:max(12px, var(--mdc-shape-small, 4px))}}@supports(top: max(0%)){.mdc-text-field--outlined .mdc-notched-outline .mdc-notched-outline__notch{max-width:calc(100% - max(12px, var(--mdc-shape-small, 4px)) * 2)}}.mdc-text-field--outlined .mdc-notched-outline .mdc-notched-outline__trailing{border-top-left-radius:0;border-top-right-radius:4px;border-top-right-radius:var(--mdc-shape-small, 4px);border-bottom-right-radius:4px;border-bottom-right-radius:var(--mdc-shape-small, 4px);border-bottom-left-radius:0}[dir=rtl] .mdc-text-field--outlined .mdc-notched-outline .mdc-notched-outline__trailing,.mdc-text-field--outlined .mdc-notched-outline .mdc-notched-outline__trailing[dir=rtl]{border-top-left-radius:4px;border-top-left-radius:var(--mdc-shape-small, 4px);border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:4px;border-bottom-left-radius:var(--mdc-shape-small, 4px)}@supports(top: max(0%)){.mdc-text-field--outlined{padding-left:max(16px, calc(var(--mdc-shape-small, 4px) + 4px))}}@supports(top: max(0%)){.mdc-text-field--outlined{padding-right:max(16px, var(--mdc-shape-small, 4px))}}@supports(top: max(0%)){.mdc-text-field--outlined+.mdc-text-field-helper-line{padding-left:max(16px, calc(var(--mdc-shape-small, 4px) + 4px))}}@supports(top: max(0%)){.mdc-text-field--outlined+.mdc-text-field-helper-line{padding-right:max(16px, var(--mdc-shape-small, 4px))}}.mdc-text-field--outlined.mdc-text-field--with-leading-icon{padding-left:0}@supports(top: max(0%)){.mdc-text-field--outlined.mdc-text-field--with-leading-icon{padding-right:max(16px, var(--mdc-shape-small, 4px))}}[dir=rtl] .mdc-text-field--outlined.mdc-text-field--with-leading-icon,.mdc-text-field--outlined.mdc-text-field--with-leading-icon[dir=rtl]{padding-right:0}@supports(top: max(0%)){[dir=rtl] .mdc-text-field--outlined.mdc-text-field--with-leading-icon,.mdc-text-field--outlined.mdc-text-field--with-leading-icon[dir=rtl]{padding-left:max(16px, var(--mdc-shape-small, 4px))}}.mdc-text-field--outlined.mdc-text-field--with-trailing-icon{padding-right:0}@supports(top: max(0%)){.mdc-text-field--outlined.mdc-text-field--with-trailing-icon{padding-left:max(16px, calc(var(--mdc-shape-small, 4px) + 4px))}}[dir=rtl] .mdc-text-field--outlined.mdc-text-field--with-trailing-icon,.mdc-text-field--outlined.mdc-text-field--with-trailing-icon[dir=rtl]{padding-left:0}@supports(top: max(0%)){[dir=rtl] .mdc-text-field--outlined.mdc-text-field--with-trailing-icon,.mdc-text-field--outlined.mdc-text-field--with-trailing-icon[dir=rtl]{padding-right:max(16px, calc(var(--mdc-shape-small, 4px) + 4px))}}.mdc-text-field--outlined.mdc-text-field--with-leading-icon.mdc-text-field--with-trailing-icon{padding-left:0;padding-right:0}.mdc-text-field--outlined .mdc-notched-outline--notched .mdc-notched-outline__notch{padding-top:1px}.mdc-text-field--outlined .mdc-text-field__ripple::before,.mdc-text-field--outlined .mdc-text-field__ripple::after{background-color:transparent;background-color:var(--mdc-ripple-color, transparent)}.mdc-text-field--outlined .mdc-floating-label{left:4px;right:initial}[dir=rtl] .mdc-text-field--outlined .mdc-floating-label,.mdc-text-field--outlined .mdc-floating-label[dir=rtl]{left:initial;right:4px}.mdc-text-field--outlined .mdc-text-field__input{display:flex;border:none !important;background-color:transparent}.mdc-text-field--outlined .mdc-notched-outline{z-index:1}.mdc-text-field--textarea{flex-direction:column;align-items:center;width:auto;height:auto;padding:0;transition:none}.mdc-text-field--textarea .mdc-floating-label{top:19px}.mdc-text-field--textarea .mdc-floating-label:not(.mdc-floating-label--float-above){transform:none}.mdc-text-field--textarea .mdc-text-field__input{flex-grow:1;height:auto;min-height:1.5rem;overflow-x:hidden;overflow-y:auto;box-sizing:border-box;resize:none;padding:0 16px;line-height:1.5rem}.mdc-text-field--textarea.mdc-text-field--filled::before{display:none}.mdc-text-field--textarea.mdc-text-field--filled .mdc-floating-label--float-above{transform:translateY(-10.25px) scale(0.75)}.mdc-text-field--textarea.mdc-text-field--filled .mdc-floating-label--shake{animation:mdc-floating-label-shake-float-above-textarea-filled 250ms 1}@keyframes mdc-floating-label-shake-float-above-textarea-filled{0%{transform:translateX(calc(0 - 0%)) translateY(-10.25px) scale(0.75)}33%{animation-timing-function:cubic-bezier(0.5, 0, 0.701732, 0.495819);transform:translateX(calc(4% - 0%)) translateY(-10.25px) scale(0.75)}66%{animation-timing-function:cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);transform:translateX(calc(-4% - 0%)) translateY(-10.25px) scale(0.75)}100%{transform:translateX(calc(0 - 0%)) translateY(-10.25px) scale(0.75)}}.mdc-text-field--textarea.mdc-text-field--filled .mdc-text-field__input{margin-top:23px;margin-bottom:9px}.mdc-text-field--textarea.mdc-text-field--filled.mdc-text-field--no-label .mdc-text-field__input{margin-top:16px;margin-bottom:16px}.mdc-text-field--textarea.mdc-text-field--outlined .mdc-notched-outline--notched .mdc-notched-outline__notch{padding-top:0}.mdc-text-field--textarea.mdc-text-field--outlined .mdc-floating-label--float-above{transform:translateY(-27.25px) scale(1)}.mdc-text-field--textarea.mdc-text-field--outlined .mdc-floating-label--float-above{font-size:.75rem}.mdc-text-field--textarea.mdc-text-field--outlined.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-text-field--textarea.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{transform:translateY(-24.75px) scale(0.75)}.mdc-text-field--textarea.mdc-text-field--outlined.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-text-field--textarea.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{font-size:1rem}.mdc-text-field--textarea.mdc-text-field--outlined .mdc-floating-label--shake{animation:mdc-floating-label-shake-float-above-textarea-outlined 250ms 1}@keyframes mdc-floating-label-shake-float-above-textarea-outlined{0%{transform:translateX(calc(0 - 0%)) translateY(-24.75px) scale(0.75)}33%{animation-timing-function:cubic-bezier(0.5, 0, 0.701732, 0.495819);transform:translateX(calc(4% - 0%)) translateY(-24.75px) scale(0.75)}66%{animation-timing-function:cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);transform:translateX(calc(-4% - 0%)) translateY(-24.75px) scale(0.75)}100%{transform:translateX(calc(0 - 0%)) translateY(-24.75px) scale(0.75)}}.mdc-text-field--textarea.mdc-text-field--outlined .mdc-text-field__input{margin-top:16px;margin-bottom:16px}.mdc-text-field--textarea.mdc-text-field--outlined .mdc-floating-label{top:18px}.mdc-text-field--textarea.mdc-text-field--with-internal-counter .mdc-text-field__input{margin-bottom:2px}.mdc-text-field--textarea.mdc-text-field--with-internal-counter .mdc-text-field-character-counter{align-self:flex-end;padding:0 16px}.mdc-text-field--textarea.mdc-text-field--with-internal-counter .mdc-text-field-character-counter::after{display:inline-block;width:0;height:16px;content:"";vertical-align:-16px}.mdc-text-field--textarea.mdc-text-field--with-internal-counter .mdc-text-field-character-counter::before{display:none}.mdc-text-field__resizer{align-self:stretch;display:inline-flex;flex-direction:column;flex-grow:1;max-height:100%;max-width:100%;min-height:56px;min-width:fit-content;min-width:-moz-available;min-width:-webkit-fill-available;overflow:hidden;resize:both}.mdc-text-field--filled .mdc-text-field__resizer{transform:translateY(-1px)}.mdc-text-field--filled .mdc-text-field__resizer .mdc-text-field__input,.mdc-text-field--filled .mdc-text-field__resizer .mdc-text-field-character-counter{transform:translateY(1px)}.mdc-text-field--outlined .mdc-text-field__resizer{transform:translateX(-1px) translateY(-1px)}[dir=rtl] .mdc-text-field--outlined .mdc-text-field__resizer,.mdc-text-field--outlined .mdc-text-field__resizer[dir=rtl]{transform:translateX(1px) translateY(-1px)}.mdc-text-field--outlined .mdc-text-field__resizer .mdc-text-field__input,.mdc-text-field--outlined .mdc-text-field__resizer .mdc-text-field-character-counter{transform:translateX(1px) translateY(1px)}[dir=rtl] .mdc-text-field--outlined .mdc-text-field__resizer .mdc-text-field__input,[dir=rtl] .mdc-text-field--outlined .mdc-text-field__resizer .mdc-text-field-character-counter,.mdc-text-field--outlined .mdc-text-field__resizer .mdc-text-field__input[dir=rtl],.mdc-text-field--outlined .mdc-text-field__resizer .mdc-text-field-character-counter[dir=rtl]{transform:translateX(-1px) translateY(1px)}.mdc-text-field--with-leading-icon{padding-left:0;padding-right:16px}[dir=rtl] .mdc-text-field--with-leading-icon,.mdc-text-field--with-leading-icon[dir=rtl]{padding-left:16px;padding-right:0}.mdc-text-field--with-leading-icon.mdc-text-field--filled .mdc-floating-label{max-width:calc(100% - 48px);left:48px;right:initial}[dir=rtl] .mdc-text-field--with-leading-icon.mdc-text-field--filled .mdc-floating-label,.mdc-text-field--with-leading-icon.mdc-text-field--filled .mdc-floating-label[dir=rtl]{left:initial;right:48px}.mdc-text-field--with-leading-icon.mdc-text-field--filled .mdc-floating-label--float-above{max-width:calc(100% / 0.75 - 64px / 0.75)}.mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-floating-label{left:36px;right:initial}[dir=rtl] .mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-floating-label,.mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-floating-label[dir=rtl]{left:initial;right:36px}.mdc-text-field--with-leading-icon.mdc-text-field--outlined :not(.mdc-notched-outline--notched) .mdc-notched-outline__notch{max-width:calc(100% - 60px)}.mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-floating-label--float-above{transform:translateY(-37.25px) translateX(-32px) scale(1)}[dir=rtl] .mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-floating-label--float-above,.mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-floating-label--float-above[dir=rtl]{transform:translateY(-37.25px) translateX(32px) scale(1)}.mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-floating-label--float-above{font-size:.75rem}.mdc-text-field--with-leading-icon.mdc-text-field--outlined.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{transform:translateY(-34.75px) translateX(-32px) scale(0.75)}[dir=rtl] .mdc-text-field--with-leading-icon.mdc-text-field--outlined.mdc-notched-outline--upgraded .mdc-floating-label--float-above,[dir=rtl] .mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-text-field--with-leading-icon.mdc-text-field--outlined.mdc-notched-outline--upgraded .mdc-floating-label--float-above[dir=rtl],.mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above[dir=rtl]{transform:translateY(-34.75px) translateX(32px) scale(0.75)}.mdc-text-field--with-leading-icon.mdc-text-field--outlined.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{font-size:1rem}.mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-floating-label--shake{animation:mdc-floating-label-shake-float-above-text-field-outlined-leading-icon 250ms 1}@keyframes mdc-floating-label-shake-float-above-text-field-outlined-leading-icon{0%{transform:translateX(calc(0 - 32px)) translateY(-34.75px) scale(0.75)}33%{animation-timing-function:cubic-bezier(0.5, 0, 0.701732, 0.495819);transform:translateX(calc(4% - 32px)) translateY(-34.75px) scale(0.75)}66%{animation-timing-function:cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);transform:translateX(calc(-4% - 32px)) translateY(-34.75px) scale(0.75)}100%{transform:translateX(calc(0 - 32px)) translateY(-34.75px) scale(0.75)}}[dir=rtl] .mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-floating-label--shake,.mdc-text-field--with-leading-icon.mdc-text-field--outlined[dir=rtl] .mdc-floating-label--shake{animation:mdc-floating-label-shake-float-above-text-field-outlined-leading-icon 250ms 1}@keyframes mdc-floating-label-shake-float-above-text-field-outlined-leading-icon-rtl{0%{transform:translateX(calc(0 - -32px)) translateY(-34.75px) scale(0.75)}33%{animation-timing-function:cubic-bezier(0.5, 0, 0.701732, 0.495819);transform:translateX(calc(4% - -32px)) translateY(-34.75px) scale(0.75)}66%{animation-timing-function:cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);transform:translateX(calc(-4% - -32px)) translateY(-34.75px) scale(0.75)}100%{transform:translateX(calc(0 - -32px)) translateY(-34.75px) scale(0.75)}}.mdc-text-field--with-trailing-icon{padding-left:16px;padding-right:0}[dir=rtl] .mdc-text-field--with-trailing-icon,.mdc-text-field--with-trailing-icon[dir=rtl]{padding-left:0;padding-right:16px}.mdc-text-field--with-trailing-icon.mdc-text-field--filled .mdc-floating-label{max-width:calc(100% - 64px)}.mdc-text-field--with-trailing-icon.mdc-text-field--filled .mdc-floating-label--float-above{max-width:calc(100% / 0.75 - 64px / 0.75)}.mdc-text-field--with-trailing-icon.mdc-text-field--outlined :not(.mdc-notched-outline--notched) .mdc-notched-outline__notch{max-width:calc(100% - 60px)}.mdc-text-field--with-leading-icon.mdc-text-field--with-trailing-icon{padding-left:0;padding-right:0}.mdc-text-field--with-leading-icon.mdc-text-field--with-trailing-icon.mdc-text-field--filled .mdc-floating-label{max-width:calc(100% - 96px)}.mdc-text-field--with-leading-icon.mdc-text-field--with-trailing-icon.mdc-text-field--filled .mdc-floating-label--float-above{max-width:calc(100% / 0.75 - 96px / 0.75)}.mdc-text-field-helper-line{display:flex;justify-content:space-between;box-sizing:border-box}.mdc-text-field+.mdc-text-field-helper-line{padding-right:16px;padding-left:16px}.mdc-form-field>.mdc-text-field+label{align-self:flex-start}.mdc-text-field--focused:not(.mdc-text-field--disabled) .mdc-floating-label{color:rgba(98, 0, 238, 0.87)}.mdc-text-field--focused .mdc-notched-outline__leading,.mdc-text-field--focused .mdc-notched-outline__notch,.mdc-text-field--focused .mdc-notched-outline__trailing{border-width:2px}.mdc-text-field--focused+.mdc-text-field-helper-line .mdc-text-field-helper-text:not(.mdc-text-field-helper-text--validation-msg){opacity:1}.mdc-text-field--focused.mdc-text-field--outlined .mdc-notched-outline--notched .mdc-notched-outline__notch{padding-top:2px}.mdc-text-field--focused.mdc-text-field--outlined.mdc-text-field--textarea .mdc-notched-outline--notched .mdc-notched-outline__notch{padding-top:0}.mdc-text-field--invalid:not(.mdc-text-field--disabled):hover .mdc-line-ripple::before{border-bottom-color:#b00020;border-bottom-color:var(--mdc-theme-error, #b00020)}.mdc-text-field--invalid:not(.mdc-text-field--disabled) .mdc-line-ripple::after{border-bottom-color:#b00020;border-bottom-color:var(--mdc-theme-error, #b00020)}.mdc-text-field--invalid:not(.mdc-text-field--disabled) .mdc-floating-label{color:#b00020;color:var(--mdc-theme-error, #b00020)}.mdc-text-field--invalid:not(.mdc-text-field--disabled).mdc-text-field--invalid+.mdc-text-field-helper-line .mdc-text-field-helper-text--validation-msg{color:#b00020;color:var(--mdc-theme-error, #b00020)}.mdc-text-field--invalid .mdc-text-field__input{caret-color:#b00020;caret-color:var(--mdc-theme-error, #b00020)}.mdc-text-field--invalid:not(.mdc-text-field--disabled) .mdc-text-field__icon--trailing{color:#b00020;color:var(--mdc-theme-error, #b00020)}.mdc-text-field--invalid:not(.mdc-text-field--disabled) .mdc-line-ripple::before{border-bottom-color:#b00020;border-bottom-color:var(--mdc-theme-error, #b00020)}.mdc-text-field--invalid:not(.mdc-text-field--disabled) .mdc-notched-outline__leading,.mdc-text-field--invalid:not(.mdc-text-field--disabled) .mdc-notched-outline__notch,.mdc-text-field--invalid:not(.mdc-text-field--disabled) .mdc-notched-outline__trailing{border-color:#b00020;border-color:var(--mdc-theme-error, #b00020)}.mdc-text-field--invalid:not(.mdc-text-field--disabled):not(.mdc-text-field--focused):hover .mdc-notched-outline .mdc-notched-outline__leading,.mdc-text-field--invalid:not(.mdc-text-field--disabled):not(.mdc-text-field--focused):hover .mdc-notched-outline .mdc-notched-outline__notch,.mdc-text-field--invalid:not(.mdc-text-field--disabled):not(.mdc-text-field--focused):hover .mdc-notched-outline .mdc-notched-outline__trailing{border-color:#b00020;border-color:var(--mdc-theme-error, #b00020)}.mdc-text-field--invalid:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-notched-outline__leading,.mdc-text-field--invalid:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-notched-outline__notch,.mdc-text-field--invalid:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-notched-outline__trailing{border-color:#b00020;border-color:var(--mdc-theme-error, #b00020)}.mdc-text-field--invalid+.mdc-text-field-helper-line .mdc-text-field-helper-text--validation-msg{opacity:1}.mdc-text-field--disabled{pointer-events:none}.mdc-text-field--disabled .mdc-text-field__input{color:rgba(0, 0, 0, 0.38)}@media all{.mdc-text-field--disabled .mdc-text-field__input::placeholder{color:rgba(0, 0, 0, 0.38)}}@media all{.mdc-text-field--disabled .mdc-text-field__input:-ms-input-placeholder{color:rgba(0, 0, 0, 0.38)}}.mdc-text-field--disabled .mdc-floating-label{color:rgba(0, 0, 0, 0.38)}.mdc-text-field--disabled+.mdc-text-field-helper-line .mdc-text-field-helper-text{color:rgba(0, 0, 0, 0.38)}.mdc-text-field--disabled .mdc-text-field-character-counter,.mdc-text-field--disabled+.mdc-text-field-helper-line .mdc-text-field-character-counter{color:rgba(0, 0, 0, 0.38)}.mdc-text-field--disabled .mdc-text-field__icon--leading{color:rgba(0, 0, 0, 0.3)}.mdc-text-field--disabled .mdc-text-field__icon--trailing{color:rgba(0, 0, 0, 0.3)}.mdc-text-field--disabled .mdc-text-field__affix--prefix{color:rgba(0, 0, 0, 0.38)}.mdc-text-field--disabled .mdc-text-field__affix--suffix{color:rgba(0, 0, 0, 0.38)}.mdc-text-field--disabled .mdc-line-ripple::before{border-bottom-color:rgba(0, 0, 0, 0.06)}.mdc-text-field--disabled .mdc-notched-outline__leading,.mdc-text-field--disabled .mdc-notched-outline__notch,.mdc-text-field--disabled .mdc-notched-outline__trailing{border-color:rgba(0, 0, 0, 0.06)}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-text-field--disabled .mdc-text-field__input::placeholder{color:GrayText}}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-text-field--disabled .mdc-text-field__input:-ms-input-placeholder{color:GrayText}}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-text-field--disabled .mdc-floating-label{color:GrayText}}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-text-field--disabled+.mdc-text-field-helper-line .mdc-text-field-helper-text{color:GrayText}}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-text-field--disabled .mdc-text-field-character-counter,.mdc-text-field--disabled+.mdc-text-field-helper-line .mdc-text-field-character-counter{color:GrayText}}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-text-field--disabled .mdc-text-field__icon--leading{color:GrayText}}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-text-field--disabled .mdc-text-field__icon--trailing{color:GrayText}}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-text-field--disabled .mdc-text-field__affix--prefix{color:GrayText}}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-text-field--disabled .mdc-text-field__affix--suffix{color:GrayText}}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-text-field--disabled .mdc-line-ripple::before{border-bottom-color:GrayText}}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-text-field--disabled .mdc-notched-outline__leading,.mdc-text-field--disabled .mdc-notched-outline__notch,.mdc-text-field--disabled .mdc-notched-outline__trailing{border-color:GrayText}}@media screen and (forced-colors: active){.mdc-text-field--disabled .mdc-text-field__input{background-color:Window}.mdc-text-field--disabled .mdc-floating-label{z-index:1}}.mdc-text-field--disabled .mdc-floating-label{cursor:default}.mdc-text-field--disabled.mdc-text-field--filled{background-color:#fafafa}.mdc-text-field--disabled.mdc-text-field--filled .mdc-text-field__ripple{display:none}.mdc-text-field--disabled .mdc-text-field__input{pointer-events:auto}.mdc-text-field--end-aligned .mdc-text-field__input{text-align:right}[dir=rtl] .mdc-text-field--end-aligned .mdc-text-field__input,.mdc-text-field--end-aligned .mdc-text-field__input[dir=rtl]{text-align:left}[dir=rtl] .mdc-text-field--ltr-text .mdc-text-field__input,[dir=rtl] .mdc-text-field--ltr-text .mdc-text-field__affix,.mdc-text-field--ltr-text[dir=rtl] .mdc-text-field__input,.mdc-text-field--ltr-text[dir=rtl] .mdc-text-field__affix{direction:ltr}[dir=rtl] .mdc-text-field--ltr-text .mdc-text-field__affix--prefix,.mdc-text-field--ltr-text[dir=rtl] .mdc-text-field__affix--prefix{padding-left:0;padding-right:2px}[dir=rtl] .mdc-text-field--ltr-text .mdc-text-field__affix--suffix,.mdc-text-field--ltr-text[dir=rtl] .mdc-text-field__affix--suffix{padding-left:12px;padding-right:0}[dir=rtl] .mdc-text-field--ltr-text .mdc-text-field__icon--leading,.mdc-text-field--ltr-text[dir=rtl] .mdc-text-field__icon--leading{order:1}[dir=rtl] .mdc-text-field--ltr-text .mdc-text-field__affix--suffix,.mdc-text-field--ltr-text[dir=rtl] .mdc-text-field__affix--suffix{order:2}[dir=rtl] .mdc-text-field--ltr-text .mdc-text-field__input,.mdc-text-field--ltr-text[dir=rtl] .mdc-text-field__input{order:3}[dir=rtl] .mdc-text-field--ltr-text .mdc-text-field__affix--prefix,.mdc-text-field--ltr-text[dir=rtl] .mdc-text-field__affix--prefix{order:4}[dir=rtl] .mdc-text-field--ltr-text .mdc-text-field__icon--trailing,.mdc-text-field--ltr-text[dir=rtl] .mdc-text-field__icon--trailing{order:5}[dir=rtl] .mdc-text-field--ltr-text.mdc-text-field--end-aligned .mdc-text-field__input,.mdc-text-field--ltr-text.mdc-text-field--end-aligned[dir=rtl] .mdc-text-field__input{text-align:right}[dir=rtl] .mdc-text-field--ltr-text.mdc-text-field--end-aligned .mdc-text-field__affix--prefix,.mdc-text-field--ltr-text.mdc-text-field--end-aligned[dir=rtl] .mdc-text-field__affix--prefix{padding-right:12px}[dir=rtl] .mdc-text-field--ltr-text.mdc-text-field--end-aligned .mdc-text-field__affix--suffix,.mdc-text-field--ltr-text.mdc-text-field--end-aligned[dir=rtl] .mdc-text-field__affix--suffix{padding-left:2px}.mdc-text-field-helper-text{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-caption-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:0.75rem;font-size:var(--mdc-typography-caption-font-size, 0.75rem);line-height:1.25rem;line-height:var(--mdc-typography-caption-line-height, 1.25rem);font-weight:400;font-weight:var(--mdc-typography-caption-font-weight, 400);letter-spacing:0.0333333333em;letter-spacing:var(--mdc-typography-caption-letter-spacing, 0.0333333333em);text-decoration:inherit;text-decoration:var(--mdc-typography-caption-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-caption-text-transform, inherit);display:block;margin-top:0;line-height:normal;margin:0;opacity:0;will-change:opacity;transition:opacity 150ms 0ms cubic-bezier(0.4, 0, 0.2, 1)}.mdc-text-field-helper-text::before{display:inline-block;width:0;height:16px;content:"";vertical-align:0}.mdc-text-field-helper-text--persistent{transition:none;opacity:1;will-change:initial}.mdc-text-field-character-counter{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-caption-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:0.75rem;font-size:var(--mdc-typography-caption-font-size, 0.75rem);line-height:1.25rem;line-height:var(--mdc-typography-caption-line-height, 1.25rem);font-weight:400;font-weight:var(--mdc-typography-caption-font-weight, 400);letter-spacing:0.0333333333em;letter-spacing:var(--mdc-typography-caption-letter-spacing, 0.0333333333em);text-decoration:inherit;text-decoration:var(--mdc-typography-caption-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-caption-text-transform, inherit);display:block;margin-top:0;line-height:normal;margin-left:auto;margin-right:0;padding-left:16px;padding-right:0;white-space:nowrap}.mdc-text-field-character-counter::before{display:inline-block;width:0;height:16px;content:"";vertical-align:0}[dir=rtl] .mdc-text-field-character-counter,.mdc-text-field-character-counter[dir=rtl]{margin-left:0;margin-right:auto}[dir=rtl] .mdc-text-field-character-counter,.mdc-text-field-character-counter[dir=rtl]{padding-left:0;padding-right:16px}.mdc-text-field__icon{align-self:center;cursor:pointer}.mdc-text-field__icon:not([tabindex]),.mdc-text-field__icon[tabindex="-1"]{cursor:default;pointer-events:none}.mdc-text-field__icon svg{display:block}.mdc-text-field__icon--leading{margin-left:16px;margin-right:8px}[dir=rtl] .mdc-text-field__icon--leading,.mdc-text-field__icon--leading[dir=rtl]{margin-left:8px;margin-right:16px}.mdc-text-field__icon--trailing{padding:12px;margin-left:0px;margin-right:0px}[dir=rtl] .mdc-text-field__icon--trailing,.mdc-text-field__icon--trailing[dir=rtl]{margin-left:0px;margin-right:0px}.material-icons{font-family:var(--mdc-icon-font, "Material Icons");font-weight:normal;font-style:normal;font-size:var(--mdc-icon-size, 24px);line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;-moz-osx-font-smoothing:grayscale;font-feature-settings:"liga"}:host{display:inline-flex;flex-direction:column;outline:none}.mdc-text-field{width:100%}.mdc-text-field:not(.mdc-text-field--disabled) .mdc-line-ripple::before{border-bottom-color:rgba(0, 0, 0, 0.42);border-bottom-color:var(--mdc-text-field-idle-line-color, rgba(0, 0, 0, 0.42))}.mdc-text-field:not(.mdc-text-field--disabled):hover .mdc-line-ripple::before{border-bottom-color:rgba(0, 0, 0, 0.87);border-bottom-color:var(--mdc-text-field-hover-line-color, rgba(0, 0, 0, 0.87))}.mdc-text-field.mdc-text-field--disabled .mdc-line-ripple::before{border-bottom-color:rgba(0, 0, 0, 0.06);border-bottom-color:var(--mdc-text-field-disabled-line-color, rgba(0, 0, 0, 0.06))}.mdc-text-field.mdc-text-field--invalid:not(.mdc-text-field--disabled) .mdc-line-ripple::before{border-bottom-color:#b00020;border-bottom-color:var(--mdc-theme-error, #b00020)}.mdc-text-field__input{direction:inherit}mwc-notched-outline{--mdc-notched-outline-border-color: var( --mdc-text-field-outlined-idle-border-color, rgba(0, 0, 0, 0.38) )}:host(:not([disabled]):hover) :not(.mdc-text-field--invalid):not(.mdc-text-field--focused) mwc-notched-outline{--mdc-notched-outline-border-color: var( --mdc-text-field-outlined-hover-border-color, rgba(0, 0, 0, 0.87) )}:host(:not([disabled])) .mdc-text-field:not(.mdc-text-field--outlined){background-color:var(--mdc-text-field-fill-color, whitesmoke)}:host(:not([disabled])) .mdc-text-field.mdc-text-field--invalid mwc-notched-outline{--mdc-notched-outline-border-color: var( --mdc-text-field-error-color, var(--mdc-theme-error, #b00020) )}:host(:not([disabled])) .mdc-text-field.mdc-text-field--invalid+.mdc-text-field-helper-line .mdc-text-field-character-counter,:host(:not([disabled])) .mdc-text-field.mdc-text-field--invalid .mdc-text-field__icon{color:var(--mdc-text-field-error-color, var(--mdc-theme-error, #b00020))}:host(:not([disabled])) .mdc-text-field:not(.mdc-text-field--invalid):not(.mdc-text-field--focused) .mdc-floating-label,:host(:not([disabled])) .mdc-text-field:not(.mdc-text-field--invalid):not(.mdc-text-field--focused) .mdc-floating-label::after{color:var(--mdc-text-field-label-ink-color, rgba(0, 0, 0, 0.6))}:host(:not([disabled])) .mdc-text-field.mdc-text-field--focused mwc-notched-outline{--mdc-notched-outline-stroke-width: 2px}:host(:not([disabled])) .mdc-text-field.mdc-text-field--focused:not(.mdc-text-field--invalid) mwc-notched-outline{--mdc-notched-outline-border-color: var( --mdc-text-field-focused-label-color, var(--mdc-theme-primary, rgba(98, 0, 238, 0.87)) )}:host(:not([disabled])) .mdc-text-field.mdc-text-field--focused:not(.mdc-text-field--invalid) .mdc-floating-label{color:#6200ee;color:var(--mdc-theme-primary, #6200ee)}:host(:not([disabled])) .mdc-text-field .mdc-text-field__input{color:var(--mdc-text-field-ink-color, rgba(0, 0, 0, 0.87))}:host(:not([disabled])) .mdc-text-field .mdc-text-field__input::placeholder{color:var(--mdc-text-field-label-ink-color, rgba(0, 0, 0, 0.6))}:host(:not([disabled])) .mdc-text-field-helper-line .mdc-text-field-helper-text:not(.mdc-text-field-helper-text--validation-msg),:host(:not([disabled])) .mdc-text-field-helper-line:not(.mdc-text-field--invalid) .mdc-text-field-character-counter{color:var(--mdc-text-field-label-ink-color, rgba(0, 0, 0, 0.6))}:host([disabled]) .mdc-text-field:not(.mdc-text-field--outlined){background-color:var(--mdc-text-field-disabled-fill-color, #fafafa)}:host([disabled]) .mdc-text-field.mdc-text-field--outlined mwc-notched-outline{--mdc-notched-outline-border-color: var( --mdc-text-field-outlined-disabled-border-color, rgba(0, 0, 0, 0.06) )}:host([disabled]) .mdc-text-field:not(.mdc-text-field--invalid):not(.mdc-text-field--focused) .mdc-floating-label,:host([disabled]) .mdc-text-field:not(.mdc-text-field--invalid):not(.mdc-text-field--focused) .mdc-floating-label::after{color:var(--mdc-text-field-disabled-ink-color, rgba(0, 0, 0, 0.38))}:host([disabled]) .mdc-text-field .mdc-text-field__input,:host([disabled]) .mdc-text-field .mdc-text-field__input::placeholder{color:var(--mdc-text-field-disabled-ink-color, rgba(0, 0, 0, 0.38))}:host([disabled]) .mdc-text-field-helper-line .mdc-text-field-helper-text,:host([disabled]) .mdc-text-field-helper-line .mdc-text-field-character-counter{color:var(--mdc-text-field-disabled-ink-color, rgba(0, 0, 0, 0.38))}`,zv={"mwc-textfield":class extends Hv{static get styles(){return Uv}},"mwc-notched-outline":class extends Lm{static get styles(){return Fm}}};let Fv=class extends( -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -function(t){return class extends t{createRenderRoot(){const t=this.constructor,{registry:e,elementDefinitions:i,shadowRootOptions:s}=t;i&&!e&&(t.registry=new CustomElementRegistry,Object.entries(i).forEach(([e,i])=>t.registry.define(e,i)));const n=this.renderOptions.creationScope=this.attachShadow({...s,customElements:t.registry});return p(n,this.constructor.elementStyles),n}}}(ht)){constructor(){super(...arguments),this._initialized=!1}setConfig(t){this._config=t,this.loadCardHelpers()}shouldUpdate(){return this._initialized||this._initialize(),!0}get _name(){var t;return(null===(t=this._config)||void 0===t?void 0:t.name)||""}get _hub(){var t;return(null===(t=this._config)||void 0===t?void 0:t.hub)||""}get _selected_schedule(){var t;return(null===(t=this._config)||void 0===t?void 0:t.selected_schedule)||""}get _theme_colors(){var t;return(null===(t=this._config)||void 0===t?void 0:t.theme_colors)||!1}get _show_badges(){var t;return(null===(t=this._config)||void 0===t?void 0:t.show_badges)||!1}get _show_schedule_id(){var t;return(null===(t=this._config)||void 0===t?void 0:t.show_schedule_id)||!1}get _display_only(){var t;return(null===(t=this._config)||void 0===t?void 0:t.display_only)||!1}get _hide_hw_schedule(){var t;return(null===(t=this._config)||void 0===t?void 0:t.hide_hw_schedule)||!1}get _admin_only(){var t;return(null===(t=this._config)||void 0===t?void 0:t.admin_only)||!1}get _view_type(){var t,e;return(null===(t=this._config)||void 0===t?void 0:t.view_type)?null===(e=this._config)||void 0===e?void 0:e.view_type:"default"}get _hide_card_borders(){var t;return(null===(t=this._config)||void 0===t?void 0:t.hide_card_borders)||!1}async loadData(){var t;this.hass&&(this._hubs=await(t=this.hass,t.callWS({type:"wiser/hubs"})),this._schedules=await qt(this.hass,this._hub?this._hub:this._hubs[0]))}render(){return this.hass&&this._helpers&&this._config&&this._hubs&&this._schedules?X` - - ${this.hubSelector()} - t.stopPropagation()} - > - - ${this._schedules.map(t=>X`${t.Name}`)} - - t.stopPropagation()} - > - ${["default","list"].map(t=>{return X`${e=t,e.charAt(0).toUpperCase()+e.slice(1)}`;var e})} - - - - - - - -
- - - - - - - - - -
-

Default View Options

- - - - - - -
-
Version: ${$t}
- `:X``}hubSelector(){var t;const e=this._hubs?this._hubs:[];return e.length>1?X` - t.stopPropagation()} - > - ${null===(t=this._hubs)||void 0===t?void 0:t.map(t=>X`${t}`)} - - `:X``}_initialize(){void 0!==this.hass&&void 0!==this._config&&void 0!==this._helpers&&(this._initialized=!0)}async loadCardHelpers(){this._helpers=await window.loadCardHelpers(),await this.loadData()}_valueChanged(t){if(!this._config||!this.hass)return;const e=t.target;if(this[`_${e.configValue}`]!==e.value){if(e.configValue)if(""===e.value){const t=Object.assign({},this._config);delete t[e.configValue],this._config=t}else this._config=Object.assign(Object.assign({},this._config),{[e.configValue]:void 0!==e.checked?e.checked:e.value});"hub"===e.configValue&&(this._config.selected_schedule=""),yt(this,"config-changed",{config:this._config})}}};return Fv.elementDefinitions=Object.assign(Object.assign(Object.assign(Object.assign({},zv),Bm),ag),$n),Fv.styles=h` - mwc-select, - mwc-textfield { - margin-bottom: 16px; + ${this._error?W`
${this._error}
`:""} +
+ ${this.localize("wiser.editor.permissions")} + ${this.toggle("display_only",this.localize("wiser.editor.display_only"))} +

${this.localize("wiser.editor.display_only_help")}

+ ${this.toggle("admin_only",this.localize("wiser.editor.admin_only"),e.display_only)} +
+
+ ${this.localize("wiser.editor.appearance")} + ${this.toggle("theme_colors",this.localize("wiser.editor.theme_colors"))} + ${this.toggle("hide_card_borders",this.localize("wiser.editor.hide_card_borders"))} + ${this.toggle("hide_card_background",this.localize("wiser.editor.hide_card_background"))} +
+
Wiser Schedule Card · ${ye}
+ `}};si.styles=n` + .field-help { + color: var(--secondary-text-color); + font-size: 13px; + margin: 0 0 12px; + } + :host { display: block; + color: var(--primary-text-color); } - mwc-formfield { - padding-bottom: 20px; + .home-screen { display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + flex-wrap: wrap; } - mwc-switch { - --mdc-theme-secondary: var(--switch-checked-color); + .home-screen ha-selector { + width: max-content; + margin-inline-start: auto; + display: flex; + justify-content: flex-end; + max-width: 100%; } - `,n([gt({attribute:!1})],Fv.prototype,"hass",void 0),n([vt()],Fv.prototype,"_config",void 0),n([vt()],Fv.prototype,"_helpers",void 0),n([vt()],Fv.prototype,"_hubs",void 0),n([vt()],Fv.prototype,"_schedules",void 0),Fv=n([ut("wiser-schedule-card-editor")],Fv),console.info(`%c WISER-SCHEDULE-CARD \n%c ${Vt("common.version")} ${$t} `,"color: orange; font-weight: bold; background: black","color: white; font-weight: bold; background: dimgray"),window.customCards=window.customCards||[],window.customCards.push({type:"wiser-schedule-card",name:"Wiser Schedule Card",description:"A card to manage Wiser schedules",preview:!1}),t.WiserScheduleCard=class extends ht{constructor(){super(),this._view=Et.Overview,this.translationsLoaded=!0,this.component_loaded=!1,this._schedule_id=0,this._schedule_type="heating",this.initialise()}static async getConfigElement(){return document.createElement("wiser-schedule-card-editor")}static getStubConfig(){return{}}setConfig(t){if(!t)throw new Error(Vt("common.invalid_configuration"));t.test_gui&&function(){var t=document.querySelector("home-assistant");if(t=(t=(t=(t=(t=(t=(t=(t=t&&t.shadowRoot)&&t.querySelector("home-assistant-main"))&&t.shadowRoot)&&t.querySelector("app-drawer-layout partial-panel-resolver"))&&t.shadowRoot||t)&&t.querySelector("ha-panel-lovelace"))&&t.shadowRoot)&&t.querySelector("hui-root")){var e=t.lovelace;return e.current_view=t.___curView,e}return null}().setEditMode(!0),this.config=Object.assign({name:"Wiser Schedule"},t)}set hass(t){this._hass=t}async initialise(){return await this.isComponentLoaded()&&(this.component_loaded=!0),this.processConfigSchedule(),!0}async isComponentLoaded(){for(;!this._hass||!this._hass.config.components.includes("wiser");)await new Promise(t=>setTimeout(t,100));return!0}processConfigSchedule(){this.config.selected_schedule?(this._schedule_type=this.config.selected_schedule.split("|")[0],this._schedule_id=parseInt(this.config.selected_schedule.split("|")[1]),this._view=Et.ScheduleEdit):(this._schedule_type="",this._schedule_id=0,this._view=Et.Overview)}getCardSize(){return 9}shouldUpdate(t){return!(!this.config||!this.component_loaded)&&(t.has("config")&&this.processConfigSchedule(),!!t.has("component_loaded")||(!!t.has("_view")||(!!t.has("_schedule_list")||xt(this,t,!1))))}async _handleEvent(t){if("wiser_update_received"===t.event_type){const t=new CustomEvent("wiser-update",{});this.dispatchEvent(t)}}render(){if(!this._hass||!this.config||!this.translationsLoaded)return X``;const t=this.config.hide_card_borders?"border-width: 0px":"";return this._view==Et.Overview?X` - -
- -
-
- `:this._view==Et.ScheduleEdit&&this._schedule_id?X` - -
+ .fields { + display: grid; + gap: 16px; + } + label { + display: grid; + gap: 8px; + font-size: calc(14px + 1pt); + } + input[type='text'], + select { + box-sizing: border-box; + width: 100%; + min-height: 44px; + border: 1px solid var(--divider-color, #ddd); + border-radius: 10px; + padding: 10px 12px; + background: var(--card-background-color, white); + color: var(--primary-text-color); + font: inherit; + } + fieldset { + border: 0; + border-top: 1px solid var(--divider-color, #ddd); + padding: 16px 0 0; + margin: 24px 0 0; + min-width: 0; + } + legend { + padding-right: 12px; + color: var(--secondary-text-color); + font-size: calc(13px + 1pt); + } + .toggle { + display: flex; + justify-content: space-between; + align-items: center; + gap: 16px; + min-height: 44px; + } + input[type='checkbox'] { + width: 20px; + height: 20px; + flex-shrink: 0; + accent-color: var(--primary-color); + } + input:focus-visible, + select:focus-visible { + outline: 2px solid var(--primary-color); + outline-offset: 2px; + } + .version { + margin-top: 24px; + color: var(--secondary-text-color); + font-size: calc(12px + 1pt); + } + `,e([pe({attribute:!1})],si.prototype,"hass",void 0),e([ue()],si.prototype,"_config",void 0),e([ue()],si.prototype,"_hubs",void 0),e([ue()],si.prototype,"_error",void 0),si=e([t("wiser-schedule-card-editor")],si);class oi extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this.shadowRoot.innerHTML='\n \n
\n

Wiser Schedules

\n \n \n
\n \n

Customize this panel. Dashboard cards keep their own settings.

\n
\n
\n Cancel\n Save\n
\n
\n

Loading Wiser schedules…

',this.shadowRoot.getElementById("menu").addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("hass-toggle-menu",{bubbles:!0,composed:!0}))}),this.shadowRoot.getElementById("settings").addEventListener("click",()=>this._openEditor()),this.shadowRoot.getElementById("cancel").addEventListener("click",()=>this._closeEditor()),this.shadowRoot.getElementById("save").addEventListener("click",()=>this._saveEditor()),this.shadowRoot.getElementById("editor-dialog").addEventListener("closed",()=>this._closeEditor()),this.shadowRoot.getElementById("editor-dialog").addEventListener("close-dialog",()=>this._closeEditor()),this._editors=[],this._cards=[],this._generation=0}set hass(e){this._hass=e;for(const t of this._cards)t.hass=e;for(const t of this._editors)t.hass=e;this.shadowRoot.getElementById("settings").hidden=!e?.user?.is_admin}set panel(e){const t=e.config;JSON.stringify(t)!==JSON.stringify(this._config)&&(this._config=t,this._loadCards())}_cardConfig(e){return{name:this._config.hubs.length>1?e:"Wiser Schedules",...this._config.card_configs?.[e],type:"custom:wiser-schedule-card",hub:e}}_closeEditor(){this.shadowRoot.getElementById("editor-dialog").open=!1,this._editors=[]}async _openEditor(){const e=this.shadowRoot.getElementById("editor-dialog");if(e.open||!this._cards.length||!this._hass?.user?.is_admin)return;const t=this.shadowRoot.getElementById("editors"),i=this.shadowRoot.getElementById("editor-error"),s=this.shadowRoot.getElementById("save");this._drafts={},this._editors=[],i.textContent="",t.replaceChildren(),s.disabled=!0,e.heading="Panel settings","headerTitle"in(customElements.get("ha-dialog")?.prototype||{})||this.shadowRoot.getElementById("editor-actions").removeAttribute("slot"),e.open=!0;try{if(!window.loadCardHelpers){const e=document.createElement("partial-panel-resolver"),t=e._getRoutes?.({lovelace:{component_name:"lovelace",url_path:"lovelace"}});await(t?.routes?.lovelace?.load?.())}const i=customElements.get("wiser-schedule-card");for(const s of this._config.hubs){const o=await i.getConfigElement();if(!e.open)return;const a=this._cardConfig(s);this._drafts[s]=a,o.hass=this._hass,o.setConfig({...a}),o.addEventListener("config-changed",e=>{e.stopPropagation(),this._drafts[s]={...e.detail.config}});const r=document.createElement("section"),n=document.createElement("h3");n.textContent=s,r.replaceChildren(...this._config.hubs.length>1?[n,o]:[o]),t.append(r),this._editors.push(o)}s.disabled=!1}catch(e){i.textContent="Unable to open the editor. Close this dialog and try again.",console.error("Unable to open Wiser editor",e)}}async _saveEditor(){const e=this.shadowRoot.getElementById("save");e.disabled=!0;try{await this._hass.callWS({type:"wiser/schedules_panel/configure",configs:this._drafts}),this._config={...this._config,card_configs:{...this._config.card_configs,...this._drafts}},this._closeEditor(),this._editors=[],this._loadCards()}catch(e){this.shadowRoot.getElementById("editor-error").textContent="Unable to save settings to Home Assistant. Please try again.",console.error("Unable to save Wiser panel settings",e)}finally{e.disabled=!1}}async _loadCards(){const e=++this._generation,t=this._config,i=this.shadowRoot.querySelector("main");try{const s=customElements.get("wiser-schedule-card");if(1!==s?.panelApiVersion)throw new Error("Wiser Schedules needs its matching schedule card build. Update the card resource and refresh the browser.");if(e!==this._generation)return;const o=t.hubs.map(e=>{const t=document.createElement("wiser-schedule-card");return t.setConfig(this._cardConfig(e)),t.hass=this._hass,t});this._cards=o,i.replaceChildren(...o),this.shadowRoot.getElementById("settings").disabled=!1}catch(t){if(e!==this._generation)return;this._cards=[],this.shadowRoot.getElementById("settings").disabled=!0;const s=document.createElement("p");s.setAttribute("role","alert"),s.textContent=t.message||"Unable to load Wiser schedules. Please try again.";const o=document.createElement("ha-button");o.textContent="Retry",o.addEventListener("click",()=>this._loadCards()),i.replaceChildren(s,o),console.error("Unable to load Wiser schedules",t)}}}customElements.get("wiser-schedules-panel")||customElements.define("wiser-schedules-panel",oi),console.info(`%c WISER-SCHEDULE-CARD \n%c ${He("common.version")} ${ye} `,"color: orange; font-weight: bold; background: black","color: white; font-weight: bold; background: dimgray"),window.customCards=window.customCards||[],window.customCards.some(e=>"wiser-schedule-card"===e.type)||window.customCards.push({type:"wiser-schedule-card",name:"Wiser Schedule Card",description:"A card to manage Wiser schedules",preview:!1});let ai=class extends le{constructor(){super(...arguments),this._view=fe.Overview,this.component_loaded=!1,this._schedule_id=0,this._schedule_type="heating",this._homeView="schedules",this._target_type="heating",this._returnView=fe.Overview}static async getConfigElement(){return document.createElement("wiser-schedule-card-editor")}static getStubConfig(){return{}}setConfig(e){var t;if(!e)throw new Error(He("common.invalid_configuration"));e.test_gui&&function(){var e=document.querySelector("home-assistant");if(e=(e=(e=(e=(e=(e=(e=(e=e&&e.shadowRoot)&&e.querySelector("home-assistant-main"))&&e.shadowRoot)&&e.querySelector("app-drawer-layout partial-panel-resolver"))&&e.shadowRoot||e)&&e.querySelector("ha-panel-lovelace"))&&e.shadowRoot)&&e.querySelector("hui-root")){var t=e.lovelace;return t.current_view=e.___curView,t}return null}().setEditMode(!0),this.config=Object.assign(Object.assign({name:"Wiser Schedule"},e),{home_screen:"devices"===e.home_screen?"overview":null!==(t=e.home_screen)&&void 0!==t?t:"schedules"})}set hass(e){this._hass=e}processConfigSchedule(){var e,t,i;(null===(e=this.config)||void 0===e?void 0:e.selected_schedule)?(this._schedule_type=null===(t=this.config)||void 0===t?void 0:t.selected_schedule.split("|")[0],this._schedule_id=parseInt(null===(i=this.config)||void 0===i?void 0:i.selected_schedule.split("|")[1]),this._view=fe.ScheduleEdit):(this._schedule_type="",this._schedule_id=0,this._view=fe.Overview)}getCardSize(){return 9}willUpdate(e){var t,i,s;if(e.has("config"))this.style.removeProperty("--wiser-view-min-height"),this._returnView=fe.Overview,this._homeView=(null===(t=this.config)||void 0===t?void 0:t.home_screen)||"schedules",this.processConfigSchedule();else if(e.has("_view")){const e=this.renderRoot.querySelector(".card-content");e&&this.style.setProperty("--wiser-view-min-height",`${e.getBoundingClientRect().height}px`)}this.component_loaded=null!==(s=null===(i=this._hass)||void 0===i?void 0:i.config.components.includes("wiser"))&&void 0!==s&&s}_viewReady(e){const t=this.renderRoot.querySelector(".card-content");e.target===(null==t?void 0:t.firstElementChild)&&this.style.removeProperty("--wiser-view-min-height")}render(){if(!this._hass||!this.config)return W``;const e=`${this.config.hide_card_borders?"border-width: 0px;":""}${this.config.hide_card_background?"background: transparent; box-shadow: none; backdrop-filter: none;":""}`;return this.component_loaded?this._view===fe.Overview&&"schedules"===this._homeView?W` +
{"schedules"!==e.detail&&"overview"!==e.detail||(this._homeView=e.detail)}} + > + {this._schedule_id=e.detail.Id,this._schedule_type=e.detail.Type,this._returnView=fe.Overview,this._view=fe.ScheduleEdit}} + >
`:this._view===fe.Overview||this._view===fe.RoomSchedule?W` +
{"schedules"!==e.detail&&"overview"!==e.detail||(this._homeView=e.detail)}} + > + {this._created_schedule=void 0}} + @roomClick=${e=>{this._room_id=e.detail.id,this._target_type=e.detail.kind,this._view=fe.RoomSchedule}} + @roomsBack=${()=>{this._view=fe.Overview}} + @scheduleAction=${e=>{this._schedule_id=e.detail.schedule_id,this._schedule_type=e.detail.schedule_type,this._returnView=fe.RoomSchedule,this._view="rename"===e.detail.action?fe.ScheduleRename:fe.ScheduleCopy}} + @addScheduleClick=${this._addScheduleClick} + > + +
+
`:this._view==fe.ScheduleEdit&&this._schedule_id?W` + +
{"schedules"!==e.detail&&"overview"!==e.detail||(this._homeView=e.detail)}} + >
- `:this._view==Et.ScheduleAdd?X` - -
+ `:this._view==fe.ScheduleAdd?W` + +
{"schedules"!==e.detail&&"overview"!==e.detail||(this._homeView=e.detail)}} + >
- `:this._view==Et.ScheduleCopy?X` - -
+ `:this._view==fe.ScheduleCopy?W` + +
{"schedules"!==e.detail&&"overview"!==e.detail||(this._homeView=e.detail)}} + >
- `:this._view==Et.ScheduleRename?X` - -
+ `:this._view==fe.ScheduleRename?W` + +
{"schedules"!==e.detail&&"overview"!==e.detail||(this._homeView=e.detail)}} + >
- `:X``}_scheduleClick(t){this._schedule_type=t.detail.schedule_type,this._schedule_id=t.detail.schedule_id,this._view=Et.ScheduleEdit}_addScheduleClick(){this._view=Et.ScheduleAdd}_renameClick(){this._view=Et.ScheduleRename}_editClick(){this._view=Et.ScheduleEdit}_copyClick(){this._view=Et.ScheduleCopy}_backClick(t){t.detail?this._view=t.detail:this._view=Et.Overview}_scheduleDeleted(){this._schedule_id=0,this._schedule_type="",this._view=Et.Overview}_scheduleAdded(){this._view=Et.Overview}_scheduleCopied(){this._view=Et.ScheduleEdit}_scheduleRenamed(){this._view=Et.ScheduleEdit}},n([gt({attribute:!1})],t.WiserScheduleCard.prototype,"_hass",void 0),n([vt()],t.WiserScheduleCard.prototype,"config",void 0),n([vt()],t.WiserScheduleCard.prototype,"_view",void 0),n([vt()],t.WiserScheduleCard.prototype,"translationsLoaded",void 0),n([vt()],t.WiserScheduleCard.prototype,"component_loaded",void 0),n([vt()],t.WiserScheduleCard.prototype,"_schedule_id",void 0),n([vt()],t.WiserScheduleCard.prototype,"_schedule_type",void 0),t.WiserScheduleCard=n([ut("wiser-schedule-card")],t.WiserScheduleCard),t}({}); + `:W``:W`
${He("common.integration_unavailable")}
`}_addScheduleClick(){this._returnView=this._view,this._view=fe.ScheduleAdd}_renameClick(){this._view=fe.ScheduleRename}_editClick(){this._view=fe.ScheduleEdit}_copyClick(){this._view=fe.ScheduleCopy}_backClick(e){e.detail?this._view=e.detail===fe.ScheduleEdit&&this._returnView===fe.RoomSchedule?fe.RoomSchedule:e.detail:this._view=this._returnView}_scheduleDeleted(){this._view=this._returnView}_scheduleAdded(e){var t;if(this._created_schedule=e.detail,"schedules"===(null===(t=this.config)||void 0===t?void 0:t.home_screen)&&e.detail)return this._schedule_id=e.detail.Id,this._schedule_type=e.detail.Type,void(this._view=fe.ScheduleEdit);this._view=this._returnView}_scheduleCopied(){this._view=this._returnView===fe.RoomSchedule?fe.RoomSchedule:fe.ScheduleEdit}_scheduleRenamed(){this._view=this._returnView===fe.RoomSchedule?fe.RoomSchedule:fe.ScheduleEdit}};ai.panelApiVersion=1,ai.styles=n` + :host { + font-size: calc(14px + 1pt); + --mdc-typography-body1-font-size: calc(16px + 1pt); + --mdc-typography-subtitle1-font-size: calc(16px + 1pt); + --ha-font-size-m: calc(14px + 1pt); + display: block; + color: var(--primary-text-color); + } + ha-card { + overflow: hidden; + } + .card-header { + display: flex; + align-items: center; + gap: 12px; + min-height: 44px; + padding: 22px 20px 20px; + } + .brand-header { + display: flex; + align-items: center; + gap: 14px; + margin: 0; + min-width: 0; + line-height: 1.2; + } + .brand-name { + flex-shrink: 0; + color: var(--wiser-brand-color, #279f43); + font-family: 'Arial Rounded MT Bold', 'Trebuchet MS', sans-serif; + font-size: calc(32px + 1pt); + font-weight: 700; + letter-spacing: -1.5px; + } + .brand-title { + min-width: 0; + padding-inline-start: 14px; + border-inline-start: 1px solid var(--divider-color, #ddd); + color: var(--primary-text-color); + font-size: calc(15px + 1pt); + font-weight: 500; + line-height: 1.4; + overflow-wrap: anywhere; + } + .card-content { + box-sizing: border-box; + min-height: var(--wiser-view-min-height, 0px); + padding: 22px 20px 20px; + } + .status { + padding: 20px; + color: var(--secondary-text-color); + } + @media (max-width: 400px) { + .card-header { + padding: 18px 12px; + } + .brand-header { + gap: 12px; + } + .brand-title { + padding-inline-start: 12px; + } + .card-content { + padding: 18px 12px 12px; + } + } + `,e([pe({attribute:!1})],ai.prototype,"_hass",void 0),e([ue()],ai.prototype,"config",void 0),e([ue()],ai.prototype,"_view",void 0),e([ue()],ai.prototype,"component_loaded",void 0),e([ue()],ai.prototype,"_schedule_id",void 0),e([ue()],ai.prototype,"_schedule_type",void 0),e([ue()],ai.prototype,"_room_id",void 0),e([ue()],ai.prototype,"_homeView",void 0),e([ue()],ai.prototype,"_target_type",void 0),e([ue()],ai.prototype,"_created_schedule",void 0),ai=e([t("wiser-schedule-card")],ai);export{ai as WiserScheduleCard}; diff --git a/custom_components/wiser/strings.json b/custom_components/wiser/strings.json index fe7b8324..4c368777 100755 --- a/custom_components/wiser/strings.json +++ b/custom_components/wiser/strings.json @@ -58,6 +58,7 @@ "title": "Wiser Integration Options", "description": "Main Parameters", "data": { + "show_schedules_sidebar": "Show Wiser Schedules in sidebar", "host": "IP Address or Hostname", "port": "Port number", "scan_interval": "Scan Interval (secs)", diff --git a/custom_components/wiser/translations/de.json b/custom_components/wiser/translations/de.json index 63d5de74..793af578 100644 --- a/custom_components/wiser/translations/de.json +++ b/custom_components/wiser/translations/de.json @@ -58,6 +58,7 @@ "title": "Wiser Integrationsoptionen", "description": "Hauptparameter", "data": { + "show_schedules_sidebar": "Wiser-Zeitpläne in der Seitenleiste anzeigen", "host": "IP Adresse", "port": "Portnummer", "scan_interval": "Scan Intervall", diff --git a/custom_components/wiser/translations/en.json b/custom_components/wiser/translations/en.json index 9d79e073..a9092523 100755 --- a/custom_components/wiser/translations/en.json +++ b/custom_components/wiser/translations/en.json @@ -58,6 +58,7 @@ "title": "Wiser Integration Options", "description": "Main Parameters", "data": { + "show_schedules_sidebar": "Show Wiser Schedules in sidebar", "host": "IP Address or Hostname", "port": "Port number", "scan_interval": "Scan Interval (secs)", diff --git a/custom_components/wiser/translations/fr.json b/custom_components/wiser/translations/fr.json index 56b07641..2b831123 100644 --- a/custom_components/wiser/translations/fr.json +++ b/custom_components/wiser/translations/fr.json @@ -58,6 +58,7 @@ "title": "Wiser possibilités d'intégration", "description": "Paramètres principaux", "data": { + "show_schedules_sidebar": "Afficher les programmes Wiser dans la barre latérale", "host": "Adresse IP ou nom d'hote", "port": "Numéro de port", "scan_interval": " Période d'acquisition", diff --git a/custom_components/wiser/websockets.py b/custom_components/wiser/websockets.py index cd06ea46..5e2d8983 100644 --- a/custom_components/wiser/websockets.py +++ b/custom_components/wiser/websockets.py @@ -10,6 +10,7 @@ from aioWiserHeatAPI.schedule import WiserScheduleTypeEnum from homeassistant.helpers.dispatcher import async_dispatcher_connect from .const import DATA, DOMAIN +from .frontend.sidebar import save_schedules_panel_config _LOGGER = logging.getLogger(__name__) @@ -76,6 +77,21 @@ def get_entity_from_entity_id(entity: str): return entity_comp.get_entity(entity) return None + @callback + @websocket_api.websocket_command({ + vol.Required("type"): "wiser/schedules_panel/configure", + vol.Required("configs"): {str: dict}, + }) + @websocket_api.require_admin + def websocket_configure_schedules_panel(hass, connection, msg): + """Save shared panel preferences in the Wiser config entries.""" + try: + save_schedules_panel_config(hass, msg["configs"]) + except ValueError as err: + connection.send_error(msg["id"], "invalid_config", str(err)) + return + connection.send_result(msg["id"]) + # Get Hubs @websocket_api.websocket_command( { @@ -540,6 +556,7 @@ async def websocket_get_zigbee_data( else: connection.send_error(msg["id"], "wiser error", "hub not recognised") + async_register_command(hass, websocket_configure_schedules_panel) async_register_command(hass, websocket_get_hubs) async_register_command(hass, websocket_get_suntimes) async_register_command(hass, websocket_get_schedules) diff --git a/tests/test_schedule_card_hide_hw_schedule.py b/tests/test_schedule_card_hide_hw_schedule.py index 83763565..16cb787d 100644 --- a/tests/test_schedule_card_hide_hw_schedule.py +++ b/tests/test_schedule_card_hide_hw_schedule.py @@ -1,89 +1,25 @@ -from pathlib import Path -import unittest - +"""Integration contract for the externally built schedule card/panel bundle. +Card behaviour is tested in the wiser-schedule-card source repository. +""" +from pathlib import Path import re -CARD = ( - Path(__file__).resolve().parents[1] - / "custom_components" - / "wiser" - / "frontend" - / "wiser-schedule-card.js" -) -CONST = Path(__file__).resolve().parents[1] / "custom_components" / "wiser" / "const.py" -WEBSOCKETS = ( - Path(__file__).resolve().parents[1] - / "custom_components" - / "wiser" - / "websockets.py" -) - - -class ScheduleCardHideHotWaterScheduleTest(unittest.TestCase): - def test_schedule_card_filters_hot_water_schedule_when_configured(self): - card_source = CARD.read_text() - - self.assertTrue( - "hide_hw_schedule" in card_source, - "schedule card should read the hide_hw_schedule config option", - ) - self.assertTrue( - "filter(e=>1e3!=e.Id)" in card_source, - "schedule card should remove the hot water schedule when configured", - ) - - def test_schedule_card_editor_exposes_hide_hot_water_schedule_option(self): - card_source = CARD.read_text() - - self.assertTrue( - "get _hide_hw_schedule()" in card_source, - "card editor should expose the hide_hw_schedule getter", - ) - self.assertTrue( - "Hide Hot Water Schedule" in card_source, - "card editor should show the hot water schedule toggle", - ) - self.assertTrue( - 'configValue=${"hide_hw_schedule"}' in card_source, - "card editor should write the hide_hw_schedule config value", - ) - - def test_registered_schedule_card_resource_version_matches_card_version(self): - card_source = CARD.read_text() - const_source = CONST.read_text() +import unittest - self.assertTrue( - 'const $t="1.5.6"' in card_source, - "schedule card should advertise version 1.5.6", - ) - self.assertTrue( - '"version": "1.5.6"' in const_source, - "registered Lovelace module version should match the card version", - ) +ROOT = Path(__file__).resolve().parents[1] / "custom_components/wiser" +CARD = ROOT / "frontend/wiser-schedule-card.js" +CONST = ROOT / "const.py" +WEBSOCKETS = ROOT / "websockets.py" - def test_delete_confirmation_uses_current_home_assistant_dialog_footer(self): - card_source = CARD.read_text() - self.assertTrue( - 'header-title=${Vt("wiser.headings.delete_schedule")}' in card_source, - "delete dialog should use the current Home Assistant title attribute", - ) - self.assertTrue( - '' in card_source, - "delete dialog should put its controls in the dialog footer", - ) - self.assertTrue( - 'slot="primaryAction"' in card_source, - "delete dialog should expose its confirmation control as the primary action", - ) - self.assertTrue( - 'slot="secondaryAction"' in card_source, - "delete dialog should expose its cancellation control as the secondary action", - ) - self.assertTrue( - 'data-dialog="close"' in card_source, - "delete dialog actions should use the current Home Assistant close API", - ) +class ScheduleCardBundleTest(unittest.TestCase): + def test_matching_card_and_panel_are_bundled_together(self): + source = CARD.read_text() + version = re.search(r'"filename": "wiser-schedule-card.js",\s*"version": "([^"]+)"', CONST.read_text()).group(1) + self.assertIn(version, source) + self.assertIn('wiser-schedules-panel', source) + self.assertIn('wiser-schedule-card-editor', source) + self.assertIn('panelApiVersion', source) def test_delete_websocket_reconciles_ambiguous_hub_errors(self): websocket_source = WEBSOCKETS.read_text() @@ -106,56 +42,3 @@ def test_delete_websocket_reconciles_ambiguous_hub_errors(self): in websocket_source, "delete websocket should report an error only when the schedule remains", ) - - def test_successful_delete_notifies_parent_to_return_to_overview(self): - card_source = CARD.read_text() - - self.assertTrue( - 'new CustomEvent("schedule-deleted",{bubbles:!0,composed:!0})' - in card_source, - "successful deletion should emit an event across card boundaries", - ) - self.assertTrue( - "@schedule-deleted=${this._scheduleDeleted}" in card_source, - "parent card should listen for the standard delete completion event", - ) - self.assertTrue( - "_scheduleDeleted(){this._schedule_id=0,this._schedule_type=\"\",this._view=Et.Overview}" - in card_source, - "parent card should clear the deleted selection before returning to overview", - ) - - def test_delete_confirmation_explains_delayed_ui_update(self): - card_source = CARD.read_text() - - self.assertTrue( - "Note : UI can take 5-10 seconds to reflect change" in card_source, - "delete dialog should set expectations for the hub response delay", - ) - - def test_schedule_name_forms_use_current_home_assistant_input(self): - card_source = CARD.read_text() - inputs = re.findall( - r".*?)", - card_source, - re.DOTALL, - ) - - self.assertEqual(len(inputs), 2) - self.assertNotIn(" Date: Sat, 12 Sep 2026 14:26:01 +0100 Subject: [PATCH 007/154] fix: detect schedule card resource version from installed bundle --- custom_components/wiser/frontend/__init__.py | 26 ++++++++------ custom_components/wiser/frontend/version.py | 31 ++++++++++++++++ tests/test_frontend_version.py | 38 ++++++++++++++++++++ 3 files changed, 84 insertions(+), 11 deletions(-) create mode 100644 custom_components/wiser/frontend/version.py create mode 100644 tests/test_frontend_version.py diff --git a/custom_components/wiser/frontend/__init__.py b/custom_components/wiser/frontend/__init__.py index 79ac53f3..2a6825ff 100644 --- a/custom_components/wiser/frontend/__init__.py +++ b/custom_components/wiser/frontend/__init__.py @@ -3,6 +3,7 @@ import logging import os from pathlib import Path +from urllib.parse import parse_qs, urlsplit from homeassistant.components.http import StaticPathConfig from homeassistant.components.lovelace import MODE_STORAGE, LovelaceData @@ -11,6 +12,7 @@ from homeassistant.helpers.event import async_call_later from ..const import JSMODULES, URL_BASE # noqa: TID252 +from .version import schedule_card_version _LOGGER = logging.getLogger(__name__) @@ -77,26 +79,30 @@ async def _async_register_modules(self): for module in JSMODULES: url = f"{URL_BASE}/{module.get('filename')}" + version = module["version"] + if module["filename"] == "wiser-schedule-card.js": + version = await self.hass.async_add_executor_job( + schedule_card_version, Path(__file__).parent / module["filename"], version + ) + card_registered = False for resource in resources: if self._get_resource_path(resource["url"]) == url: card_registered = True # check version - if self._get_resource_version(resource["url"]) != module.get( - "version" - ): + if self._get_resource_version(resource["url"]) != version: # Update card version _LOGGER.debug( "Updating %s to version %s", module.get("name"), - module.get("version"), + version, ) await self.lovelace.resources.async_update_item( resource.get("id"), { "res_type": "module", - "url": url + "?v=" + module.get("version"), + "url": url + "?v=" + version, }, ) # Remove old gzipped files @@ -105,26 +111,24 @@ async def _async_register_modules(self): _LOGGER.debug( "%s already registered as version %s", module.get("name"), - module.get("version"), + version, ) if not card_registered: _LOGGER.debug( "Registering %s as version %s", module.get("name"), - module.get("version"), + version, ) await self.lovelace.resources.async_create_item( - {"res_type": "module", "url": url + "?v=" + module.get("version")} + {"res_type": "module", "url": url + "?v=" + version} ) def _get_resource_path(self, url: str): return url.split("?")[0] def _get_resource_version(self, url: str): - if version := url.split("?")[1].replace("v=", ""): - return version - return 0 + return parse_qs(urlsplit(url).query).get("v", [None])[0] async def async_unregister(self): """Unload lovelace module resource.""" diff --git a/custom_components/wiser/frontend/version.py b/custom_components/wiser/frontend/version.py new file mode 100644 index 00000000..2e681585 --- /dev/null +++ b/custom_components/wiser/frontend/version.py @@ -0,0 +1,31 @@ +"""Read the installed card version without executing JavaScript.""" + +from hashlib import sha256 +from pathlib import Path +import re + + +_VERSION = r"\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?" + + +def schedule_card_version(path: Path, fallback: str) -> str: + """Resolve the card's banner variable, ignoring bundled library versions.""" + try: + contents = path.read_bytes() + except OSError: + return fallback + source = contents.decode("utf-8", errors="replace") + banner = re.search( + r'WISER-SCHEDULE-CARD[^`]*?common\.version[\"\']\)\}\s*\$\{([\w$]+)\}', + source, + ) + if banner: + assignment = re.search( + rf'(? Date: Sat, 12 Sep 2026 14:32:41 +0100 Subject: [PATCH 008/154] fix: detect Zigbee card resource version from installed bundle --- custom_components/wiser/frontend/__init__.py | 7 ++++ .../wiser/frontend/zigbee_version.py | 31 +++++++++++++++ tests/test_zigbee_version.py | 38 +++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 custom_components/wiser/frontend/zigbee_version.py create mode 100644 tests/test_zigbee_version.py diff --git a/custom_components/wiser/frontend/__init__.py b/custom_components/wiser/frontend/__init__.py index 2a6825ff..e191493c 100644 --- a/custom_components/wiser/frontend/__init__.py +++ b/custom_components/wiser/frontend/__init__.py @@ -13,6 +13,7 @@ from ..const import JSMODULES, URL_BASE # noqa: TID252 from .version import schedule_card_version +from .zigbee_version import zigbee_card_version _LOGGER = logging.getLogger(__name__) @@ -84,6 +85,12 @@ async def _async_register_modules(self): version = await self.hass.async_add_executor_job( schedule_card_version, Path(__file__).parent / module["filename"], version ) + elif module["filename"] == "wiser-zigbee-card.js": + version = await self.hass.async_add_executor_job( + zigbee_card_version, + Path(__file__).parent / module["filename"], + version, + ) card_registered = False diff --git a/custom_components/wiser/frontend/zigbee_version.py b/custom_components/wiser/frontend/zigbee_version.py new file mode 100644 index 00000000..a0009caf --- /dev/null +++ b/custom_components/wiser/frontend/zigbee_version.py @@ -0,0 +1,31 @@ +"""Read the installed Zigbee card version without executing JavaScript.""" + +from hashlib import sha256 +from pathlib import Path +import re + + +_VERSION = r"\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?" + + +def zigbee_card_version(path: Path, fallback: str) -> str: + """Resolve the card's banner variable, ignoring bundled library versions.""" + try: + contents = path.read_bytes() + except OSError: + return fallback + source = contents.decode("utf-8", errors="replace") + banner = re.search( + r'WISER-ZIGBEE(?:-NETWORK)?-CARD[^`]*?common\.version[\"\']\)\}\s*\$\{([\w$]+)\}', + source, + ) + if banner: + assignment = re.search( + rf'(? Date: Sat, 12 Sep 2026 14:41:56 +0100 Subject: [PATCH 009/154] fix: read explicit card version markers from bundles --- custom_components/wiser/frontend/__init__.py | 2 +- .../{version.py => schedule_version.py} | 7 +++++++ .../wiser/frontend/zigbee_version.py | 17 +++++++++++++++++ tests/test_frontend_version.py | 8 +++++++- tests/test_zigbee_version.py | 14 ++++++++++++++ 5 files changed, 46 insertions(+), 2 deletions(-) rename custom_components/wiser/frontend/{version.py => schedule_version.py} (81%) diff --git a/custom_components/wiser/frontend/__init__.py b/custom_components/wiser/frontend/__init__.py index e191493c..3fb854c2 100644 --- a/custom_components/wiser/frontend/__init__.py +++ b/custom_components/wiser/frontend/__init__.py @@ -12,7 +12,7 @@ from homeassistant.helpers.event import async_call_later from ..const import JSMODULES, URL_BASE # noqa: TID252 -from .version import schedule_card_version +from .schedule_version import schedule_card_version from .zigbee_version import zigbee_card_version _LOGGER = logging.getLogger(__name__) diff --git a/custom_components/wiser/frontend/version.py b/custom_components/wiser/frontend/schedule_version.py similarity index 81% rename from custom_components/wiser/frontend/version.py rename to custom_components/wiser/frontend/schedule_version.py index 2e681585..c24f09b7 100644 --- a/custom_components/wiser/frontend/version.py +++ b/custom_components/wiser/frontend/schedule_version.py @@ -15,6 +15,13 @@ def schedule_card_version(path: Path, fallback: str) -> str: except OSError: return fallback source = contents.decode("utf-8", errors="replace") + # Explicit build metadata is authoritative; legacy parsing remains below. + marker = re.search( + rf"/\*!\s*WISER-CARD-VERSION wiser-schedule-card\s+({_VERSION})\s*\*/", + source, + ) + if marker: + return marker[1] banner = re.search( r'WISER-SCHEDULE-CARD[^`]*?common\.version[\"\']\)\}\s*\$\{([\w$]+)\}', source, diff --git a/custom_components/wiser/frontend/zigbee_version.py b/custom_components/wiser/frontend/zigbee_version.py index a0009caf..4afa476c 100644 --- a/custom_components/wiser/frontend/zigbee_version.py +++ b/custom_components/wiser/frontend/zigbee_version.py @@ -15,6 +15,23 @@ def zigbee_card_version(path: Path, fallback: str) -> str: except OSError: return fallback source = contents.decode("utf-8", errors="replace") + # Explicit build metadata is authoritative; legacy parsing remains below. + marker = re.search( + rf"/\*!\s*WISER-CARD-VERSION wiser-zigbee-card\s+({_VERSION})\s*\*/", + source, + ) + if marker: + return marker[1] + # New builds inline CARD_VERSION into the editor's version footer and + # no longer emit the legacy startup banner. + footer = re.search( + rf'class=["\']version["\'][^`]*?common\.version["\']\)\}}:\s*' + rf'\$\{{["\']({_VERSION})["\']\}}', + source, + ) + if footer: + return footer[1] + banner = re.search( r'WISER-ZIGBEE(?:-NETWORK)?-CARD[^`]*?common\.version[\"\']\)\}\s*\$\{([\w$]+)\}', source, diff --git a/tests/test_frontend_version.py b/tests/test_frontend_version.py index 0ecac8df..8b0477f9 100644 --- a/tests/test_frontend_version.py +++ b/tests/test_frontend_version.py @@ -5,7 +5,7 @@ import unittest ROOT = Path(__file__).resolve().parents[1] -spec = importlib.util.spec_from_file_location("card_version", ROOT / "custom_components/wiser/frontend/version.py") +spec = importlib.util.spec_from_file_location("card_version", ROOT / "custom_components/wiser/frontend/schedule_version.py") module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) @@ -36,3 +36,9 @@ def test_missing_file_keeps_fallback(self): def test_installed_bundle_has_readable_version(self): version = module.schedule_card_version(ROOT / "custom_components/wiser/frontend/wiser-schedule-card.js", "missing") self.assertRegex(version, r"^\d+\.\d+\.\d+") + + def test_explicit_version_marker(self): + self.assertEqual(self.version('/*! WISER-CARD-VERSION wiser-schedule-card 4.0.0-dev.9 */\nconst library="3.3.3";'), "4.0.0-dev.9") + + def test_other_card_marker_is_ignored(self): + self.assertTrue(self.version('/*! WISER-CARD-VERSION wiser-zigbee-card 4.0.0 */').startswith("sha256-")) diff --git a/tests/test_zigbee_version.py b/tests/test_zigbee_version.py index 61686b13..fe57565a 100644 --- a/tests/test_zigbee_version.py +++ b/tests/test_zigbee_version.py @@ -36,3 +36,17 @@ def test_zigbee_dev_version(self): def test_installed_zigbee_bundle_has_readable_version(self): version = module.zigbee_card_version(ROOT / "custom_components/wiser/frontend/wiser-zigbee-card.js", "missing") self.assertEqual(version, "2.1.2") + + def test_modern_editor_footer_with_inlined_version(self): + source = 'const library="3.3.3";html`
${this.t("common.version")}: ${"3.0.0-dev.65"}
`' + self.assertEqual(self.version(source), "3.0.0-dev.65") + + def test_modern_release_footer(self): + source = 'html`
${this.t("common.version")}: ${"3.0.0"}
`' + self.assertEqual(self.version(source), "3.0.0") + + def test_explicit_version_marker(self): + self.assertEqual(self.version('/*! WISER-CARD-VERSION wiser-zigbee-card 4.0.0-dev.9 */\nconst library="3.3.3";'), "4.0.0-dev.9") + + def test_other_card_marker_is_ignored(self): + self.assertTrue(self.version('/*! WISER-CARD-VERSION wiser-schedule-card 4.0.0 */').startswith("sha256-")) From 596e242b6803920b6cf38b690fe724850fa23010 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Sat, 12 Sep 2026 15:52:57 +0100 Subject: [PATCH 010/154] build: fetch card release assets by integration release channel --- .github/workflows/publish.yml | 77 +++++++++++++++---- README.md | 16 ++++ scripts/fetch_card_releases.py | 130 +++++++++++++++++++++++++++++++++ tests/test_card_releases.py | 85 +++++++++++++++++++++ 4 files changed, 292 insertions(+), 16 deletions(-) create mode 100644 scripts/fetch_card_releases.py create mode 100644 tests/test_card_releases.py diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 80e5098f..fa6c380e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -2,26 +2,71 @@ name: Publish on: release: - types: - - published + types: [published] + push: + branches: [test-build] + workflow_dispatch: + inputs: + channel: + description: Card release channel to test (does not publish a release) + type: choice + options: [dev, stable] + default: dev + +permissions: + contents: read jobs: - release_zip_file: - name: Publish Wiser zip file asset + package: + name: Build Wiser with published card assets + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.13' + - name: Test release selection + run: python -m unittest discover -s tests -p test_card_releases.py + - name: Stage integration + run: | + mkdir -p dist/wiser + cp -a custom_components/wiser/. dist/wiser/ + - name: Fetch card release assets + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CARD_CHANNEL: ${{ github.event_name == 'release' && (github.event.release.prerelease && 'dev' || 'stable') || inputs.channel || 'dev' }} + SCHEDULE_REPOSITORY: ${{ vars.WISER_SCHEDULE_CARD_REPOSITORY || 'andyblac/wiser-schedule-card' }} + ZIGBEE_REPOSITORY: ${{ vars.WISER_ZIGBEE_CARD_REPOSITORY || 'andyblac/wiser-zigbee-card' }} + run: >- + python scripts/fetch_card_releases.py + --channel "$CARD_CHANNEL" + --schedule-repository "$SCHEDULE_REPOSITORY" + --zigbee-repository "$ZIGBEE_REPOSITORY" + - name: Package integration + working-directory: dist/wiser + run: zip -r ../wiser.zip . -x '*/__pycache__/*' '*.pyc' + - name: Upload test artifact + uses: actions/upload-artifact@v4 + with: + name: wiser-package + path: | + dist/wiser.zip + dist/wiser/frontend/card-releases.json + if-no-files-found: error + + publish: + name: Attach package to published release + if: github.event_name == 'release' + needs: package runs-on: ubuntu-latest permissions: contents: write steps: - - name: 📥 Checkout the repository - uses: actions/checkout@v3.0.2 - # Pack the Wiser dir as a zip and upload to the release - - name: 📦 ZIP Wiser Dir - if: ${{ github.event_name == 'release' }} - run: | - cd ${{ github.workspace }}/custom_components/wiser - zip wiser.zip -r ./ - - name: 📤 Upload zip to release - uses: softprops/action-gh-release@v0.1.14 - if: ${{ github.event_name == 'release' }} + - uses: actions/download-artifact@v4 + with: + name: wiser-package + path: dist + - uses: softprops/action-gh-release@v2 with: - files: ${{ github.workspace }}/custom_components/wiser/wiser.zip + files: dist/wiser.zip + fail_on_unmatched_files: true diff --git a/README.md b/README.md index aff61649..5658d619 100755 --- a/README.md +++ b/README.md @@ -221,3 +221,19 @@ For more information checkout the AMAZING community thread available on A full change log can be seen on our wiki [here](https://github.com/asantaga/wiserHomeAssistantPlatform/wiki/Full-Change-Log) The sidebar panel is built together with the schedule card in the `wiser-schedule-card` repository. The integration distributes that matching bundle; it does not maintain a separate panel JavaScript source. + +### Packaging published cards + +The Publish workflow downloads compiled card assets from `andyblac/wiser-schedule-card` and `andyblac/wiser-zigbee-card` into the integration's `frontend` directory in a temporary staging copy. It does not change the tracked card files or build branch source. + +- Pushes to `test-build` and prereleases select the newest published prerelease of each card, falling back to its newest stable release if no prerelease exists. +- Stable integration releases select only stable card releases. +- Manual workflow runs let you test either channel and produce a downloadable `wiser-package` artifact, without publishing a release. + +Each card release must have its compiled `wiser-schedule-card.js` or `wiser-zigbee-card.js` attached. Missing releases or assets fail the build instead of silently shipping old files. The schedule asset must include the sidebar panel when packaging a panel-enabled integration. The ZIP includes `frontend/card-releases.json` recording the exact tags, asset IDs, download URLs, and SHA-256 digests used. Repository variables `WISER_SCHEDULE_CARD_REPOSITORY` and `WISER_ZIGBEE_CARD_REPOSITORY` can override the source repositories. + +To preview selection without changing files: + +```sh +python3 scripts/fetch_card_releases.py --channel dev --plan +``` diff --git a/scripts/fetch_card_releases.py b/scripts/fetch_card_releases.py new file mode 100644 index 00000000..92811c0d --- /dev/null +++ b/scripts/fetch_card_releases.py @@ -0,0 +1,130 @@ +"""Fetch published card assets for integration packaging (never branch source).""" + +import argparse +from hashlib import sha256 +import json +import os +from pathlib import Path +import re +import tempfile +from urllib.parse import urlparse +from urllib.request import Request, urlopen + +CARD_REPOSITORIES = { + "schedule": "andyblac/wiser-schedule-card", + "zigbee": "andyblac/wiser-zigbee-card", +} + + +def list_releases(repository): + if not re.fullmatch(r"[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+", repository): + raise ValueError(f"Invalid repository: {repository}") + releases = [] + for page in range(1, 101): + headers = {"Accept": "application/vnd.github+json", "User-Agent": "wiser-card-packager"} + if token := os.environ.get("GITHUB_TOKEN"): + headers["Authorization"] = f"Bearer {token}" + request = Request( + f"https://api.github.com/repos/{repository}/releases?per_page=100&page={page}", + headers=headers, + ) + with urlopen(request, timeout=30) as response: + batch = json.load(response) + releases.extend(batch) + if len(batch) < 100: + return releases + raise ValueError(f"Too many releases in {repository}") + + +def select_release(releases, channel): + published = [r for r in releases if not r.get("draft") and r.get("published_at")] + stable = [r for r in published if not r.get("prerelease")] + beta = [r for r in published if r.get("prerelease")] + candidates = (beta or stable) if channel == "dev" else stable + if not candidates: + raise ValueError(f"No published {'prerelease or stable' if channel == 'dev' else 'stable'} release available") + return max(candidates, key=lambda r: r["published_at"]) + + +def select_asset(release, filename): + assets = [a for a in release.get("assets", []) if a["name"] == filename and a.get("state") == "uploaded"] + if len(assets) != 1: + raise ValueError(f"Release {release['tag_name']} must have one uploaded {filename} asset") + return assets[0] + + +def download_asset(repository, asset): + url = asset["browser_download_url"] + parsed = urlparse(url) + if parsed.scheme != "https" or parsed.netloc != "github.com" or not parsed.path.startswith(f"/{repository}/releases/download/"): + raise ValueError("Asset URL is not a GitHub release download for the selected repository") + # Public assets do not require forwarding the API token through redirects. + with urlopen(Request(url, headers={"User-Agent": "wiser-card-packager"}), timeout=60) as response: + contents = response.read() + if len(contents) != asset["size"] or len(contents) < 100: + raise ValueError(f"Incorrect size for {asset['name']}") + digest = "sha256:" + sha256(contents).hexdigest() + if asset.get("digest") and asset["digest"] != digest: + raise ValueError(f"Digest mismatch for {asset['name']}") + if contents.lstrip().lower().startswith((b" Date: Sat, 12 Sep 2026 17:20:01 +0100 Subject: [PATCH 011/154] Use installed Schedule card version for resources and sidebar --- custom_components/wiser/const.py | 1 - custom_components/wiser/frontend/__init__.py | 6 ++++-- .../wiser/frontend/schedule_version.py | 4 ++-- custom_components/wiser/frontend/sidebar.py | 18 ++++++++++-------- tests/test_frontend_version.py | 8 ++++---- tests/test_schedules_sidebar.py | 18 ++++++++++++++++-- 6 files changed, 36 insertions(+), 19 deletions(-) diff --git a/custom_components/wiser/const.py b/custom_components/wiser/const.py index 2a147677..7e535b39 100755 --- a/custom_components/wiser/const.py +++ b/custom_components/wiser/const.py @@ -19,7 +19,6 @@ { "name": "Wiser Schedule Card", "filename": "wiser-schedule-card.js", - "version": "2.0.0-dev.60", }, { "name": "Wiser Zigbee Card", diff --git a/custom_components/wiser/frontend/__init__.py b/custom_components/wiser/frontend/__init__.py index 3fb854c2..77bcb94b 100644 --- a/custom_components/wiser/frontend/__init__.py +++ b/custom_components/wiser/frontend/__init__.py @@ -80,10 +80,9 @@ async def _async_register_modules(self): for module in JSMODULES: url = f"{URL_BASE}/{module.get('filename')}" - version = module["version"] if module["filename"] == "wiser-schedule-card.js": version = await self.hass.async_add_executor_job( - schedule_card_version, Path(__file__).parent / module["filename"], version + schedule_card_version, Path(__file__).parent / module["filename"] ) elif module["filename"] == "wiser-zigbee-card.js": version = await self.hass.async_add_executor_job( @@ -92,6 +91,9 @@ async def _async_register_modules(self): version, ) + if module["filename"] != "wiser-schedule-card.js": + version = module["version"] + card_registered = False for resource in resources: diff --git a/custom_components/wiser/frontend/schedule_version.py b/custom_components/wiser/frontend/schedule_version.py index c24f09b7..4d700708 100644 --- a/custom_components/wiser/frontend/schedule_version.py +++ b/custom_components/wiser/frontend/schedule_version.py @@ -8,12 +8,12 @@ _VERSION = r"\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?" -def schedule_card_version(path: Path, fallback: str) -> str: +def schedule_card_version(path: Path) -> str: """Resolve the card's banner variable, ignoring bundled library versions.""" try: contents = path.read_bytes() except OSError: - return fallback + return "missing" source = contents.decode("utf-8", errors="replace") # Explicit build metadata is authoritative; legacy parsing remains below. marker = re.search( diff --git a/custom_components/wiser/frontend/sidebar.py b/custom_components/wiser/frontend/sidebar.py index 27f7aee2..56985e54 100644 --- a/custom_components/wiser/frontend/sidebar.py +++ b/custom_components/wiser/frontend/sidebar.py @@ -1,6 +1,9 @@ """Manage the shared Wiser schedules sidebar panel.""" +from pathlib import Path + from homeassistant.components import frontend, panel_custom +from .schedule_version import schedule_card_version from ..const import ( CONF_SHOW_SCHEDULES_SIDEBAR, CONF_SCHEDULES_PANEL_CONFIG, @@ -29,6 +32,12 @@ async def async_update_schedules_panel(hass): and loaded[entry.entry_id][DATA].wiserhub.system.name in hubs } state = {"hubs": hubs, "card_configs": card_configs} + if hubs: + card = next(module for module in JSMODULES if module["filename"] == "wiser-schedule-card.js") + version = await hass.async_add_executor_job( + schedule_card_version, Path(__file__).parent / card["filename"] + ) + state["card_url"] = f"{URL_BASE}/{card['filename']}?v={version}" if state == hass.data.get(PANEL_STATE) or (not hubs and PANEL_STATE not in hass.data): return @@ -37,14 +46,7 @@ async def async_update_schedules_panel(hass): hass.data.pop(PANEL_STATE) if hubs: - card = next( - module for module in JSMODULES - if module["filename"] == "wiser-schedule-card.js" - ) - config = { - **state, - "card_url": f"{URL_BASE}/{card['filename']}?v={card['version']}", - } + config = dict(state) module_url = config["card_url"] if PANEL_STATE in hass.data: # Keep the route registered while notifying clients of new settings. diff --git a/tests/test_frontend_version.py b/tests/test_frontend_version.py index 8b0477f9..a3d87fb0 100644 --- a/tests/test_frontend_version.py +++ b/tests/test_frontend_version.py @@ -15,7 +15,7 @@ def version(self, source): with TemporaryDirectory() as directory: path = Path(directory) / "card.js" path.write_text(source) - return module.schedule_card_version(path, "1.0.0") + return module.schedule_card_version(path) def test_legacy_banner_ignores_library_versions(self): self.assertEqual(self.version('const library="3.3.3";const $t="1.5.6";console.info(`WISER-SCHEDULE-CARD ${Vt("common.version")} ${$t}`)'), "1.5.6") @@ -29,12 +29,12 @@ def test_unknown_build_uses_stable_content_hash(self): self.assertEqual(first, self.version('const library="3.3.3"')) self.assertNotEqual(first, self.version('const library="4.0.0"')) - def test_missing_file_keeps_fallback(self): + def test_missing_file_returns_missing(self): with TemporaryDirectory() as directory: - self.assertEqual(module.schedule_card_version(Path(directory) / "missing.js", "1.5.6"), "1.5.6") + self.assertEqual(module.schedule_card_version(Path(directory) / "missing.js"), "missing") def test_installed_bundle_has_readable_version(self): - version = module.schedule_card_version(ROOT / "custom_components/wiser/frontend/wiser-schedule-card.js", "missing") + version = module.schedule_card_version(ROOT / "custom_components/wiser/frontend/wiser-schedule-card.js") self.assertRegex(version, r"^\d+\.\d+\.\d+") def test_explicit_version_marker(self): diff --git a/tests/test_schedules_sidebar.py b/tests/test_schedules_sidebar.py index e59c65e8..bfb9dda3 100644 --- a/tests/test_schedules_sidebar.py +++ b/tests/test_schedules_sidebar.py @@ -24,11 +24,14 @@ def setUp(self): constants = ModuleType("sidebar_test.const") constants.CONF_SHOW_SCHEDULES_SIDEBAR = "show_schedules_sidebar" constants.CONF_SCHEDULES_PANEL_CONFIG = "schedules_panel_config" + version_module = ModuleType("sidebar_test.frontend.schedule_version") + self.version_reader = Mock(return_value="4.5.6-beta.2") + version_module.schedule_card_version = self.version_reader constants.DATA = "data" constants.DOMAIN = "wiser" constants.URL_BASE = "/wiser" constants.JSMODULES = [ - {"filename": "wiser-schedule-card.js", "version": "1.5.6"} + {"filename": "wiser-schedule-card.js"} ] with patch.dict(sys.modules, { "homeassistant": ModuleType("homeassistant"), @@ -36,6 +39,7 @@ def setUp(self): "sidebar_test": ModuleType("sidebar_test"), "sidebar_test.frontend": ModuleType("sidebar_test.frontend"), "sidebar_test.const": constants, + "sidebar_test.frontend.schedule_version": version_module, }): spec = importlib.util.spec_from_file_location( "sidebar_test.frontend.sidebar", ROOT / "frontend/sidebar.py" @@ -45,6 +49,7 @@ def setUp(self): self.entries = [] self.hass = SimpleNamespace( data={"wiser": {}}, + async_add_executor_job=AsyncMock(side_effect=lambda fn, *args: fn(*args)), config_entries=SimpleNamespace(async_entries=lambda _: self.entries), ) @@ -80,7 +85,7 @@ async def test_enable_registers_dedicated_panel_once(self): self.assertEqual(args["frontend_url_path"], "wiser-schedules") self.assertEqual(args["webcomponent_name"], "wiser-schedules-panel") self.assertEqual(args["config"]["hubs"], ["hub"]) - self.assertEqual(args["config"]["card_url"], "/wiser/wiser-schedule-card.js?v=1.5.6") + self.assertEqual(args["config"]["card_url"], "/wiser/wiser-schedule-card.js?v=4.5.6-beta.2") async def test_disable_last_hub_removes_panel(self): entry = self.add_hub("hub", True) @@ -183,3 +188,12 @@ async def test_other_options_and_connection_changes_still_reload(self): entry.data = {"host": "other.local"} await self.sidebar.async_handle_entry_update(self.hass, entry) self.hass.config_entries.async_reload.assert_awaited_once_with("hub") + + async def test_new_bundle_updates_panel_version(self): + self.add_hub("hub", True) + await self.sidebar.async_update_schedules_panel(self.hass) + self.version_reader.return_value = "4.5.6-beta.3" + await self.sidebar.async_update_schedules_panel(self.hass) + config = self.frontend.async_register_built_in_panel.call_args.kwargs["config"] + self.assertEqual(config["card_url"], "/wiser/wiser-schedule-card.js?v=4.5.6-beta.3") + self.assertEqual(config["_panel_custom"]["module_url"], config["card_url"]) From f9af5b55b2d1d552e1526651f748e48f5e3f8bda Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Sat, 12 Sep 2026 17:19:58 +0100 Subject: [PATCH 012/154] Add Zigbee sidebar and detect installed card version --- custom_components/wiser/__init__.py | 3 + custom_components/wiser/config_flow.py | 5 + custom_components/wiser/const.py | 3 +- custom_components/wiser/frontend/__init__.py | 20 +- custom_components/wiser/frontend/sidebar.py | 6 +- .../wiser/frontend/wiser-zigbee-card.js | 1477 ++++++----------- .../wiser/frontend/zigbee_sidebar.py | 153 ++ .../wiser/frontend/zigbee_version.py | 4 +- custom_components/wiser/strings.json | 1 + custom_components/wiser/translations/de.json | 1 + custom_components/wiser/translations/en.json | 1 + custom_components/wiser/translations/fr.json | 1 + custom_components/wiser/websockets.py | 17 + tests/test_schedules_sidebar.py | 14 + tests/test_zigbee_sidebar.py | 212 +++ tests/test_zigbee_version.py | 14 +- 16 files changed, 923 insertions(+), 1009 deletions(-) create mode 100644 custom_components/wiser/frontend/zigbee_sidebar.py create mode 100644 tests/test_zigbee_sidebar.py diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index 0b75cfc6..0bc2001d 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -57,6 +57,7 @@ get_legacy_room_identifier, ) from .services import async_setup_services +from .frontend.zigbee_sidebar import async_update_zigbee_panel from .websockets import async_register_websockets _LOGGER = logging.getLogger(__name__) @@ -234,6 +235,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): moodule_register = JSModuleRegistration(hass) await moodule_register.async_register() await async_update_schedules_panel(hass) + await async_update_zigbee_panel(hass) _LOGGER.info( "Wiser Component Setup Completed (%s)", coordinator.wiserhub.system.name @@ -393,5 +395,6 @@ async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry): hass.data[DOMAIN].pop(config_entry.entry_id) await async_update_schedules_panel(hass) update_hub_device_names(hass) + await async_update_zigbee_panel(hass) return unload_ok diff --git a/custom_components/wiser/config_flow.py b/custom_components/wiser/config_flow.py index a740b591..17e9030d 100755 --- a/custom_components/wiser/config_flow.py +++ b/custom_components/wiser/config_flow.py @@ -39,6 +39,7 @@ from homeassistant.helpers.service_info.zeroconf import ZeroconfServiceInfo from .const import ( + CONF_SHOW_ZIGBEE_SIDEBAR, CONF_AUTOMATIONS_HW_AUTO_MODE, CONF_AUTOMATIONS_HW_BOOST_MODE, CONF_AUTOMATIONS_HW_CLIMATE, @@ -396,6 +397,10 @@ async def async_step_main_params(self, user_input=None): CONF_SHOW_SCHEDULES_SIDEBAR, default=self.config_entry.options.get(CONF_SHOW_SCHEDULES_SIDEBAR, False), ): BooleanSelector(), + vol.Optional( + CONF_SHOW_ZIGBEE_SIDEBAR, + default=self.config_entry.options.get(CONF_SHOW_ZIGBEE_SIDEBAR, False), + ): BooleanSelector(), vol.Required(CONF_HOST, default=self.config_entry.data[CONF_HOST]): str, vol.Optional( CONF_PORT, default=self.config_entry.data.get(CONF_PORT, 80) diff --git a/custom_components/wiser/const.py b/custom_components/wiser/const.py index 7e535b39..eb56a676 100755 --- a/custom_components/wiser/const.py +++ b/custom_components/wiser/const.py @@ -14,6 +14,8 @@ URL_BASE = "/wiser" CONF_SHOW_SCHEDULES_SIDEBAR = "show_schedules_sidebar" CONF_SCHEDULES_PANEL_CONFIG = "schedules_panel_config" +CONF_SHOW_ZIGBEE_SIDEBAR = "show_zigbee_sidebar" +CONF_ZIGBEE_PANEL_CONFIG = "zigbee_panel_config" JSMODULES = [ { @@ -23,7 +25,6 @@ { "name": "Wiser Zigbee Card", "filename": "wiser-zigbee-card.js", - "version": "2.1.2", }, ] diff --git a/custom_components/wiser/frontend/__init__.py b/custom_components/wiser/frontend/__init__.py index 77bcb94b..2b143986 100644 --- a/custom_components/wiser/frontend/__init__.py +++ b/custom_components/wiser/frontend/__init__.py @@ -80,19 +80,13 @@ async def _async_register_modules(self): for module in JSMODULES: url = f"{URL_BASE}/{module.get('filename')}" - if module["filename"] == "wiser-schedule-card.js": - version = await self.hass.async_add_executor_job( - schedule_card_version, Path(__file__).parent / module["filename"] - ) - elif module["filename"] == "wiser-zigbee-card.js": - version = await self.hass.async_add_executor_job( - zigbee_card_version, - Path(__file__).parent / module["filename"], - version, - ) - - if module["filename"] != "wiser-schedule-card.js": - version = module["version"] + reader = ( + schedule_card_version if module["filename"] == "wiser-schedule-card.js" + else zigbee_card_version + ) + version = await self.hass.async_add_executor_job( + reader, Path(__file__).parent / module["filename"] + ) card_registered = False diff --git a/custom_components/wiser/frontend/sidebar.py b/custom_components/wiser/frontend/sidebar.py index 56985e54..6ef71892 100644 --- a/custom_components/wiser/frontend/sidebar.py +++ b/custom_components/wiser/frontend/sidebar.py @@ -4,9 +4,10 @@ from homeassistant.components import frontend, panel_custom from .schedule_version import schedule_card_version +from .zigbee_sidebar import async_update_zigbee_panel from ..const import ( - CONF_SHOW_SCHEDULES_SIDEBAR, CONF_SCHEDULES_PANEL_CONFIG, + CONF_SHOW_SCHEDULES_SIDEBAR, CONF_SCHEDULES_PANEL_CONFIG, CONF_ZIGBEE_PANEL_CONFIG, DATA, DOMAIN, JSMODULES, URL_BASE, ) @@ -119,7 +120,7 @@ def integration_reload_settings(entry): return ( dict(entry.data), {key: value for key, value in entry.options.items() - if key != CONF_SCHEDULES_PANEL_CONFIG}, + if key not in {CONF_SCHEDULES_PANEL_CONFIG, CONF_ZIGBEE_PANEL_CONFIG}}, ) @@ -129,5 +130,6 @@ async def async_handle_entry_update(hass, entry): settings = integration_reload_settings(entry) if loaded is not None and loaded.get("reload_settings") == settings: await async_update_schedules_panel(hass) + await async_update_zigbee_panel(hass) return await hass.config_entries.async_reload(entry.entry_id) diff --git a/custom_components/wiser/frontend/wiser-zigbee-card.js b/custom_components/wiser/frontend/wiser-zigbee-card.js index 6d299dca..321f341e 100644 --- a/custom_components/wiser/frontend/wiser-zigbee-card.js +++ b/custom_components/wiser/frontend/wiser-zigbee-card.js @@ -1,997 +1,69 @@ -var wiserzigbeecard=function(t){"use strict";var e=function(t,i){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&(t[i]=e[i])},e(t,i)};function i(t,i){if("function"!=typeof i&&null!==i)throw new TypeError("Class extends value "+String(i)+" is not a constructor or null");function n(){this.constructor=t}e(t,i),t.prototype=null===i?Object.create(i):(n.prototype=i.prototype,new n)}var n=function(){return n=Object.assign||function(t){for(var e,i=1,n=arguments.length;i=0;a--)(o=t[a])&&(s=(r<3?o(s):r>3?o(e,i,s):o(e,i))||s);return r>3&&s&&Object.defineProperty(e,i,s),s}function r(t){var e="function"==typeof Symbol&&Symbol.iterator,i=e&&t[e],n=0;if(i)return i.call(t);if(t&&"number"==typeof t.length)return{next:function(){return t&&n>=t.length&&(t=void 0),{value:t&&t[n++],done:!t}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}"function"==typeof SuppressedError&&SuppressedError; +/*! WISER-CARD-VERSION wiser-zigbee-card 3.0.0-dev.67 */ +var wiserzigbeecard=function(t){"use strict";function e(t,e,i,o){var n,r=arguments.length,s=r<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 a=t.length-1;a>=0;a--)(n=t[a])&&(s=(r<3?n(s):r>3?n(e,i,s):n(e,i))||s);return r>3&&s&&Object.defineProperty(e,i,s),s}"function"==typeof SuppressedError&&SuppressedError;const i="wiser-zigbee-magnifier-size",o="wiser-zigbee-magnifier-zoom";class n{constructor(){this.zoom=2,this.size=180;try{const t=Number(localStorage.getItem(o));[2,3,4].includes(t)&&(this.zoom=t);const e=Number(localStorage.getItem(i));e>=100&&e<=360&&(this.size=10*Math.round(e/10))}catch(t){}}setSize(t){if(Number.isFinite(t)){this.size=Math.max(100,Math.min(360,10*Math.round(t/10)));try{localStorage.setItem(i,String(this.size))}catch(t){}this.refresh()}}setZoom(t){if([2,3,4].includes(t)){this.zoom=t;try{localStorage.setItem(o,String(t))}catch(t){}this.refresh()}}show(t,e){if("touch"===e.pointerType||e.buttons)return void this.hide();const i=t.getBoundingClientRect();this.map=t,this.point={x:(e.clientX-i.left)*t.clientWidth/(i.width||t.clientWidth),y:(e.clientY-i.top)*t.clientHeight/(i.height||t.clientHeight)},this.refresh()}refresh(){this.point&&void 0===this.frame&&(this.frame=requestAnimationFrame((()=>{this.frame=void 0,this.draw()})))}hide(){var t;void 0!==this.frame&&cancelAnimationFrame(this.frame),this.frame=void 0,this.point=void 0,null===(t=this.lens)||void 0===t||t.remove(),this.lens=void 0}draw(){var t;const e=this.map,i=this.point,o=null==e?void 0:e.querySelector("canvas");if(!((null==e?void 0:e.isConnected)&&i&&o&&e.clientWidth&&e.clientHeight))return void this.hide();this.lens||(this.lens=e.ownerDocument.createElement("div"),this.lens.className="map-magnifier",this.lens.setAttribute("aria-hidden","true"),this.lens.append(e.ownerDocument.createElement("canvas"),e.ownerDocument.createElement("div")),e.parentElement.append(this.lens));const n=function(t,e,i,o,n=2,r=180){const s=Math.min(r,i,o);return{size:s,left:Math.max(0,Math.min(i-s,t-s/2)),top:Math.max(0,Math.min(o-s,e-s/2)),imageX:s/2-t*n,imageY:s/2-e*n}}(i.x,i.y,e.clientWidth,e.clientHeight,this.zoom,this.size);this.lens.style.cssText=`left:${n.left}px;top:${n.top}px;width:${n.size}px;height:${n.size}px`;const r=this.lens.firstElementChild,s=(null===(t=e.ownerDocument.defaultView)||void 0===t?void 0:t.devicePixelRatio)||1;r.width=Math.round(n.size*s),r.height=Math.round(n.size*s),r.style.width=r.style.height=`${n.size}px`;const a=r.getContext("2d");if(!a)return;a.scale(s,s),a.drawImage(o,n.imageX,n.imageY,e.clientWidth*this.zoom,e.clientHeight*this.zoom);const l=this.lens.lastElementChild;l.className="magnifier-area-icons",l.style.transform=`translate(${n.imageX}px, ${n.imageY}px) scale(${this.zoom})`,l.replaceChildren(),e.parentElement.querySelectorAll(".area-icons ha-icon").forEach((t=>{const e=t.cloneNode(!1);e.icon=t.icon,l.append(e)}))}}function r(t){var e,i;const o=Object.assign({},t);return(void 0!==o.layout_orientation&&o.layout_orientation!==(null!==(e=o.orientation)&&void 0!==e?e:"vertical")||void 0!==o.layout_group_by&&o.layout_group_by!==(null!==(i=o.group_by)&&void 0!==i?i:"none"))&&delete o.layout_data,delete o.show_layout_export,delete o.layout_orientation,delete o.layout_group_by,o}const s=t=>JSON.stringify(t,((t,e)=>e&&"object"==typeof e&&!Array.isArray(e)?Object.keys(e).sort().reduce(((t,i)=>(t[i]=e[i],t)),{}):e));async function a(t,e,i){var o,n,a,l,h,c;let d,u=t;for(;u;){if("wiser-zigbee-panel"===u.localName&&u.saveZigbeeCardConfig)return u.saveZigbeeCardConfig(t,r(Object.assign(Object.assign({},e),i)));if(null===(o=u.lovelace)||void 0===o?void 0:o.saveConfig){d=u.lovelace;break}u=null!==(n=u.parentElement)&&void 0!==n?n:null===(a=u.getRootNode)||void 0===a?void 0:a.call(u).host}const f=null!==(l=null==d?void 0:d.rawConfig)&&void 0!==l?l:null==d?void 0:d.config;if(!d||"storage"!==d.mode||!f||f.strategy)throw new Error("Dashboard configuration is not editable");const p=[],v=(t,i)=>{if(t&&"object"==typeof t){t.type===e.type&&s(t)===s(e)&&p.push({value:t,path:i});for(const[e,o]of Object.entries(t))v(o,[...i,e])}};v(f,[]);const g=p.filter((t=>t.value===e)),y=g.length?g:p;if(1!==y.length)throw new Error("Cannot uniquely identify this card");const m=JSON.parse(JSON.stringify(f)),b=y[0].path;let w=m;for(const t of b.slice(0,-1))w=w[t];const A=r(Object.assign(Object.assign({},y[0].value),i));w[b[b.length-1]]=A;const E=function(t){if(!t)return()=>{};const{scrollX:e,scrollY:i}=t,o=t.location.href;let n=!1,r=0,s=Date.now()+2500;const a=["wheel","touchstart","pointerdown","keydown","popstate","hashchange"],l=()=>{n=!0,t.cancelAnimationFrame(r),a.forEach((e=>t.removeEventListener(e,l,!0)))},h=()=>{n||Date.now()>=s||t.location.href!==o?l():(t.scrollX===e&&t.scrollY===i||t.scrollTo({left:e,top:i,behavior:"instant"}),r=t.requestAnimationFrame(h))};return a.forEach((e=>t.addEventListener(e,l,{capture:!0,passive:!0}))),r=t.requestAnimationFrame(h),()=>{s=Math.min(s,Date.now()+500)}}(null!==(c=null===(h=t.ownerDocument)||void 0===h?void 0:h.defaultView)&&void 0!==c?c:null);try{await d.saveConfig(m)}finally{E()}return A}const l=new Map,h=t=>t.replace(/&/g,"&").replace(/"/g,""").replace(/`:"";n="data:image/svg+xml,"+encodeURIComponent(`${r}`),l.set(o,n)}return n}function d(t){const e=t.match(/^([\s\S]*?)\n\s*\(([\s\S]*)\)\s*$/);if(!e)return t.replace(/\n/g," ").trim();const i=e[1].trim(),o=e[2].trim();return!o||/^no room$/i.test(o)?i:o}function u(t,e,i){var o,n;const r=new Map;for(const e of t.filter((t=>"Controller"!==t.group))){const t=null!==(o=e.area_id)&&void 0!==o?o:"";r.set(t,[...null!==(n=r.get(t))&&void 0!==n?n:[],e])}const s=t=>{var e;return null!==(e=null==i?void 0:i(t))&&void 0!==e?e:{left:Math.min(...t.map((t=>t.x-Math.max(40,4.5*t.label.length))))-18,right:Math.max(...t.map((t=>t.x+Math.max(40,4.5*t.label.length))))+18,top:Math.min(...t.map((t=>t.y-32)))-18,bottom:Math.max(...t.map((t=>t.y+60)))+18}},a=(t,e)=>Math.max(0,Math.min(t.right,e.right)-Math.max(t.left,e.left))*Math.max(0,Math.min(t.bottom,e.bottom)-Math.max(t.top,e.top)),l=new Map(t.map((t=>[t.id,{x:t.x,y:t.y}]))),h=[...r.values()];if(!t.length)return;const c=h.map(s);if(!c.length)return;const d=c.some(((t,e)=>c.slice(e+1).some((e=>a(t,e)>0)))),u=Math.min(...c.map((t=>t.left))),f=Math.max(...c.map((t=>t.right))),p=Math.min(...c.map((t=>t.top))),v=Math.max(...c.map((t=>t.bottom))),g=Math.max(480,Math.min(1200,Math.hypot(f-u,v-p)));for(let i=0;i<12;i++){let i=!1;for(const o of h){if(o.some((t=>e.has(t.id))))continue;const n=h.filter((t=>t!==o)).map(s),r=s(o),c=t=>n.reduce(((e,i)=>e+a(t,i)),0),u=t=>{const e=[...n,t];return(Math.max(...e.map((t=>t.right)))-Math.min(...e.map((t=>t.left))))*(Math.max(...e.map((t=>t.bottom)))-Math.min(...e.map((t=>t.top))))};let f=c(r),p=u(r),v={x:0,y:0};for(const e of n.filter((t=>d||a(r,t)>0))){const i=[{x:e.left-r.right-16,y:0},{x:e.right-r.left+16,y:0},{x:0,y:e.top-r.bottom-16},{x:0,y:e.bottom-r.top+16},{x:e.right-r.left+16,y:e.top-r.bottom-16},{x:e.left-r.right-16,y:e.top-r.bottom-16},{x:e.right-r.left+16,y:e.bottom-r.top+16},{x:e.left-r.right-16,y:e.bottom-r.top+16}].sort(((t,e)=>Math.hypot(t.x,t.y)-Math.hypot(e.x,e.y)));for(const e of i){if(o.some((t=>Math.hypot(t.x+e.x-l.get(t.id).x,t.y+e.y-l.get(t.id).y)>g)))continue;const i={left:r.left+e.x,right:r.right+e.x,top:r.top+e.y,bottom:r.bottom+e.y};if(t.some((t=>"Controller"===t.group&&a(i,s([t]))>0)))continue;const n=c(i),h=u(i);(nf(e,!0,t))).join("|")} /** * @license * Copyright 2019 Google LLC * SPDX-License-Identifier: BSD-3-Clause - */ -const s=window,a=s.ShadowRoot&&(void 0===s.ShadyCSS||s.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,d=Symbol(),l=new WeakMap;let c=class{constructor(t,e,i){if(this._$cssResult$=!0,i!==d)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(a&&void 0===t){const i=void 0!==e&&1===e.length;i&&(t=l.get(e)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&l.set(e,t))}return t}toString(){return this.cssText}};const h=a?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new c("string"==typeof t?t:t+"",void 0,d))(e)})(t):t + */const v=window,g=v.ShadowRoot&&(void 0===v.ShadyCSS||v.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,y=Symbol(),m=new WeakMap;let b=class{constructor(t,e,i){if(this._$cssResult$=!0,i!==y)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(g&&void 0===t){const i=void 0!==e&&1===e.length;i&&(t=m.get(e)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&m.set(e,t))}return t}toString(){return this.cssText}};const w=g?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new b("string"==typeof t?t:t+"",void 0,y))(e)})(t):t /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause - */;var u;const p=window,f=p.trustedTypes,m=f?f.emptyScript:"",v=p.reactiveElementPolyfillSupport,g={toAttribute(t,e){switch(e){case Boolean:t=t?m: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)=>e!==t&&(e==e||t==t),b={attribute:!0,type:String,converter:g,reflect:!1,hasChanged:y},x="finalized";let _=class extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(t){var e;this.finalize(),(null!==(e=this.h)&&void 0!==e?e:this.h=[]).push(t)}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach(((e,i)=>{const n=this._$Ep(i,e);void 0!==n&&(this._$Ev.set(n,i),t.push(n))})),t}static createProperty(t,e=b){if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){const i="symbol"==typeof t?Symbol():"__"+t,n=this.getPropertyDescriptor(t,i,e);void 0!==n&&Object.defineProperty(this.prototype,t,n)}}static getPropertyDescriptor(t,e,i){return{get(){return this[e]},set(n){const o=this[t];this[e]=n,this.requestUpdate(t,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||b}static finalize(){if(this.hasOwnProperty(x))return!1;this[x]=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),void 0!==t.h&&(this.h=[...t.h]),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,e=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const i of e)this.createProperty(i,t[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}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(h(t))}else void 0!==t&&e.push(h(t));return e}static _$Ep(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}_$Eu(){var t;this._$E_=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach((t=>t(this)))}addController(t){var e,i;(null!==(e=this._$ES)&&void 0!==e?e:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(i=t.hostConnected)||void 0===i||i.call(t))}removeController(t){var e;null===(e=this._$ES)||void 0===e||e.splice(this._$ES.indexOf(t)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach(((t,e)=>{this.hasOwnProperty(e)&&(this._$Ei.set(e,this[e]),delete this[e])}))}createRenderRoot(){var t;const e=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return((t,e)=>{a?t.adoptedStyleSheets=e.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet)):e.forEach((e=>{const i=document.createElement("style"),n=s.litNonce;void 0!==n&&i.setAttribute("nonce",n),i.textContent=e.cssText,t.appendChild(i)}))})(e,this.constructor.elementStyles),e}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)}))}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)}))}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$EO(t,e,i=b){var n;const o=this.constructor._$Ep(t,i);if(void 0!==o&&!0===i.reflect){const r=(void 0!==(null===(n=i.converter)||void 0===n?void 0:n.toAttribute)?i.converter:g).toAttribute(e,i.type);this._$El=t,null==r?this.removeAttribute(o):this.setAttribute(o,r),this._$El=null}}_$AK(t,e){var i;const n=this.constructor,o=n._$Ev.get(t);if(void 0!==o&&this._$El!==o){const t=n.getPropertyOptions(o),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(i=t.converter)||void 0===i?void 0:i.fromAttribute)?t.converter:g;this._$El=o,this[o]=r.fromAttribute(e,t.type),this._$El=null}}requestUpdate(t,e,i){let n=!0;void 0!==t&&(((i=i||this.constructor.getPropertyOptions(t)).hasChanged||y)(this[t],e)?(this._$AL.has(t)||this._$AL.set(t,e),!0===i.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,i))):n=!1),!this.isUpdatePending&&n&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach(((t,e)=>this[e]=t)),this._$Ei=void 0);let e=!1;const i=this._$AL;try{e=this.shouldUpdate(i),e?(this.willUpdate(i),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)})),this.update(i)):this._$Ek()}catch(t){throw e=!1,this._$Ek(),t}e&&this._$AE(i)}willUpdate(t){}_$AE(t){var e;null===(e=this._$ES)||void 0===e||e.forEach((t=>{var e;return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)})),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return!0}update(t){void 0!==this._$EC&&(this._$EC.forEach(((t,e)=>this._$EO(e,this[e],t))),this._$EC=void 0),this._$Ek()}updated(t){}firstUpdated(t){}}; + */;var A;const E=window,k=E.trustedTypes,C=k?k.emptyScript:"",x=E.reactiveElementPolyfillSupport,S={toAttribute(t,e){switch(e){case Boolean:t=t?C: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}},I=(t,e)=>e!==t&&(e==e||t==t),M={attribute:!0,type:String,converter:S,reflect:!1,hasChanged:I},O="finalized";let D=class extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(t){var e;this.finalize(),(null!==(e=this.h)&&void 0!==e?e:this.h=[]).push(t)}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach(((e,i)=>{const o=this._$Ep(i,e);void 0!==o&&(this._$Ev.set(o,i),t.push(o))})),t}static createProperty(t,e=M){if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){const i="symbol"==typeof t?Symbol():"__"+t,o=this.getPropertyDescriptor(t,i,e);void 0!==o&&Object.defineProperty(this.prototype,t,o)}}static getPropertyDescriptor(t,e,i){return{get(){return this[e]},set(o){const n=this[t];this[e]=o,this.requestUpdate(t,n,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||M}static finalize(){if(this.hasOwnProperty(O))return!1;this[O]=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),void 0!==t.h&&(this.h=[...t.h]),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,e=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const i of e)this.createProperty(i,t[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}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(w(t))}else void 0!==t&&e.push(w(t));return e}static _$Ep(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}_$Eu(){var t;this._$E_=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach((t=>t(this)))}addController(t){var e,i;(null!==(e=this._$ES)&&void 0!==e?e:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(i=t.hostConnected)||void 0===i||i.call(t))}removeController(t){var e;null===(e=this._$ES)||void 0===e||e.splice(this._$ES.indexOf(t)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach(((t,e)=>{this.hasOwnProperty(e)&&(this._$Ei.set(e,this[e]),delete this[e])}))}createRenderRoot(){var t;const e=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return((t,e)=>{g?t.adoptedStyleSheets=e.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet)):e.forEach((e=>{const i=document.createElement("style"),o=v.litNonce;void 0!==o&&i.setAttribute("nonce",o),i.textContent=e.cssText,t.appendChild(i)}))})(e,this.constructor.elementStyles),e}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)}))}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)}))}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$EO(t,e,i=M){var o;const n=this.constructor._$Ep(t,i);if(void 0!==n&&!0===i.reflect){const r=(void 0!==(null===(o=i.converter)||void 0===o?void 0:o.toAttribute)?i.converter:S).toAttribute(e,i.type);this._$El=t,null==r?this.removeAttribute(n):this.setAttribute(n,r),this._$El=null}}_$AK(t,e){var i;const o=this.constructor,n=o._$Ev.get(t);if(void 0!==n&&this._$El!==n){const t=o.getPropertyOptions(n),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(i=t.converter)||void 0===i?void 0:i.fromAttribute)?t.converter:S;this._$El=n,this[n]=r.fromAttribute(e,t.type),this._$El=null}}requestUpdate(t,e,i){let o=!0;void 0!==t&&(((i=i||this.constructor.getPropertyOptions(t)).hasChanged||I)(this[t],e)?(this._$AL.has(t)||this._$AL.set(t,e),!0===i.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,i))):o=!1),!this.isUpdatePending&&o&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach(((t,e)=>this[e]=t)),this._$Ei=void 0);let e=!1;const i=this._$AL;try{e=this.shouldUpdate(i),e?(this.willUpdate(i),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)})),this.update(i)):this._$Ek()}catch(t){throw e=!1,this._$Ek(),t}e&&this._$AE(i)}willUpdate(t){}_$AE(t){var e;null===(e=this._$ES)||void 0===e||e.forEach((t=>{var e;return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)})),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return!0}update(t){void 0!==this._$EC&&(this._$EC.forEach(((t,e)=>this._$EO(e,this[e],t))),this._$EC=void 0),this._$Ek()}updated(t){}firstUpdated(t){}}; /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause */ -var w;_[x]=!0,_.elementProperties=new Map,_.elementStyles=[],_.shadowRootOptions={mode:"open"},null==v||v({ReactiveElement:_}),(null!==(u=p.reactiveElementVersions)&&void 0!==u?u:p.reactiveElementVersions=[]).push("1.6.3");const E=window,k=E.trustedTypes,O=k?k.createPolicy("lit-html",{createHTML:t=>t}):void 0,C="$lit$",S=`lit$${(Math.random()+"").slice(9)}$`,T="?"+S,I=`<${T}>`,A=document,R=()=>A.createComment(""),P=t=>null===t||"object"!=typeof t&&"function"!=typeof t,D=Array.isArray,M="[ \t\n\f\r]",F=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,N=/-->/g,B=/>/g,L=RegExp(`>|${M}(?:([^\\s"'>=/]+)(${M}*=${M}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),z=/'/g,j=/"/g,H=/^(?:script|style|textarea|title)$/i,$=(t=>(e,...i)=>({_$litType$:t,strings:e,values:i}))(1),U=Symbol.for("lit-noChange"),W=Symbol.for("lit-nothing"),V=new WeakMap,q=A.createTreeWalker(A,129,null,!1);function X(t,e){if(!Array.isArray(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==O?O.createHTML(e):e}const Y=(t,e)=>{const i=t.length-1,n=[];let o,r=2===e?"":"",s=F;for(let e=0;e"===d[0]?(s=null!=o?o:F,l=-1):void 0===d[1]?l=-2:(l=s.lastIndex-d[2].length,a=d[1],s=void 0===d[3]?L:'"'===d[3]?j:z):s===j||s===z?s=L:s===N||s===B?s=F:(s=L,o=void 0);const h=s===L&&t[e+1].startsWith("/>")?" ":"";r+=s===F?i+I:l>=0?(n.push(a),i.slice(0,l)+C+i.slice(l)+S+h):i+S+(-2===l?(n.push(void 0),e):h)}return[X(t,r+(t[i]||"")+(2===e?"":"")),n]};class G{constructor({strings:t,_$litType$:e},i){let n;this.parts=[];let o=0,r=0;const s=t.length-1,a=this.parts,[d,l]=Y(t,e);if(this.el=G.createElement(d,i),q.currentNode=this.el.content,2===e){const t=this.el.content,e=t.firstChild;e.remove(),t.append(...e.childNodes)}for(;null!==(n=q.nextNode())&&a.length0){n.textContent=k?k.emptyScript:"";for(let i=0;iD(t)||"function"==typeof(null==t?void 0: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!==W&&P(this._$AH)?this._$AA.nextSibling.data=t:this.$(A.createTextNode(t)),this._$AH=t}g(t){var e;const{values:i,_$litType$:n}=t,o="number"==typeof n?this._$AC(t):(void 0===n.el&&(n.el=G.createElement(X(n.h,n.h[0]),this.options)),n);if((null===(e=this._$AH)||void 0===e?void 0:e._$AD)===o)this._$AH.v(i);else{const t=new Z(o,this),e=t.u(this.options);t.v(i),this.$(e),this._$AH=t}}_$AC(t){let e=V.get(t.strings);return void 0===e&&V.set(t.strings,e=new G(t)),e}T(t){D(this._$AH)||(this._$AH=[],this._$AR());const e=this._$AH;let i,n=0;for(const o of t)n===e.length?e.push(i=new Q(this.k(R()),this.k(R()),this,this.options)):i=e[n],i._$AI(o),n++;n2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=W}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(t,e=this,i,n){const o=this.strings;let r=!1;if(void 0===o)t=K(this,t,e,0),r=!P(t)||t!==this._$AH&&t!==U,r&&(this._$AH=t);else{const n=t;let s,a;for(t=o[0],s=0;st}):void 0,F="$lit$",T=`lit$${(Math.random()+"").slice(9)}$`,N="?"+T,j=`<${N}>`,U=document,L=()=>U.createComment(""),Q=t=>null===t||"object"!=typeof t&&"function"!=typeof t,H=Array.isArray,V="[ \t\n\f\r]",W=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,G=/-->/g,K=/>/g,q=RegExp(`>|${V}(?:([^\\s"'>=/]+)(${V}*=${V}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),Y=/'/g,Z=/"/g,J=/^(?:script|style|textarea|title)$/i,X=(t=>(e,...i)=>({_$litType$:t,strings:e,values:i}))(1),_=Symbol.for("lit-noChange"),$=Symbol.for("lit-nothing"),tt=new WeakMap,et=U.createTreeWalker(U,129,null,!1);function it(t,e){if(!Array.isArray(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==P?P.createHTML(e):e}const ot=(t,e)=>{const i=t.length-1,o=[];let n,r=2===e?"":"",s=W;for(let e=0;e"===l[0]?(s=null!=n?n:W,h=-1):void 0===l[1]?h=-2:(h=s.lastIndex-l[2].length,a=l[1],s=void 0===l[3]?q:'"'===l[3]?Z:Y):s===Z||s===Y?s=q:s===G||s===K?s=W:(s=q,n=void 0);const d=s===q&&t[e+1].startsWith("/>")?" ":"";r+=s===W?i+j:h>=0?(o.push(a),i.slice(0,h)+F+i.slice(h)+T+d):i+T+(-2===h?(o.push(void 0),e):d)}return[it(t,r+(t[i]||"")+(2===e?"":"")),o]};class nt{constructor({strings:t,_$litType$:e},i){let o;this.parts=[];let n=0,r=0;const s=t.length-1,a=this.parts,[l,h]=ot(t,e);if(this.el=nt.createElement(l,i),et.currentNode=this.el.content,2===e){const t=this.el.content,e=t.firstChild;e.remove(),t.append(...e.childNodes)}for(;null!==(o=et.nextNode())&&a.length0){o.textContent=z?z.emptyScript:"";for(let i=0;iH(t)||"function"==typeof(null==t?void 0: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!==$&&Q(this._$AH)?this._$AA.nextSibling.data=t:this.$(U.createTextNode(t)),this._$AH=t}g(t){var e;const{values:i,_$litType$:o}=t,n="number"==typeof o?this._$AC(t):(void 0===o.el&&(o.el=nt.createElement(it(o.h,o.h[0]),this.options)),o);if((null===(e=this._$AH)||void 0===e?void 0:e._$AD)===n)this._$AH.v(i);else{const t=new st(n,this),e=t.u(this.options);t.v(i),this.$(e),this._$AH=t}}_$AC(t){let e=tt.get(t.strings);return void 0===e&&tt.set(t.strings,e=new nt(t)),e}T(t){H(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 at(this.k(L()),this.k(L()),this,this.options)):i=e[o],i._$AI(n),o++;o2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=$}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(t,e=this,i,o){const n=this.strings;let r=!1;if(void 0===n)t=rt(this,t,e,0),r=!Q(t)||t!==this._$AH&&t!==_,r&&(this._$AH=t);else{const o=t;let s,a;for(t=n[0],s=0;s{const i=1===t.length?t[0]:e.reduce(((e,i,n)=>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[n+1]),t[0]);return new ct(i,t,dt)},ut=at?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new ct("string"==typeof t?t:t+"",void 0,dt))(e)})(t):t + */let bt=class{constructor(t,e,i){if(this._$cssResult$=!0,i!==yt)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(gt&&void 0===t){const i=void 0!==e&&1===e.length;i&&(t=mt.get(e)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&mt.set(e,t))}return t}toString(){return this.cssText}};const wt=(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 bt(i,t,yt)},At=gt?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new bt("string"==typeof t?t:t+"",void 0,yt))(e)})(t):t /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause - */;var pt;const ft=window,mt=ft.trustedTypes,vt=mt?mt.emptyScript:"",gt=ft.reactiveElementPolyfillSupport,yt={toAttribute(t,e){switch(e){case Boolean:t=t?vt: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}},bt=(t,e)=>e!==t&&(e==e||t==t),xt={attribute:!0,type:String,converter:yt,reflect:!1,hasChanged:bt},_t="finalized";class wt extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(t){var e;this.finalize(),(null!==(e=this.h)&&void 0!==e?e:this.h=[]).push(t)}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach(((e,i)=>{const n=this._$Ep(i,e);void 0!==n&&(this._$Ev.set(n,i),t.push(n))})),t}static createProperty(t,e=xt){if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){const i="symbol"==typeof t?Symbol():"__"+t,n=this.getPropertyDescriptor(t,i,e);void 0!==n&&Object.defineProperty(this.prototype,t,n)}}static getPropertyDescriptor(t,e,i){return{get(){return this[e]},set(n){const o=this[t];this[e]=n,this.requestUpdate(t,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||xt}static finalize(){if(this.hasOwnProperty(_t))return!1;this[_t]=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),void 0!==t.h&&(this.h=[...t.h]),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,e=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const i of e)this.createProperty(i,t[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}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(ut(t))}else void 0!==t&&e.push(ut(t));return e}static _$Ep(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}_$Eu(){var t;this._$E_=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach((t=>t(this)))}addController(t){var e,i;(null!==(e=this._$ES)&&void 0!==e?e:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(i=t.hostConnected)||void 0===i||i.call(t))}removeController(t){var e;null===(e=this._$ES)||void 0===e||e.splice(this._$ES.indexOf(t)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach(((t,e)=>{this.hasOwnProperty(e)&&(this._$Ei.set(e,this[e]),delete this[e])}))}createRenderRoot(){var t;const e=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return((t,e)=>{at?t.adoptedStyleSheets=e.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet)):e.forEach((e=>{const i=document.createElement("style"),n=st.litNonce;void 0!==n&&i.setAttribute("nonce",n),i.textContent=e.cssText,t.appendChild(i)}))})(e,this.constructor.elementStyles),e}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)}))}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)}))}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$EO(t,e,i=xt){var n;const o=this.constructor._$Ep(t,i);if(void 0!==o&&!0===i.reflect){const r=(void 0!==(null===(n=i.converter)||void 0===n?void 0:n.toAttribute)?i.converter:yt).toAttribute(e,i.type);this._$El=t,null==r?this.removeAttribute(o):this.setAttribute(o,r),this._$El=null}}_$AK(t,e){var i;const n=this.constructor,o=n._$Ev.get(t);if(void 0!==o&&this._$El!==o){const t=n.getPropertyOptions(o),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(i=t.converter)||void 0===i?void 0:i.fromAttribute)?t.converter:yt;this._$El=o,this[o]=r.fromAttribute(e,t.type),this._$El=null}}requestUpdate(t,e,i){let n=!0;void 0!==t&&(((i=i||this.constructor.getPropertyOptions(t)).hasChanged||bt)(this[t],e)?(this._$AL.has(t)||this._$AL.set(t,e),!0===i.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,i))):n=!1),!this.isUpdatePending&&n&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach(((t,e)=>this[e]=t)),this._$Ei=void 0);let e=!1;const i=this._$AL;try{e=this.shouldUpdate(i),e?(this.willUpdate(i),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)})),this.update(i)):this._$Ek()}catch(t){throw e=!1,this._$Ek(),t}e&&this._$AE(i)}willUpdate(t){}_$AE(t){var e;null===(e=this._$ES)||void 0===e||e.forEach((t=>{var e;return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)})),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return!0}update(t){void 0!==this._$EC&&(this._$EC.forEach(((t,e)=>this._$EO(e,this[e],t))),this._$EC=void 0),this._$Ek()}updated(t){}firstUpdated(t){}} + */;var Et;const kt=window,Ct=kt.trustedTypes,xt=Ct?Ct.emptyScript:"",St=kt.reactiveElementPolyfillSupport,It={toAttribute(t,e){switch(e){case Boolean:t=t?xt: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}},Mt=(t,e)=>e!==t&&(e==e||t==t),Ot={attribute:!0,type:String,converter:It,reflect:!1,hasChanged:Mt},Dt="finalized";class Rt extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(t){var e;this.finalize(),(null!==(e=this.h)&&void 0!==e?e:this.h=[]).push(t)}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach(((e,i)=>{const o=this._$Ep(i,e);void 0!==o&&(this._$Ev.set(o,i),t.push(o))})),t}static createProperty(t,e=Ot){if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){const i="symbol"==typeof t?Symbol():"__"+t,o=this.getPropertyDescriptor(t,i,e);void 0!==o&&Object.defineProperty(this.prototype,t,o)}}static getPropertyDescriptor(t,e,i){return{get(){return this[e]},set(o){const n=this[t];this[e]=o,this.requestUpdate(t,n,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||Ot}static finalize(){if(this.hasOwnProperty(Dt))return!1;this[Dt]=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),void 0!==t.h&&(this.h=[...t.h]),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,e=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const i of e)this.createProperty(i,t[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}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(At(t))}else void 0!==t&&e.push(At(t));return e}static _$Ep(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}_$Eu(){var t;this._$E_=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach((t=>t(this)))}addController(t){var e,i;(null!==(e=this._$ES)&&void 0!==e?e:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(i=t.hostConnected)||void 0===i||i.call(t))}removeController(t){var e;null===(e=this._$ES)||void 0===e||e.splice(this._$ES.indexOf(t)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach(((t,e)=>{this.hasOwnProperty(e)&&(this._$Ei.set(e,this[e]),delete this[e])}))}createRenderRoot(){var t;const e=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return((t,e)=>{gt?t.adoptedStyleSheets=e.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet)):e.forEach((e=>{const i=document.createElement("style"),o=vt.litNonce;void 0!==o&&i.setAttribute("nonce",o),i.textContent=e.cssText,t.appendChild(i)}))})(e,this.constructor.elementStyles),e}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)}))}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)}))}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$EO(t,e,i=Ot){var o;const n=this.constructor._$Ep(t,i);if(void 0!==n&&!0===i.reflect){const r=(void 0!==(null===(o=i.converter)||void 0===o?void 0:o.toAttribute)?i.converter:It).toAttribute(e,i.type);this._$El=t,null==r?this.removeAttribute(n):this.setAttribute(n,r),this._$El=null}}_$AK(t,e){var i;const o=this.constructor,n=o._$Ev.get(t);if(void 0!==n&&this._$El!==n){const t=o.getPropertyOptions(n),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(i=t.converter)||void 0===i?void 0:i.fromAttribute)?t.converter:It;this._$El=n,this[n]=r.fromAttribute(e,t.type),this._$El=null}}requestUpdate(t,e,i){let o=!0;void 0!==t&&(((i=i||this.constructor.getPropertyOptions(t)).hasChanged||Mt)(this[t],e)?(this._$AL.has(t)||this._$AL.set(t,e),!0===i.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,i))):o=!1),!this.isUpdatePending&&o&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach(((t,e)=>this[e]=t)),this._$Ei=void 0);let e=!1;const i=this._$AL;try{e=this.shouldUpdate(i),e?(this.willUpdate(i),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)})),this.update(i)):this._$Ek()}catch(t){throw e=!1,this._$Ek(),t}e&&this._$AE(i)}willUpdate(t){}_$AE(t){var e;null===(e=this._$ES)||void 0===e||e.forEach((t=>{var e;return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)})),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return!0}update(t){void 0!==this._$EC&&(this._$EC.forEach(((t,e)=>this._$EO(e,this[e],t))),this._$EC=void 0),this._$Ek()}updated(t){}firstUpdated(t){}} /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause */ -var Et,kt;wt[_t]=!0,wt.elementProperties=new Map,wt.elementStyles=[],wt.shadowRootOptions={mode:"open"},null==gt||gt({ReactiveElement:wt}),(null!==(pt=ft.reactiveElementVersions)&&void 0!==pt?pt:ft.reactiveElementVersions=[]).push("1.6.3");let Ot=class extends wt{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){var t,e;const i=super.createRenderRoot();return null!==(t=(e=this.renderOptions).renderBefore)&&void 0!==t||(e.renderBefore=i.firstChild),i}update(t){const e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=((t,e,i)=>{var n,o;const r=null!==(n=null==i?void 0:i.renderBefore)&&void 0!==n?n:e;let s=r._$litPart$;if(void 0===s){const t=null!==(o=null==i?void 0:i.renderBefore)&&void 0!==o?o:null;r._$litPart$=s=new Q(e.insertBefore(R(),t),t,void 0,null!=i?i:{})}return s._$AI(t),s})(e,this.renderRoot,this.renderOptions)}connectedCallback(){var t;super.connectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!0)}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!1)}render(){return U}};Ot.finalized=!0,Ot._$litElement$=!0,null===(Et=globalThis.litElementHydrateSupport)||void 0===Et||Et.call(globalThis,{LitElement:Ot});const Ct=globalThis.litElementPolyfillSupport;null==Ct||Ct({LitElement:Ot}),(null!==(kt=globalThis.litElementVersions)&&void 0!==kt?kt:globalThis.litElementVersions=[]).push("3.3.3"); +var Bt,zt;Rt[Dt]=!0,Rt.elementProperties=new Map,Rt.elementStyles=[],Rt.shadowRootOptions={mode:"open"},null==St||St({ReactiveElement:Rt}),(null!==(Et=kt.reactiveElementVersions)&&void 0!==Et?Et:kt.reactiveElementVersions=[]).push("1.6.3");class Pt extends Rt{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){var t,e;const i=super.createRenderRoot();return null!==(t=(e=this.renderOptions).renderBefore)&&void 0!==t||(e.renderBefore=i.firstChild),i}update(t){const e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=((t,e,i)=>{var o,n;const r=null!==(o=null==i?void 0:i.renderBefore)&&void 0!==o?o:e;let s=r._$litPart$;if(void 0===s){const t=null!==(n=null==i?void 0:i.renderBefore)&&void 0!==n?n:null;r._$litPart$=s=new at(e.insertBefore(L(),t),t,void 0,null!=i?i:{})}return s._$AI(t),s})(e,this.renderRoot,this.renderOptions)}connectedCallback(){var t;super.connectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!0)}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!1)}render(){return _}}Pt.finalized=!0,Pt._$litElement$=!0,null===(Bt=globalThis.litElementHydrateSupport)||void 0===Bt||Bt.call(globalThis,{LitElement:Pt});const Ft=globalThis.litElementPolyfillSupport;null==Ft||Ft({LitElement:Pt}),(null!==(zt=globalThis.litElementVersions)&&void 0!==zt?zt:globalThis.litElementVersions=[]).push("3.3.3"); /** * @license - * Copyright 2017 Google LLC + * Copyright 2018 Google LLC * SPDX-License-Identifier: BSD-3-Clause */ -const St=t=>e=>"function"==typeof e?((t,e)=>(customElements.define(t,e),e))(t,e):((t,e)=>{const{kind:i,elements:n}=e;return{kind:i,elements:n,finisher(e){customElements.define(t,e)}}})(t,e) -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */,Tt=(t,e)=>"method"===e.kind&&e.descriptor&&!("value"in e.descriptor)?{...e,finisher(i){i.createProperty(e.key,t)}}:{kind:"field",key:Symbol(),placement:"own",descriptor:{},originalKey:e.key,initializer(){"function"==typeof e.initializer&&(this[e.key]=e.initializer.call(this))},finisher(i){i.createProperty(e.key,t)}},It=(t,e,i)=>{e.constructor.createProperty(i,t)};function At(t){return(e,i)=>void 0!==i?It(t,e,i):Tt(t,e) -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */}function Rt(t){return At({...t,state:!0})} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */const Pt=({finisher:t,descriptor:e})=>(i,n)=>{var o;if(void 0===n){const n=null!==(o=i.originalKey)&&void 0!==o?o:i.key,r=null!=e?{kind:"method",placement:"prototype",key:n,descriptor:e(i.key)}:{...i,key:n};return null!=t&&(r.finisher=function(e){t(e,n)}),r}{const o=i.constructor;void 0!==e&&Object.defineProperty(i,n,e(n)),null==t||t(o,n)}} +const Tt=t=>null!=t?t:$ /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause - */;function Dt(t){return Pt({finisher:(e,i)=>{Object.assign(e.prototype[i],t)}})} + */,Nt=(t,e)=>"method"===e.kind&&e.descriptor&&!("value"in e.descriptor)?{...e,finisher(i){i.createProperty(e.key,t)}}:{kind:"field",key:Symbol(),placement:"own",descriptor:{},originalKey:e.key,initializer(){"function"==typeof e.initializer&&(this[e.key]=e.initializer.call(this))},finisher(i){i.createProperty(e.key,t)}},jt=(t,e,i)=>{e.constructor.createProperty(i,t)};function Ut(t){return(e,i)=>void 0!==i?jt(t,e,i):Nt(t,e) /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause - */function Mt(t,e){return Pt({descriptor:e=>{const i={get(){var e,i;return null!==(i=null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(t))&&void 0!==i?i:null},enumerable:!0,configurable:!0};return i}})} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */function Ft(t){return Pt({descriptor:e=>({async get(){var e;return await this.updateComplete,null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(t)},enumerable:!0,configurable:!0})})} -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */var Nt;const Bt=null!=(null===(Nt=window.HTMLSlotElement)||void 0===Nt?void 0:Nt.prototype.assignedElements)?(t,e)=>t.assignedElements(e):(t,e)=>t.assignedNodes(e).filter((t=>t.nodeType===Node.ELEMENT_NODE)); + */}function Lt(t){return Ut({...t,state:!0})} /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause */ -function Lt(t,e,i){let n;return n={flatten:e},i?function(t){const{slot:e,selector:i}=null!=t?t:{};return Pt({descriptor:n=>({get(){var n;const o="slot"+(e?`[name=${e}]`:":not([name])"),r=null===(n=this.renderRoot)||void 0===n?void 0:n.querySelector(o),s=null!=r?Bt(r,t):[];return i?s.filter((t=>t.matches(i))):s},enumerable:!0,configurable:!0})})}({slot:t,flatten:e,selector:i}):Pt({descriptor:t=>({get(){var t,e;const i=null===(t=this.renderRoot)||void 0===t?void 0:t.querySelector("slot:not([name])");return null!==(e=null==i?void 0:i.assignedNodes(n))&&void 0!==e?e:[]},enumerable:!0,configurable:!0})})}var zt,jt;!function(t){t.language="language",t.system="system",t.comma_decimal="comma_decimal",t.decimal_comma="decimal_comma",t.space_comma="space_comma",t.none="none"}(zt||(zt={})),function(t){t.language="language",t.system="system",t.am_pm="12",t.twenty_four="24"}(jt||(jt={}));var Ht=function(t,e,i,n){n=n||{},i=null==i?{}:i;var o=new Event(e,{bubbles:void 0===n.bubbles||n.bubbles,cancelable:Boolean(n.cancelable),composed:void 0===n.composed||n.composed});return o.detail=i,t.dispatchEvent(o),o};const $t="2.1.2",Ut={autoResize:!0,height:"500px",configure:{enabled:!1},edges:{arrows:{to:{enabled:!0,scaleFactor:1},middle:{enabled:!1},from:{enabled:!1}},color:"#03a9f4",smooth:!0,physics:!1,width:2,labelHighlightBold:!1,font:{align:"top",color:"var(--primary-text-color, #fff)",strokeWidth:0,size:14}},groups:{Controller:{color:{background:"#518C43"},shape:"circle",margin:{top:15,right:10,bottom:15,left:10}},RoomStat:{color:{background:"#B1345C"}},iTRV:{color:{background:"#E48629"}},SmartPlug:{color:{background:"#3B808E"}},HeatingActuator:{color:{background:"#5A87FA"}},UnderFloorHeating:{color:{background:"#0D47A1"}},Shutter:{color:{background:"#4A5963"}},OnOffLight:{color:{background:"#E4B62B"}},DimmableLight:{color:{background:"#E4B62B"}}},interaction:{selectable:!1,selectConnectedEdges:!1},layout:{randomSeed:"1:1"},nodes:{shape:"box",size:25,font:{size:14,color:"#fff"},margin:{top:10,bottom:10,left:10,right:10},borderWidth:0,mass:1.3,chosen:!1},physics:{enabled:!1}};var Wt={version:"Version",invalid_configuration:"Invalid configuration"},Vt={actions:{copy:"Copy",files:"Files",add_before:"Add Before",add_after:"Add After"},headings:{schedule_actions:"Schedule Actions",schedule_type:"Schedule Type",schedule_id:"Schedule Id",schedule_name:"Schedule Name",schedule_assignment:"Schedule Assignment",not_assigned:"(Not Assigned)"}},qt={common:Wt,wiser:Vt},Xt={version:"Déclinaison",invalid_configuration:"Configuration Invalide"},Yt={actions:{copy:"Copie",files:"Fichier",add_before:"Ajouter Avant",add_after:"Ajouter Après"},headings:{schedule_actions:"Schedule Actions",schedule_type:"Schedule Type",schedule_id:"Schedule Id",schedule_name:"Schedule Name",schedule_assignment:"Schedule Assignment",not_assigned:"(Not Assigned)"}},Gt={common:Xt,wiser:Yt};const Kt={en:Object.freeze({__proto__:null,common:Wt,default:qt,wiser:Vt}),fr:Object.freeze({__proto__:null,common:Xt,default:Gt,wiser:Yt})};function Zt(t,e="",i=""){const n=(localStorage.getItem("selectedLanguage")||"en").replace(/['"]+/g,"").replace("-","_");let o;try{o=t.split(".").reduce(((t,e)=>t[e]),Kt[n]),o||(o=t.split(".").reduce(((t,e)=>t[e]),Kt.en))}catch(e){try{o=t.split(".").reduce(((t,e)=>t[e]),Kt.en)}catch(t){o=""}}return void 0===o&&(o=t.split(".").reduce(((t,e)=>t[e]),Kt.en)),""!==e&&""!==i&&(o=o.replace(e,i)),o} -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */const Qt=globalThis,Jt=Qt.ShadowRoot&&(void 0===Qt.ShadyCSS||Qt.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype; -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -function te(t){return class extends t{createRenderRoot(){const t=this.constructor,{registry:e,elementDefinitions:i,shadowRootOptions:n}=t;i&&!e&&(t.registry=new CustomElementRegistry,Object.entries(i).forEach((([e,i])=>t.registry.define(e,i))));const o=this.renderOptions.creationScope=this.attachShadow({...n,customElements:t.registry});return((t,e)=>{if(Jt)t.adoptedStyleSheets=e.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet));else for(const i of e){const e=document.createElement("style"),n=Qt.litNonce;void 0!==n&&e.setAttribute("nonce",n),e.textContent=i.cssText,t.appendChild(e)}})(o,this.constructor.elementStyles),o}}} -/** - * @license - * Copyright 2016 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */var ee=function(){function t(t){void 0===t&&(t={}),this.adapter=t}return Object.defineProperty(t,"cssClasses",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"strings",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"numbers",{get:function(){return{}},enumerable:!1,configurable:!0}),Object.defineProperty(t,"defaultAdapter",{get:function(){return{}},enumerable:!1,configurable:!0}),t.prototype.init=function(){},t.prototype.destroy=function(){},t}(),ie={ROOT:"mdc-form-field"},ne={LABEL_SELECTOR:".mdc-form-field > label"},oe=function(t){function e(i){var o=t.call(this,n(n({},e.defaultAdapter),i))||this;return o.click=function(){o.handleClick()},o}return i(e,t),Object.defineProperty(e,"cssClasses",{get:function(){return ie},enumerable:!1,configurable:!0}),Object.defineProperty(e,"strings",{get:function(){return ne},enumerable:!1,configurable:!0}),Object.defineProperty(e,"defaultAdapter",{get:function(){return{activateInputRipple:function(){},deactivateInputRipple:function(){},deregisterInteractionHandler:function(){},registerInteractionHandler:function(){}}},enumerable:!1,configurable:!0}),e.prototype.init=function(){this.adapter.registerInteractionHandler("click",this.click)},e.prototype.destroy=function(){this.adapter.deregisterInteractionHandler("click",this.click)},e.prototype.handleClick=function(){var t=this;this.adapter.activateInputRipple(),requestAnimationFrame((function(){t.adapter.deactivateInputRipple()}))},e}(ee); -/** - * @license - * Copyright 2017 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -const re=t=>t.nodeType===Node.ELEMENT_NODE;function se(t){return{addClass:e=>{t.classList.add(e)},removeClass:e=>{t.classList.remove(e)},hasClass:e=>t.classList.contains(e)}}const ae=()=>{},de={get passive(){return!1}};document.addEventListener("x",ae,de),document.removeEventListener("x",ae);const le=(t=window.document)=>{let e=t.activeElement;const i=[];if(!e)return i;for(;e&&(i.push(e),e.shadowRoot);)e=e.shadowRoot.activeElement;return i},ce=t=>{const e=le();if(!e.length)return!1;const i=e[e.length-1],n=new Event("check-if-focused",{bubbles:!0,composed:!0});let o=[];const r=t=>{o=t.composedPath()};return document.body.addEventListener("check-if-focused",r),i.dispatchEvent(n),document.body.removeEventListener("check-if-focused",r),-1!==o.indexOf(t)}; -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -class he extends Ot{click(){if(this.mdcRoot)return this.mdcRoot.focus(),void this.mdcRoot.click();super.click()}createFoundation(){void 0!==this.mdcFoundation&&this.mdcFoundation.destroy(),this.mdcFoundationClass&&(this.mdcFoundation=new this.mdcFoundationClass(this.createAdapter()),this.mdcFoundation.init())}firstUpdated(){this.createFoundation()}} -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */var ue,pe;const fe=null!==(pe=null===(ue=window.ShadyDOM)||void 0===ue?void 0:ue.inUse)&&void 0!==pe&&pe;class me extends he{constructor(){super(...arguments),this.disabled=!1,this.containingForm=null,this.formDataListener=t=>{this.disabled||this.setFormData(t.formData)}}findFormElement(){if(!this.shadowRoot||fe)return null;const t=this.getRootNode().querySelectorAll("form");for(const e of Array.from(t))if(e.contains(this))return e;return null}connectedCallback(){var t;super.connectedCallback(),this.containingForm=this.findFormElement(),null===(t=this.containingForm)||void 0===t||t.addEventListener("formdata",this.formDataListener)}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this.containingForm)||void 0===t||t.removeEventListener("formdata",this.formDataListener),this.containingForm=null}click(){this.formElement&&!this.disabled&&(this.formElement.focus(),this.formElement.click())}firstUpdated(){super.firstUpdated(),this.shadowRoot&&this.mdcRoot.addEventListener("change",(t=>{this.dispatchEvent(new Event("change",t))}))}}me.shadowRootOptions={mode:"open",delegatesFocus:!0},o([At({type:Boolean})],me.prototype,"disabled",void 0); -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -const ve=t=>(e,i)=>{if(e.constructor._observers){if(!e.constructor.hasOwnProperty("_observers")){const t=e.constructor._observers;e.constructor._observers=new Map,t.forEach(((t,i)=>e.constructor._observers.set(i,t)))}}else{e.constructor._observers=new Map;const t=e.updated;e.updated=function(e){t.call(this,e),e.forEach(((t,e)=>{const i=this.constructor._observers.get(e);void 0!==i&&i.call(this,this[e],t)}))}}e.constructor._observers.set(i,t)} /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause - */,ge=1,ye=3,be=4,xe=t=>(...e)=>({_$litDirective$:t,values:e});let _e=class{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 2018 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */const we=xe(class extends _e{constructor(t){var e;if(super(t),t.type!==ge||"class"!==t.name||(null===(e=t.strings)||void 0===e?void 0:e.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]){var i,n;if(void 0===this.it){this.it=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]&&!(null===(i=this.nt)||void 0===i?void 0:i.has(t))&&this.it.add(t);return this.render(e)}const o=t.element.classList;this.it.forEach((t=>{t in e||(o.remove(t),this.it.delete(t))}));for(const t in e){const i=!!e[t];i===this.it.has(t)||(null===(n=this.nt)||void 0===n?void 0:n.has(t))||(i?(o.add(t),this.it.add(t)):(o.remove(t),this.it.delete(t)))}return U}}); -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */class Ee extends he{constructor(){super(...arguments),this.alignEnd=!1,this.spaceBetween=!1,this.nowrap=!1,this.label="",this.mdcFoundationClass=oe}createAdapter(){return{registerInteractionHandler:(t,e)=>{this.labelEl.addEventListener(t,e)},deregisterInteractionHandler:(t,e)=>{this.labelEl.removeEventListener(t,e)},activateInputRipple:async()=>{const t=this.input;if(t instanceof me){const e=await t.ripple;e&&e.startPress()}},deactivateInputRipple:async()=>{const t=this.input;if(t instanceof me){const e=await t.ripple;e&&e.endPress()}}}}get input(){var t,e;return null!==(e=null===(t=this.slottedInputs)||void 0===t?void 0:t[0])&&void 0!==e?e:null}render(){const t={"mdc-form-field--align-end":this.alignEnd,"mdc-form-field--space-between":this.spaceBetween,"mdc-form-field--nowrap":this.nowrap};return $` -
- - -
`}click(){this._labelClick()}_labelClick(){const t=this.input;t&&(t.focus(),t.click())}}o([At({type:Boolean})],Ee.prototype,"alignEnd",void 0),o([At({type:Boolean})],Ee.prototype,"spaceBetween",void 0),o([At({type:Boolean})],Ee.prototype,"nowrap",void 0),o([At({type:String}),ve((async function(t){var e;null===(e=this.input)||void 0===e||e.setAttribute("aria-label",t)}))],Ee.prototype,"label",void 0),o([Mt(".mdc-form-field")],Ee.prototype,"mdcRoot",void 0),o([Lt("",!0,"*")],Ee.prototype,"slottedInputs",void 0),o([Mt("label")],Ee.prototype,"labelEl",void 0); -/** - * @license - * Copyright 2021 Google LLC - * SPDX-LIcense-Identifier: Apache-2.0 - */ -const ke=ht`.mdc-form-field{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-body2-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:0.875rem;font-size:var(--mdc-typography-body2-font-size, 0.875rem);line-height:1.25rem;line-height:var(--mdc-typography-body2-line-height, 1.25rem);font-weight:400;font-weight:var(--mdc-typography-body2-font-weight, 400);letter-spacing:0.0178571429em;letter-spacing:var(--mdc-typography-body2-letter-spacing, 0.0178571429em);text-decoration:inherit;text-decoration:var(--mdc-typography-body2-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-body2-text-transform, inherit);color:rgba(0, 0, 0, 0.87);color:var(--mdc-theme-text-primary-on-background, rgba(0, 0, 0, 0.87));display:inline-flex;align-items:center;vertical-align:middle}.mdc-form-field>label{margin-left:0;margin-right:auto;padding-left:4px;padding-right:0;order:0}[dir=rtl] .mdc-form-field>label,.mdc-form-field>label[dir=rtl]{margin-left:auto;margin-right:0}[dir=rtl] .mdc-form-field>label,.mdc-form-field>label[dir=rtl]{padding-left:0;padding-right:4px}.mdc-form-field--nowrap>label{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.mdc-form-field--align-end>label{margin-left:auto;margin-right:0;padding-left:0;padding-right:4px;order:-1}[dir=rtl] .mdc-form-field--align-end>label,.mdc-form-field--align-end>label[dir=rtl]{margin-left:0;margin-right:auto}[dir=rtl] .mdc-form-field--align-end>label,.mdc-form-field--align-end>label[dir=rtl]{padding-left:4px;padding-right:0}.mdc-form-field--space-between{justify-content:space-between}.mdc-form-field--space-between>label{margin:0}[dir=rtl] .mdc-form-field--space-between>label,.mdc-form-field--space-between>label[dir=rtl]{margin:0}:host{display:inline-flex}.mdc-form-field{width:100%}::slotted(*){-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-body2-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:0.875rem;font-size:var(--mdc-typography-body2-font-size, 0.875rem);line-height:1.25rem;line-height:var(--mdc-typography-body2-line-height, 1.25rem);font-weight:400;font-weight:var(--mdc-typography-body2-font-weight, 400);letter-spacing:0.0178571429em;letter-spacing:var(--mdc-typography-body2-letter-spacing, 0.0178571429em);text-decoration:inherit;text-decoration:var(--mdc-typography-body2-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-body2-text-transform, inherit);color:rgba(0, 0, 0, 0.87);color:var(--mdc-theme-text-primary-on-background, rgba(0, 0, 0, 0.87))}::slotted(mwc-switch){margin-right:10px}[dir=rtl] ::slotted(mwc-switch),::slotted(mwc-switch[dir=rtl]){margin-left:10px}`,Oe={"mwc-formfield":class extends Ee{static get styles(){return ke}}}; -/** - * @license - * Copyright 2020 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -var Ce={UNKNOWN:"Unknown",BACKSPACE:"Backspace",ENTER:"Enter",SPACEBAR:"Spacebar",PAGE_UP:"PageUp",PAGE_DOWN:"PageDown",END:"End",HOME:"Home",ARROW_LEFT:"ArrowLeft",ARROW_UP:"ArrowUp",ARROW_RIGHT:"ArrowRight",ARROW_DOWN:"ArrowDown",DELETE:"Delete",ESCAPE:"Escape",TAB:"Tab"},Se=new Set;Se.add(Ce.BACKSPACE),Se.add(Ce.ENTER),Se.add(Ce.SPACEBAR),Se.add(Ce.PAGE_UP),Se.add(Ce.PAGE_DOWN),Se.add(Ce.END),Se.add(Ce.HOME),Se.add(Ce.ARROW_LEFT),Se.add(Ce.ARROW_UP),Se.add(Ce.ARROW_RIGHT),Se.add(Ce.ARROW_DOWN),Se.add(Ce.DELETE),Se.add(Ce.ESCAPE),Se.add(Ce.TAB);var Te=8,Ie=13,Ae=32,Re=33,Pe=34,De=35,Me=36,Fe=37,Ne=38,Be=39,Le=40,ze=46,je=27,He=9,$e=new Map;$e.set(Te,Ce.BACKSPACE),$e.set(Ie,Ce.ENTER),$e.set(Ae,Ce.SPACEBAR),$e.set(Re,Ce.PAGE_UP),$e.set(Pe,Ce.PAGE_DOWN),$e.set(De,Ce.END),$e.set(Me,Ce.HOME),$e.set(Fe,Ce.ARROW_LEFT),$e.set(Ne,Ce.ARROW_UP),$e.set(Be,Ce.ARROW_RIGHT),$e.set(Le,Ce.ARROW_DOWN),$e.set(ze,Ce.DELETE),$e.set(je,Ce.ESCAPE),$e.set(He,Ce.TAB);var Ue,We,Ve=new Set;function qe(t){var e=t.key;if(Se.has(e))return e;var i=$e.get(t.keyCode);return i||Ce.UNKNOWN} -/** - * @license - * Copyright 2018 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */Ve.add(Ce.PAGE_UP),Ve.add(Ce.PAGE_DOWN),Ve.add(Ce.END),Ve.add(Ce.HOME),Ve.add(Ce.ARROW_LEFT),Ve.add(Ce.ARROW_UP),Ve.add(Ce.ARROW_RIGHT),Ve.add(Ce.ARROW_DOWN);var Xe="mdc-list-item--activated",Ye="mdc-list-item",Ge="mdc-list-item--disabled",Ke="mdc-list-item--selected",Ze="mdc-list-item__text",Qe="mdc-list-item__primary-text",Je="mdc-list";(Ue={})[""+Xe]="mdc-list-item--activated",Ue[""+Ye]="mdc-list-item",Ue[""+Ge]="mdc-list-item--disabled",Ue[""+Ke]="mdc-list-item--selected",Ue[""+Qe]="mdc-list-item__primary-text",Ue[""+Je]="mdc-list";var ti=((We={})[""+Xe]="mdc-deprecated-list-item--activated",We[""+Ye]="mdc-deprecated-list-item",We[""+Ge]="mdc-deprecated-list-item--disabled",We[""+Ke]="mdc-deprecated-list-item--selected",We[""+Ze]="mdc-deprecated-list-item__text",We[""+Qe]="mdc-deprecated-list-item__primary-text",We[""+Je]="mdc-deprecated-list",We),ei={ACTION_EVENT:"MDCList:action",SELECTION_CHANGE_EVENT:"MDCList:selectionChange",ARIA_CHECKED:"aria-checked",ARIA_CHECKED_CHECKBOX_SELECTOR:'[role="checkbox"][aria-checked="true"]',ARIA_CHECKED_RADIO_SELECTOR:'[role="radio"][aria-checked="true"]',ARIA_CURRENT:"aria-current",ARIA_DISABLED:"aria-disabled",ARIA_ORIENTATION:"aria-orientation",ARIA_ORIENTATION_HORIZONTAL:"horizontal",ARIA_ROLE_CHECKBOX_SELECTOR:'[role="checkbox"]',ARIA_SELECTED:"aria-selected",ARIA_INTERACTIVE_ROLES_SELECTOR:'[role="listbox"], [role="menu"]',ARIA_MULTI_SELECTABLE_SELECTOR:'[aria-multiselectable="true"]',CHECKBOX_RADIO_SELECTOR:'input[type="checkbox"], input[type="radio"]',CHECKBOX_SELECTOR:'input[type="checkbox"]',CHILD_ELEMENTS_TO_TOGGLE_TABINDEX:"\n ."+Ye+" button:not(:disabled),\n ."+Ye+" a,\n ."+ti[Ye]+" button:not(:disabled),\n ."+ti[Ye]+" a\n ",DEPRECATED_SELECTOR:".mdc-deprecated-list",FOCUSABLE_CHILD_ELEMENTS:"\n ."+Ye+" button:not(:disabled),\n ."+Ye+" a,\n ."+Ye+' input[type="radio"]:not(:disabled),\n .'+Ye+' input[type="checkbox"]:not(:disabled),\n .'+ti[Ye]+" button:not(:disabled),\n ."+ti[Ye]+" a,\n ."+ti[Ye]+' input[type="radio"]:not(:disabled),\n .'+ti[Ye]+' input[type="checkbox"]:not(:disabled)\n ',RADIO_SELECTOR:'input[type="radio"]',SELECTED_ITEM_SELECTOR:'[aria-selected="true"], [aria-current="true"]'},ii={UNSET_INDEX:-1,TYPEAHEAD_BUFFER_CLEAR_TIMEOUT_MS:300},ni=["input","button","textarea","select"],oi=function(t){var e=t.target;if(e){var i=(""+e.tagName).toLowerCase();-1===ni.indexOf(i)&&t.preventDefault()}};function ri(t,e){for(var i=new Map,n=0;ne&&!i(r[a].index)){d=a;break}if(-1!==d)return n.sortedIndexCursor=d,r[n.sortedIndexCursor].index;return-1}(r,s,d,e):function(t,e,i){var n=i.typeaheadBuffer[0],o=t.get(n);if(!o)return-1;var r=o[i.sortedIndexCursor];if(0===r.text.lastIndexOf(i.typeaheadBuffer,0)&&!e(r.index))return r.index;var s=(i.sortedIndexCursor+1)%o.length,a=-1;for(;s!==i.sortedIndexCursor;){var d=o[s],l=0===d.text.lastIndexOf(i.typeaheadBuffer,0),c=!e(d.index);if(l&&c){a=s;break}s=(s+1)%o.length}if(-1!==a)return i.sortedIndexCursor=a,o[i.sortedIndexCursor].index;return-1}(r,d,e),-1===i||a||o(i),i}function ai(t){return t.typeaheadBuffer.length>0} -/** - * @license - * Copyright 2016 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -var di={LABEL_FLOAT_ABOVE:"mdc-floating-label--float-above",LABEL_REQUIRED:"mdc-floating-label--required",LABEL_SHAKE:"mdc-floating-label--shake",ROOT:"mdc-floating-label"},li=function(t){function e(i){var o=t.call(this,n(n({},e.defaultAdapter),i))||this;return o.shakeAnimationEndHandler=function(){o.handleShakeAnimationEnd()},o}return i(e,t),Object.defineProperty(e,"cssClasses",{get:function(){return di},enumerable:!1,configurable:!0}),Object.defineProperty(e,"defaultAdapter",{get:function(){return{addClass:function(){},removeClass:function(){},getWidth:function(){return 0},registerInteractionHandler:function(){},deregisterInteractionHandler:function(){}}},enumerable:!1,configurable:!0}),e.prototype.init=function(){this.adapter.registerInteractionHandler("animationend",this.shakeAnimationEndHandler)},e.prototype.destroy=function(){this.adapter.deregisterInteractionHandler("animationend",this.shakeAnimationEndHandler)},e.prototype.getWidth=function(){return this.adapter.getWidth()},e.prototype.shake=function(t){var i=e.cssClasses.LABEL_SHAKE;t?this.adapter.addClass(i):this.adapter.removeClass(i)},e.prototype.float=function(t){var i=e.cssClasses,n=i.LABEL_FLOAT_ABOVE,o=i.LABEL_SHAKE;t?this.adapter.addClass(n):(this.adapter.removeClass(n),this.adapter.removeClass(o))},e.prototype.setRequired=function(t){var i=e.cssClasses.LABEL_REQUIRED;t?this.adapter.addClass(i):this.adapter.removeClass(i)},e.prototype.handleShakeAnimationEnd=function(){var t=e.cssClasses.LABEL_SHAKE;this.adapter.removeClass(t)},e}(ee); -/** - * @license - * Copyright 2016 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */const ci=xe(class extends _e{constructor(t){switch(super(t),this.foundation=null,this.previousPart=null,t.type){case ge:case ye:break;default:throw new Error("FloatingLabel directive only support attribute and property parts")}}update(t,[e]){if(t!==this.previousPart){this.foundation&&this.foundation.destroy(),this.previousPart=t;const e=t.element;e.classList.add("mdc-floating-label");const i=(t=>({addClass:e=>t.classList.add(e),removeClass:e=>t.classList.remove(e),getWidth:()=>t.scrollWidth,registerInteractionHandler:(e,i)=>{t.addEventListener(e,i)},deregisterInteractionHandler:(e,i)=>{t.removeEventListener(e,i)}}))(e);this.foundation=new li(i),this.foundation.init()}return this.render(e)}render(t){return this.foundation}}); -/** - * @license - * Copyright 2018 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */var hi={LINE_RIPPLE_ACTIVE:"mdc-line-ripple--active",LINE_RIPPLE_DEACTIVATING:"mdc-line-ripple--deactivating"},ui=function(t){function e(i){var o=t.call(this,n(n({},e.defaultAdapter),i))||this;return o.transitionEndHandler=function(t){o.handleTransitionEnd(t)},o}return i(e,t),Object.defineProperty(e,"cssClasses",{get:function(){return hi},enumerable:!1,configurable:!0}),Object.defineProperty(e,"defaultAdapter",{get:function(){return{addClass:function(){},removeClass:function(){},hasClass:function(){return!1},setStyle:function(){},registerEventHandler:function(){},deregisterEventHandler:function(){}}},enumerable:!1,configurable:!0}),e.prototype.init=function(){this.adapter.registerEventHandler("transitionend",this.transitionEndHandler)},e.prototype.destroy=function(){this.adapter.deregisterEventHandler("transitionend",this.transitionEndHandler)},e.prototype.activate=function(){this.adapter.removeClass(hi.LINE_RIPPLE_DEACTIVATING),this.adapter.addClass(hi.LINE_RIPPLE_ACTIVE)},e.prototype.setRippleCenter=function(t){this.adapter.setStyle("transform-origin",t+"px center")},e.prototype.deactivate=function(){this.adapter.addClass(hi.LINE_RIPPLE_DEACTIVATING)},e.prototype.handleTransitionEnd=function(t){var e=this.adapter.hasClass(hi.LINE_RIPPLE_DEACTIVATING);"opacity"===t.propertyName&&e&&(this.adapter.removeClass(hi.LINE_RIPPLE_ACTIVE),this.adapter.removeClass(hi.LINE_RIPPLE_DEACTIVATING))},e}(ee); -/** - * @license - * Copyright 2018 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */const pi=xe(class extends _e{constructor(t){switch(super(t),this.previousPart=null,this.foundation=null,t.type){case ge:case ye:return;default:throw new Error("LineRipple only support attribute and property parts.")}}update(t,e){if(this.previousPart!==t){this.foundation&&this.foundation.destroy(),this.previousPart=t;const e=t.element;e.classList.add("mdc-line-ripple");const i=(t=>({addClass:e=>t.classList.add(e),removeClass:e=>t.classList.remove(e),hasClass:e=>t.classList.contains(e),setStyle:(e,i)=>t.style.setProperty(e,i),registerEventHandler:(e,i)=>{t.addEventListener(e,i)},deregisterEventHandler:(e,i)=>{t.removeEventListener(e,i)}}))(e);this.foundation=new ui(i),this.foundation.init()}return this.render()}render(){return this.foundation}}); -/** - * @license - * Copyright 2018 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */var fi,mi,vi={ANCHOR:"mdc-menu-surface--anchor",ANIMATING_CLOSED:"mdc-menu-surface--animating-closed",ANIMATING_OPEN:"mdc-menu-surface--animating-open",FIXED:"mdc-menu-surface--fixed",IS_OPEN_BELOW:"mdc-menu-surface--is-open-below",OPEN:"mdc-menu-surface--open",ROOT:"mdc-menu-surface"},gi={CLOSED_EVENT:"MDCMenuSurface:closed",CLOSING_EVENT:"MDCMenuSurface:closing",OPENED_EVENT:"MDCMenuSurface:opened",OPENING_EVENT:"MDCMenuSurface:opening",FOCUSABLE_ELEMENTS:["button:not(:disabled)",'[href]:not([aria-disabled="true"])',"input:not(:disabled)","select:not(:disabled)","textarea:not(:disabled)",'[tabindex]:not([tabindex="-1"]):not([aria-disabled="true"])'].join(", ")},yi={TRANSITION_OPEN_DURATION:120,TRANSITION_CLOSE_DURATION:75,MARGIN_TO_EDGE:32,ANCHOR_TO_MENU_SURFACE_WIDTH_RATIO:.67,TOUCH_EVENT_WAIT_MS:30};!function(t){t[t.BOTTOM=1]="BOTTOM",t[t.CENTER=2]="CENTER",t[t.RIGHT=4]="RIGHT",t[t.FLIP_RTL=8]="FLIP_RTL"}(fi||(fi={})),function(t){t[t.TOP_LEFT=0]="TOP_LEFT",t[t.TOP_RIGHT=4]="TOP_RIGHT",t[t.BOTTOM_LEFT=1]="BOTTOM_LEFT",t[t.BOTTOM_RIGHT=5]="BOTTOM_RIGHT",t[t.TOP_START=8]="TOP_START",t[t.TOP_END=12]="TOP_END",t[t.BOTTOM_START=9]="BOTTOM_START",t[t.BOTTOM_END=13]="BOTTOM_END"}(mi||(mi={})); -/** - * @license - * Copyright 2016 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -var bi={ACTIVATED:"mdc-select--activated",DISABLED:"mdc-select--disabled",FOCUSED:"mdc-select--focused",INVALID:"mdc-select--invalid",MENU_INVALID:"mdc-select__menu--invalid",OUTLINED:"mdc-select--outlined",REQUIRED:"mdc-select--required",ROOT:"mdc-select",WITH_LEADING_ICON:"mdc-select--with-leading-icon"},xi={ARIA_CONTROLS:"aria-controls",ARIA_DESCRIBEDBY:"aria-describedby",ARIA_SELECTED_ATTR:"aria-selected",CHANGE_EVENT:"MDCSelect:change",HIDDEN_INPUT_SELECTOR:'input[type="hidden"]',LABEL_SELECTOR:".mdc-floating-label",LEADING_ICON_SELECTOR:".mdc-select__icon",LINE_RIPPLE_SELECTOR:".mdc-line-ripple",MENU_SELECTOR:".mdc-select__menu",OUTLINE_SELECTOR:".mdc-notched-outline",SELECTED_TEXT_SELECTOR:".mdc-select__selected-text",SELECT_ANCHOR_SELECTOR:".mdc-select__anchor",VALUE_ATTR:"data-value"},_i={LABEL_SCALE:.75,UNSET_INDEX:-1,CLICK_DEBOUNCE_TIMEOUT_MS:330},wi=function(t){function e(i,o){void 0===o&&(o={});var r=t.call(this,n(n({},e.defaultAdapter),i))||this;return r.disabled=!1,r.isMenuOpen=!1,r.useDefaultValidation=!0,r.customValidity=!0,r.lastSelectedIndex=_i.UNSET_INDEX,r.clickDebounceTimeout=0,r.recentlyClicked=!1,r.leadingIcon=o.leadingIcon,r.helperText=o.helperText,r}return i(e,t),Object.defineProperty(e,"cssClasses",{get:function(){return bi},enumerable:!1,configurable:!0}),Object.defineProperty(e,"numbers",{get:function(){return _i},enumerable:!1,configurable:!0}),Object.defineProperty(e,"strings",{get:function(){return xi},enumerable:!1,configurable:!0}),Object.defineProperty(e,"defaultAdapter",{get:function(){return{addClass:function(){},removeClass:function(){},hasClass:function(){return!1},activateBottomLine:function(){},deactivateBottomLine:function(){},getSelectedIndex:function(){return-1},setSelectedIndex:function(){},hasLabel:function(){return!1},floatLabel:function(){},getLabelWidth:function(){return 0},setLabelRequired:function(){},hasOutline:function(){return!1},notchOutline:function(){},closeOutline:function(){},setRippleCenter:function(){},notifyChange:function(){},setSelectedText:function(){},isSelectAnchorFocused:function(){return!1},getSelectAnchorAttr:function(){return""},setSelectAnchorAttr:function(){},removeSelectAnchorAttr:function(){},addMenuClass:function(){},removeMenuClass:function(){},openMenu:function(){},closeMenu:function(){},getAnchorElement:function(){return null},setMenuAnchorElement:function(){},setMenuAnchorCorner:function(){},setMenuWrapFocus:function(){},focusMenuItemAtIndex:function(){},getMenuItemCount:function(){return 0},getMenuItemValues:function(){return[]},getMenuItemTextAtIndex:function(){return""},isTypeaheadInProgress:function(){return!1},typeaheadMatchItem:function(){return-1}}},enumerable:!1,configurable:!0}),e.prototype.getSelectedIndex=function(){return this.adapter.getSelectedIndex()},e.prototype.setSelectedIndex=function(t,e,i){void 0===e&&(e=!1),void 0===i&&(i=!1),t>=this.adapter.getMenuItemCount()||(t===_i.UNSET_INDEX?this.adapter.setSelectedText(""):this.adapter.setSelectedText(this.adapter.getMenuItemTextAtIndex(t).trim()),this.adapter.setSelectedIndex(t),e&&this.adapter.closeMenu(),i||this.lastSelectedIndex===t||this.handleChange(),this.lastSelectedIndex=t)},e.prototype.setValue=function(t,e){void 0===e&&(e=!1);var i=this.adapter.getMenuItemValues().indexOf(t);this.setSelectedIndex(i,!1,e)},e.prototype.getValue=function(){var t=this.adapter.getSelectedIndex(),e=this.adapter.getMenuItemValues();return t!==_i.UNSET_INDEX?e[t]:""},e.prototype.getDisabled=function(){return this.disabled},e.prototype.setDisabled=function(t){this.disabled=t,this.disabled?(this.adapter.addClass(bi.DISABLED),this.adapter.closeMenu()):this.adapter.removeClass(bi.DISABLED),this.leadingIcon&&this.leadingIcon.setDisabled(this.disabled),this.disabled?this.adapter.removeSelectAnchorAttr("tabindex"):this.adapter.setSelectAnchorAttr("tabindex","0"),this.adapter.setSelectAnchorAttr("aria-disabled",this.disabled.toString())},e.prototype.openMenu=function(){this.adapter.addClass(bi.ACTIVATED),this.adapter.openMenu(),this.isMenuOpen=!0,this.adapter.setSelectAnchorAttr("aria-expanded","true")},e.prototype.setHelperTextContent=function(t){this.helperText&&this.helperText.setContent(t)},e.prototype.layout=function(){if(this.adapter.hasLabel()){var t=this.getValue().length>0,e=this.adapter.hasClass(bi.FOCUSED),i=t||e,n=this.adapter.hasClass(bi.REQUIRED);this.notchOutline(i),this.adapter.floatLabel(i),this.adapter.setLabelRequired(n)}},e.prototype.layoutOptions=function(){var t=this.adapter.getMenuItemValues().indexOf(this.getValue());this.setSelectedIndex(t,!1,!0)},e.prototype.handleMenuOpened=function(){if(0!==this.adapter.getMenuItemValues().length){var t=this.getSelectedIndex(),e=t>=0?t:0;this.adapter.focusMenuItemAtIndex(e)}},e.prototype.handleMenuClosing=function(){this.adapter.setSelectAnchorAttr("aria-expanded","false")},e.prototype.handleMenuClosed=function(){this.adapter.removeClass(bi.ACTIVATED),this.isMenuOpen=!1,this.adapter.isSelectAnchorFocused()||this.blur()},e.prototype.handleChange=function(){this.layout(),this.adapter.notifyChange(this.getValue()),this.adapter.hasClass(bi.REQUIRED)&&this.useDefaultValidation&&this.setValid(this.isValid())},e.prototype.handleMenuItemAction=function(t){this.setSelectedIndex(t,!0)},e.prototype.handleFocus=function(){this.adapter.addClass(bi.FOCUSED),this.layout(),this.adapter.activateBottomLine()},e.prototype.handleBlur=function(){this.isMenuOpen||this.blur()},e.prototype.handleClick=function(t){this.disabled||this.recentlyClicked||(this.setClickDebounceTimeout(),this.isMenuOpen?this.adapter.closeMenu():(this.adapter.setRippleCenter(t),this.openMenu()))},e.prototype.handleKeydown=function(t){if(!this.isMenuOpen&&this.adapter.hasClass(bi.FOCUSED)){var e=qe(t)===Ce.ENTER,i=qe(t)===Ce.SPACEBAR,n=qe(t)===Ce.ARROW_UP,o=qe(t)===Ce.ARROW_DOWN;if(!(t.ctrlKey||t.metaKey)&&(!i&&t.key&&1===t.key.length||i&&this.adapter.isTypeaheadInProgress())){var r=i?" ":t.key,s=this.adapter.typeaheadMatchItem(r,this.getSelectedIndex());return s>=0&&this.setSelectedIndex(s),void t.preventDefault()}(e||i||n||o)&&(this.openMenu(),t.preventDefault())}},e.prototype.notchOutline=function(t){if(this.adapter.hasOutline()){var e=this.adapter.hasClass(bi.FOCUSED);if(t){var i=_i.LABEL_SCALE,n=this.adapter.getLabelWidth()*i;this.adapter.notchOutline(n)}else e||this.adapter.closeOutline()}},e.prototype.setLeadingIconAriaLabel=function(t){this.leadingIcon&&this.leadingIcon.setAriaLabel(t)},e.prototype.setLeadingIconContent=function(t){this.leadingIcon&&this.leadingIcon.setContent(t)},e.prototype.getUseDefaultValidation=function(){return this.useDefaultValidation},e.prototype.setUseDefaultValidation=function(t){this.useDefaultValidation=t},e.prototype.setValid=function(t){this.useDefaultValidation||(this.customValidity=t),this.adapter.setSelectAnchorAttr("aria-invalid",(!t).toString()),t?(this.adapter.removeClass(bi.INVALID),this.adapter.removeMenuClass(bi.MENU_INVALID)):(this.adapter.addClass(bi.INVALID),this.adapter.addMenuClass(bi.MENU_INVALID)),this.syncHelperTextValidity(t)},e.prototype.isValid=function(){return this.useDefaultValidation&&this.adapter.hasClass(bi.REQUIRED)&&!this.adapter.hasClass(bi.DISABLED)?this.getSelectedIndex()!==_i.UNSET_INDEX&&(0!==this.getSelectedIndex()||Boolean(this.getValue())):this.customValidity},e.prototype.setRequired=function(t){t?this.adapter.addClass(bi.REQUIRED):this.adapter.removeClass(bi.REQUIRED),this.adapter.setSelectAnchorAttr("aria-required",t.toString()),this.adapter.setLabelRequired(t)},e.prototype.getRequired=function(){return"true"===this.adapter.getSelectAnchorAttr("aria-required")},e.prototype.init=function(){var t=this.adapter.getAnchorElement();t&&(this.adapter.setMenuAnchorElement(t),this.adapter.setMenuAnchorCorner(mi.BOTTOM_START)),this.adapter.setMenuWrapFocus(!1),this.setDisabled(this.adapter.hasClass(bi.DISABLED)),this.syncHelperTextValidity(!this.adapter.hasClass(bi.INVALID)),this.layout(),this.layoutOptions()},e.prototype.blur=function(){this.adapter.removeClass(bi.FOCUSED),this.layout(),this.adapter.deactivateBottomLine(),this.adapter.hasClass(bi.REQUIRED)&&this.useDefaultValidation&&this.setValid(this.isValid())},e.prototype.syncHelperTextValidity=function(t){if(this.helperText){this.helperText.setValidity(t);var e=this.helperText.isVisible(),i=this.helperText.getId();e&&i?this.adapter.setSelectAnchorAttr(xi.ARIA_DESCRIBEDBY,i):this.adapter.removeSelectAnchorAttr(xi.ARIA_DESCRIBEDBY)}},e.prototype.setClickDebounceTimeout=function(){var t=this;clearTimeout(this.clickDebounceTimeout),this.clickDebounceTimeout=setTimeout((function(){t.recentlyClicked=!1}),_i.CLICK_DEBOUNCE_TIMEOUT_MS),this.recentlyClicked=!0},e}(ee); -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const Ei=t=>null!=t?t:W -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */,ki=(t={})=>{const e={};for(const i in t)e[i]=t[i];return Object.assign({badInput:!1,customError:!1,patternMismatch:!1,rangeOverflow:!1,rangeUnderflow:!1,stepMismatch:!1,tooLong:!1,tooShort:!1,typeMismatch:!1,valid:!0,valueMissing:!1},e)};class Oi extends me{constructor(){super(...arguments),this.mdcFoundationClass=wi,this.disabled=!1,this.outlined=!1,this.label="",this.outlineOpen=!1,this.outlineWidth=0,this.value="",this.name="",this.selectedText="",this.icon="",this.menuOpen=!1,this.helper="",this.validateOnInitialRender=!1,this.validationMessage="",this.required=!1,this.naturalMenuWidth=!1,this.isUiValid=!0,this.fixedMenuPosition=!1,this.typeaheadState={bufferClearTimeout:0,currentFirstChar:"",sortedIndexCursor:0,typeaheadBuffer:""},this.sortedIndexByFirstChar=new Map,this.menuElement_=null,this.listeners=[],this.onBodyClickBound=()=>{},this._menuUpdateComplete=null,this.valueSetDirectly=!1,this.validityTransform=null,this._validity=ki()}get items(){return this.menuElement_||(this.menuElement_=this.menuElement),this.menuElement_?this.menuElement_.items:[]}get selected(){const t=this.menuElement;return t?t.selected:null}get index(){const t=this.menuElement;return t?t.index:-1}get shouldRenderHelperText(){return!!this.helper||!!this.validationMessage}get validity(){return this._checkValidity(this.value),this._validity}render(){const t={"mdc-select--disabled":this.disabled,"mdc-select--no-label":!this.label,"mdc-select--filled":!this.outlined,"mdc-select--outlined":this.outlined,"mdc-select--with-leading-icon":!!this.icon,"mdc-select--required":this.required,"mdc-select--invalid":!this.isUiValid},e=this.label?"label":void 0,i=this.shouldRenderHelperText?"helper-text":void 0;return $` -
- - -
- ${this.renderRipple()} - ${this.outlined?this.renderOutline():this.renderLabel()} - ${this.renderLeadingIcon()} - - ${this.selectedText} - - - - - - - - - - ${this.renderLineRipple()} -
- ${this.renderMenu()} -
- ${this.renderHelperText()}`}renderMenu(){const t=this.getMenuClasses();return $` - - ${this.renderMenuContent()} - `}getMenuClasses(){return{"mdc-select__menu":!0,"mdc-menu":!0,"mdc-menu-surface":!0,"mdc-select__menu--invalid":!this.isUiValid}}renderMenuContent(){return $``}renderRipple(){return this.outlined?W:$` - - `}renderOutline(){return this.outlined?$` - - ${this.renderLabel()} - `:W}renderLabel(){return this.label?$` - ${this.label} - `:W}renderLeadingIcon(){return this.icon?$`
${this.icon}
`:W}renderLineRipple(){return this.outlined?W:$` - - `}renderHelperText(){if(!this.shouldRenderHelperText)return W;const t=this.validationMessage&&!this.isUiValid;return $` -

${t?this.validationMessage:this.helper}

`}createAdapter(){return Object.assign(Object.assign({},se(this.mdcRoot)),{activateBottomLine:()=>{this.lineRippleElement&&this.lineRippleElement.lineRippleFoundation.activate()},deactivateBottomLine:()=>{this.lineRippleElement&&this.lineRippleElement.lineRippleFoundation.deactivate()},hasLabel:()=>!!this.label,floatLabel:t=>{this.labelElement&&this.labelElement.floatingLabelFoundation.float(t)},getLabelWidth:()=>this.labelElement?this.labelElement.floatingLabelFoundation.getWidth():0,setLabelRequired:t=>{this.labelElement&&this.labelElement.floatingLabelFoundation.setRequired(t)},hasOutline:()=>this.outlined,notchOutline:t=>{this.outlineElement&&!this.outlineOpen&&(this.outlineWidth=t,this.outlineOpen=!0)},closeOutline:()=>{this.outlineElement&&(this.outlineOpen=!1)},setRippleCenter:t=>{if(this.lineRippleElement){this.lineRippleElement.lineRippleFoundation.setRippleCenter(t)}},notifyChange:async t=>{if(!this.valueSetDirectly&&t===this.value)return;this.valueSetDirectly=!1,this.value=t,await this.updateComplete;const e=new Event("change",{bubbles:!0});this.dispatchEvent(e)},setSelectedText:t=>this.selectedText=t,isSelectAnchorFocused:()=>{const t=this.anchorElement;if(!t)return!1;return t.getRootNode().activeElement===t},getSelectAnchorAttr:t=>{const e=this.anchorElement;return e?e.getAttribute(t):null},setSelectAnchorAttr:(t,e)=>{const i=this.anchorElement;i&&i.setAttribute(t,e)},removeSelectAnchorAttr:t=>{const e=this.anchorElement;e&&e.removeAttribute(t)},openMenu:()=>{this.menuOpen=!0},closeMenu:()=>{this.menuOpen=!1},addMenuClass:()=>{},removeMenuClass:()=>{},getAnchorElement:()=>this.anchorElement,setMenuAnchorElement:()=>{},setMenuAnchorCorner:()=>{const t=this.menuElement;t&&(t.corner="BOTTOM_START")},setMenuWrapFocus:t=>{const e=this.menuElement;e&&(e.wrapFocus=t)},focusMenuItemAtIndex:t=>{const e=this.menuElement;if(!e)return;const i=e.items[t];i&&i.focus()},getMenuItemCount:()=>{const t=this.menuElement;return t?t.items.length:0},getMenuItemValues:()=>{const t=this.menuElement;if(!t)return[];return t.items.map((t=>t.value))},getMenuItemTextAtIndex:t=>{const e=this.menuElement;if(!e)return"";const i=e.items[t];return i?i.text:""},getSelectedIndex:()=>this.index,setSelectedIndex:()=>{},isTypeaheadInProgress:()=>ai(this.typeaheadState),typeaheadMatchItem:(t,e)=>{if(!this.menuElement)return-1;const i={focusItemAtIndex:t=>{this.menuElement.focusItemAtIndex(t)},focusedItemIndex:e||this.menuElement.getFocusedItemIndex(),nextChar:t,sortedIndexByFirstChar:this.sortedIndexByFirstChar,skipFocus:!1,isItemAtIndexDisabled:t=>this.items[t].disabled},n=si(i,this.typeaheadState);return-1!==n&&this.select(n),n}})}checkValidity(){const t=this._checkValidity(this.value);if(!t){const t=new Event("invalid",{bubbles:!1,cancelable:!0});this.dispatchEvent(t)}return t}reportValidity(){const t=this.checkValidity();return this.isUiValid=t,t}_checkValidity(t){const e=this.formElement.validity;let i=ki(e);if(this.validityTransform){const e=this.validityTransform(t,i);i=Object.assign(Object.assign({},i),e)}return this._validity=i,this._validity.valid}setCustomValidity(t){this.validationMessage=t,this.formElement.setCustomValidity(t)}async getUpdateComplete(){await this._menuUpdateComplete;return await super.getUpdateComplete()}async firstUpdated(){const t=this.menuElement;if(t&&(this._menuUpdateComplete=t.updateComplete,await this._menuUpdateComplete),super.firstUpdated(),this.mdcFoundation.isValid=()=>!0,this.mdcFoundation.setValid=()=>{},this.mdcFoundation.setDisabled(this.disabled),this.validateOnInitialRender&&this.reportValidity(),!this.selected){!this.items.length&&this.slotElement&&this.slotElement.assignedNodes({flatten:!0}).length&&(await new Promise((t=>requestAnimationFrame(t))),await this.layout());const t=this.items.length&&""===this.items[0].value;if(!this.value&&t)return void this.select(0);this.selectByValue(this.value)}this.sortedIndexByFirstChar=ri(this.items.length,(t=>this.items[t].text))}onItemsUpdated(){this.sortedIndexByFirstChar=ri(this.items.length,(t=>this.items[t].text))}select(t){const e=this.menuElement;e&&e.select(t)}selectByValue(t){let e=-1;for(let i=0;i0,o=i&&this.index{this.menuElement.focusItemAtIndex(t)},focusedItemIndex:e,isTargetListItem:!!i&&i.hasAttribute("mwc-list-item"),sortedIndexByFirstChar:this.sortedIndexByFirstChar,isItemAtIndexDisabled:t=>this.items[t].disabled};!function(t,e){var i=t.event,n=t.isTargetListItem,o=t.focusedItemIndex,r=t.focusItemAtIndex,s=t.sortedIndexByFirstChar,a=t.isItemAtIndexDisabled,d="ArrowLeft"===qe(i),l="ArrowUp"===qe(i),c="ArrowRight"===qe(i),h="ArrowDown"===qe(i),u="Home"===qe(i),p="End"===qe(i),f="Enter"===qe(i),m="Spacebar"===qe(i);i.altKey||i.ctrlKey||i.metaKey||d||l||c||h||u||p||f||(m||1!==i.key.length?m&&(n&&oi(i),n&&ai(e)&&si({focusItemAtIndex:r,focusedItemIndex:o,nextChar:" ",sortedIndexByFirstChar:s,skipFocus:!1,isItemAtIndexDisabled:a},e)):(oi(i),si({focusItemAtIndex:r,focusedItemIndex:o,nextChar:i.key.toLowerCase(),sortedIndexByFirstChar:s,skipFocus:!1,isItemAtIndexDisabled:a},e)))}(n,this.typeaheadState)}async onSelected(t){this.mdcFoundation||await this.updateComplete,this.mdcFoundation.handleMenuItemAction(t.detail.index);const e=this.items[t.detail.index];e&&(this.value=e.value)}onOpened(){this.mdcFoundation&&(this.menuOpen=!0,this.mdcFoundation.handleMenuOpened())}onClosed(){this.mdcFoundation&&(this.menuOpen=!1,this.mdcFoundation.handleMenuClosed())}setFormData(t){this.name&&null!==this.selected&&t.append(this.name,this.value)}async layout(t=!0){this.mdcFoundation&&this.mdcFoundation.layout(),await this.updateComplete;const e=this.menuElement;e&&e.layout(t);const i=this.labelElement;if(!i)return void(this.outlineOpen=!1);const n=!!this.label&&!!this.value;if(i.floatingLabelFoundation.float(n),!this.outlined)return;this.outlineOpen=n,await this.updateComplete;const o=i.floatingLabelFoundation.getWidth();this.outlineOpen&&(this.outlineWidth=o)}async layoutOptions(){this.mdcFoundation&&this.mdcFoundation.layoutOptions()}}o([Mt(".mdc-select")],Oi.prototype,"mdcRoot",void 0),o([Mt(".formElement")],Oi.prototype,"formElement",void 0),o([Mt("slot")],Oi.prototype,"slotElement",void 0),o([Mt("select")],Oi.prototype,"nativeSelectElement",void 0),o([Mt("input")],Oi.prototype,"nativeInputElement",void 0),o([Mt(".mdc-line-ripple")],Oi.prototype,"lineRippleElement",void 0),o([Mt(".mdc-floating-label")],Oi.prototype,"labelElement",void 0),o([Mt("mwc-notched-outline")],Oi.prototype,"outlineElement",void 0),o([Mt(".mdc-menu")],Oi.prototype,"menuElement",void 0),o([Mt(".mdc-select__anchor")],Oi.prototype,"anchorElement",void 0),o([At({type:Boolean,attribute:"disabled",reflect:!0}),ve((function(t){this.mdcFoundation&&this.mdcFoundation.setDisabled(t)}))],Oi.prototype,"disabled",void 0),o([At({type:Boolean}),ve((function(t,e){void 0!==e&&this.outlined!==e&&this.layout(!1)}))],Oi.prototype,"outlined",void 0),o([At({type:String}),ve((function(t,e){void 0!==e&&this.label!==e&&this.layout(!1)}))],Oi.prototype,"label",void 0),o([Rt()],Oi.prototype,"outlineOpen",void 0),o([Rt()],Oi.prototype,"outlineWidth",void 0),o([At({type:String}),ve((function(t){if(this.mdcFoundation){const e=null===this.selected&&!!t,i=this.selected&&this.selected.value!==t;(e||i)&&this.selectByValue(t),this.reportValidity()}}))],Oi.prototype,"value",void 0),o([At()],Oi.prototype,"name",void 0),o([Rt()],Oi.prototype,"selectedText",void 0),o([At({type:String})],Oi.prototype,"icon",void 0),o([Rt()],Oi.prototype,"menuOpen",void 0),o([At({type:String})],Oi.prototype,"helper",void 0),o([At({type:Boolean})],Oi.prototype,"validateOnInitialRender",void 0),o([At({type:String})],Oi.prototype,"validationMessage",void 0),o([At({type:Boolean})],Oi.prototype,"required",void 0),o([At({type:Boolean})],Oi.prototype,"naturalMenuWidth",void 0),o([Rt()],Oi.prototype,"isUiValid",void 0),o([At({type:Boolean})],Oi.prototype,"fixedMenuPosition",void 0),o([Dt({capture:!0})],Oi.prototype,"handleTypeahead",null); -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -const Ci=(t,e)=>t-e,Si=["input","button","textarea","select"];function Ti(t){return t instanceof Set}const Ii=t=>{const e=t===ii.UNSET_INDEX?new Set:t;return Ti(e)?new Set(e):new Set([e])};class Ai extends ee{constructor(t){super(Object.assign(Object.assign({},Ai.defaultAdapter),t)),this.isMulti_=!1,this.wrapFocus_=!1,this.isVertical_=!0,this.selectedIndex_=ii.UNSET_INDEX,this.focusedItemIndex_=ii.UNSET_INDEX,this.useActivatedClass_=!1,this.ariaCurrentAttrValue_=null}static get strings(){return ei}static get numbers(){return ii}static get defaultAdapter(){return{focusItemAtIndex:()=>{},getFocusedElementIndex:()=>0,getListItemCount:()=>0,isFocusInsideList:()=>!1,isRootFocused:()=>!1,notifyAction:()=>{},notifySelected:()=>{},getSelectedStateForElementIndex:()=>!1,setDisabledStateForElementIndex:()=>{},getDisabledStateForElementIndex:()=>!1,setSelectedStateForElementIndex:()=>{},setActivatedStateForElementIndex:()=>{},setTabIndexForElementIndex:()=>{},setAttributeForElementIndex:()=>{},getAttributeForElementIndex:()=>null}}setWrapFocus(t){this.wrapFocus_=t}setMulti(t){this.isMulti_=t;const e=this.selectedIndex_;if(t){if(!Ti(e)){const t=e===ii.UNSET_INDEX;this.selectedIndex_=t?new Set:new Set([e])}}else if(Ti(e))if(e.size){const t=Array.from(e).sort(Ci);this.selectedIndex_=t[0]}else this.selectedIndex_=ii.UNSET_INDEX}setVerticalOrientation(t){this.isVertical_=t}setUseActivatedClass(t){this.useActivatedClass_=t}getSelectedIndex(){return this.selectedIndex_}setSelectedIndex(t){this.isIndexValid_(t)&&(this.isMulti_?this.setMultiSelectionAtIndex_(Ii(t)):this.setSingleSelectionAtIndex_(t))}handleFocusIn(t,e){e>=0&&this.adapter.setTabIndexForElementIndex(e,0)}handleFocusOut(t,e){e>=0&&this.adapter.setTabIndexForElementIndex(e,-1),setTimeout((()=>{this.adapter.isFocusInsideList()||this.setTabindexToFirstSelectedItem_()}),0)}handleKeydown(t,e,i){const n="ArrowLeft"===qe(t),o="ArrowUp"===qe(t),r="ArrowRight"===qe(t),s="ArrowDown"===qe(t),a="Home"===qe(t),d="End"===qe(t),l="Enter"===qe(t),c="Spacebar"===qe(t);if(this.adapter.isRootFocused())return void(o||d?(t.preventDefault(),this.focusLastElement()):(s||a)&&(t.preventDefault(),this.focusFirstElement()));let h,u=this.adapter.getFocusedElementIndex();if(!(-1===u&&(u=i,u<0))){if(this.isVertical_&&s||!this.isVertical_&&r)this.preventDefaultEvent(t),h=this.focusNextElement(u);else if(this.isVertical_&&o||!this.isVertical_&&n)this.preventDefaultEvent(t),h=this.focusPrevElement(u);else if(a)this.preventDefaultEvent(t),h=this.focusFirstElement();else if(d)this.preventDefaultEvent(t),h=this.focusLastElement();else if((l||c)&&e){const e=t.target;if(e&&"A"===e.tagName&&l)return;this.preventDefaultEvent(t),this.setSelectedIndexOnAction_(u,!0)}this.focusedItemIndex_=u,void 0!==h&&(this.setTabindexAtIndex_(h),this.focusedItemIndex_=h)}}handleSingleSelection(t,e,i){t!==ii.UNSET_INDEX&&(this.setSelectedIndexOnAction_(t,e,i),this.setTabindexAtIndex_(t),this.focusedItemIndex_=t)}focusNextElement(t){let e=t+1;if(e>=this.adapter.getListItemCount()){if(!this.wrapFocus_)return t;e=0}return this.adapter.focusItemAtIndex(e),e}focusPrevElement(t){let e=t-1;if(e<0){if(!this.wrapFocus_)return t;e=this.adapter.getListItemCount()-1}return this.adapter.focusItemAtIndex(e),e}focusFirstElement(){return this.adapter.focusItemAtIndex(0),0}focusLastElement(){const t=this.adapter.getListItemCount()-1;return this.adapter.focusItemAtIndex(t),t}setEnabled(t,e){this.isIndexValid_(t)&&this.adapter.setDisabledStateForElementIndex(t,!e)}preventDefaultEvent(t){const e=`${t.target.tagName}`.toLowerCase();-1===Si.indexOf(e)&&t.preventDefault()}setSingleSelectionAtIndex_(t,e=!0){this.selectedIndex_!==t&&(this.selectedIndex_!==ii.UNSET_INDEX&&(this.adapter.setSelectedStateForElementIndex(this.selectedIndex_,!1),this.useActivatedClass_&&this.adapter.setActivatedStateForElementIndex(this.selectedIndex_,!1)),e&&this.adapter.setSelectedStateForElementIndex(t,!0),this.useActivatedClass_&&this.adapter.setActivatedStateForElementIndex(t,!0),this.setAriaForSingleSelectionAtIndex_(t),this.selectedIndex_=t,this.adapter.notifySelected(t))}setMultiSelectionAtIndex_(t,e=!0){const i=((t,e)=>{const i=Array.from(t),n=Array.from(e),o={added:[],removed:[]},r=i.sort(Ci),s=n.sort(Ci);let a=0,d=0;for(;a=0&&this.focusedItemIndex_!==t&&this.adapter.setTabIndexForElementIndex(this.focusedItemIndex_,-1),this.adapter.setTabIndexForElementIndex(t,0)}setTabindexToFirstSelectedItem_(){let t=0;"number"==typeof this.selectedIndex_&&this.selectedIndex_!==ii.UNSET_INDEX?t=this.selectedIndex_:Ti(this.selectedIndex_)&&this.selectedIndex_.size>0&&(t=Math.min(...this.selectedIndex_)),this.setTabindexAtIndex_(t)}isIndexValid_(t){if(t instanceof Set){if(!this.isMulti_)throw new Error("MDCListFoundation: Array of index is only supported for checkbox based list");if(0===t.size)return!0;{let e=!1;for(const i of t)if(e=this.isIndexInRange_(i),e)break;return e}}if("number"==typeof t){if(this.isMulti_)throw new Error("MDCListFoundation: Expected array of index for checkbox based list but got number: "+t);return t===ii.UNSET_INDEX||this.isIndexInRange_(t)}return!1}isIndexInRange_(t){const e=this.adapter.getListItemCount();return t>=0&&tt.hasAttribute("mwc-list-item");function Pi(){const t=this.itemsReadyResolver;this.itemsReady=new Promise((t=>this.itemsReadyResolver=t)),t()}class Di extends he{constructor(){super(),this.mdcAdapter=null,this.mdcFoundationClass=Ai,this.activatable=!1,this.multi=!1,this.wrapFocus=!1,this.itemRoles=null,this.innerRole=null,this.innerAriaLabel=null,this.rootTabbable=!1,this.previousTabindex=null,this.noninteractive=!1,this.itemsReadyResolver=()=>{},this.itemsReady=Promise.resolve([]),this.items_=[];const t=function(t,e=50){let i;return function(n=!0){clearTimeout(i),i=setTimeout((()=>{t(n)}),e)}}(this.layout.bind(this));this.debouncedLayout=(e=!0)=>{Pi.call(this),t(e)}}async getUpdateComplete(){const t=await super.getUpdateComplete();return await this.itemsReady,t}get items(){return this.items_}updateItems(){var t;const e=null!==(t=this.assignedElements)&&void 0!==t?t:[],i=[];for(const t of e)Ri(t)&&(i.push(t),t._managingList=this),t.hasAttribute("divider")&&!t.hasAttribute("role")&&t.setAttribute("role","separator");this.items_=i;const n=new Set;if(this.items_.forEach(((t,e)=>{this.itemRoles?t.setAttribute("role",this.itemRoles):t.removeAttribute("role"),t.selected&&n.add(e)})),this.multi)this.select(n);else{const t=n.size?n.entries().next().value[1]:-1;this.select(t)}const o=new Event("items-updated",{bubbles:!0,composed:!0});this.dispatchEvent(o)}get selected(){const t=this.index;if(!Ti(t))return-1===t?null:this.items[t];const e=[];for(const i of t)e.push(this.items[i]);return e}get index(){return this.mdcFoundation?this.mdcFoundation.getSelectedIndex():-1}render(){const t=null===this.innerRole?void 0:this.innerRole,e=null===this.innerAriaLabel?void 0:this.innerAriaLabel,i=this.rootTabbable?"0":"-1";return $` - -
    - - ${this.renderPlaceholder()} -
- `}renderPlaceholder(){var t;const e=null!==(t=this.assignedElements)&&void 0!==t?t:[];return void 0!==this.emptyMessage&&0===e.length?$` - ${this.emptyMessage} - `:null}firstUpdated(){super.firstUpdated(),this.items.length||(this.mdcFoundation.setMulti(this.multi),this.layout())}onFocusIn(t){if(this.mdcFoundation&&this.mdcRoot){const e=this.getIndexOfTarget(t);this.mdcFoundation.handleFocusIn(t,e)}}onFocusOut(t){if(this.mdcFoundation&&this.mdcRoot){const e=this.getIndexOfTarget(t);this.mdcFoundation.handleFocusOut(t,e)}}onKeydown(t){if(this.mdcFoundation&&this.mdcRoot){const e=this.getIndexOfTarget(t),i=t.target,n=Ri(i);this.mdcFoundation.handleKeydown(t,n,e)}}onRequestSelected(t){if(this.mdcFoundation){let e=this.getIndexOfTarget(t);if(-1===e&&(this.layout(),e=this.getIndexOfTarget(t),-1===e))return;if(this.items[e].disabled)return;const i=t.detail.selected,n=t.detail.source;this.mdcFoundation.handleSingleSelection(e,"interaction"===n,i),t.stopPropagation()}}getIndexOfTarget(t){const e=this.items,i=t.composedPath();for(const t of i){let i=-1;if(re(t)&&Ri(t)&&(i=e.indexOf(t)),-1!==i)return i}return-1}createAdapter(){return this.mdcAdapter={getListItemCount:()=>this.mdcRoot?this.items.length:0,getFocusedElementIndex:this.getFocusedItemIndex,getAttributeForElementIndex:(t,e)=>{if(!this.mdcRoot)return"";const i=this.items[t];return i?i.getAttribute(e):""},setAttributeForElementIndex:(t,e,i)=>{if(!this.mdcRoot)return;const n=this.items[t];n&&n.setAttribute(e,i)},focusItemAtIndex:t=>{const e=this.items[t];e&&e.focus()},setTabIndexForElementIndex:(t,e)=>{const i=this.items[t];i&&(i.tabindex=e)},notifyAction:t=>{const e={bubbles:!0,composed:!0};e.detail={index:t};const i=new CustomEvent("action",e);this.dispatchEvent(i)},notifySelected:(t,e)=>{const i={bubbles:!0,composed:!0};i.detail={index:t,diff:e};const n=new CustomEvent("selected",i);this.dispatchEvent(n)},isFocusInsideList:()=>ce(this),isRootFocused:()=>{const t=this.mdcRoot;return t.getRootNode().activeElement===t},setDisabledStateForElementIndex:(t,e)=>{const i=this.items[t];i&&(i.disabled=e)},getDisabledStateForElementIndex:t=>{const e=this.items[t];return!!e&&e.disabled},setSelectedStateForElementIndex:(t,e)=>{const i=this.items[t];i&&(i.selected=e)},getSelectedStateForElementIndex:t=>{const e=this.items[t];return!!e&&e.selected},setActivatedStateForElementIndex:(t,e)=>{const i=this.items[t];i&&(i.activated=e)}},this.mdcAdapter}selectUi(t,e=!1){const i=this.items[t];i&&(i.selected=!0,i.activated=e)}deselectUi(t){const e=this.items[t];e&&(e.selected=!1,e.activated=!1)}select(t){this.mdcFoundation&&this.mdcFoundation.setSelectedIndex(t)}toggle(t,e){this.multi&&this.mdcFoundation.toggleMultiAtIndex(t,e)}onListItemConnected(t){const e=t.target;this.layout(-1===this.items.indexOf(e))}layout(t=!0){t&&this.updateItems();const e=this.items[0];for(const t of this.items)t.tabindex=-1;e&&(this.noninteractive?this.previousTabindex||(this.previousTabindex=e):e.tabindex=0),this.itemsReadyResolver()}getFocusedItemIndex(){if(!this.mdcRoot)return-1;if(!this.items.length)return-1;const t=le();if(!t.length)return-1;for(let e=t.length-1;e>=0;e--){const i=t[e];if(Ri(i))return this.items.indexOf(i)}return-1}focusItemAtIndex(t){for(const t of this.items)if(0===t.tabindex){t.tabindex=-1;break}this.items[t].tabindex=0,this.items[t].focus()}focus(){const t=this.mdcRoot;t&&t.focus()}blur(){const t=this.mdcRoot;t&&t.blur()}}o([At({type:String})],Di.prototype,"emptyMessage",void 0),o([Mt(".mdc-deprecated-list")],Di.prototype,"mdcRoot",void 0),o([Lt("",!0,"*")],Di.prototype,"assignedElements",void 0),o([Lt("",!0,'[tabindex="0"]')],Di.prototype,"tabbableElements",void 0),o([At({type:Boolean}),ve((function(t){this.mdcFoundation&&this.mdcFoundation.setUseActivatedClass(t)}))],Di.prototype,"activatable",void 0),o([At({type:Boolean}),ve((function(t,e){this.mdcFoundation&&this.mdcFoundation.setMulti(t),void 0!==e&&this.layout()}))],Di.prototype,"multi",void 0),o([At({type:Boolean}),ve((function(t){this.mdcFoundation&&this.mdcFoundation.setWrapFocus(t)}))],Di.prototype,"wrapFocus",void 0),o([At({type:String}),ve((function(t,e){void 0!==e&&this.updateItems()}))],Di.prototype,"itemRoles",void 0),o([At({type:String})],Di.prototype,"innerRole",void 0),o([At({type:String})],Di.prototype,"innerAriaLabel",void 0),o([At({type:Boolean})],Di.prototype,"rootTabbable",void 0),o([At({type:Boolean,reflect:!0}),ve((function(t){var e,i;if(t){const t=null!==(i=null===(e=this.tabbableElements)||void 0===e?void 0:e[0])&&void 0!==i?i:null;this.previousTabindex=t,t&&t.setAttribute("tabindex","-1")}else!t&&this.previousTabindex&&(this.previousTabindex.setAttribute("tabindex","0"),this.previousTabindex=null)}))],Di.prototype,"noninteractive",void 0); -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -class Mi{constructor(t){this.startPress=e=>{t().then((t=>{t&&t.startPress(e)}))},this.endPress=()=>{t().then((t=>{t&&t.endPress()}))},this.startFocus=()=>{t().then((t=>{t&&t.startFocus()}))},this.endFocus=()=>{t().then((t=>{t&&t.endFocus()}))},this.startHover=()=>{t().then((t=>{t&&t.startHover()}))},this.endHover=()=>{t().then((t=>{t&&t.endHover()}))}}} -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */class Fi extends Ot{constructor(){super(...arguments),this.value="",this.group=null,this.tabindex=-1,this.disabled=!1,this.twoline=!1,this.activated=!1,this.graphic=null,this.multipleGraphics=!1,this.hasMeta=!1,this.noninteractive=!1,this.selected=!1,this.shouldRenderRipple=!1,this._managingList=null,this.boundOnClick=this.onClick.bind(this),this._firstChanged=!0,this._skipPropRequest=!1,this.rippleHandlers=new Mi((()=>(this.shouldRenderRipple=!0,this.ripple))),this.listeners=[{target:this,eventNames:["click"],cb:()=>{this.onClick()}},{target:this,eventNames:["mouseenter"],cb:this.rippleHandlers.startHover},{target:this,eventNames:["mouseleave"],cb:this.rippleHandlers.endHover},{target:this,eventNames:["focus"],cb:this.rippleHandlers.startFocus},{target:this,eventNames:["blur"],cb:this.rippleHandlers.endFocus},{target:this,eventNames:["mousedown","touchstart"],cb:t=>{const e=t.type;this.onDown("mousedown"===e?"mouseup":"touchend",t)}}]}get text(){const t=this.textContent;return t?t.trim():""}render(){const t=this.renderText(),e=this.graphic?this.renderGraphic():$``,i=this.hasMeta?this.renderMeta():$``;return $` - ${this.renderRipple()} - ${e} - ${t} - ${i}`}renderRipple(){return this.shouldRenderRipple?$` - - `:this.activated?$`
`:""}renderGraphic(){const t={multi:this.multipleGraphics};return $` - - - `}renderMeta(){return $` - - - `}renderText(){const t=this.twoline?this.renderTwoline():this.renderSingleLine();return $` - - ${t} - `}renderSingleLine(){return $``}renderTwoline(){return $` - - - - - - - `}onClick(){this.fireRequestSelected(!this.selected,"interaction")}onDown(t,e){const i=()=>{window.removeEventListener(t,i),this.rippleHandlers.endPress()};window.addEventListener(t,i),this.rippleHandlers.startPress(e)}fireRequestSelected(t,e){if(this.noninteractive)return;const i=new CustomEvent("request-selected",{bubbles:!0,composed:!0,detail:{source:e,selected:t}});this.dispatchEvent(i)}connectedCallback(){super.connectedCallback(),this.noninteractive||this.setAttribute("mwc-list-item","");for(const t of this.listeners)for(const e of t.eventNames)t.target.addEventListener(e,t.cb,{passive:!0})}disconnectedCallback(){super.disconnectedCallback();for(const t of this.listeners)for(const e of t.eventNames)t.target.removeEventListener(e,t.cb);this._managingList&&(this._managingList.debouncedLayout?this._managingList.debouncedLayout(!0):this._managingList.layout(!0))}firstUpdated(){const t=new Event("list-item-rendered",{bubbles:!0,composed:!0});this.dispatchEvent(t)}}o([Mt("slot")],Fi.prototype,"slotElement",void 0),o([Ft("mwc-ripple")],Fi.prototype,"ripple",void 0),o([At({type:String})],Fi.prototype,"value",void 0),o([At({type:String,reflect:!0})],Fi.prototype,"group",void 0),o([At({type:Number,reflect:!0})],Fi.prototype,"tabindex",void 0),o([At({type:Boolean,reflect:!0}),ve((function(t){t?this.setAttribute("aria-disabled","true"):this.setAttribute("aria-disabled","false")}))],Fi.prototype,"disabled",void 0),o([At({type:Boolean,reflect:!0})],Fi.prototype,"twoline",void 0),o([At({type:Boolean,reflect:!0})],Fi.prototype,"activated",void 0),o([At({type:String,reflect:!0})],Fi.prototype,"graphic",void 0),o([At({type:Boolean})],Fi.prototype,"multipleGraphics",void 0),o([At({type:Boolean})],Fi.prototype,"hasMeta",void 0),o([At({type:Boolean,reflect:!0}),ve((function(t){t?(this.removeAttribute("aria-checked"),this.removeAttribute("mwc-list-item"),this.selected=!1,this.activated=!1,this.tabIndex=-1):this.setAttribute("mwc-list-item","")}))],Fi.prototype,"noninteractive",void 0),o([At({type:Boolean,reflect:!0}),ve((function(t){const e=this.getAttribute("role"),i="gridcell"===e||"option"===e||"row"===e||"tab"===e;i&&t?this.setAttribute("aria-selected","true"):i&&this.setAttribute("aria-selected","false"),this._firstChanged?this._firstChanged=!1:this._skipPropRequest||this.fireRequestSelected(t,"property")}))],Fi.prototype,"selected",void 0),o([Rt()],Fi.prototype,"shouldRenderRipple",void 0),o([Rt()],Fi.prototype,"_managingList",void 0); -/** - * @license - * Copyright 2018 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -var Ni,Bi={MENU_SELECTED_LIST_ITEM:"mdc-menu-item--selected",MENU_SELECTION_GROUP:"mdc-menu__selection-group",ROOT:"mdc-menu"},Li={ARIA_CHECKED_ATTR:"aria-checked",ARIA_DISABLED_ATTR:"aria-disabled",CHECKBOX_SELECTOR:'input[type="checkbox"]',LIST_SELECTOR:".mdc-list,.mdc-deprecated-list",SELECTED_EVENT:"MDCMenu:selected",SKIP_RESTORE_FOCUS:"data-menu-item-skip-restore-focus"},zi={FOCUS_ROOT_INDEX:-1};!function(t){t[t.NONE=0]="NONE",t[t.LIST_ROOT=1]="LIST_ROOT",t[t.FIRST_ITEM=2]="FIRST_ITEM",t[t.LAST_ITEM=3]="LAST_ITEM"}(Ni||(Ni={})); -/** - * @license - * Copyright 2018 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -var ji=function(t){function e(i){var o=t.call(this,n(n({},e.defaultAdapter),i))||this;return o.isSurfaceOpen=!1,o.isQuickOpen=!1,o.isHoistedElement=!1,o.isFixedPosition=!1,o.isHorizontallyCenteredOnViewport=!1,o.maxHeight=0,o.openBottomBias=0,o.openAnimationEndTimerId=0,o.closeAnimationEndTimerId=0,o.animationRequestId=0,o.anchorCorner=mi.TOP_START,o.originCorner=mi.TOP_START,o.anchorMargin={top:0,right:0,bottom:0,left:0},o.position={x:0,y:0},o}return i(e,t),Object.defineProperty(e,"cssClasses",{get:function(){return vi},enumerable:!1,configurable:!0}),Object.defineProperty(e,"strings",{get:function(){return gi},enumerable:!1,configurable:!0}),Object.defineProperty(e,"numbers",{get:function(){return yi},enumerable:!1,configurable:!0}),Object.defineProperty(e,"Corner",{get:function(){return mi},enumerable:!1,configurable:!0}),Object.defineProperty(e,"defaultAdapter",{get:function(){return{addClass:function(){},removeClass:function(){},hasClass:function(){return!1},hasAnchor:function(){return!1},isElementInContainer:function(){return!1},isFocused:function(){return!1},isRtl:function(){return!1},getInnerDimensions:function(){return{height:0,width:0}},getAnchorDimensions:function(){return null},getWindowDimensions:function(){return{height:0,width:0}},getBodyDimensions:function(){return{height:0,width:0}},getWindowScroll:function(){return{x:0,y:0}},setPosition:function(){},setMaxHeight:function(){},setTransformOrigin:function(){},saveFocus:function(){},restoreFocus:function(){},notifyClose:function(){},notifyClosing:function(){},notifyOpen:function(){},notifyOpening:function(){}}},enumerable:!1,configurable:!0}),e.prototype.init=function(){var t=e.cssClasses,i=t.ROOT,n=t.OPEN;if(!this.adapter.hasClass(i))throw new Error(i+" class required in root element.");this.adapter.hasClass(n)&&(this.isSurfaceOpen=!0)},e.prototype.destroy=function(){clearTimeout(this.openAnimationEndTimerId),clearTimeout(this.closeAnimationEndTimerId),cancelAnimationFrame(this.animationRequestId)},e.prototype.setAnchorCorner=function(t){this.anchorCorner=t},e.prototype.flipCornerHorizontally=function(){this.originCorner=this.originCorner^fi.RIGHT},e.prototype.setAnchorMargin=function(t){this.anchorMargin.top=t.top||0,this.anchorMargin.right=t.right||0,this.anchorMargin.bottom=t.bottom||0,this.anchorMargin.left=t.left||0},e.prototype.setIsHoisted=function(t){this.isHoistedElement=t},e.prototype.setFixedPosition=function(t){this.isFixedPosition=t},e.prototype.isFixed=function(){return this.isFixedPosition},e.prototype.setAbsolutePosition=function(t,e){this.position.x=this.isFinite(t)?t:0,this.position.y=this.isFinite(e)?e:0},e.prototype.setIsHorizontallyCenteredOnViewport=function(t){this.isHorizontallyCenteredOnViewport=t},e.prototype.setQuickOpen=function(t){this.isQuickOpen=t},e.prototype.setMaxHeight=function(t){this.maxHeight=t},e.prototype.setOpenBottomBias=function(t){this.openBottomBias=t},e.prototype.isOpen=function(){return this.isSurfaceOpen},e.prototype.open=function(){var t=this;this.isSurfaceOpen||(this.adapter.notifyOpening(),this.adapter.saveFocus(),this.isQuickOpen?(this.isSurfaceOpen=!0,this.adapter.addClass(e.cssClasses.OPEN),this.dimensions=this.adapter.getInnerDimensions(),this.autoposition(),this.adapter.notifyOpen()):(this.adapter.addClass(e.cssClasses.ANIMATING_OPEN),this.animationRequestId=requestAnimationFrame((function(){t.dimensions=t.adapter.getInnerDimensions(),t.autoposition(),t.adapter.addClass(e.cssClasses.OPEN),t.openAnimationEndTimerId=setTimeout((function(){t.openAnimationEndTimerId=0,t.adapter.removeClass(e.cssClasses.ANIMATING_OPEN),t.adapter.notifyOpen()}),yi.TRANSITION_OPEN_DURATION)})),this.isSurfaceOpen=!0))},e.prototype.close=function(t){var i=this;if(void 0===t&&(t=!1),this.isSurfaceOpen){if(this.adapter.notifyClosing(),this.isQuickOpen)return this.isSurfaceOpen=!1,t||this.maybeRestoreFocus(),this.adapter.removeClass(e.cssClasses.OPEN),this.adapter.removeClass(e.cssClasses.IS_OPEN_BELOW),void this.adapter.notifyClose();this.adapter.addClass(e.cssClasses.ANIMATING_CLOSED),requestAnimationFrame((function(){i.adapter.removeClass(e.cssClasses.OPEN),i.adapter.removeClass(e.cssClasses.IS_OPEN_BELOW),i.closeAnimationEndTimerId=setTimeout((function(){i.closeAnimationEndTimerId=0,i.adapter.removeClass(e.cssClasses.ANIMATING_CLOSED),i.adapter.notifyClose()}),yi.TRANSITION_CLOSE_DURATION)})),this.isSurfaceOpen=!1,t||this.maybeRestoreFocus()}},e.prototype.handleBodyClick=function(t){var e=t.target;this.adapter.isElementInContainer(e)||this.close()},e.prototype.handleKeydown=function(t){var e=t.keyCode;("Escape"===t.key||27===e)&&this.close()},e.prototype.autoposition=function(){var t;this.measurements=this.getAutoLayoutmeasurements();var i=this.getoriginCorner(),n=this.getMenuSurfaceMaxHeight(i),o=this.hasBit(i,fi.BOTTOM)?"bottom":"top",r=this.hasBit(i,fi.RIGHT)?"right":"left",s=this.getHorizontalOriginOffset(i),a=this.getVerticalOriginOffset(i),d=this.measurements,l=d.anchorSize,c=d.surfaceSize,h=((t={})[r]=s,t[o]=a,t);l.width/c.width>yi.ANCHOR_TO_MENU_SURFACE_WIDTH_RATIO&&(r="center"),(this.isHoistedElement||this.isFixedPosition)&&this.adjustPositionForHoistedElement(h),this.adapter.setTransformOrigin(r+" "+o),this.adapter.setPosition(h),this.adapter.setMaxHeight(n?n+"px":""),this.hasBit(i,fi.BOTTOM)||this.adapter.addClass(e.cssClasses.IS_OPEN_BELOW)},e.prototype.getAutoLayoutmeasurements=function(){var t=this.adapter.getAnchorDimensions(),e=this.adapter.getBodyDimensions(),i=this.adapter.getWindowDimensions(),n=this.adapter.getWindowScroll();return t||(t={top:this.position.y,right:this.position.x,bottom:this.position.y,left:this.position.x,width:0,height:0}),{anchorSize:t,bodySize:e,surfaceSize:this.dimensions,viewportDistance:{top:t.top,right:i.width-t.right,bottom:i.height-t.bottom,left:t.left},viewportSize:i,windowScroll:n}},e.prototype.getoriginCorner=function(){var t,i,n=this.originCorner,o=this.measurements,r=o.viewportDistance,s=o.anchorSize,a=o.surfaceSize,d=e.numbers.MARGIN_TO_EDGE;this.hasBit(this.anchorCorner,fi.BOTTOM)?(t=r.top-d+this.anchorMargin.bottom,i=r.bottom-d-this.anchorMargin.bottom):(t=r.top-d+this.anchorMargin.top,i=r.bottom-d+s.height-this.anchorMargin.top),!(i-a.height>0)&&t>i+this.openBottomBias&&(n=this.setBit(n,fi.BOTTOM));var l,c,h=this.adapter.isRtl(),u=this.hasBit(this.anchorCorner,fi.FLIP_RTL),p=this.hasBit(this.anchorCorner,fi.RIGHT)||this.hasBit(n,fi.RIGHT),f=!1;(f=h&&u?!p:p)?(l=r.left+s.width+this.anchorMargin.right,c=r.right-this.anchorMargin.right):(l=r.left+this.anchorMargin.left,c=r.right+s.width-this.anchorMargin.left);var m=l-a.width>0,v=c-a.width>0,g=this.hasBit(n,fi.FLIP_RTL)&&this.hasBit(n,fi.RIGHT);return v&&g&&h||!m&&g?n=this.unsetBit(n,fi.RIGHT):(m&&f&&h||m&&!f&&p||!v&&l>=c)&&(n=this.setBit(n,fi.RIGHT)),n},e.prototype.getMenuSurfaceMaxHeight=function(t){if(this.maxHeight>0)return this.maxHeight;var i=this.measurements.viewportDistance,n=0,o=this.hasBit(t,fi.BOTTOM),r=this.hasBit(this.anchorCorner,fi.BOTTOM),s=e.numbers.MARGIN_TO_EDGE;return o?(n=i.top+this.anchorMargin.top-s,r||(n+=this.measurements.anchorSize.height)):(n=i.bottom-this.anchorMargin.bottom+this.measurements.anchorSize.height-s,r&&(n-=this.measurements.anchorSize.height)),n},e.prototype.getHorizontalOriginOffset=function(t){var e=this.measurements.anchorSize,i=this.hasBit(t,fi.RIGHT),n=this.hasBit(this.anchorCorner,fi.RIGHT);if(i){var o=n?e.width-this.anchorMargin.left:this.anchorMargin.right;return this.isHoistedElement||this.isFixedPosition?o-(this.measurements.viewportSize.width-this.measurements.bodySize.width):o}return n?e.width-this.anchorMargin.right:this.anchorMargin.left},e.prototype.getVerticalOriginOffset=function(t){var e=this.measurements.anchorSize,i=this.hasBit(t,fi.BOTTOM),n=this.hasBit(this.anchorCorner,fi.BOTTOM);return i?n?e.height-this.anchorMargin.top:-this.anchorMargin.bottom:n?e.height+this.anchorMargin.bottom:this.anchorMargin.top},e.prototype.adjustPositionForHoistedElement=function(t){var e,i,n=this.measurements,o=n.windowScroll,s=n.viewportDistance,a=n.surfaceSize,d=n.viewportSize,l=Object.keys(t);try{for(var c=r(l),h=c.next();!h.done;h=c.next()){var u=h.value,p=t[u]||0;!this.isHorizontallyCenteredOnViewport||"left"!==u&&"right"!==u?(p+=s[u],this.isFixedPosition||("top"===u?p+=o.y:"bottom"===u?p-=o.y:"left"===u?p+=o.x:p-=o.x),t[u]=p):t[u]=(d.width-a.width)/2}}catch(t){e={error:t}}finally{try{h&&!h.done&&(i=c.return)&&i.call(c)}finally{if(e)throw e.error}}},e.prototype.maybeRestoreFocus=function(){var t=this,e=this.adapter.isFocused(),i=this.adapter.getOwnerDocument?this.adapter.getOwnerDocument():document,n=i.activeElement&&this.adapter.isElementInContainer(i.activeElement);(e||n)&&setTimeout((function(){t.adapter.restoreFocus()}),yi.TOUCH_EVENT_WAIT_MS)},e.prototype.hasBit=function(t,e){return Boolean(t&e)},e.prototype.setBit=function(t,e){return t|e},e.prototype.unsetBit=function(t,e){return t^e},e.prototype.isFinite=function(t){return"number"==typeof t&&isFinite(t)},e}(ee),Hi=function(t){function e(i){var o=t.call(this,n(n({},e.defaultAdapter),i))||this;return o.closeAnimationEndTimerId=0,o.defaultFocusState=Ni.LIST_ROOT,o.selectedIndex=-1,o}return i(e,t),Object.defineProperty(e,"cssClasses",{get:function(){return Bi},enumerable:!1,configurable:!0}),Object.defineProperty(e,"strings",{get:function(){return Li},enumerable:!1,configurable:!0}),Object.defineProperty(e,"numbers",{get:function(){return zi},enumerable:!1,configurable:!0}),Object.defineProperty(e,"defaultAdapter",{get:function(){return{addClassToElementAtIndex:function(){},removeClassFromElementAtIndex:function(){},addAttributeToElementAtIndex:function(){},removeAttributeFromElementAtIndex:function(){},getAttributeFromElementAtIndex:function(){return null},elementContainsClass:function(){return!1},closeSurface:function(){},getElementIndex:function(){return-1},notifySelected:function(){},getMenuItemCount:function(){return 0},focusItemAtIndex:function(){},focusListRoot:function(){},getSelectedSiblingOfItemAtIndex:function(){return-1},isSelectableItemAtIndex:function(){return!1}}},enumerable:!1,configurable:!0}),e.prototype.destroy=function(){this.closeAnimationEndTimerId&&clearTimeout(this.closeAnimationEndTimerId),this.adapter.closeSurface()},e.prototype.handleKeydown=function(t){var e=t.key,i=t.keyCode;("Tab"===e||9===i)&&this.adapter.closeSurface(!0)},e.prototype.handleItemAction=function(t){var e=this,i=this.adapter.getElementIndex(t);if(!(i<0)){this.adapter.notifySelected({index:i});var n="true"===this.adapter.getAttributeFromElementAtIndex(i,Li.SKIP_RESTORE_FOCUS);this.adapter.closeSurface(n),this.closeAnimationEndTimerId=setTimeout((function(){var i=e.adapter.getElementIndex(t);i>=0&&e.adapter.isSelectableItemAtIndex(i)&&e.setSelectedIndex(i)}),ji.numbers.TRANSITION_CLOSE_DURATION)}},e.prototype.handleMenuSurfaceOpened=function(){switch(this.defaultFocusState){case Ni.FIRST_ITEM:this.adapter.focusItemAtIndex(0);break;case Ni.LAST_ITEM:this.adapter.focusItemAtIndex(this.adapter.getMenuItemCount()-1);break;case Ni.NONE:break;default:this.adapter.focusListRoot()}},e.prototype.setDefaultFocusState=function(t){this.defaultFocusState=t},e.prototype.getSelectedIndex=function(){return this.selectedIndex},e.prototype.setSelectedIndex=function(t){if(this.validatedIndex(t),!this.adapter.isSelectableItemAtIndex(t))throw new Error("MDCMenuFoundation: No selection group at specified index.");var e=this.adapter.getSelectedSiblingOfItemAtIndex(t);e>=0&&(this.adapter.removeAttributeFromElementAtIndex(e,Li.ARIA_CHECKED_ATTR),this.adapter.removeClassFromElementAtIndex(e,Bi.MENU_SELECTED_LIST_ITEM)),this.adapter.addClassToElementAtIndex(t,Bi.MENU_SELECTED_LIST_ITEM),this.adapter.addAttributeToElementAtIndex(t,Li.ARIA_CHECKED_ATTR,"true"),this.selectedIndex=t},e.prototype.setEnabled=function(t,e){this.validatedIndex(t),e?(this.adapter.removeClassFromElementAtIndex(t,Ge),this.adapter.addAttributeToElementAtIndex(t,Li.ARIA_DISABLED_ATTR,"false")):(this.adapter.addClassToElementAtIndex(t,Ge),this.adapter.addAttributeToElementAtIndex(t,Li.ARIA_DISABLED_ATTR,"true"))},e.prototype.validatedIndex=function(t){var e=this.adapter.getMenuItemCount();if(!(t>=0&&t - ${this.renderList()} - `}getSurfaceClasses(){return{"mdc-menu":!0,"mdc-menu-surface":!0}}renderList(){const t="menu"===this.innerRole?"menuitem":"option",e=this.renderListClasses();return $` - - - `}renderListClasses(){return{"mdc-deprecated-list":!0}}createAdapter(){return{addClassToElementAtIndex:(t,e)=>{const i=this.listElement;if(!i)return;const n=i.items[t];n&&("mdc-menu-item--selected"===e?this.forceGroupSelection&&!n.selected&&i.toggle(t,!0):n.classList.add(e))},removeClassFromElementAtIndex:(t,e)=>{const i=this.listElement;if(!i)return;const n=i.items[t];n&&("mdc-menu-item--selected"===e?n.selected&&i.toggle(t,!1):n.classList.remove(e))},addAttributeToElementAtIndex:(t,e,i)=>{const n=this.listElement;if(!n)return;const o=n.items[t];o&&o.setAttribute(e,i)},removeAttributeFromElementAtIndex:(t,e)=>{const i=this.listElement;if(!i)return;const n=i.items[t];n&&n.removeAttribute(e)},getAttributeFromElementAtIndex:(t,e)=>{const i=this.listElement;if(!i)return null;const n=i.items[t];return n?n.getAttribute(e):null},elementContainsClass:(t,e)=>t.classList.contains(e),closeSurface:()=>{this.open=!1},getElementIndex:t=>{const e=this.listElement;return e?e.items.indexOf(t):-1},notifySelected:()=>{},getMenuItemCount:()=>{const t=this.listElement;return t?t.items.length:0},focusItemAtIndex:t=>{const e=this.listElement;if(!e)return;const i=e.items[t];i&&i.focus()},focusListRoot:()=>{this.listElement&&this.listElement.focus()},getSelectedSiblingOfItemAtIndex:t=>{const e=this.listElement;if(!e)return-1;const i=e.items[t];if(!i||!i.group)return-1;for(let n=0;n{const e=this.listElement;if(!e)return!1;const i=e.items[t];return!!i&&i.hasAttribute("group")}}}onKeydown(t){this.mdcFoundation&&this.mdcFoundation.handleKeydown(t)}onAction(t){const e=this.listElement;if(this.mdcFoundation&&e){const i=t.detail.index,n=e.items[i];n&&this.mdcFoundation.handleItemAction(n)}}onOpened(){this.open=!0,this.mdcFoundation&&this.mdcFoundation.handleMenuSurfaceOpened()}onClosed(){this.open=!1}async getUpdateComplete(){await this._listUpdateComplete;return await super.getUpdateComplete()}async firstUpdated(){super.firstUpdated();const t=this.listElement;t&&(this._listUpdateComplete=t.updateComplete,await this._listUpdateComplete)}select(t){const e=this.listElement;e&&e.select(t)}close(){this.open=!1}show(){this.open=!0}getFocusedItemIndex(){const t=this.listElement;return t?t.getFocusedItemIndex():-1}focusItemAtIndex(t){const e=this.listElement;e&&e.focusItemAtIndex(t)}layout(t=!0){const e=this.listElement;e&&e.layout(t)}}o([Mt(".mdc-menu")],$i.prototype,"mdcRoot",void 0),o([Mt("slot")],$i.prototype,"slotElement",void 0),o([At({type:Object})],$i.prototype,"anchor",void 0),o([At({type:Boolean,reflect:!0})],$i.prototype,"open",void 0),o([At({type:Boolean})],$i.prototype,"quick",void 0),o([At({type:Boolean})],$i.prototype,"wrapFocus",void 0),o([At({type:String})],$i.prototype,"innerRole",void 0),o([At({type:String})],$i.prototype,"innerAriaLabel",void 0),o([At({type:String})],$i.prototype,"corner",void 0),o([At({type:Number})],$i.prototype,"x",void 0),o([At({type:Number})],$i.prototype,"y",void 0),o([At({type:Boolean})],$i.prototype,"absolute",void 0),o([At({type:Boolean})],$i.prototype,"multi",void 0),o([At({type:Boolean})],$i.prototype,"activatable",void 0),o([At({type:Boolean})],$i.prototype,"fixed",void 0),o([At({type:Boolean})],$i.prototype,"forceGroupSelection",void 0),o([At({type:Boolean})],$i.prototype,"fullwidth",void 0),o([At({type:String})],$i.prototype,"menuCorner",void 0),o([At({type:Boolean})],$i.prototype,"stayOpenOnBodyClick",void 0),o([At({type:String}),ve((function(t){this.mdcFoundation&&this.mdcFoundation.setDefaultFocusState(Ni[t])}))],$i.prototype,"defaultFocus",void 0); -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const Ui="important",Wi=" !"+Ui,Vi=xe(class extends _e{constructor(t){var e;if(super(t),t.type!==ge||"style"!==t.name||(null===(e=t.strings)||void 0===e?void 0:e.length)>2)throw Error("The `styleMap` directive must be used in the `style` attribute and must be the only part in the attribute.")}render(t){return Object.keys(t).reduce(((e,i)=>{const n=t[i];return null==n?e:e+`${i=i.includes("-")?i:i.replace(/(?:^(webkit|moz|ms|o)|)(?=[A-Z])/g,"-$&").toLowerCase()}:${n};`}),"")}update(t,[e]){const{style:i}=t.element;if(void 0===this.ht){this.ht=new Set;for(const t in e)this.ht.add(t);return this.render(e)}this.ht.forEach((t=>{null==e[t]&&(this.ht.delete(t),t.includes("-")?i.removeProperty(t):i[t]="")}));for(const t in e){const n=e[t];if(null!=n){this.ht.add(t);const e="string"==typeof n&&n.endsWith(Wi);t.includes("-")||e?i.setProperty(t,e?n.slice(0,-11):n,e?Ui:""):i[t]=n}}return U}}),qi={TOP_LEFT:mi.TOP_LEFT,TOP_RIGHT:mi.TOP_RIGHT,BOTTOM_LEFT:mi.BOTTOM_LEFT,BOTTOM_RIGHT:mi.BOTTOM_RIGHT,TOP_START:mi.TOP_START,TOP_END:mi.TOP_END,BOTTOM_START:mi.BOTTOM_START,BOTTOM_END:mi.BOTTOM_END}; -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */class Xi extends he{constructor(){super(...arguments),this.mdcFoundationClass=ji,this.absolute=!1,this.fullwidth=!1,this.fixed=!1,this.x=null,this.y=null,this.quick=!1,this.open=!1,this.stayOpenOnBodyClick=!1,this.bitwiseCorner=mi.TOP_START,this.previousMenuCorner=null,this.menuCorner="START",this.corner="TOP_START",this.styleTop="",this.styleLeft="",this.styleRight="",this.styleBottom="",this.styleMaxHeight="",this.styleTransformOrigin="",this.anchor=null,this.previouslyFocused=null,this.previousAnchor=null,this.onBodyClickBound=()=>{}}render(){return this.renderSurface()}renderSurface(){const t=this.getRootClasses(),e=this.getRootStyles();return $` -
- ${this.renderContent()} -
`}getRootClasses(){return{"mdc-menu-surface":!0,"mdc-menu-surface--fixed":this.fixed,"mdc-menu-surface--fullwidth":this.fullwidth}}getRootStyles(){return{top:this.styleTop,left:this.styleLeft,right:this.styleRight,bottom:this.styleBottom,"max-height":this.styleMaxHeight,"transform-origin":this.styleTransformOrigin}}renderContent(){return $``}createAdapter(){return Object.assign(Object.assign({},se(this.mdcRoot)),{hasAnchor:()=>!!this.anchor,notifyClose:()=>{const t=new CustomEvent("closed",{bubbles:!0,composed:!0});this.open=!1,this.mdcRoot.dispatchEvent(t)},notifyClosing:()=>{const t=new CustomEvent("closing",{bubbles:!0,composed:!0});this.mdcRoot.dispatchEvent(t)},notifyOpen:()=>{const t=new CustomEvent("opened",{bubbles:!0,composed:!0});this.open=!0,this.mdcRoot.dispatchEvent(t)},notifyOpening:()=>{const t=new CustomEvent("opening",{bubbles:!0,composed:!0});this.mdcRoot.dispatchEvent(t)},isElementInContainer:()=>!1,isRtl:()=>!!this.mdcRoot&&"rtl"===getComputedStyle(this.mdcRoot).direction,setTransformOrigin:t=>{this.mdcRoot&&(this.styleTransformOrigin=t)},isFocused:()=>ce(this),saveFocus:()=>{const t=le(),e=t.length;e||(this.previouslyFocused=null),this.previouslyFocused=t[e-1]},restoreFocus:()=>{this.previouslyFocused&&"focus"in this.previouslyFocused&&this.previouslyFocused.focus()},getInnerDimensions:()=>{const t=this.mdcRoot;return t?{width:t.offsetWidth,height:t.offsetHeight}:{width:0,height:0}},getAnchorDimensions:()=>{const t=this.anchor;return t?t.getBoundingClientRect():null},getBodyDimensions:()=>({width:document.body.clientWidth,height:document.body.clientHeight}),getWindowDimensions:()=>({width:window.innerWidth,height:window.innerHeight}),getWindowScroll:()=>({x:window.pageXOffset,y:window.pageYOffset}),setPosition:t=>{this.mdcRoot&&(this.styleLeft="left"in t?`${t.left}px`:"",this.styleRight="right"in t?`${t.right}px`:"",this.styleTop="top"in t?`${t.top}px`:"",this.styleBottom="bottom"in t?`${t.bottom}px`:"")},setMaxHeight:async t=>{this.mdcRoot&&(this.styleMaxHeight=t,await this.updateComplete,this.styleMaxHeight=`var(--mdc-menu-max-height, ${t})`)}})}onKeydown(t){this.mdcFoundation&&this.mdcFoundation.handleKeydown(t)}onBodyClick(t){if(this.stayOpenOnBodyClick)return;-1===t.composedPath().indexOf(this)&&this.close()}registerBodyClick(){this.onBodyClickBound=this.onBodyClick.bind(this),document.body.addEventListener("click",this.onBodyClickBound,{passive:!0,capture:!0})}deregisterBodyClick(){document.body.removeEventListener("click",this.onBodyClickBound,{capture:!0})}onOpenChanged(t,e){this.mdcFoundation&&(t?this.mdcFoundation.open():void 0!==e&&this.mdcFoundation.close())}close(){this.open=!1}show(){this.open=!0}}o([Mt(".mdc-menu-surface")],Xi.prototype,"mdcRoot",void 0),o([Mt("slot")],Xi.prototype,"slotElement",void 0),o([At({type:Boolean}),ve((function(t){this.mdcFoundation&&!this.fixed&&this.mdcFoundation.setIsHoisted(t)}))],Xi.prototype,"absolute",void 0),o([At({type:Boolean})],Xi.prototype,"fullwidth",void 0),o([At({type:Boolean}),ve((function(t){this.mdcFoundation&&!this.absolute&&this.mdcFoundation.setFixedPosition(t)}))],Xi.prototype,"fixed",void 0),o([At({type:Number}),ve((function(t){this.mdcFoundation&&null!==this.y&&null!==t&&(this.mdcFoundation.setAbsolutePosition(t,this.y),this.mdcFoundation.setAnchorMargin({left:t,top:this.y,right:-t,bottom:this.y}))}))],Xi.prototype,"x",void 0),o([At({type:Number}),ve((function(t){this.mdcFoundation&&null!==this.x&&null!==t&&(this.mdcFoundation.setAbsolutePosition(this.x,t),this.mdcFoundation.setAnchorMargin({left:this.x,top:t,right:-this.x,bottom:t}))}))],Xi.prototype,"y",void 0),o([At({type:Boolean}),ve((function(t){this.mdcFoundation&&this.mdcFoundation.setQuickOpen(t)}))],Xi.prototype,"quick",void 0),o([At({type:Boolean,reflect:!0}),ve((function(t,e){this.onOpenChanged(t,e)}))],Xi.prototype,"open",void 0),o([At({type:Boolean})],Xi.prototype,"stayOpenOnBodyClick",void 0),o([Rt(),ve((function(t){this.mdcFoundation&&this.mdcFoundation.setAnchorCorner(t)}))],Xi.prototype,"bitwiseCorner",void 0),o([At({type:String}),ve((function(t){if(this.mdcFoundation){const e="START"===t||"END"===t,i=null===this.previousMenuCorner,n=!i&&t!==this.previousMenuCorner;e&&(n||i&&"END"===t)&&(this.bitwiseCorner=this.bitwiseCorner^fi.RIGHT,this.mdcFoundation.flipCornerHorizontally(),this.previousMenuCorner=t)}}))],Xi.prototype,"menuCorner",void 0),o([At({type:String}),ve((function(t){if(this.mdcFoundation&&t){let e=qi[t];"END"===this.menuCorner&&(e^=fi.RIGHT),this.bitwiseCorner=e}}))],Xi.prototype,"corner",void 0),o([Rt()],Xi.prototype,"styleTop",void 0),o([Rt()],Xi.prototype,"styleLeft",void 0),o([Rt()],Xi.prototype,"styleRight",void 0),o([Rt()],Xi.prototype,"styleBottom",void 0),o([Rt()],Xi.prototype,"styleMaxHeight",void 0),o([Rt()],Xi.prototype,"styleTransformOrigin",void 0); -/** - * @license - * Copyright 2016 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -var Yi={BG_FOCUSED:"mdc-ripple-upgraded--background-focused",FG_ACTIVATION:"mdc-ripple-upgraded--foreground-activation",FG_DEACTIVATION:"mdc-ripple-upgraded--foreground-deactivation",ROOT:"mdc-ripple-upgraded",UNBOUNDED:"mdc-ripple-upgraded--unbounded"},Gi={VAR_FG_SCALE:"--mdc-ripple-fg-scale",VAR_FG_SIZE:"--mdc-ripple-fg-size",VAR_FG_TRANSLATE_END:"--mdc-ripple-fg-translate-end",VAR_FG_TRANSLATE_START:"--mdc-ripple-fg-translate-start",VAR_LEFT:"--mdc-ripple-left",VAR_TOP:"--mdc-ripple-top"},Ki={DEACTIVATION_TIMEOUT_MS:225,FG_DEACTIVATION_MS:150,INITIAL_ORIGIN_SCALE:.6,PADDING:10,TAP_DELAY_MS:300}; -/** - * @license - * Copyright 2016 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -var Zi=["touchstart","pointerdown","mousedown","keydown"],Qi=["touchend","pointerup","mouseup","contextmenu"],Ji=[],tn=function(t){function e(i){var o=t.call(this,n(n({},e.defaultAdapter),i))||this;return o.activationAnimationHasEnded=!1,o.activationTimer=0,o.fgDeactivationRemovalTimer=0,o.fgScale="0",o.frame={width:0,height:0},o.initialSize=0,o.layoutFrame=0,o.maxRadius=0,o.unboundedCoords={left:0,top:0},o.activationState=o.defaultActivationState(),o.activationTimerCallback=function(){o.activationAnimationHasEnded=!0,o.runDeactivationUXLogicIfReady()},o.activateHandler=function(t){o.activateImpl(t)},o.deactivateHandler=function(){o.deactivateImpl()},o.focusHandler=function(){o.handleFocus()},o.blurHandler=function(){o.handleBlur()},o.resizeHandler=function(){o.layout()},o}return i(e,t),Object.defineProperty(e,"cssClasses",{get:function(){return Yi},enumerable:!1,configurable:!0}),Object.defineProperty(e,"strings",{get:function(){return Gi},enumerable:!1,configurable:!0}),Object.defineProperty(e,"numbers",{get:function(){return Ki},enumerable:!1,configurable:!0}),Object.defineProperty(e,"defaultAdapter",{get:function(){return{addClass:function(){},browserSupportsCssVars:function(){return!0},computeBoundingRect:function(){return{top:0,right:0,bottom:0,left:0,width:0,height:0}},containsEventTarget:function(){return!0},deregisterDocumentInteractionHandler:function(){},deregisterInteractionHandler:function(){},deregisterResizeHandler:function(){},getWindowPageOffset:function(){return{x:0,y:0}},isSurfaceActive:function(){return!0},isSurfaceDisabled:function(){return!0},isUnbounded:function(){return!0},registerDocumentInteractionHandler:function(){},registerInteractionHandler:function(){},registerResizeHandler:function(){},removeClass:function(){},updateCssVariable:function(){}}},enumerable:!1,configurable:!0}),e.prototype.init=function(){var t=this,i=this.supportsPressRipple();if(this.registerRootHandlers(i),i){var n=e.cssClasses,o=n.ROOT,r=n.UNBOUNDED;requestAnimationFrame((function(){t.adapter.addClass(o),t.adapter.isUnbounded()&&(t.adapter.addClass(r),t.layoutInternal())}))}},e.prototype.destroy=function(){var t=this;if(this.supportsPressRipple()){this.activationTimer&&(clearTimeout(this.activationTimer),this.activationTimer=0,this.adapter.removeClass(e.cssClasses.FG_ACTIVATION)),this.fgDeactivationRemovalTimer&&(clearTimeout(this.fgDeactivationRemovalTimer),this.fgDeactivationRemovalTimer=0,this.adapter.removeClass(e.cssClasses.FG_DEACTIVATION));var i=e.cssClasses,n=i.ROOT,o=i.UNBOUNDED;requestAnimationFrame((function(){t.adapter.removeClass(n),t.adapter.removeClass(o),t.removeCssVars()}))}this.deregisterRootHandlers(),this.deregisterDeactivationHandlers()},e.prototype.activate=function(t){this.activateImpl(t)},e.prototype.deactivate=function(){this.deactivateImpl()},e.prototype.layout=function(){var t=this;this.layoutFrame&&cancelAnimationFrame(this.layoutFrame),this.layoutFrame=requestAnimationFrame((function(){t.layoutInternal(),t.layoutFrame=0}))},e.prototype.setUnbounded=function(t){var i=e.cssClasses.UNBOUNDED;t?this.adapter.addClass(i):this.adapter.removeClass(i)},e.prototype.handleFocus=function(){var t=this;requestAnimationFrame((function(){return t.adapter.addClass(e.cssClasses.BG_FOCUSED)}))},e.prototype.handleBlur=function(){var t=this;requestAnimationFrame((function(){return t.adapter.removeClass(e.cssClasses.BG_FOCUSED)}))},e.prototype.supportsPressRipple=function(){return this.adapter.browserSupportsCssVars()},e.prototype.defaultActivationState=function(){return{activationEvent:void 0,hasDeactivationUXRun:!1,isActivated:!1,isProgrammatic:!1,wasActivatedByPointer:!1,wasElementMadeActive:!1}},e.prototype.registerRootHandlers=function(t){var e,i;if(t){try{for(var n=r(Zi),o=n.next();!o.done;o=n.next()){var s=o.value;this.adapter.registerInteractionHandler(s,this.activateHandler)}}catch(t){e={error:t}}finally{try{o&&!o.done&&(i=n.return)&&i.call(n)}finally{if(e)throw e.error}}this.adapter.isUnbounded()&&this.adapter.registerResizeHandler(this.resizeHandler)}this.adapter.registerInteractionHandler("focus",this.focusHandler),this.adapter.registerInteractionHandler("blur",this.blurHandler)},e.prototype.registerDeactivationHandlers=function(t){var e,i;if("keydown"===t.type)this.adapter.registerInteractionHandler("keyup",this.deactivateHandler);else try{for(var n=r(Qi),o=n.next();!o.done;o=n.next()){var s=o.value;this.adapter.registerDocumentInteractionHandler(s,this.deactivateHandler)}}catch(t){e={error:t}}finally{try{o&&!o.done&&(i=n.return)&&i.call(n)}finally{if(e)throw e.error}}},e.prototype.deregisterRootHandlers=function(){var t,e;try{for(var i=r(Zi),n=i.next();!n.done;n=i.next()){var o=n.value;this.adapter.deregisterInteractionHandler(o,this.activateHandler)}}catch(e){t={error:e}}finally{try{n&&!n.done&&(e=i.return)&&e.call(i)}finally{if(t)throw t.error}}this.adapter.deregisterInteractionHandler("focus",this.focusHandler),this.adapter.deregisterInteractionHandler("blur",this.blurHandler),this.adapter.isUnbounded()&&this.adapter.deregisterResizeHandler(this.resizeHandler)},e.prototype.deregisterDeactivationHandlers=function(){var t,e;this.adapter.deregisterInteractionHandler("keyup",this.deactivateHandler);try{for(var i=r(Qi),n=i.next();!n.done;n=i.next()){var o=n.value;this.adapter.deregisterDocumentInteractionHandler(o,this.deactivateHandler)}}catch(e){t={error:e}}finally{try{n&&!n.done&&(e=i.return)&&e.call(i)}finally{if(t)throw t.error}}},e.prototype.removeCssVars=function(){var t=this,i=e.strings;Object.keys(i).forEach((function(e){0===e.indexOf("VAR_")&&t.adapter.updateCssVariable(i[e],null)}))},e.prototype.activateImpl=function(t){var e=this;if(!this.adapter.isSurfaceDisabled()){var i=this.activationState;if(!i.isActivated){var n=this.previousActivationEvent;if(!(n&&void 0!==t&&n.type!==t.type))i.isActivated=!0,i.isProgrammatic=void 0===t,i.activationEvent=t,i.wasActivatedByPointer=!i.isProgrammatic&&(void 0!==t&&("mousedown"===t.type||"touchstart"===t.type||"pointerdown"===t.type)),void 0!==t&&Ji.length>0&&Ji.some((function(t){return e.adapter.containsEventTarget(t)}))?this.resetActivationState():(void 0!==t&&(Ji.push(t.target),this.registerDeactivationHandlers(t)),i.wasElementMadeActive=this.checkElementMadeActive(t),i.wasElementMadeActive&&this.animateActivation(),requestAnimationFrame((function(){Ji=[],i.wasElementMadeActive||void 0===t||" "!==t.key&&32!==t.keyCode||(i.wasElementMadeActive=e.checkElementMadeActive(t),i.wasElementMadeActive&&e.animateActivation()),i.wasElementMadeActive||(e.activationState=e.defaultActivationState())})))}}},e.prototype.checkElementMadeActive=function(t){return void 0===t||"keydown"!==t.type||this.adapter.isSurfaceActive()},e.prototype.animateActivation=function(){var t=this,i=e.strings,n=i.VAR_FG_TRANSLATE_START,o=i.VAR_FG_TRANSLATE_END,r=e.cssClasses,s=r.FG_DEACTIVATION,a=r.FG_ACTIVATION,d=e.numbers.DEACTIVATION_TIMEOUT_MS;this.layoutInternal();var l="",c="";if(!this.adapter.isUnbounded()){var h=this.getFgTranslationCoordinates(),u=h.startPoint,p=h.endPoint;l=u.x+"px, "+u.y+"px",c=p.x+"px, "+p.y+"px"}this.adapter.updateCssVariable(n,l),this.adapter.updateCssVariable(o,c),clearTimeout(this.activationTimer),clearTimeout(this.fgDeactivationRemovalTimer),this.rmBoundedActivationClasses(),this.adapter.removeClass(s),this.adapter.computeBoundingRect(),this.adapter.addClass(a),this.activationTimer=setTimeout((function(){t.activationTimerCallback()}),d)},e.prototype.getFgTranslationCoordinates=function(){var t,e=this.activationState,i=e.activationEvent;return t=e.wasActivatedByPointer?function(t,e,i){if(!t)return{x:0,y:0};var n,o,r=e.x,s=e.y,a=r+i.left,d=s+i.top;if("touchstart"===t.type){var l=t;n=l.changedTouches[0].pageX-a,o=l.changedTouches[0].pageY-d}else{var c=t;n=c.pageX-a,o=c.pageY-d}return{x:n,y:o}}(i,this.adapter.getWindowPageOffset(),this.adapter.computeBoundingRect()):{x:this.frame.width/2,y:this.frame.height/2},{startPoint:t={x:t.x-this.initialSize/2,y:t.y-this.initialSize/2},endPoint:{x:this.frame.width/2-this.initialSize/2,y:this.frame.height/2-this.initialSize/2}}},e.prototype.runDeactivationUXLogicIfReady=function(){var t=this,i=e.cssClasses.FG_DEACTIVATION,n=this.activationState,o=n.hasDeactivationUXRun,r=n.isActivated;(o||!r)&&this.activationAnimationHasEnded&&(this.rmBoundedActivationClasses(),this.adapter.addClass(i),this.fgDeactivationRemovalTimer=setTimeout((function(){t.adapter.removeClass(i)}),Ki.FG_DEACTIVATION_MS))},e.prototype.rmBoundedActivationClasses=function(){var t=e.cssClasses.FG_ACTIVATION;this.adapter.removeClass(t),this.activationAnimationHasEnded=!1,this.adapter.computeBoundingRect()},e.prototype.resetActivationState=function(){var t=this;this.previousActivationEvent=this.activationState.activationEvent,this.activationState=this.defaultActivationState(),setTimeout((function(){return t.previousActivationEvent=void 0}),e.numbers.TAP_DELAY_MS)},e.prototype.deactivateImpl=function(){var t=this,e=this.activationState;if(e.isActivated){var i=n({},e);e.isProgrammatic?(requestAnimationFrame((function(){t.animateDeactivation(i)})),this.resetActivationState()):(this.deregisterDeactivationHandlers(),requestAnimationFrame((function(){t.activationState.hasDeactivationUXRun=!0,t.animateDeactivation(i),t.resetActivationState()})))}},e.prototype.animateDeactivation=function(t){var e=t.wasActivatedByPointer,i=t.wasElementMadeActive;(e||i)&&this.runDeactivationUXLogicIfReady()},e.prototype.layoutInternal=function(){var t=this;this.frame=this.adapter.computeBoundingRect();var i=Math.max(this.frame.height,this.frame.width);this.maxRadius=this.adapter.isUnbounded()?i:Math.sqrt(Math.pow(t.frame.width,2)+Math.pow(t.frame.height,2))+e.numbers.PADDING;var n=Math.floor(i*e.numbers.INITIAL_ORIGIN_SCALE);this.adapter.isUnbounded()&&n%2!=0?this.initialSize=n-1:this.initialSize=n,this.fgScale=""+this.maxRadius/this.initialSize,this.updateLayoutCssVars()},e.prototype.updateLayoutCssVars=function(){var t=e.strings,i=t.VAR_FG_SIZE,n=t.VAR_LEFT,o=t.VAR_TOP,r=t.VAR_FG_SCALE;this.adapter.updateCssVariable(i,this.initialSize+"px"),this.adapter.updateCssVariable(r,this.fgScale),this.adapter.isUnbounded()&&(this.unboundedCoords={left:Math.round(this.frame.width/2-this.initialSize/2),top:Math.round(this.frame.height/2-this.initialSize/2)},this.adapter.updateCssVariable(n,this.unboundedCoords.left+"px"),this.adapter.updateCssVariable(o,this.unboundedCoords.top+"px"))},e}(ee); -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -class en extends he{constructor(){super(...arguments),this.primary=!1,this.accent=!1,this.unbounded=!1,this.disabled=!1,this.activated=!1,this.selected=!1,this.internalUseStateLayerCustomProperties=!1,this.hovering=!1,this.bgFocused=!1,this.fgActivation=!1,this.fgDeactivation=!1,this.fgScale="",this.fgSize="",this.translateStart="",this.translateEnd="",this.leftPos="",this.topPos="",this.mdcFoundationClass=tn}get isActive(){return t=this.parentElement||this,e=":active",(t.matches||t.webkitMatchesSelector||t.msMatchesSelector).call(t,e); -/** - * @license - * Copyright 2018 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -var t,e}createAdapter(){return{browserSupportsCssVars:()=>!0,isUnbounded:()=>this.unbounded,isSurfaceActive:()=>this.isActive,isSurfaceDisabled:()=>this.disabled,addClass:t=>{switch(t){case"mdc-ripple-upgraded--background-focused":this.bgFocused=!0;break;case"mdc-ripple-upgraded--foreground-activation":this.fgActivation=!0;break;case"mdc-ripple-upgraded--foreground-deactivation":this.fgDeactivation=!0}},removeClass:t=>{switch(t){case"mdc-ripple-upgraded--background-focused":this.bgFocused=!1;break;case"mdc-ripple-upgraded--foreground-activation":this.fgActivation=!1;break;case"mdc-ripple-upgraded--foreground-deactivation":this.fgDeactivation=!1}},containsEventTarget:()=>!0,registerInteractionHandler:()=>{},deregisterInteractionHandler:()=>{},registerDocumentInteractionHandler:()=>{},deregisterDocumentInteractionHandler:()=>{},registerResizeHandler:()=>{},deregisterResizeHandler:()=>{},updateCssVariable:(t,e)=>{switch(t){case"--mdc-ripple-fg-scale":this.fgScale=e;break;case"--mdc-ripple-fg-size":this.fgSize=e;break;case"--mdc-ripple-fg-translate-end":this.translateEnd=e;break;case"--mdc-ripple-fg-translate-start":this.translateStart=e;break;case"--mdc-ripple-left":this.leftPos=e;break;case"--mdc-ripple-top":this.topPos=e}},computeBoundingRect:()=>(this.parentElement||this).getBoundingClientRect(),getWindowPageOffset:()=>({x:window.pageXOffset,y:window.pageYOffset})}}startPress(t){this.waitForFoundation((()=>{this.mdcFoundation.activate(t)}))}endPress(){this.waitForFoundation((()=>{this.mdcFoundation.deactivate()}))}startFocus(){this.waitForFoundation((()=>{this.mdcFoundation.handleFocus()}))}endFocus(){this.waitForFoundation((()=>{this.mdcFoundation.handleBlur()}))}startHover(){this.hovering=!0}endHover(){this.hovering=!1}waitForFoundation(t){this.mdcFoundation?t():this.updateComplete.then(t)}update(t){t.has("disabled")&&this.disabled&&this.endHover(),super.update(t)}render(){const t=this.activated&&(this.primary||!this.accent),e=this.selected&&(this.primary||!this.accent),i={"mdc-ripple-surface--accent":this.accent,"mdc-ripple-surface--primary--activated":t,"mdc-ripple-surface--accent--activated":this.accent&&this.activated,"mdc-ripple-surface--primary--selected":e,"mdc-ripple-surface--accent--selected":this.accent&&this.selected,"mdc-ripple-surface--disabled":this.disabled,"mdc-ripple-surface--hover":this.hovering,"mdc-ripple-surface--primary":this.primary,"mdc-ripple-surface--selected":this.selected,"mdc-ripple-upgraded--background-focused":this.bgFocused,"mdc-ripple-upgraded--foreground-activation":this.fgActivation,"mdc-ripple-upgraded--foreground-deactivation":this.fgDeactivation,"mdc-ripple-upgraded--unbounded":this.unbounded,"mdc-ripple-surface--internal-use-state-layer-custom-properties":this.internalUseStateLayerCustomProperties};return $` -
`}}o([Mt(".mdc-ripple-surface")],en.prototype,"mdcRoot",void 0),o([At({type:Boolean})],en.prototype,"primary",void 0),o([At({type:Boolean})],en.prototype,"accent",void 0),o([At({type:Boolean})],en.prototype,"unbounded",void 0),o([At({type:Boolean})],en.prototype,"disabled",void 0),o([At({type:Boolean})],en.prototype,"activated",void 0),o([At({type:Boolean})],en.prototype,"selected",void 0),o([At({type:Boolean})],en.prototype,"internalUseStateLayerCustomProperties",void 0),o([Rt()],en.prototype,"hovering",void 0),o([Rt()],en.prototype,"bgFocused",void 0),o([Rt()],en.prototype,"fgActivation",void 0),o([Rt()],en.prototype,"fgDeactivation",void 0),o([Rt()],en.prototype,"fgScale",void 0),o([Rt()],en.prototype,"fgSize",void 0),o([Rt()],en.prototype,"translateStart",void 0),o([Rt()],en.prototype,"translateEnd",void 0),o([Rt()],en.prototype,"leftPos",void 0),o([Rt()],en.prototype,"topPos",void 0); -/** - * @license - * Copyright 2018 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -var nn={NOTCH_ELEMENT_SELECTOR:".mdc-notched-outline__notch"},on={NOTCH_ELEMENT_PADDING:8},rn={NO_LABEL:"mdc-notched-outline--no-label",OUTLINE_NOTCHED:"mdc-notched-outline--notched",OUTLINE_UPGRADED:"mdc-notched-outline--upgraded"},sn=function(t){function e(i){return t.call(this,n(n({},e.defaultAdapter),i))||this}return i(e,t),Object.defineProperty(e,"strings",{get:function(){return nn},enumerable:!1,configurable:!0}),Object.defineProperty(e,"cssClasses",{get:function(){return rn},enumerable:!1,configurable:!0}),Object.defineProperty(e,"numbers",{get:function(){return on},enumerable:!1,configurable:!0}),Object.defineProperty(e,"defaultAdapter",{get:function(){return{addClass:function(){},removeClass:function(){},setNotchWidthProperty:function(){},removeNotchWidthProperty:function(){}}},enumerable:!1,configurable:!0}),e.prototype.notch=function(t){var i=e.cssClasses.OUTLINE_NOTCHED;t>0&&(t+=on.NOTCH_ELEMENT_PADDING),this.adapter.setNotchWidthProperty(t),this.adapter.addClass(i)},e.prototype.closeNotch=function(){var t=e.cssClasses.OUTLINE_NOTCHED;this.adapter.removeClass(t),this.adapter.removeNotchWidthProperty()},e}(ee); -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -class an extends he{constructor(){super(...arguments),this.mdcFoundationClass=sn,this.width=0,this.open=!1,this.lastOpen=this.open}createAdapter(){return{addClass:t=>this.mdcRoot.classList.add(t),removeClass:t=>this.mdcRoot.classList.remove(t),setNotchWidthProperty:t=>this.notchElement.style.setProperty("width",`${t}px`),removeNotchWidthProperty:()=>this.notchElement.style.removeProperty("width")}}openOrClose(t,e){this.mdcFoundation&&(t&&void 0!==e?this.mdcFoundation.notch(e):this.mdcFoundation.closeNotch())}render(){this.openOrClose(this.open,this.width);const t=we({"mdc-notched-outline--notched":this.open});return $` - - - - - - - `}}o([Mt(".mdc-notched-outline")],an.prototype,"mdcRoot",void 0),o([At({type:Number})],an.prototype,"width",void 0),o([At({type:Boolean,reflect:!0})],an.prototype,"open",void 0),o([Mt(".mdc-notched-outline__notch")],an.prototype,"notchElement",void 0); -/** - * @license - * Copyright 2021 Google LLC - * SPDX-LIcense-Identifier: Apache-2.0 - */ -const dn=ht`.mdc-floating-label{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-subtitle1-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:1rem;font-size:var(--mdc-typography-subtitle1-font-size, 1rem);font-weight:400;font-weight:var(--mdc-typography-subtitle1-font-weight, 400);letter-spacing:0.009375em;letter-spacing:var(--mdc-typography-subtitle1-letter-spacing, 0.009375em);text-decoration:inherit;text-decoration:var(--mdc-typography-subtitle1-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-subtitle1-text-transform, inherit);position:absolute;left:0;-webkit-transform-origin:left top;transform-origin:left top;line-height:1.15rem;text-align:left;text-overflow:ellipsis;white-space:nowrap;cursor:text;overflow:hidden;will-change:transform;transition:transform 150ms cubic-bezier(0.4, 0, 0.2, 1),color 150ms cubic-bezier(0.4, 0, 0.2, 1)}[dir=rtl] .mdc-floating-label,.mdc-floating-label[dir=rtl]{right:0;left:auto;-webkit-transform-origin:right top;transform-origin:right top;text-align:right}.mdc-floating-label--float-above{cursor:auto}.mdc-floating-label--required::after{margin-left:1px;margin-right:0px;content:"*"}[dir=rtl] .mdc-floating-label--required::after,.mdc-floating-label--required[dir=rtl]::after{margin-left:0;margin-right:1px}.mdc-floating-label--float-above{transform:translateY(-106%) scale(0.75)}.mdc-floating-label--shake{animation:mdc-floating-label-shake-float-above-standard 250ms 1}@keyframes mdc-floating-label-shake-float-above-standard{0%{transform:translateX(calc(0 - 0%)) translateY(-106%) scale(0.75)}33%{animation-timing-function:cubic-bezier(0.5, 0, 0.701732, 0.495819);transform:translateX(calc(4% - 0%)) translateY(-106%) scale(0.75)}66%{animation-timing-function:cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);transform:translateX(calc(-4% - 0%)) translateY(-106%) scale(0.75)}100%{transform:translateX(calc(0 - 0%)) translateY(-106%) scale(0.75)}}@keyframes mdc-ripple-fg-radius-in{from{animation-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transform:translate(var(--mdc-ripple-fg-translate-start, 0)) scale(1)}to{transform:translate(var(--mdc-ripple-fg-translate-end, 0)) scale(var(--mdc-ripple-fg-scale, 1))}}@keyframes mdc-ripple-fg-opacity-in{from{animation-timing-function:linear;opacity:0}to{opacity:var(--mdc-ripple-fg-opacity, 0)}}@keyframes mdc-ripple-fg-opacity-out{from{animation-timing-function:linear;opacity:var(--mdc-ripple-fg-opacity, 0)}to{opacity:0}}.mdc-line-ripple::before,.mdc-line-ripple::after{position:absolute;bottom:0;left:0;width:100%;border-bottom-style:solid;content:""}.mdc-line-ripple::before{border-bottom-width:1px}.mdc-line-ripple::before{z-index:1}.mdc-line-ripple::after{transform:scaleX(0);border-bottom-width:2px;opacity:0;z-index:2}.mdc-line-ripple::after{transition:transform 180ms cubic-bezier(0.4, 0, 0.2, 1),opacity 180ms cubic-bezier(0.4, 0, 0.2, 1)}.mdc-line-ripple--active::after{transform:scaleX(1);opacity:1}.mdc-line-ripple--deactivating::after{opacity:0}.mdc-notched-outline{display:flex;position:absolute;top:0;right:0;left:0;box-sizing:border-box;width:100%;max-width:100%;height:100%;text-align:left;pointer-events:none}[dir=rtl] .mdc-notched-outline,.mdc-notched-outline[dir=rtl]{text-align:right}.mdc-notched-outline__leading,.mdc-notched-outline__notch,.mdc-notched-outline__trailing{box-sizing:border-box;height:100%;border-top:1px solid;border-bottom:1px solid;pointer-events:none}.mdc-notched-outline__leading{border-left:1px solid;border-right:none;width:12px}[dir=rtl] .mdc-notched-outline__leading,.mdc-notched-outline__leading[dir=rtl]{border-left:none;border-right:1px solid}.mdc-notched-outline__trailing{border-left:none;border-right:1px solid;flex-grow:1}[dir=rtl] .mdc-notched-outline__trailing,.mdc-notched-outline__trailing[dir=rtl]{border-left:1px solid;border-right:none}.mdc-notched-outline__notch{flex:0 0 auto;width:auto;max-width:calc(100% - 12px * 2)}.mdc-notched-outline .mdc-floating-label{display:inline-block;position:relative;max-width:100%}.mdc-notched-outline .mdc-floating-label--float-above{text-overflow:clip}.mdc-notched-outline--upgraded .mdc-floating-label--float-above{max-width:calc(100% / 0.75)}.mdc-notched-outline--notched .mdc-notched-outline__notch{padding-left:0;padding-right:8px;border-top:none}[dir=rtl] .mdc-notched-outline--notched .mdc-notched-outline__notch,.mdc-notched-outline--notched .mdc-notched-outline__notch[dir=rtl]{padding-left:8px;padding-right:0}.mdc-notched-outline--no-label .mdc-notched-outline__notch{display:none}.mdc-select{display:inline-flex;position:relative}.mdc-select:not(.mdc-select--disabled) .mdc-select__selected-text{color:rgba(0, 0, 0, 0.87)}.mdc-select.mdc-select--disabled .mdc-select__selected-text{color:rgba(0, 0, 0, 0.38)}.mdc-select:not(.mdc-select--disabled) .mdc-floating-label{color:rgba(0, 0, 0, 0.6)}.mdc-select:not(.mdc-select--disabled).mdc-select--focused .mdc-floating-label{color:rgba(98, 0, 238, 0.87)}.mdc-select.mdc-select--disabled .mdc-floating-label{color:rgba(0, 0, 0, 0.38)}.mdc-select:not(.mdc-select--disabled) .mdc-select__dropdown-icon{fill:rgba(0, 0, 0, 0.54)}.mdc-select:not(.mdc-select--disabled).mdc-select--focused .mdc-select__dropdown-icon{fill:#6200ee;fill:var(--mdc-theme-primary, #6200ee)}.mdc-select.mdc-select--disabled .mdc-select__dropdown-icon{fill:rgba(0, 0, 0, 0.38)}.mdc-select:not(.mdc-select--disabled)+.mdc-select-helper-text{color:rgba(0, 0, 0, 0.6)}.mdc-select.mdc-select--disabled+.mdc-select-helper-text{color:rgba(0, 0, 0, 0.38)}.mdc-select:not(.mdc-select--disabled) .mdc-select__icon{color:rgba(0, 0, 0, 0.54)}.mdc-select.mdc-select--disabled .mdc-select__icon{color:rgba(0, 0, 0, 0.38)}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-select.mdc-select--disabled .mdc-select__selected-text{color:GrayText}.mdc-select.mdc-select--disabled .mdc-select__dropdown-icon{fill:red}.mdc-select.mdc-select--disabled .mdc-floating-label{color:GrayText}.mdc-select.mdc-select--disabled .mdc-line-ripple::before{border-bottom-color:GrayText}.mdc-select.mdc-select--disabled .mdc-notched-outline__leading,.mdc-select.mdc-select--disabled .mdc-notched-outline__notch,.mdc-select.mdc-select--disabled .mdc-notched-outline__trailing{border-color:GrayText}.mdc-select.mdc-select--disabled .mdc-select__icon{color:GrayText}.mdc-select.mdc-select--disabled+.mdc-select-helper-text{color:GrayText}}.mdc-select .mdc-floating-label{top:50%;transform:translateY(-50%);pointer-events:none}.mdc-select .mdc-select__anchor{padding-left:16px;padding-right:0}[dir=rtl] .mdc-select .mdc-select__anchor,.mdc-select .mdc-select__anchor[dir=rtl]{padding-left:0;padding-right:16px}.mdc-select.mdc-select--with-leading-icon .mdc-select__anchor{padding-left:0;padding-right:0}[dir=rtl] .mdc-select.mdc-select--with-leading-icon .mdc-select__anchor,.mdc-select.mdc-select--with-leading-icon .mdc-select__anchor[dir=rtl]{padding-left:0;padding-right:0}.mdc-select .mdc-select__icon{width:24px;height:24px;font-size:24px}.mdc-select .mdc-select__dropdown-icon{width:24px;height:24px}.mdc-select .mdc-select__menu .mdc-deprecated-list-item{padding-left:16px;padding-right:16px}[dir=rtl] .mdc-select .mdc-select__menu .mdc-deprecated-list-item,.mdc-select .mdc-select__menu .mdc-deprecated-list-item[dir=rtl]{padding-left:16px;padding-right:16px}.mdc-select .mdc-select__menu .mdc-deprecated-list-item__graphic{margin-left:0;margin-right:12px}[dir=rtl] .mdc-select .mdc-select__menu .mdc-deprecated-list-item__graphic,.mdc-select .mdc-select__menu .mdc-deprecated-list-item__graphic[dir=rtl]{margin-left:12px;margin-right:0}.mdc-select__dropdown-icon{margin-left:12px;margin-right:12px;display:inline-flex;position:relative;align-self:center;align-items:center;justify-content:center;flex-shrink:0;pointer-events:none}.mdc-select__dropdown-icon .mdc-select__dropdown-icon-active,.mdc-select__dropdown-icon .mdc-select__dropdown-icon-inactive{position:absolute;top:0;left:0}.mdc-select__dropdown-icon .mdc-select__dropdown-icon-graphic{width:41.6666666667%;height:20.8333333333%}.mdc-select__dropdown-icon .mdc-select__dropdown-icon-inactive{opacity:1;transition:opacity 75ms linear 75ms}.mdc-select__dropdown-icon .mdc-select__dropdown-icon-active{opacity:0;transition:opacity 75ms linear}[dir=rtl] .mdc-select__dropdown-icon,.mdc-select__dropdown-icon[dir=rtl]{margin-left:12px;margin-right:12px}.mdc-select--activated .mdc-select__dropdown-icon .mdc-select__dropdown-icon-inactive{opacity:0;transition:opacity 49.5ms linear}.mdc-select--activated .mdc-select__dropdown-icon .mdc-select__dropdown-icon-active{opacity:1;transition:opacity 100.5ms linear 49.5ms}.mdc-select__anchor{width:200px;min-width:0;flex:1 1 auto;position:relative;box-sizing:border-box;overflow:hidden;outline:none;cursor:pointer}.mdc-select__anchor .mdc-floating-label--float-above{transform:translateY(-106%) scale(0.75)}.mdc-select__selected-text-container{display:flex;appearance:none;pointer-events:none;box-sizing:border-box;width:auto;min-width:0;flex-grow:1;height:28px;border:none;outline:none;padding:0;background-color:transparent;color:inherit}.mdc-select__selected-text{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-subtitle1-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:1rem;font-size:var(--mdc-typography-subtitle1-font-size, 1rem);line-height:1.75rem;line-height:var(--mdc-typography-subtitle1-line-height, 1.75rem);font-weight:400;font-weight:var(--mdc-typography-subtitle1-font-weight, 400);letter-spacing:0.009375em;letter-spacing:var(--mdc-typography-subtitle1-letter-spacing, 0.009375em);text-decoration:inherit;text-decoration:var(--mdc-typography-subtitle1-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-subtitle1-text-transform, inherit);text-overflow:ellipsis;white-space:nowrap;overflow:hidden;display:block;width:100%;text-align:left}[dir=rtl] .mdc-select__selected-text,.mdc-select__selected-text[dir=rtl]{text-align:right}.mdc-select--invalid:not(.mdc-select--disabled) .mdc-floating-label{color:#b00020;color:var(--mdc-theme-error, #b00020)}.mdc-select--invalid:not(.mdc-select--disabled).mdc-select--focused .mdc-floating-label{color:#b00020;color:var(--mdc-theme-error, #b00020)}.mdc-select--invalid:not(.mdc-select--disabled).mdc-select--invalid+.mdc-select-helper-text--validation-msg{color:#b00020;color:var(--mdc-theme-error, #b00020)}.mdc-select--invalid:not(.mdc-select--disabled) .mdc-select__dropdown-icon{fill:#b00020;fill:var(--mdc-theme-error, #b00020)}.mdc-select--invalid:not(.mdc-select--disabled).mdc-select--focused .mdc-select__dropdown-icon{fill:#b00020;fill:var(--mdc-theme-error, #b00020)}.mdc-select--disabled{cursor:default;pointer-events:none}.mdc-select--with-leading-icon .mdc-select__menu .mdc-deprecated-list-item{padding-left:12px;padding-right:12px}[dir=rtl] .mdc-select--with-leading-icon .mdc-select__menu .mdc-deprecated-list-item,.mdc-select--with-leading-icon .mdc-select__menu .mdc-deprecated-list-item[dir=rtl]{padding-left:12px;padding-right:12px}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-select__menu::before{position:absolute;box-sizing:border-box;width:100%;height:100%;top:0;left:0;border:1px solid transparent;border-radius:inherit;content:"";pointer-events:none}}@media screen and (forced-colors: active)and (forced-colors: active),screen and (-ms-high-contrast: active)and (forced-colors: active){.mdc-select__menu::before{border-color:CanvasText}}.mdc-select__menu .mdc-deprecated-list .mdc-select__icon,.mdc-select__menu .mdc-list .mdc-select__icon{margin-left:0;margin-right:0}[dir=rtl] .mdc-select__menu .mdc-deprecated-list .mdc-select__icon,[dir=rtl] .mdc-select__menu .mdc-list .mdc-select__icon,.mdc-select__menu .mdc-deprecated-list .mdc-select__icon[dir=rtl],.mdc-select__menu .mdc-list .mdc-select__icon[dir=rtl]{margin-left:0;margin-right:0}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected,.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--activated,.mdc-select__menu .mdc-list .mdc-deprecated-list-item--selected,.mdc-select__menu .mdc-list .mdc-deprecated-list-item--activated{color:#000;color:var(--mdc-theme-on-surface, #000)}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected .mdc-deprecated-list-item__graphic,.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--activated .mdc-deprecated-list-item__graphic,.mdc-select__menu .mdc-list .mdc-deprecated-list-item--selected .mdc-deprecated-list-item__graphic,.mdc-select__menu .mdc-list .mdc-deprecated-list-item--activated .mdc-deprecated-list-item__graphic{color:#000;color:var(--mdc-theme-on-surface, #000)}.mdc-select__menu .mdc-list-item__start{display:inline-flex;align-items:center}.mdc-select__option{padding-left:16px;padding-right:16px}[dir=rtl] .mdc-select__option,.mdc-select__option[dir=rtl]{padding-left:16px;padding-right:16px}.mdc-select__one-line-option.mdc-list-item--with-one-line{height:48px}.mdc-select__two-line-option.mdc-list-item--with-two-lines{height:64px}.mdc-select__two-line-option.mdc-list-item--with-two-lines .mdc-list-item__start{margin-top:20px}.mdc-select__two-line-option.mdc-list-item--with-two-lines .mdc-list-item__primary-text{display:block;margin-top:0;line-height:normal;margin-bottom:-20px}.mdc-select__two-line-option.mdc-list-item--with-two-lines .mdc-list-item__primary-text::before{display:inline-block;width:0;height:28px;content:"";vertical-align:0}.mdc-select__two-line-option.mdc-list-item--with-two-lines .mdc-list-item__primary-text::after{display:inline-block;width:0;height:20px;content:"";vertical-align:-20px}.mdc-select__two-line-option.mdc-list-item--with-two-lines.mdc-list-item--with-trailing-meta .mdc-list-item__end{display:block;margin-top:0;line-height:normal}.mdc-select__two-line-option.mdc-list-item--with-two-lines.mdc-list-item--with-trailing-meta .mdc-list-item__end::before{display:inline-block;width:0;height:36px;content:"";vertical-align:0}.mdc-select__option-with-leading-content{padding-left:0;padding-right:12px}.mdc-select__option-with-leading-content.mdc-list-item{padding-left:0;padding-right:auto}[dir=rtl] .mdc-select__option-with-leading-content.mdc-list-item,.mdc-select__option-with-leading-content.mdc-list-item[dir=rtl]{padding-left:auto;padding-right:0}.mdc-select__option-with-leading-content .mdc-list-item__start{margin-left:12px;margin-right:0}[dir=rtl] .mdc-select__option-with-leading-content .mdc-list-item__start,.mdc-select__option-with-leading-content .mdc-list-item__start[dir=rtl]{margin-left:0;margin-right:12px}.mdc-select__option-with-leading-content .mdc-list-item__start{width:36px;height:24px}[dir=rtl] .mdc-select__option-with-leading-content,.mdc-select__option-with-leading-content[dir=rtl]{padding-left:12px;padding-right:0}.mdc-select__option-with-meta.mdc-list-item{padding-left:auto;padding-right:0}[dir=rtl] .mdc-select__option-with-meta.mdc-list-item,.mdc-select__option-with-meta.mdc-list-item[dir=rtl]{padding-left:0;padding-right:auto}.mdc-select__option-with-meta .mdc-list-item__end{margin-left:12px;margin-right:12px}[dir=rtl] .mdc-select__option-with-meta .mdc-list-item__end,.mdc-select__option-with-meta .mdc-list-item__end[dir=rtl]{margin-left:12px;margin-right:12px}.mdc-select--filled .mdc-select__anchor{height:56px;display:flex;align-items:baseline}.mdc-select--filled .mdc-select__anchor::before{display:inline-block;width:0;height:40px;content:"";vertical-align:0}.mdc-select--filled.mdc-select--no-label .mdc-select__anchor .mdc-select__selected-text::before{content:"​"}.mdc-select--filled.mdc-select--no-label .mdc-select__anchor .mdc-select__selected-text-container{height:100%;display:inline-flex;align-items:center}.mdc-select--filled.mdc-select--no-label .mdc-select__anchor::before{display:none}.mdc-select--filled .mdc-select__anchor{border-top-left-radius:4px;border-top-left-radius:var(--mdc-shape-small, 4px);border-top-right-radius:4px;border-top-right-radius:var(--mdc-shape-small, 4px);border-bottom-right-radius:0;border-bottom-left-radius:0}.mdc-select--filled:not(.mdc-select--disabled) .mdc-select__anchor{background-color:whitesmoke}.mdc-select--filled.mdc-select--disabled .mdc-select__anchor{background-color:#fafafa}.mdc-select--filled:not(.mdc-select--disabled) .mdc-line-ripple::before{border-bottom-color:rgba(0, 0, 0, 0.42)}.mdc-select--filled:not(.mdc-select--disabled):hover .mdc-line-ripple::before{border-bottom-color:rgba(0, 0, 0, 0.87)}.mdc-select--filled:not(.mdc-select--disabled) .mdc-line-ripple::after{border-bottom-color:#6200ee;border-bottom-color:var(--mdc-theme-primary, #6200ee)}.mdc-select--filled.mdc-select--disabled .mdc-line-ripple::before{border-bottom-color:rgba(0, 0, 0, 0.06)}.mdc-select--filled .mdc-floating-label{max-width:calc(100% - 64px)}.mdc-select--filled .mdc-floating-label--float-above{max-width:calc(100% / 0.75 - 64px / 0.75)}.mdc-select--filled .mdc-menu-surface--is-open-below{border-top-left-radius:0px;border-top-right-radius:0px}.mdc-select--filled.mdc-select--focused.mdc-line-ripple::after{transform:scale(1, 2);opacity:1}.mdc-select--filled .mdc-floating-label{left:16px;right:initial}[dir=rtl] .mdc-select--filled .mdc-floating-label,.mdc-select--filled .mdc-floating-label[dir=rtl]{left:initial;right:16px}.mdc-select--filled.mdc-select--with-leading-icon .mdc-floating-label{left:48px;right:initial}[dir=rtl] .mdc-select--filled.mdc-select--with-leading-icon .mdc-floating-label,.mdc-select--filled.mdc-select--with-leading-icon .mdc-floating-label[dir=rtl]{left:initial;right:48px}.mdc-select--filled.mdc-select--with-leading-icon .mdc-floating-label{max-width:calc(100% - 96px)}.mdc-select--filled.mdc-select--with-leading-icon .mdc-floating-label--float-above{max-width:calc(100% / 0.75 - 96px / 0.75)}.mdc-select--invalid:not(.mdc-select--disabled) .mdc-line-ripple::before{border-bottom-color:#b00020;border-bottom-color:var(--mdc-theme-error, #b00020)}.mdc-select--invalid:not(.mdc-select--disabled):hover .mdc-line-ripple::before{border-bottom-color:#b00020;border-bottom-color:var(--mdc-theme-error, #b00020)}.mdc-select--invalid:not(.mdc-select--disabled) .mdc-line-ripple::after{border-bottom-color:#b00020;border-bottom-color:var(--mdc-theme-error, #b00020)}.mdc-select--outlined{border:none}.mdc-select--outlined .mdc-select__anchor{height:56px}.mdc-select--outlined .mdc-select__anchor .mdc-floating-label--float-above{transform:translateY(-37.25px) scale(1)}.mdc-select--outlined .mdc-select__anchor .mdc-floating-label--float-above{font-size:.75rem}.mdc-select--outlined .mdc-select__anchor.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-select--outlined .mdc-select__anchor .mdc-notched-outline--upgraded .mdc-floating-label--float-above{transform:translateY(-34.75px) scale(0.75)}.mdc-select--outlined .mdc-select__anchor.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-select--outlined .mdc-select__anchor .mdc-notched-outline--upgraded .mdc-floating-label--float-above{font-size:1rem}.mdc-select--outlined .mdc-select__anchor .mdc-floating-label--shake{animation:mdc-floating-label-shake-float-above-select-outlined-56px 250ms 1}@keyframes mdc-floating-label-shake-float-above-select-outlined-56px{0%{transform:translateX(calc(0 - 0%)) translateY(-34.75px) scale(0.75)}33%{animation-timing-function:cubic-bezier(0.5, 0, 0.701732, 0.495819);transform:translateX(calc(4% - 0%)) translateY(-34.75px) scale(0.75)}66%{animation-timing-function:cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);transform:translateX(calc(-4% - 0%)) translateY(-34.75px) scale(0.75)}100%{transform:translateX(calc(0 - 0%)) translateY(-34.75px) scale(0.75)}}.mdc-select--outlined .mdc-notched-outline .mdc-notched-outline__leading{border-top-left-radius:4px;border-top-left-radius:var(--mdc-shape-small, 4px);border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:4px;border-bottom-left-radius:var(--mdc-shape-small, 4px)}[dir=rtl] .mdc-select--outlined .mdc-notched-outline .mdc-notched-outline__leading,.mdc-select--outlined .mdc-notched-outline .mdc-notched-outline__leading[dir=rtl]{border-top-left-radius:0;border-top-right-radius:4px;border-top-right-radius:var(--mdc-shape-small, 4px);border-bottom-right-radius:4px;border-bottom-right-radius:var(--mdc-shape-small, 4px);border-bottom-left-radius:0}@supports(top: max(0%)){.mdc-select--outlined .mdc-notched-outline .mdc-notched-outline__leading{width:max(12px, var(--mdc-shape-small, 4px))}}@supports(top: max(0%)){.mdc-select--outlined .mdc-notched-outline .mdc-notched-outline__notch{max-width:calc(100% - max(12px, var(--mdc-shape-small, 4px)) * 2)}}.mdc-select--outlined .mdc-notched-outline .mdc-notched-outline__trailing{border-top-left-radius:0;border-top-right-radius:4px;border-top-right-radius:var(--mdc-shape-small, 4px);border-bottom-right-radius:4px;border-bottom-right-radius:var(--mdc-shape-small, 4px);border-bottom-left-radius:0}[dir=rtl] .mdc-select--outlined .mdc-notched-outline .mdc-notched-outline__trailing,.mdc-select--outlined .mdc-notched-outline .mdc-notched-outline__trailing[dir=rtl]{border-top-left-radius:4px;border-top-left-radius:var(--mdc-shape-small, 4px);border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:4px;border-bottom-left-radius:var(--mdc-shape-small, 4px)}@supports(top: max(0%)){.mdc-select--outlined .mdc-select__anchor{padding-left:max(16px, calc(var(--mdc-shape-small, 4px) + 4px))}}[dir=rtl] .mdc-select--outlined .mdc-select__anchor,.mdc-select--outlined .mdc-select__anchor[dir=rtl]{padding-left:0}@supports(top: max(0%)){[dir=rtl] .mdc-select--outlined .mdc-select__anchor,.mdc-select--outlined .mdc-select__anchor[dir=rtl]{padding-right:max(16px, calc(var(--mdc-shape-small, 4px) + 4px))}}@supports(top: max(0%)){.mdc-select--outlined+.mdc-select-helper-text{margin-left:max(16px, calc(var(--mdc-shape-small, 4px) + 4px))}}[dir=rtl] .mdc-select--outlined+.mdc-select-helper-text,.mdc-select--outlined+.mdc-select-helper-text[dir=rtl]{margin-left:0}@supports(top: max(0%)){[dir=rtl] .mdc-select--outlined+.mdc-select-helper-text,.mdc-select--outlined+.mdc-select-helper-text[dir=rtl]{margin-right:max(16px, calc(var(--mdc-shape-small, 4px) + 4px))}}.mdc-select--outlined:not(.mdc-select--disabled) .mdc-select__anchor{background-color:transparent}.mdc-select--outlined.mdc-select--disabled .mdc-select__anchor{background-color:transparent}.mdc-select--outlined:not(.mdc-select--disabled) .mdc-notched-outline__leading,.mdc-select--outlined:not(.mdc-select--disabled) .mdc-notched-outline__notch,.mdc-select--outlined:not(.mdc-select--disabled) .mdc-notched-outline__trailing{border-color:rgba(0, 0, 0, 0.38)}.mdc-select--outlined:not(.mdc-select--disabled):not(.mdc-select--focused) .mdc-select__anchor:hover .mdc-notched-outline .mdc-notched-outline__leading,.mdc-select--outlined:not(.mdc-select--disabled):not(.mdc-select--focused) .mdc-select__anchor:hover .mdc-notched-outline .mdc-notched-outline__notch,.mdc-select--outlined:not(.mdc-select--disabled):not(.mdc-select--focused) .mdc-select__anchor:hover .mdc-notched-outline .mdc-notched-outline__trailing{border-color:rgba(0, 0, 0, 0.87)}.mdc-select--outlined:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__leading,.mdc-select--outlined:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__notch,.mdc-select--outlined:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__trailing{border-width:2px}.mdc-select--outlined:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__leading,.mdc-select--outlined:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__notch,.mdc-select--outlined:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__trailing{border-color:#6200ee;border-color:var(--mdc-theme-primary, #6200ee)}.mdc-select--outlined.mdc-select--disabled .mdc-notched-outline__leading,.mdc-select--outlined.mdc-select--disabled .mdc-notched-outline__notch,.mdc-select--outlined.mdc-select--disabled .mdc-notched-outline__trailing{border-color:rgba(0, 0, 0, 0.06)}.mdc-select--outlined .mdc-select__anchor :not(.mdc-notched-outline--notched) .mdc-notched-outline__notch{max-width:calc(100% - 60px)}.mdc-select--outlined .mdc-select__anchor{display:flex;align-items:baseline;overflow:visible}.mdc-select--outlined .mdc-select__anchor .mdc-floating-label--shake{animation:mdc-floating-label-shake-float-above-select-outlined 250ms 1}.mdc-select--outlined .mdc-select__anchor .mdc-floating-label--float-above{transform:translateY(-37.25px) scale(1)}.mdc-select--outlined .mdc-select__anchor .mdc-floating-label--float-above{font-size:.75rem}.mdc-select--outlined .mdc-select__anchor.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-select--outlined .mdc-select__anchor .mdc-notched-outline--upgraded .mdc-floating-label--float-above{transform:translateY(-34.75px) scale(0.75)}.mdc-select--outlined .mdc-select__anchor.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-select--outlined .mdc-select__anchor .mdc-notched-outline--upgraded .mdc-floating-label--float-above{font-size:1rem}.mdc-select--outlined .mdc-select__anchor .mdc-notched-outline--notched .mdc-notched-outline__notch{padding-top:1px}.mdc-select--outlined .mdc-select__anchor .mdc-select__selected-text::before{content:"​"}.mdc-select--outlined .mdc-select__anchor .mdc-select__selected-text-container{height:100%;display:inline-flex;align-items:center}.mdc-select--outlined .mdc-select__anchor::before{display:none}.mdc-select--outlined .mdc-select__selected-text-container{display:flex;border:none;z-index:1;background-color:transparent}.mdc-select--outlined .mdc-select__icon{z-index:2}.mdc-select--outlined .mdc-floating-label{line-height:1.15rem;left:4px;right:initial}[dir=rtl] .mdc-select--outlined .mdc-floating-label,.mdc-select--outlined .mdc-floating-label[dir=rtl]{left:initial;right:4px}.mdc-select--outlined.mdc-select--focused .mdc-notched-outline--notched .mdc-notched-outline__notch{padding-top:2px}.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled) .mdc-notched-outline__leading,.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled) .mdc-notched-outline__notch,.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled) .mdc-notched-outline__trailing{border-color:#b00020;border-color:var(--mdc-theme-error, #b00020)}.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled):not(.mdc-select--focused) .mdc-select__anchor:hover .mdc-notched-outline .mdc-notched-outline__leading,.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled):not(.mdc-select--focused) .mdc-select__anchor:hover .mdc-notched-outline .mdc-notched-outline__notch,.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled):not(.mdc-select--focused) .mdc-select__anchor:hover .mdc-notched-outline .mdc-notched-outline__trailing{border-color:#b00020;border-color:var(--mdc-theme-error, #b00020)}.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__leading,.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__notch,.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__trailing{border-width:2px}.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__leading,.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__notch,.mdc-select--outlined.mdc-select--invalid:not(.mdc-select--disabled).mdc-select--focused .mdc-notched-outline .mdc-notched-outline__trailing{border-color:#b00020;border-color:var(--mdc-theme-error, #b00020)}.mdc-select--outlined.mdc-select--with-leading-icon .mdc-floating-label{left:36px;right:initial}[dir=rtl] .mdc-select--outlined.mdc-select--with-leading-icon .mdc-floating-label,.mdc-select--outlined.mdc-select--with-leading-icon .mdc-floating-label[dir=rtl]{left:initial;right:36px}.mdc-select--outlined.mdc-select--with-leading-icon .mdc-floating-label--float-above{transform:translateY(-37.25px) translateX(-32px) scale(1)}[dir=rtl] .mdc-select--outlined.mdc-select--with-leading-icon .mdc-floating-label--float-above,.mdc-select--outlined.mdc-select--with-leading-icon .mdc-floating-label--float-above[dir=rtl]{transform:translateY(-37.25px) translateX(32px) scale(1)}.mdc-select--outlined.mdc-select--with-leading-icon .mdc-floating-label--float-above{font-size:.75rem}.mdc-select--outlined.mdc-select--with-leading-icon.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-select--outlined.mdc-select--with-leading-icon .mdc-notched-outline--upgraded .mdc-floating-label--float-above{transform:translateY(-34.75px) translateX(-32px) scale(0.75)}[dir=rtl] .mdc-select--outlined.mdc-select--with-leading-icon.mdc-notched-outline--upgraded .mdc-floating-label--float-above,[dir=rtl] .mdc-select--outlined.mdc-select--with-leading-icon .mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-select--outlined.mdc-select--with-leading-icon.mdc-notched-outline--upgraded .mdc-floating-label--float-above[dir=rtl],.mdc-select--outlined.mdc-select--with-leading-icon .mdc-notched-outline--upgraded .mdc-floating-label--float-above[dir=rtl]{transform:translateY(-34.75px) translateX(32px) scale(0.75)}.mdc-select--outlined.mdc-select--with-leading-icon.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-select--outlined.mdc-select--with-leading-icon .mdc-notched-outline--upgraded .mdc-floating-label--float-above{font-size:1rem}.mdc-select--outlined.mdc-select--with-leading-icon .mdc-floating-label--shake{animation:mdc-floating-label-shake-float-above-select-outlined-leading-icon-56px 250ms 1}@keyframes mdc-floating-label-shake-float-above-select-outlined-leading-icon-56px{0%{transform:translateX(calc(0 - 32px)) translateY(-34.75px) scale(0.75)}33%{animation-timing-function:cubic-bezier(0.5, 0, 0.701732, 0.495819);transform:translateX(calc(4% - 32px)) translateY(-34.75px) scale(0.75)}66%{animation-timing-function:cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);transform:translateX(calc(-4% - 32px)) translateY(-34.75px) scale(0.75)}100%{transform:translateX(calc(0 - 32px)) translateY(-34.75px) scale(0.75)}}[dir=rtl] .mdc-select--outlined.mdc-select--with-leading-icon .mdc-floating-label--shake,.mdc-select--outlined.mdc-select--with-leading-icon[dir=rtl] .mdc-floating-label--shake{animation:mdc-floating-label-shake-float-above-select-outlined-leading-icon-56px 250ms 1}@keyframes mdc-floating-label-shake-float-above-select-outlined-leading-icon-56px-rtl{0%{transform:translateX(calc(0 - -32px)) translateY(-34.75px) scale(0.75)}33%{animation-timing-function:cubic-bezier(0.5, 0, 0.701732, 0.495819);transform:translateX(calc(4% - -32px)) translateY(-34.75px) scale(0.75)}66%{animation-timing-function:cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);transform:translateX(calc(-4% - -32px)) translateY(-34.75px) scale(0.75)}100%{transform:translateX(calc(0 - -32px)) translateY(-34.75px) scale(0.75)}}.mdc-select--outlined.mdc-select--with-leading-icon .mdc-select__anchor :not(.mdc-notched-outline--notched) .mdc-notched-outline__notch{max-width:calc(100% - 96px)}.mdc-select--outlined .mdc-menu-surface{margin-bottom:8px}.mdc-select--outlined.mdc-select--no-label .mdc-menu-surface,.mdc-select--outlined .mdc-menu-surface--is-open-below{margin-bottom:0}.mdc-select__anchor{--mdc-ripple-fg-size: 0;--mdc-ripple-left: 0;--mdc-ripple-top: 0;--mdc-ripple-fg-scale: 1;--mdc-ripple-fg-translate-end: 0;--mdc-ripple-fg-translate-start: 0;-webkit-tap-highlight-color:rgba(0,0,0,0);will-change:transform,opacity}.mdc-select__anchor .mdc-select__ripple::before,.mdc-select__anchor .mdc-select__ripple::after{position:absolute;border-radius:50%;opacity:0;pointer-events:none;content:""}.mdc-select__anchor .mdc-select__ripple::before{transition:opacity 15ms linear,background-color 15ms linear;z-index:1;z-index:var(--mdc-ripple-z-index, 1)}.mdc-select__anchor .mdc-select__ripple::after{z-index:0;z-index:var(--mdc-ripple-z-index, 0)}.mdc-select__anchor.mdc-ripple-upgraded .mdc-select__ripple::before{transform:scale(var(--mdc-ripple-fg-scale, 1))}.mdc-select__anchor.mdc-ripple-upgraded .mdc-select__ripple::after{top:0;left:0;transform:scale(0);transform-origin:center center}.mdc-select__anchor.mdc-ripple-upgraded--unbounded .mdc-select__ripple::after{top:var(--mdc-ripple-top, 0);left:var(--mdc-ripple-left, 0)}.mdc-select__anchor.mdc-ripple-upgraded--foreground-activation .mdc-select__ripple::after{animation:mdc-ripple-fg-radius-in 225ms forwards,mdc-ripple-fg-opacity-in 75ms forwards}.mdc-select__anchor.mdc-ripple-upgraded--foreground-deactivation .mdc-select__ripple::after{animation:mdc-ripple-fg-opacity-out 150ms;transform:translate(var(--mdc-ripple-fg-translate-end, 0)) scale(var(--mdc-ripple-fg-scale, 1))}.mdc-select__anchor .mdc-select__ripple::before,.mdc-select__anchor .mdc-select__ripple::after{top:calc(50% - 100%);left:calc(50% - 100%);width:200%;height:200%}.mdc-select__anchor.mdc-ripple-upgraded .mdc-select__ripple::after{width:var(--mdc-ripple-fg-size, 100%);height:var(--mdc-ripple-fg-size, 100%)}.mdc-select__anchor .mdc-select__ripple::before,.mdc-select__anchor .mdc-select__ripple::after{background-color:rgba(0, 0, 0, 0.87);background-color:var(--mdc-ripple-color, rgba(0, 0, 0, 0.87))}.mdc-select__anchor:hover .mdc-select__ripple::before,.mdc-select__anchor.mdc-ripple-surface--hover .mdc-select__ripple::before{opacity:0.04;opacity:var(--mdc-ripple-hover-opacity, 0.04)}.mdc-select__anchor.mdc-ripple-upgraded--background-focused .mdc-select__ripple::before,.mdc-select__anchor:not(.mdc-ripple-upgraded):focus .mdc-select__ripple::before{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-focus-opacity, 0.12)}.mdc-select__anchor .mdc-select__ripple{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected .mdc-deprecated-list-item__ripple::before,.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected .mdc-deprecated-list-item__ripple::after{background-color:#000;background-color:var(--mdc-ripple-color, var(--mdc-theme-on-surface, #000))}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected:hover .mdc-deprecated-list-item__ripple::before,.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected.mdc-ripple-surface--hover .mdc-deprecated-list-item__ripple::before{opacity:0.04;opacity:var(--mdc-ripple-hover-opacity, 0.04)}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected.mdc-ripple-upgraded--background-focused .mdc-deprecated-list-item__ripple::before,.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected:not(.mdc-ripple-upgraded):focus .mdc-deprecated-list-item__ripple::before{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-focus-opacity, 0.12)}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected:not(.mdc-ripple-upgraded) .mdc-deprecated-list-item__ripple::after{transition:opacity 150ms linear}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected:not(.mdc-ripple-upgraded):active .mdc-deprecated-list-item__ripple::after{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-press-opacity, 0.12)}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected.mdc-ripple-upgraded{--mdc-ripple-fg-opacity:var(--mdc-ripple-press-opacity, 0.12)}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected .mdc-list-item__ripple::before,.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected .mdc-list-item__ripple::after{background-color:#000;background-color:var(--mdc-ripple-color, var(--mdc-theme-on-surface, #000))}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected:hover .mdc-list-item__ripple::before,.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected.mdc-ripple-surface--hover .mdc-list-item__ripple::before{opacity:0.04;opacity:var(--mdc-ripple-hover-opacity, 0.04)}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected.mdc-ripple-upgraded--background-focused .mdc-list-item__ripple::before,.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected:not(.mdc-ripple-upgraded):focus .mdc-list-item__ripple::before{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-focus-opacity, 0.12)}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected:not(.mdc-ripple-upgraded) .mdc-list-item__ripple::after{transition:opacity 150ms linear}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected:not(.mdc-ripple-upgraded):active .mdc-list-item__ripple::after{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-press-opacity, 0.12)}.mdc-select__menu .mdc-deprecated-list .mdc-deprecated-list-item--selected.mdc-ripple-upgraded{--mdc-ripple-fg-opacity:var(--mdc-ripple-press-opacity, 0.12)}.mdc-select-helper-text{margin:0;margin-left:16px;margin-right:16px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-caption-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:0.75rem;font-size:var(--mdc-typography-caption-font-size, 0.75rem);line-height:1.25rem;line-height:var(--mdc-typography-caption-line-height, 1.25rem);font-weight:400;font-weight:var(--mdc-typography-caption-font-weight, 400);letter-spacing:0.0333333333em;letter-spacing:var(--mdc-typography-caption-letter-spacing, 0.0333333333em);text-decoration:inherit;text-decoration:var(--mdc-typography-caption-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-caption-text-transform, inherit);display:block;margin-top:0;line-height:normal}[dir=rtl] .mdc-select-helper-text,.mdc-select-helper-text[dir=rtl]{margin-left:16px;margin-right:16px}.mdc-select-helper-text::before{display:inline-block;width:0;height:16px;content:"";vertical-align:0}.mdc-select-helper-text--validation-msg{opacity:0;transition:opacity 180ms cubic-bezier(0.4, 0, 0.2, 1)}.mdc-select--invalid+.mdc-select-helper-text--validation-msg,.mdc-select-helper-text--validation-msg-persistent{opacity:1}.mdc-select--with-leading-icon .mdc-select__icon{display:inline-block;box-sizing:border-box;border:none;text-decoration:none;cursor:pointer;user-select:none;flex-shrink:0;align-self:center;background-color:transparent;fill:currentColor}.mdc-select--with-leading-icon .mdc-select__icon{margin-left:12px;margin-right:12px}[dir=rtl] .mdc-select--with-leading-icon .mdc-select__icon,.mdc-select--with-leading-icon .mdc-select__icon[dir=rtl]{margin-left:12px;margin-right:12px}.mdc-select__icon:not([tabindex]),.mdc-select__icon[tabindex="-1"]{cursor:default;pointer-events:none}.material-icons{font-family:var(--mdc-icon-font, "Material Icons");font-weight:normal;font-style:normal;font-size:var(--mdc-icon-size, 24px);line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;-moz-osx-font-smoothing:grayscale;font-feature-settings:"liga"}:host{display:inline-block;vertical-align:top;outline:none}.mdc-select{width:100%}[hidden]{display:none}.mdc-select__icon{z-index:2}.mdc-select--with-leading-icon{--mdc-list-item-graphic-margin: calc( 48px - var(--mdc-list-item-graphic-size, 24px) - var(--mdc-list-side-padding, 16px) )}.mdc-select .mdc-select__anchor .mdc-select__selected-text{overflow:hidden}.mdc-select .mdc-select__anchor *{display:inline-flex}.mdc-select .mdc-select__anchor .mdc-floating-label{display:inline-block}mwc-notched-outline{--mdc-notched-outline-border-color: var( --mdc-select-outlined-idle-border-color, rgba(0, 0, 0, 0.38) );--mdc-notched-outline-notch-offset: 1px}:host(:not([disabled]):hover) .mdc-select:not(.mdc-select--invalid):not(.mdc-select--focused) mwc-notched-outline{--mdc-notched-outline-border-color: var( --mdc-select-outlined-hover-border-color, rgba(0, 0, 0, 0.87) )}:host(:not([disabled])) .mdc-select:not(.mdc-select--disabled) .mdc-select__selected-text{color:rgba(0, 0, 0, 0.87);color:var(--mdc-select-ink-color, rgba(0, 0, 0, 0.87))}:host(:not([disabled])) .mdc-select:not(.mdc-select--disabled) .mdc-line-ripple::before{border-bottom-color:rgba(0, 0, 0, 0.42);border-bottom-color:var(--mdc-select-idle-line-color, rgba(0, 0, 0, 0.42))}:host(:not([disabled])) .mdc-select:not(.mdc-select--disabled):hover .mdc-line-ripple::before{border-bottom-color:rgba(0, 0, 0, 0.87);border-bottom-color:var(--mdc-select-hover-line-color, rgba(0, 0, 0, 0.87))}:host(:not([disabled])) .mdc-select:not(.mdc-select--outlined):not(.mdc-select--disabled) .mdc-select__anchor{background-color:whitesmoke;background-color:var(--mdc-select-fill-color, whitesmoke)}:host(:not([disabled])) .mdc-select.mdc-select--invalid .mdc-select__dropdown-icon{fill:var(--mdc-select-error-dropdown-icon-color, var(--mdc-select-error-color, var(--mdc-theme-error, #b00020)))}:host(:not([disabled])) .mdc-select.mdc-select--invalid .mdc-floating-label,:host(:not([disabled])) .mdc-select.mdc-select--invalid .mdc-floating-label::after{color:var(--mdc-select-error-color, var(--mdc-theme-error, #b00020))}:host(:not([disabled])) .mdc-select.mdc-select--invalid mwc-notched-outline{--mdc-notched-outline-border-color: var(--mdc-select-error-color, var(--mdc-theme-error, #b00020))}.mdc-select__menu--invalid{--mdc-theme-primary: var(--mdc-select-error-color, var(--mdc-theme-error, #b00020))}:host(:not([disabled])) .mdc-select:not(.mdc-select--invalid):not(.mdc-select--focused) .mdc-floating-label,:host(:not([disabled])) .mdc-select:not(.mdc-select--invalid):not(.mdc-select--focused) .mdc-floating-label::after{color:rgba(0, 0, 0, 0.6);color:var(--mdc-select-label-ink-color, rgba(0, 0, 0, 0.6))}:host(:not([disabled])) .mdc-select:not(.mdc-select--invalid):not(.mdc-select--focused) .mdc-select__dropdown-icon{fill:rgba(0, 0, 0, 0.54);fill:var(--mdc-select-dropdown-icon-color, rgba(0, 0, 0, 0.54))}:host(:not([disabled])) .mdc-select.mdc-select--focused mwc-notched-outline{--mdc-notched-outline-stroke-width: 2px;--mdc-notched-outline-notch-offset: 2px}:host(:not([disabled])) .mdc-select.mdc-select--focused:not(.mdc-select--invalid) mwc-notched-outline{--mdc-notched-outline-border-color: var( --mdc-select-focused-label-color, var(--mdc-theme-primary, rgba(98, 0, 238, 0.87)) )}:host(:not([disabled])) .mdc-select.mdc-select--focused:not(.mdc-select--invalid) .mdc-select__dropdown-icon{fill:rgba(98,0,238,.87);fill:var(--mdc-select-focused-dropdown-icon-color, var(--mdc-theme-primary, rgba(98, 0, 238, 0.87)))}:host(:not([disabled])) .mdc-select.mdc-select--focused:not(.mdc-select--invalid) .mdc-floating-label{color:#6200ee;color:var(--mdc-theme-primary, #6200ee)}:host(:not([disabled])) .mdc-select.mdc-select--focused:not(.mdc-select--invalid) .mdc-floating-label::after{color:#6200ee;color:var(--mdc-theme-primary, #6200ee)}:host(:not([disabled])) .mdc-select-helper-text:not(.mdc-select-helper-text--validation-msg){color:var(--mdc-select-label-ink-color, rgba(0, 0, 0, 0.6))}:host([disabled]){pointer-events:none}:host([disabled]) .mdc-select:not(.mdc-select--outlined).mdc-select--disabled .mdc-select__anchor{background-color:#fafafa;background-color:var(--mdc-select-disabled-fill-color, #fafafa)}:host([disabled]) .mdc-select.mdc-select--outlined mwc-notched-outline{--mdc-notched-outline-border-color: var( --mdc-select-outlined-disabled-border-color, rgba(0, 0, 0, 0.06) )}:host([disabled]) .mdc-select .mdc-select__dropdown-icon{fill:rgba(0, 0, 0, 0.38);fill:var(--mdc-select-disabled-dropdown-icon-color, rgba(0, 0, 0, 0.38))}:host([disabled]) .mdc-select:not(.mdc-select--invalid):not(.mdc-select--focused) .mdc-floating-label,:host([disabled]) .mdc-select:not(.mdc-select--invalid):not(.mdc-select--focused) .mdc-floating-label::after{color:rgba(0, 0, 0, 0.38);color:var(--mdc-select-disabled-ink-color, rgba(0, 0, 0, 0.38))}:host([disabled]) .mdc-select-helper-text{color:rgba(0, 0, 0, 0.38);color:var(--mdc-select-disabled-ink-color, rgba(0, 0, 0, 0.38))}:host([disabled]) .mdc-select__selected-text{color:rgba(0, 0, 0, 0.38);color:var(--mdc-select-disabled-ink-color, rgba(0, 0, 0, 0.38))}` -/** - * @license - * Copyright 2021 Google LLC - * SPDX-LIcense-Identifier: Apache-2.0 - */,ln=ht`@keyframes mdc-ripple-fg-radius-in{from{animation-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transform:translate(var(--mdc-ripple-fg-translate-start, 0)) scale(1)}to{transform:translate(var(--mdc-ripple-fg-translate-end, 0)) scale(var(--mdc-ripple-fg-scale, 1))}}@keyframes mdc-ripple-fg-opacity-in{from{animation-timing-function:linear;opacity:0}to{opacity:var(--mdc-ripple-fg-opacity, 0)}}@keyframes mdc-ripple-fg-opacity-out{from{animation-timing-function:linear;opacity:var(--mdc-ripple-fg-opacity, 0)}to{opacity:0}}:host{display:block}.mdc-deprecated-list{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-subtitle1-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:1rem;font-size:var(--mdc-typography-subtitle1-font-size, 1rem);line-height:1.75rem;line-height:var(--mdc-typography-subtitle1-line-height, 1.75rem);font-weight:400;font-weight:var(--mdc-typography-subtitle1-font-weight, 400);letter-spacing:0.009375em;letter-spacing:var(--mdc-typography-subtitle1-letter-spacing, 0.009375em);text-decoration:inherit;text-decoration:var(--mdc-typography-subtitle1-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-subtitle1-text-transform, inherit);line-height:1.5rem;margin:0;padding:8px 0;list-style-type:none;color:rgba(0, 0, 0, 0.87);color:var(--mdc-theme-text-primary-on-background, rgba(0, 0, 0, 0.87));padding:var(--mdc-list-vertical-padding, 8px) 0}.mdc-deprecated-list:focus{outline:none}.mdc-deprecated-list-item{height:48px}.mdc-deprecated-list--dense{padding-top:4px;padding-bottom:4px;font-size:.812rem}.mdc-deprecated-list ::slotted([divider]){height:0;margin:0;border:none;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgba(0, 0, 0, 0.12)}.mdc-deprecated-list ::slotted([divider][padded]){margin:0 var(--mdc-list-side-padding, 16px)}.mdc-deprecated-list ::slotted([divider][inset]){margin-left:var(--mdc-list-inset-margin, 72px);margin-right:0;width:calc( 100% - var(--mdc-list-inset-margin, 72px) )}[dir=rtl] .mdc-deprecated-list ::slotted([divider][inset]),.mdc-deprecated-list ::slotted([divider][inset][dir=rtl]){margin-left:0;margin-right:var(--mdc-list-inset-margin, 72px)}.mdc-deprecated-list ::slotted([divider][inset][padded]){width:calc( 100% - var(--mdc-list-inset-margin, 72px) - var(--mdc-list-side-padding, 16px) )}.mdc-deprecated-list--dense ::slotted([mwc-list-item]){height:40px}.mdc-deprecated-list--dense ::slotted([mwc-list]){--mdc-list-item-graphic-size: 20px}.mdc-deprecated-list--two-line.mdc-deprecated-list--dense ::slotted([mwc-list-item]),.mdc-deprecated-list--avatar-list.mdc-deprecated-list--dense ::slotted([mwc-list-item]){height:60px}.mdc-deprecated-list--avatar-list.mdc-deprecated-list--dense ::slotted([mwc-list]){--mdc-list-item-graphic-size: 36px}:host([noninteractive]){pointer-events:none;cursor:default}.mdc-deprecated-list--dense ::slotted(.mdc-deprecated-list-item__primary-text){display:block;margin-top:0;line-height:normal;margin-bottom:-20px}.mdc-deprecated-list--dense ::slotted(.mdc-deprecated-list-item__primary-text)::before{display:inline-block;width:0;height:24px;content:"";vertical-align:0}.mdc-deprecated-list--dense ::slotted(.mdc-deprecated-list-item__primary-text)::after{display:inline-block;width:0;height:20px;content:"";vertical-align:-20px}` -/** - * @license - * Copyright 2021 Google LLC - * SPDX-LIcense-Identifier: Apache-2.0 - */,cn=ht`:host{cursor:pointer;user-select:none;-webkit-tap-highlight-color:transparent;height:48px;display:flex;position:relative;align-items:center;justify-content:flex-start;overflow:hidden;padding:0;padding-left:var(--mdc-list-side-padding, 16px);padding-right:var(--mdc-list-side-padding, 16px);outline:none;height:48px;color:rgba(0,0,0,.87);color:var(--mdc-theme-text-primary-on-background, rgba(0, 0, 0, 0.87))}:host:focus{outline:none}:host([activated]){color:#6200ee;color:var(--mdc-theme-primary, #6200ee);--mdc-ripple-color: var( --mdc-theme-primary, #6200ee )}:host([activated]) .mdc-deprecated-list-item__graphic{color:#6200ee;color:var(--mdc-theme-primary, #6200ee)}:host([activated]) .fake-activated-ripple::before{position:absolute;display:block;top:0;bottom:0;left:0;right:0;width:100%;height:100%;pointer-events:none;z-index:1;content:"";opacity:0.12;opacity:var(--mdc-ripple-activated-opacity, 0.12);background-color:#6200ee;background-color:var(--mdc-ripple-color, var(--mdc-theme-primary, #6200ee))}.mdc-deprecated-list-item__graphic{flex-shrink:0;align-items:center;justify-content:center;fill:currentColor;display:inline-flex}.mdc-deprecated-list-item__graphic ::slotted(*){flex-shrink:0;align-items:center;justify-content:center;fill:currentColor;width:100%;height:100%;text-align:center}.mdc-deprecated-list-item__meta{width:var(--mdc-list-item-meta-size, 24px);height:var(--mdc-list-item-meta-size, 24px);margin-left:auto;margin-right:0;color:rgba(0, 0, 0, 0.38);color:var(--mdc-theme-text-hint-on-background, rgba(0, 0, 0, 0.38))}.mdc-deprecated-list-item__meta.multi{width:auto}.mdc-deprecated-list-item__meta ::slotted(*){width:var(--mdc-list-item-meta-size, 24px);line-height:var(--mdc-list-item-meta-size, 24px)}.mdc-deprecated-list-item__meta ::slotted(.material-icons),.mdc-deprecated-list-item__meta ::slotted(mwc-icon){line-height:var(--mdc-list-item-meta-size, 24px) !important}.mdc-deprecated-list-item__meta ::slotted(:not(.material-icons):not(mwc-icon)){-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-caption-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:0.75rem;font-size:var(--mdc-typography-caption-font-size, 0.75rem);line-height:1.25rem;line-height:var(--mdc-typography-caption-line-height, 1.25rem);font-weight:400;font-weight:var(--mdc-typography-caption-font-weight, 400);letter-spacing:0.0333333333em;letter-spacing:var(--mdc-typography-caption-letter-spacing, 0.0333333333em);text-decoration:inherit;text-decoration:var(--mdc-typography-caption-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-caption-text-transform, inherit)}[dir=rtl] .mdc-deprecated-list-item__meta,.mdc-deprecated-list-item__meta[dir=rtl]{margin-left:0;margin-right:auto}.mdc-deprecated-list-item__meta ::slotted(*){width:100%;height:100%}.mdc-deprecated-list-item__text{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.mdc-deprecated-list-item__text ::slotted([for]),.mdc-deprecated-list-item__text[for]{pointer-events:none}.mdc-deprecated-list-item__primary-text{text-overflow:ellipsis;white-space:nowrap;overflow:hidden;display:block;margin-top:0;line-height:normal;margin-bottom:-20px;display:block}.mdc-deprecated-list-item__primary-text::before{display:inline-block;width:0;height:32px;content:"";vertical-align:0}.mdc-deprecated-list-item__primary-text::after{display:inline-block;width:0;height:20px;content:"";vertical-align:-20px}.mdc-deprecated-list-item__secondary-text{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-body2-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:0.875rem;font-size:var(--mdc-typography-body2-font-size, 0.875rem);line-height:1.25rem;line-height:var(--mdc-typography-body2-line-height, 1.25rem);font-weight:400;font-weight:var(--mdc-typography-body2-font-weight, 400);letter-spacing:0.0178571429em;letter-spacing:var(--mdc-typography-body2-letter-spacing, 0.0178571429em);text-decoration:inherit;text-decoration:var(--mdc-typography-body2-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-body2-text-transform, inherit);text-overflow:ellipsis;white-space:nowrap;overflow:hidden;display:block;margin-top:0;line-height:normal;display:block}.mdc-deprecated-list-item__secondary-text::before{display:inline-block;width:0;height:20px;content:"";vertical-align:0}.mdc-deprecated-list--dense .mdc-deprecated-list-item__secondary-text{font-size:inherit}* ::slotted(a),a{color:inherit;text-decoration:none}:host([twoline]){height:72px}:host([twoline]) .mdc-deprecated-list-item__text{align-self:flex-start}:host([disabled]),:host([noninteractive]){cursor:default;pointer-events:none}:host([disabled]) .mdc-deprecated-list-item__text ::slotted(*){opacity:.38}:host([disabled]) .mdc-deprecated-list-item__text ::slotted(*),:host([disabled]) .mdc-deprecated-list-item__primary-text ::slotted(*),:host([disabled]) .mdc-deprecated-list-item__secondary-text ::slotted(*){color:#000;color:var(--mdc-theme-on-surface, #000)}.mdc-deprecated-list-item__secondary-text ::slotted(*){color:rgba(0, 0, 0, 0.54);color:var(--mdc-theme-text-secondary-on-background, rgba(0, 0, 0, 0.54))}.mdc-deprecated-list-item__graphic ::slotted(*){background-color:transparent;color:rgba(0, 0, 0, 0.38);color:var(--mdc-theme-text-icon-on-background, rgba(0, 0, 0, 0.38))}.mdc-deprecated-list-group__subheader ::slotted(*){color:rgba(0, 0, 0, 0.87);color:var(--mdc-theme-text-primary-on-background, rgba(0, 0, 0, 0.87))}:host([graphic=avatar]) .mdc-deprecated-list-item__graphic{width:var(--mdc-list-item-graphic-size, 40px);height:var(--mdc-list-item-graphic-size, 40px)}:host([graphic=avatar]) .mdc-deprecated-list-item__graphic.multi{width:auto}:host([graphic=avatar]) .mdc-deprecated-list-item__graphic ::slotted(*){width:var(--mdc-list-item-graphic-size, 40px);line-height:var(--mdc-list-item-graphic-size, 40px)}:host([graphic=avatar]) .mdc-deprecated-list-item__graphic ::slotted(.material-icons),:host([graphic=avatar]) .mdc-deprecated-list-item__graphic ::slotted(mwc-icon){line-height:var(--mdc-list-item-graphic-size, 40px) !important}:host([graphic=avatar]) .mdc-deprecated-list-item__graphic ::slotted(*){border-radius:50%}:host([graphic=avatar]) .mdc-deprecated-list-item__graphic,:host([graphic=medium]) .mdc-deprecated-list-item__graphic,:host([graphic=large]) .mdc-deprecated-list-item__graphic,:host([graphic=control]) .mdc-deprecated-list-item__graphic{margin-left:0;margin-right:var(--mdc-list-item-graphic-margin, 16px)}[dir=rtl] :host([graphic=avatar]) .mdc-deprecated-list-item__graphic,[dir=rtl] :host([graphic=medium]) .mdc-deprecated-list-item__graphic,[dir=rtl] :host([graphic=large]) .mdc-deprecated-list-item__graphic,[dir=rtl] :host([graphic=control]) .mdc-deprecated-list-item__graphic,:host([graphic=avatar]) .mdc-deprecated-list-item__graphic[dir=rtl],:host([graphic=medium]) .mdc-deprecated-list-item__graphic[dir=rtl],:host([graphic=large]) .mdc-deprecated-list-item__graphic[dir=rtl],:host([graphic=control]) .mdc-deprecated-list-item__graphic[dir=rtl]{margin-left:var(--mdc-list-item-graphic-margin, 16px);margin-right:0}:host([graphic=icon]) .mdc-deprecated-list-item__graphic{width:var(--mdc-list-item-graphic-size, 24px);height:var(--mdc-list-item-graphic-size, 24px);margin-left:0;margin-right:var(--mdc-list-item-graphic-margin, 32px)}:host([graphic=icon]) .mdc-deprecated-list-item__graphic.multi{width:auto}:host([graphic=icon]) .mdc-deprecated-list-item__graphic ::slotted(*){width:var(--mdc-list-item-graphic-size, 24px);line-height:var(--mdc-list-item-graphic-size, 24px)}:host([graphic=icon]) .mdc-deprecated-list-item__graphic ::slotted(.material-icons),:host([graphic=icon]) .mdc-deprecated-list-item__graphic ::slotted(mwc-icon){line-height:var(--mdc-list-item-graphic-size, 24px) !important}[dir=rtl] :host([graphic=icon]) .mdc-deprecated-list-item__graphic,:host([graphic=icon]) .mdc-deprecated-list-item__graphic[dir=rtl]{margin-left:var(--mdc-list-item-graphic-margin, 32px);margin-right:0}:host([graphic=avatar]:not([twoLine])),:host([graphic=icon]:not([twoLine])){height:56px}:host([graphic=medium]:not([twoLine])),:host([graphic=large]:not([twoLine])){height:72px}:host([graphic=medium]) .mdc-deprecated-list-item__graphic,:host([graphic=large]) .mdc-deprecated-list-item__graphic{width:var(--mdc-list-item-graphic-size, 56px);height:var(--mdc-list-item-graphic-size, 56px)}:host([graphic=medium]) .mdc-deprecated-list-item__graphic.multi,:host([graphic=large]) .mdc-deprecated-list-item__graphic.multi{width:auto}:host([graphic=medium]) .mdc-deprecated-list-item__graphic ::slotted(*),:host([graphic=large]) .mdc-deprecated-list-item__graphic ::slotted(*){width:var(--mdc-list-item-graphic-size, 56px);line-height:var(--mdc-list-item-graphic-size, 56px)}:host([graphic=medium]) .mdc-deprecated-list-item__graphic ::slotted(.material-icons),:host([graphic=medium]) .mdc-deprecated-list-item__graphic ::slotted(mwc-icon),:host([graphic=large]) .mdc-deprecated-list-item__graphic ::slotted(.material-icons),:host([graphic=large]) .mdc-deprecated-list-item__graphic ::slotted(mwc-icon){line-height:var(--mdc-list-item-graphic-size, 56px) !important}:host([graphic=large]){padding-left:0px}` -/** - * @license - * Copyright 2021 Google LLC - * SPDX-LIcense-Identifier: Apache-2.0 - */,hn=ht`.mdc-ripple-surface{--mdc-ripple-fg-size: 0;--mdc-ripple-left: 0;--mdc-ripple-top: 0;--mdc-ripple-fg-scale: 1;--mdc-ripple-fg-translate-end: 0;--mdc-ripple-fg-translate-start: 0;-webkit-tap-highlight-color:rgba(0,0,0,0);will-change:transform,opacity;position:relative;outline:none;overflow:hidden}.mdc-ripple-surface::before,.mdc-ripple-surface::after{position:absolute;border-radius:50%;opacity:0;pointer-events:none;content:""}.mdc-ripple-surface::before{transition:opacity 15ms linear,background-color 15ms linear;z-index:1;z-index:var(--mdc-ripple-z-index, 1)}.mdc-ripple-surface::after{z-index:0;z-index:var(--mdc-ripple-z-index, 0)}.mdc-ripple-surface.mdc-ripple-upgraded::before{transform:scale(var(--mdc-ripple-fg-scale, 1))}.mdc-ripple-surface.mdc-ripple-upgraded::after{top:0;left:0;transform:scale(0);transform-origin:center center}.mdc-ripple-surface.mdc-ripple-upgraded--unbounded::after{top:var(--mdc-ripple-top, 0);left:var(--mdc-ripple-left, 0)}.mdc-ripple-surface.mdc-ripple-upgraded--foreground-activation::after{animation:mdc-ripple-fg-radius-in 225ms forwards,mdc-ripple-fg-opacity-in 75ms forwards}.mdc-ripple-surface.mdc-ripple-upgraded--foreground-deactivation::after{animation:mdc-ripple-fg-opacity-out 150ms;transform:translate(var(--mdc-ripple-fg-translate-end, 0)) scale(var(--mdc-ripple-fg-scale, 1))}.mdc-ripple-surface::before,.mdc-ripple-surface::after{top:calc(50% - 100%);left:calc(50% - 100%);width:200%;height:200%}.mdc-ripple-surface.mdc-ripple-upgraded::after{width:var(--mdc-ripple-fg-size, 100%);height:var(--mdc-ripple-fg-size, 100%)}.mdc-ripple-surface[data-mdc-ripple-is-unbounded],.mdc-ripple-upgraded--unbounded{overflow:visible}.mdc-ripple-surface[data-mdc-ripple-is-unbounded]::before,.mdc-ripple-surface[data-mdc-ripple-is-unbounded]::after,.mdc-ripple-upgraded--unbounded::before,.mdc-ripple-upgraded--unbounded::after{top:calc(50% - 50%);left:calc(50% - 50%);width:100%;height:100%}.mdc-ripple-surface[data-mdc-ripple-is-unbounded].mdc-ripple-upgraded::before,.mdc-ripple-surface[data-mdc-ripple-is-unbounded].mdc-ripple-upgraded::after,.mdc-ripple-upgraded--unbounded.mdc-ripple-upgraded::before,.mdc-ripple-upgraded--unbounded.mdc-ripple-upgraded::after{top:var(--mdc-ripple-top, calc(50% - 50%));left:var(--mdc-ripple-left, calc(50% - 50%));width:var(--mdc-ripple-fg-size, 100%);height:var(--mdc-ripple-fg-size, 100%)}.mdc-ripple-surface[data-mdc-ripple-is-unbounded].mdc-ripple-upgraded::after,.mdc-ripple-upgraded--unbounded.mdc-ripple-upgraded::after{width:var(--mdc-ripple-fg-size, 100%);height:var(--mdc-ripple-fg-size, 100%)}.mdc-ripple-surface::before,.mdc-ripple-surface::after{background-color:#000;background-color:var(--mdc-ripple-color, #000)}.mdc-ripple-surface:hover::before,.mdc-ripple-surface.mdc-ripple-surface--hover::before{opacity:0.04;opacity:var(--mdc-ripple-hover-opacity, 0.04)}.mdc-ripple-surface.mdc-ripple-upgraded--background-focused::before,.mdc-ripple-surface:not(.mdc-ripple-upgraded):focus::before{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-focus-opacity, 0.12)}.mdc-ripple-surface:not(.mdc-ripple-upgraded)::after{transition:opacity 150ms linear}.mdc-ripple-surface:not(.mdc-ripple-upgraded):active::after{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-press-opacity, 0.12)}.mdc-ripple-surface.mdc-ripple-upgraded{--mdc-ripple-fg-opacity:var(--mdc-ripple-press-opacity, 0.12)}@keyframes mdc-ripple-fg-radius-in{from{animation-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transform:translate(var(--mdc-ripple-fg-translate-start, 0)) scale(1)}to{transform:translate(var(--mdc-ripple-fg-translate-end, 0)) scale(var(--mdc-ripple-fg-scale, 1))}}@keyframes mdc-ripple-fg-opacity-in{from{animation-timing-function:linear;opacity:0}to{opacity:var(--mdc-ripple-fg-opacity, 0)}}@keyframes mdc-ripple-fg-opacity-out{from{animation-timing-function:linear;opacity:var(--mdc-ripple-fg-opacity, 0)}to{opacity:0}}:host{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;display:block}:host .mdc-ripple-surface{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;will-change:unset}.mdc-ripple-surface--primary::before,.mdc-ripple-surface--primary::after{background-color:#6200ee;background-color:var(--mdc-ripple-color, var(--mdc-theme-primary, #6200ee))}.mdc-ripple-surface--primary:hover::before,.mdc-ripple-surface--primary.mdc-ripple-surface--hover::before{opacity:0.04;opacity:var(--mdc-ripple-hover-opacity, 0.04)}.mdc-ripple-surface--primary.mdc-ripple-upgraded--background-focused::before,.mdc-ripple-surface--primary:not(.mdc-ripple-upgraded):focus::before{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-focus-opacity, 0.12)}.mdc-ripple-surface--primary:not(.mdc-ripple-upgraded)::after{transition:opacity 150ms linear}.mdc-ripple-surface--primary:not(.mdc-ripple-upgraded):active::after{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-press-opacity, 0.12)}.mdc-ripple-surface--primary.mdc-ripple-upgraded{--mdc-ripple-fg-opacity:var(--mdc-ripple-press-opacity, 0.12)}.mdc-ripple-surface--primary--activated::before{opacity:0.12;opacity:var(--mdc-ripple-activated-opacity, 0.12)}.mdc-ripple-surface--primary--activated::before,.mdc-ripple-surface--primary--activated::after{background-color:#6200ee;background-color:var(--mdc-ripple-color, var(--mdc-theme-primary, #6200ee))}.mdc-ripple-surface--primary--activated:hover::before,.mdc-ripple-surface--primary--activated.mdc-ripple-surface--hover::before{opacity:0.16;opacity:var(--mdc-ripple-hover-opacity, 0.16)}.mdc-ripple-surface--primary--activated.mdc-ripple-upgraded--background-focused::before,.mdc-ripple-surface--primary--activated:not(.mdc-ripple-upgraded):focus::before{transition-duration:75ms;opacity:0.24;opacity:var(--mdc-ripple-focus-opacity, 0.24)}.mdc-ripple-surface--primary--activated:not(.mdc-ripple-upgraded)::after{transition:opacity 150ms linear}.mdc-ripple-surface--primary--activated:not(.mdc-ripple-upgraded):active::after{transition-duration:75ms;opacity:0.24;opacity:var(--mdc-ripple-press-opacity, 0.24)}.mdc-ripple-surface--primary--activated.mdc-ripple-upgraded{--mdc-ripple-fg-opacity:var(--mdc-ripple-press-opacity, 0.24)}.mdc-ripple-surface--primary--selected::before{opacity:0.08;opacity:var(--mdc-ripple-selected-opacity, 0.08)}.mdc-ripple-surface--primary--selected::before,.mdc-ripple-surface--primary--selected::after{background-color:#6200ee;background-color:var(--mdc-ripple-color, var(--mdc-theme-primary, #6200ee))}.mdc-ripple-surface--primary--selected:hover::before,.mdc-ripple-surface--primary--selected.mdc-ripple-surface--hover::before{opacity:0.12;opacity:var(--mdc-ripple-hover-opacity, 0.12)}.mdc-ripple-surface--primary--selected.mdc-ripple-upgraded--background-focused::before,.mdc-ripple-surface--primary--selected:not(.mdc-ripple-upgraded):focus::before{transition-duration:75ms;opacity:0.2;opacity:var(--mdc-ripple-focus-opacity, 0.2)}.mdc-ripple-surface--primary--selected:not(.mdc-ripple-upgraded)::after{transition:opacity 150ms linear}.mdc-ripple-surface--primary--selected:not(.mdc-ripple-upgraded):active::after{transition-duration:75ms;opacity:0.2;opacity:var(--mdc-ripple-press-opacity, 0.2)}.mdc-ripple-surface--primary--selected.mdc-ripple-upgraded{--mdc-ripple-fg-opacity:var(--mdc-ripple-press-opacity, 0.2)}.mdc-ripple-surface--accent::before,.mdc-ripple-surface--accent::after{background-color:#018786;background-color:var(--mdc-ripple-color, var(--mdc-theme-secondary, #018786))}.mdc-ripple-surface--accent:hover::before,.mdc-ripple-surface--accent.mdc-ripple-surface--hover::before{opacity:0.04;opacity:var(--mdc-ripple-hover-opacity, 0.04)}.mdc-ripple-surface--accent.mdc-ripple-upgraded--background-focused::before,.mdc-ripple-surface--accent:not(.mdc-ripple-upgraded):focus::before{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-focus-opacity, 0.12)}.mdc-ripple-surface--accent:not(.mdc-ripple-upgraded)::after{transition:opacity 150ms linear}.mdc-ripple-surface--accent:not(.mdc-ripple-upgraded):active::after{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-press-opacity, 0.12)}.mdc-ripple-surface--accent.mdc-ripple-upgraded{--mdc-ripple-fg-opacity:var(--mdc-ripple-press-opacity, 0.12)}.mdc-ripple-surface--accent--activated::before{opacity:0.12;opacity:var(--mdc-ripple-activated-opacity, 0.12)}.mdc-ripple-surface--accent--activated::before,.mdc-ripple-surface--accent--activated::after{background-color:#018786;background-color:var(--mdc-ripple-color, var(--mdc-theme-secondary, #018786))}.mdc-ripple-surface--accent--activated:hover::before,.mdc-ripple-surface--accent--activated.mdc-ripple-surface--hover::before{opacity:0.16;opacity:var(--mdc-ripple-hover-opacity, 0.16)}.mdc-ripple-surface--accent--activated.mdc-ripple-upgraded--background-focused::before,.mdc-ripple-surface--accent--activated:not(.mdc-ripple-upgraded):focus::before{transition-duration:75ms;opacity:0.24;opacity:var(--mdc-ripple-focus-opacity, 0.24)}.mdc-ripple-surface--accent--activated:not(.mdc-ripple-upgraded)::after{transition:opacity 150ms linear}.mdc-ripple-surface--accent--activated:not(.mdc-ripple-upgraded):active::after{transition-duration:75ms;opacity:0.24;opacity:var(--mdc-ripple-press-opacity, 0.24)}.mdc-ripple-surface--accent--activated.mdc-ripple-upgraded{--mdc-ripple-fg-opacity:var(--mdc-ripple-press-opacity, 0.24)}.mdc-ripple-surface--accent--selected::before{opacity:0.08;opacity:var(--mdc-ripple-selected-opacity, 0.08)}.mdc-ripple-surface--accent--selected::before,.mdc-ripple-surface--accent--selected::after{background-color:#018786;background-color:var(--mdc-ripple-color, var(--mdc-theme-secondary, #018786))}.mdc-ripple-surface--accent--selected:hover::before,.mdc-ripple-surface--accent--selected.mdc-ripple-surface--hover::before{opacity:0.12;opacity:var(--mdc-ripple-hover-opacity, 0.12)}.mdc-ripple-surface--accent--selected.mdc-ripple-upgraded--background-focused::before,.mdc-ripple-surface--accent--selected:not(.mdc-ripple-upgraded):focus::before{transition-duration:75ms;opacity:0.2;opacity:var(--mdc-ripple-focus-opacity, 0.2)}.mdc-ripple-surface--accent--selected:not(.mdc-ripple-upgraded)::after{transition:opacity 150ms linear}.mdc-ripple-surface--accent--selected:not(.mdc-ripple-upgraded):active::after{transition-duration:75ms;opacity:0.2;opacity:var(--mdc-ripple-press-opacity, 0.2)}.mdc-ripple-surface--accent--selected.mdc-ripple-upgraded{--mdc-ripple-fg-opacity:var(--mdc-ripple-press-opacity, 0.2)}.mdc-ripple-surface--disabled{opacity:0}.mdc-ripple-surface--internal-use-state-layer-custom-properties::before,.mdc-ripple-surface--internal-use-state-layer-custom-properties::after{background-color:#000;background-color:var(--mdc-ripple-hover-state-layer-color, #000)}.mdc-ripple-surface--internal-use-state-layer-custom-properties:hover::before,.mdc-ripple-surface--internal-use-state-layer-custom-properties.mdc-ripple-surface--hover::before{opacity:0.04;opacity:var(--mdc-ripple-hover-state-layer-opacity, 0.04)}.mdc-ripple-surface--internal-use-state-layer-custom-properties.mdc-ripple-upgraded--background-focused::before,.mdc-ripple-surface--internal-use-state-layer-custom-properties:not(.mdc-ripple-upgraded):focus::before{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-focus-state-layer-opacity, 0.12)}.mdc-ripple-surface--internal-use-state-layer-custom-properties:not(.mdc-ripple-upgraded)::after{transition:opacity 150ms linear}.mdc-ripple-surface--internal-use-state-layer-custom-properties:not(.mdc-ripple-upgraded):active::after{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-pressed-state-layer-opacity, 0.12)}.mdc-ripple-surface--internal-use-state-layer-custom-properties.mdc-ripple-upgraded{--mdc-ripple-fg-opacity:var(--mdc-ripple-pressed-state-layer-opacity, 0.12)}` -/** - * @license - * Copyright 2021 Google LLC - * SPDX-LIcense-Identifier: Apache-2.0 - */,un=ht`mwc-list ::slotted([mwc-list-item]:not([twoline])),mwc-list ::slotted([noninteractive]:not([twoline])){height:var(--mdc-menu-item-height, 48px)}` -/** - * @license - * Copyright 2021 Google LLC - * SPDX-LIcense-Identifier: Apache-2.0 - */,pn=ht`.mdc-menu-surface{display:none;position:absolute;box-sizing:border-box;max-width:calc(100vw - 32px);max-width:var(--mdc-menu-max-width, calc(100vw - 32px));max-height:calc(100vh - 32px);max-height:var(--mdc-menu-max-height, calc(100vh - 32px));margin:0;padding:0;transform:scale(1);transform-origin:top left;opacity:0;overflow:auto;will-change:transform,opacity;z-index:8;transition:opacity .03s linear,transform .12s cubic-bezier(0, 0, 0.2, 1),height 250ms cubic-bezier(0, 0, 0.2, 1);box-shadow:0px 5px 5px -3px rgba(0, 0, 0, 0.2),0px 8px 10px 1px rgba(0, 0, 0, 0.14),0px 3px 14px 2px rgba(0,0,0,.12);background-color:#fff;background-color:var(--mdc-theme-surface, #fff);color:#000;color:var(--mdc-theme-on-surface, #000);border-radius:4px;border-radius:var(--mdc-shape-medium, 4px);transform-origin-left:top left;transform-origin-right:top right}.mdc-menu-surface:focus{outline:none}.mdc-menu-surface--animating-open{display:inline-block;transform:scale(0.8);opacity:0}.mdc-menu-surface--open{display:inline-block;transform:scale(1);opacity:1}.mdc-menu-surface--animating-closed{display:inline-block;opacity:0;transition:opacity .075s linear}[dir=rtl] .mdc-menu-surface,.mdc-menu-surface[dir=rtl]{transform-origin-left:top right;transform-origin-right:top left}.mdc-menu-surface--anchor{position:relative;overflow:visible}.mdc-menu-surface--fixed{position:fixed}.mdc-menu-surface--fullwidth{width:100%}:host(:not([open])){display:none}.mdc-menu-surface{z-index:8;z-index:var(--mdc-menu-z-index, 8);min-width:112px;min-width:var(--mdc-menu-min-width, 112px)}` -/** - * @license - * Copyright 2021 Google LLC - * SPDX-LIcense-Identifier: Apache-2.0 - */,fn=ht`.mdc-notched-outline{display:flex;position:absolute;top:0;right:0;left:0;box-sizing:border-box;width:100%;max-width:100%;height:100%;text-align:left;pointer-events:none}[dir=rtl] .mdc-notched-outline,.mdc-notched-outline[dir=rtl]{text-align:right}.mdc-notched-outline__leading,.mdc-notched-outline__notch,.mdc-notched-outline__trailing{box-sizing:border-box;height:100%;border-top:1px solid;border-bottom:1px solid;pointer-events:none}.mdc-notched-outline__leading{border-left:1px solid;border-right:none;width:12px}[dir=rtl] .mdc-notched-outline__leading,.mdc-notched-outline__leading[dir=rtl]{border-left:none;border-right:1px solid}.mdc-notched-outline__trailing{border-left:none;border-right:1px solid;flex-grow:1}[dir=rtl] .mdc-notched-outline__trailing,.mdc-notched-outline__trailing[dir=rtl]{border-left:1px solid;border-right:none}.mdc-notched-outline__notch{flex:0 0 auto;width:auto;max-width:calc(100% - 12px * 2)}.mdc-notched-outline .mdc-floating-label{display:inline-block;position:relative;max-width:100%}.mdc-notched-outline .mdc-floating-label--float-above{text-overflow:clip}.mdc-notched-outline--upgraded .mdc-floating-label--float-above{max-width:calc(100% / 0.75)}.mdc-notched-outline--notched .mdc-notched-outline__notch{padding-left:0;padding-right:8px;border-top:none}[dir=rtl] .mdc-notched-outline--notched .mdc-notched-outline__notch,.mdc-notched-outline--notched .mdc-notched-outline__notch[dir=rtl]{padding-left:8px;padding-right:0}.mdc-notched-outline--no-label .mdc-notched-outline__notch{display:none}:host{display:block;position:absolute;right:0;left:0;box-sizing:border-box;width:100%;max-width:100%;height:100%;text-align:left;pointer-events:none}[dir=rtl] :host,:host([dir=rtl]){text-align:right}::slotted(.mdc-floating-label){display:inline-block;position:relative;top:17px;bottom:auto;max-width:100%}::slotted(.mdc-floating-label--float-above){text-overflow:clip}.mdc-notched-outline--upgraded ::slotted(.mdc-floating-label--float-above){max-width:calc(100% / 0.75)}.mdc-notched-outline .mdc-notched-outline__leading{border-top-left-radius:4px;border-top-left-radius:var(--mdc-shape-small, 4px);border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:4px;border-bottom-left-radius:var(--mdc-shape-small, 4px)}[dir=rtl] .mdc-notched-outline .mdc-notched-outline__leading,.mdc-notched-outline .mdc-notched-outline__leading[dir=rtl]{border-top-left-radius:0;border-top-right-radius:4px;border-top-right-radius:var(--mdc-shape-small, 4px);border-bottom-right-radius:4px;border-bottom-right-radius:var(--mdc-shape-small, 4px);border-bottom-left-radius:0}@supports(top: max(0%)){.mdc-notched-outline .mdc-notched-outline__leading{width:max(12px, var(--mdc-shape-small, 4px))}}@supports(top: max(0%)){.mdc-notched-outline .mdc-notched-outline__notch{max-width:calc(100% - max(12px, var(--mdc-shape-small, 4px)) * 2)}}.mdc-notched-outline .mdc-notched-outline__trailing{border-top-left-radius:0;border-top-right-radius:4px;border-top-right-radius:var(--mdc-shape-small, 4px);border-bottom-right-radius:4px;border-bottom-right-radius:var(--mdc-shape-small, 4px);border-bottom-left-radius:0}[dir=rtl] .mdc-notched-outline .mdc-notched-outline__trailing,.mdc-notched-outline .mdc-notched-outline__trailing[dir=rtl]{border-top-left-radius:4px;border-top-left-radius:var(--mdc-shape-small, 4px);border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:4px;border-bottom-left-radius:var(--mdc-shape-small, 4px)}.mdc-notched-outline__leading,.mdc-notched-outline__notch,.mdc-notched-outline__trailing{border-color:var(--mdc-notched-outline-border-color, var(--mdc-theme-primary, #6200ee));border-width:1px;border-width:var(--mdc-notched-outline-stroke-width, 1px)}.mdc-notched-outline--notched .mdc-notched-outline__notch{padding-top:0;padding-top:var(--mdc-notched-outline-notch-offset, 0)}`,mn={"mwc-select":class extends Oi{static get styles(){return dn}},"mwc-list":class extends Di{static get styles(){return ln}},"mwc-list-item":class extends Fi{static get styles(){return cn}},"mwc-ripple":class extends en{static get styles(){return hn}},"mwc-menu":class extends $i{static get styles(){return un}},"mwc-menu-surface":class extends Xi{static get styles(){return pn}},"mwc-notched-outline":class extends an{static get styles(){return fn}}};function vn(t,e,i){if(void 0!==e) -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -return function(t,e,i){const n=t.constructor;if(!i){const t=`__${e}`;if(!(i=n.getPropertyDescriptor(e,t)))throw new Error("@ariaProperty must be used after a @property decorator")}const o=i;let r="";if(!o.set)throw new Error(`@ariaProperty requires a setter for ${e}`);if(t.dispatchWizEvent)return i;const s={configurable:!0,enumerable:!0,set(t){if(""===r){const t=n.getPropertyOptions(e);r="string"==typeof t.attribute?t.attribute:e}this.hasAttribute(r)&&this.removeAttribute(r),o.set.call(this,t)}};return o.get&&(s.get=function(){return o.get.call(this)}),s}(t,e,i);throw new Error("@ariaProperty only supports TypeScript Decorators")} -/** - * @license - * Copyright 2018 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */var gn={CHECKED:"mdc-switch--checked",DISABLED:"mdc-switch--disabled"},yn={ARIA_CHECKED_ATTR:"aria-checked",NATIVE_CONTROL_SELECTOR:".mdc-switch__native-control",RIPPLE_SURFACE_SELECTOR:".mdc-switch__thumb-underlay"},bn=function(t){function e(i){return t.call(this,n(n({},e.defaultAdapter),i))||this}return i(e,t),Object.defineProperty(e,"strings",{get:function(){return yn},enumerable:!1,configurable:!0}),Object.defineProperty(e,"cssClasses",{get:function(){return gn},enumerable:!1,configurable:!0}),Object.defineProperty(e,"defaultAdapter",{get:function(){return{addClass:function(){},removeClass:function(){},setNativeControlChecked:function(){},setNativeControlDisabled:function(){},setNativeControlAttr:function(){}}},enumerable:!1,configurable:!0}),e.prototype.setChecked=function(t){this.adapter.setNativeControlChecked(t),this.updateAriaChecked(t),this.updateCheckedStyling(t)},e.prototype.setDisabled=function(t){this.adapter.setNativeControlDisabled(t),t?this.adapter.addClass(gn.DISABLED):this.adapter.removeClass(gn.DISABLED)},e.prototype.handleChange=function(t){var e=t.target;this.updateAriaChecked(e.checked),this.updateCheckedStyling(e.checked)},e.prototype.updateCheckedStyling=function(t){t?this.adapter.addClass(gn.CHECKED):this.adapter.removeClass(gn.CHECKED)},e.prototype.updateAriaChecked=function(t){this.adapter.setNativeControlAttr(yn.ARIA_CHECKED_ATTR,""+!!t)},e}(ee); -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: Apache-2.0 */ -class xn extends he{constructor(){super(...arguments),this.checked=!1,this.disabled=!1,this.shouldRenderRipple=!1,this.mdcFoundationClass=bn,this.rippleHandlers=new Mi((()=>(this.shouldRenderRipple=!0,this.ripple)))}changeHandler(t){this.mdcFoundation.handleChange(t),this.checked=this.formElement.checked}createAdapter(){return Object.assign(Object.assign({},se(this.mdcRoot)),{setNativeControlChecked:t=>{this.formElement.checked=t},setNativeControlDisabled:t=>{this.formElement.disabled=t},setNativeControlAttr:(t,e)=>{this.formElement.setAttribute(t,e)}})}renderRipple(){return this.shouldRenderRipple?$` - - `:""}focus(){const t=this.formElement;t&&(this.rippleHandlers.startFocus(),t.focus())}blur(){const t=this.formElement;t&&(this.rippleHandlers.endFocus(),t.blur())}click(){this.formElement&&!this.disabled&&(this.formElement.focus(),this.formElement.click())}firstUpdated(){super.firstUpdated(),this.shadowRoot&&this.mdcRoot.addEventListener("change",(t=>{this.dispatchEvent(new Event("change",t))}))}render(){return $` -
-
-
- ${this.renderRipple()} -
- -
-
-
`}handleRippleMouseDown(t){const e=()=>{window.removeEventListener("mouseup",e),this.handleRippleDeactivate()};window.addEventListener("mouseup",e),this.rippleHandlers.startPress(t)}handleRippleTouchStart(t){this.rippleHandlers.startPress(t)}handleRippleDeactivate(){this.rippleHandlers.endPress()}handleRippleMouseEnter(){this.rippleHandlers.startHover()}handleRippleMouseLeave(){this.rippleHandlers.endHover()}handleRippleFocus(){this.rippleHandlers.startFocus()}handleRippleBlur(){this.rippleHandlers.endFocus()}}o([At({type:Boolean}),ve((function(t){this.mdcFoundation.setChecked(t)}))],xn.prototype,"checked",void 0),o([At({type:Boolean}),ve((function(t){this.mdcFoundation.setDisabled(t)}))],xn.prototype,"disabled",void 0),o([vn,At({attribute:"aria-label"})],xn.prototype,"ariaLabel",void 0),o([vn,At({attribute:"aria-labelledby"})],xn.prototype,"ariaLabelledBy",void 0),o([Mt(".mdc-switch")],xn.prototype,"mdcRoot",void 0),o([Mt("input")],xn.prototype,"formElement",void 0),o([Ft("mwc-ripple")],xn.prototype,"ripple",void 0),o([Rt()],xn.prototype,"shouldRenderRipple",void 0),o([Dt({passive:!0})],xn.prototype,"handleRippleMouseDown",null),o([Dt({passive:!0})],xn.prototype,"handleRippleTouchStart",null); +function Qt(t){return(({finisher:t,descriptor:e})=>(i,o)=>{var n;if(void 0===o){const o=null!==(n=i.originalKey)&&void 0!==n?n:i.key,r=null!=e?{kind:"method",placement:"prototype",key:o,descriptor:e(i.key)}:{...i,key:o};return null!=t&&(r.finisher=function(e){t(e,o)}),r}{const n=i.constructor;void 0!==e&&Object.defineProperty(i,o,e(o)),null==t||t(n,o)}})({finisher:(e,i)=>{Object.assign(e.prototype[i],t)}})} /** * @license * Copyright 2021 Google LLC - * SPDX-LIcense-Identifier: Apache-2.0 - */ -const _n=ht`.mdc-switch__thumb-underlay{left:-14px;right:initial;top:-17px;width:48px;height:48px}[dir=rtl] .mdc-switch__thumb-underlay,.mdc-switch__thumb-underlay[dir=rtl]{left:initial;right:-14px}.mdc-switch__native-control{width:64px;height:48px}.mdc-switch{display:inline-block;position:relative;outline:none;user-select:none}.mdc-switch.mdc-switch--checked .mdc-switch__track{background-color:#018786;background-color:var(--mdc-theme-secondary, #018786)}.mdc-switch.mdc-switch--checked .mdc-switch__thumb{background-color:#018786;background-color:var(--mdc-theme-secondary, #018786);border-color:#018786;border-color:var(--mdc-theme-secondary, #018786)}.mdc-switch:not(.mdc-switch--checked) .mdc-switch__track{background-color:#000;background-color:var(--mdc-theme-on-surface, #000)}.mdc-switch:not(.mdc-switch--checked) .mdc-switch__thumb{background-color:#fff;background-color:var(--mdc-theme-surface, #fff);border-color:#fff;border-color:var(--mdc-theme-surface, #fff)}.mdc-switch__native-control{left:0;right:initial;position:absolute;top:0;margin:0;opacity:0;cursor:pointer;pointer-events:auto;transition:transform 90ms cubic-bezier(0.4, 0, 0.2, 1)}[dir=rtl] .mdc-switch__native-control,.mdc-switch__native-control[dir=rtl]{left:initial;right:0}.mdc-switch__track{box-sizing:border-box;width:36px;height:14px;border:1px solid transparent;border-radius:7px;opacity:.38;transition:opacity 90ms cubic-bezier(0.4, 0, 0.2, 1),background-color 90ms cubic-bezier(0.4, 0, 0.2, 1),border-color 90ms cubic-bezier(0.4, 0, 0.2, 1)}.mdc-switch__thumb-underlay{display:flex;position:absolute;align-items:center;justify-content:center;transform:translateX(0);transition:transform 90ms cubic-bezier(0.4, 0, 0.2, 1),background-color 90ms cubic-bezier(0.4, 0, 0.2, 1),border-color 90ms cubic-bezier(0.4, 0, 0.2, 1)}.mdc-switch__thumb{box-shadow:0px 3px 1px -2px rgba(0, 0, 0, 0.2),0px 2px 2px 0px rgba(0, 0, 0, 0.14),0px 1px 5px 0px rgba(0,0,0,.12);box-sizing:border-box;width:20px;height:20px;border:10px solid;border-radius:50%;pointer-events:none;z-index:1}.mdc-switch--checked .mdc-switch__track{opacity:.54}.mdc-switch--checked .mdc-switch__thumb-underlay{transform:translateX(16px)}[dir=rtl] .mdc-switch--checked .mdc-switch__thumb-underlay,.mdc-switch--checked .mdc-switch__thumb-underlay[dir=rtl]{transform:translateX(-16px)}.mdc-switch--checked .mdc-switch__native-control{transform:translateX(-16px)}[dir=rtl] .mdc-switch--checked .mdc-switch__native-control,.mdc-switch--checked .mdc-switch__native-control[dir=rtl]{transform:translateX(16px)}.mdc-switch--disabled{opacity:.38;pointer-events:none}.mdc-switch--disabled .mdc-switch__thumb{border-width:1px}.mdc-switch--disabled .mdc-switch__native-control{cursor:default;pointer-events:none}:host{display:inline-flex;outline:none;-webkit-tap-highlight-color:transparent}`,wn={"mwc-switch":class extends xn{static get styles(){return _n}},"mwc-ripple":class extends en{static get styles(){return hn}}}; -/** - * @license - * Copyright 2016 Google Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -var En={ARIA_CONTROLS:"aria-controls",ARIA_DESCRIBEDBY:"aria-describedby",INPUT_SELECTOR:".mdc-text-field__input",LABEL_SELECTOR:".mdc-floating-label",LEADING_ICON_SELECTOR:".mdc-text-field__icon--leading",LINE_RIPPLE_SELECTOR:".mdc-line-ripple",OUTLINE_SELECTOR:".mdc-notched-outline",PREFIX_SELECTOR:".mdc-text-field__affix--prefix",SUFFIX_SELECTOR:".mdc-text-field__affix--suffix",TRAILING_ICON_SELECTOR:".mdc-text-field__icon--trailing"},kn={DISABLED:"mdc-text-field--disabled",FOCUSED:"mdc-text-field--focused",HELPER_LINE:"mdc-text-field-helper-line",INVALID:"mdc-text-field--invalid",LABEL_FLOATING:"mdc-text-field--label-floating",NO_LABEL:"mdc-text-field--no-label",OUTLINED:"mdc-text-field--outlined",ROOT:"mdc-text-field",TEXTAREA:"mdc-text-field--textarea",WITH_LEADING_ICON:"mdc-text-field--with-leading-icon",WITH_TRAILING_ICON:"mdc-text-field--with-trailing-icon",WITH_INTERNAL_COUNTER:"mdc-text-field--with-internal-counter"},On={LABEL_SCALE:.75},Cn=["pattern","min","max","required","step","minlength","maxlength"],Sn=["color","date","datetime-local","month","range","time","week"],Tn=["mousedown","touchstart"],In=["click","keydown"],An=function(t){function e(i,o){void 0===o&&(o={});var r=t.call(this,n(n({},e.defaultAdapter),i))||this;return r.isFocused=!1,r.receivedUserInput=!1,r.valid=!0,r.useNativeValidation=!0,r.validateOnValueChange=!0,r.helperText=o.helperText,r.characterCounter=o.characterCounter,r.leadingIcon=o.leadingIcon,r.trailingIcon=o.trailingIcon,r.inputFocusHandler=function(){r.activateFocus()},r.inputBlurHandler=function(){r.deactivateFocus()},r.inputInputHandler=function(){r.handleInput()},r.setPointerXOffset=function(t){r.setTransformOrigin(t)},r.textFieldInteractionHandler=function(){r.handleTextFieldInteraction()},r.validationAttributeChangeHandler=function(t){r.handleValidationAttributeChange(t)},r}return i(e,t),Object.defineProperty(e,"cssClasses",{get:function(){return kn},enumerable:!1,configurable:!0}),Object.defineProperty(e,"strings",{get:function(){return En},enumerable:!1,configurable:!0}),Object.defineProperty(e,"numbers",{get:function(){return On},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"shouldAlwaysFloat",{get:function(){var t=this.getNativeInput().type;return Sn.indexOf(t)>=0},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"shouldFloat",{get:function(){return this.shouldAlwaysFloat||this.isFocused||!!this.getValue()||this.isBadInput()},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"shouldShake",{get:function(){return!this.isFocused&&!this.isValid()&&!!this.getValue()},enumerable:!1,configurable:!0}),Object.defineProperty(e,"defaultAdapter",{get:function(){return{addClass:function(){},removeClass:function(){},hasClass:function(){return!0},setInputAttr:function(){},removeInputAttr:function(){},registerTextFieldInteractionHandler:function(){},deregisterTextFieldInteractionHandler:function(){},registerInputInteractionHandler:function(){},deregisterInputInteractionHandler:function(){},registerValidationAttributeChangeHandler:function(){return new MutationObserver((function(){}))},deregisterValidationAttributeChangeHandler:function(){},getNativeInput:function(){return null},isFocused:function(){return!1},activateLineRipple:function(){},deactivateLineRipple:function(){},setLineRippleTransformOrigin:function(){},shakeLabel:function(){},floatLabel:function(){},setLabelRequired:function(){},hasLabel:function(){return!1},getLabelWidth:function(){return 0},hasOutline:function(){return!1},notchOutline:function(){},closeOutline:function(){}}},enumerable:!1,configurable:!0}),e.prototype.init=function(){var t,e,i,n;this.adapter.hasLabel()&&this.getNativeInput().required&&this.adapter.setLabelRequired(!0),this.adapter.isFocused()?this.inputFocusHandler():this.adapter.hasLabel()&&this.shouldFloat&&(this.notchOutline(!0),this.adapter.floatLabel(!0),this.styleFloating(!0)),this.adapter.registerInputInteractionHandler("focus",this.inputFocusHandler),this.adapter.registerInputInteractionHandler("blur",this.inputBlurHandler),this.adapter.registerInputInteractionHandler("input",this.inputInputHandler);try{for(var o=r(Tn),s=o.next();!s.done;s=o.next()){var a=s.value;this.adapter.registerInputInteractionHandler(a,this.setPointerXOffset)}}catch(e){t={error:e}}finally{try{s&&!s.done&&(e=o.return)&&e.call(o)}finally{if(t)throw t.error}}try{for(var d=r(In),l=d.next();!l.done;l=d.next()){a=l.value;this.adapter.registerTextFieldInteractionHandler(a,this.textFieldInteractionHandler)}}catch(t){i={error:t}}finally{try{l&&!l.done&&(n=d.return)&&n.call(d)}finally{if(i)throw i.error}}this.validationObserver=this.adapter.registerValidationAttributeChangeHandler(this.validationAttributeChangeHandler),this.setcharacterCounter(this.getValue().length)},e.prototype.destroy=function(){var t,e,i,n;this.adapter.deregisterInputInteractionHandler("focus",this.inputFocusHandler),this.adapter.deregisterInputInteractionHandler("blur",this.inputBlurHandler),this.adapter.deregisterInputInteractionHandler("input",this.inputInputHandler);try{for(var o=r(Tn),s=o.next();!s.done;s=o.next()){var a=s.value;this.adapter.deregisterInputInteractionHandler(a,this.setPointerXOffset)}}catch(e){t={error:e}}finally{try{s&&!s.done&&(e=o.return)&&e.call(o)}finally{if(t)throw t.error}}try{for(var d=r(In),l=d.next();!l.done;l=d.next()){a=l.value;this.adapter.deregisterTextFieldInteractionHandler(a,this.textFieldInteractionHandler)}}catch(t){i={error:t}}finally{try{l&&!l.done&&(n=d.return)&&n.call(d)}finally{if(i)throw i.error}}this.adapter.deregisterValidationAttributeChangeHandler(this.validationObserver)},e.prototype.handleTextFieldInteraction=function(){var t=this.adapter.getNativeInput();t&&t.disabled||(this.receivedUserInput=!0)},e.prototype.handleValidationAttributeChange=function(t){var e=this;t.some((function(t){return Cn.indexOf(t)>-1&&(e.styleValidity(!0),e.adapter.setLabelRequired(e.getNativeInput().required),!0)})),t.indexOf("maxlength")>-1&&this.setcharacterCounter(this.getValue().length)},e.prototype.notchOutline=function(t){if(this.adapter.hasOutline()&&this.adapter.hasLabel())if(t){var e=this.adapter.getLabelWidth()*On.LABEL_SCALE;this.adapter.notchOutline(e)}else this.adapter.closeOutline()},e.prototype.activateFocus=function(){this.isFocused=!0,this.styleFocused(this.isFocused),this.adapter.activateLineRipple(),this.adapter.hasLabel()&&(this.notchOutline(this.shouldFloat),this.adapter.floatLabel(this.shouldFloat),this.styleFloating(this.shouldFloat),this.adapter.shakeLabel(this.shouldShake)),!this.helperText||!this.helperText.isPersistent()&&this.helperText.isValidation()&&this.valid||this.helperText.showToScreenReader()},e.prototype.setTransformOrigin=function(t){if(!this.isDisabled()&&!this.adapter.hasOutline()){var e=t.touches,i=e?e[0]:t,n=i.target.getBoundingClientRect(),o=i.clientX-n.left;this.adapter.setLineRippleTransformOrigin(o)}},e.prototype.handleInput=function(){this.autoCompleteFocus(),this.setcharacterCounter(this.getValue().length)},e.prototype.autoCompleteFocus=function(){this.receivedUserInput||this.activateFocus()},e.prototype.deactivateFocus=function(){this.isFocused=!1,this.adapter.deactivateLineRipple();var t=this.isValid();this.styleValidity(t),this.styleFocused(this.isFocused),this.adapter.hasLabel()&&(this.notchOutline(this.shouldFloat),this.adapter.floatLabel(this.shouldFloat),this.styleFloating(this.shouldFloat),this.adapter.shakeLabel(this.shouldShake)),this.shouldFloat||(this.receivedUserInput=!1)},e.prototype.getValue=function(){return this.getNativeInput().value},e.prototype.setValue=function(t){if(this.getValue()!==t&&(this.getNativeInput().value=t),this.setcharacterCounter(t.length),this.validateOnValueChange){var e=this.isValid();this.styleValidity(e)}this.adapter.hasLabel()&&(this.notchOutline(this.shouldFloat),this.adapter.floatLabel(this.shouldFloat),this.styleFloating(this.shouldFloat),this.validateOnValueChange&&this.adapter.shakeLabel(this.shouldShake))},e.prototype.isValid=function(){return this.useNativeValidation?this.isNativeInputValid():this.valid},e.prototype.setValid=function(t){this.valid=t,this.styleValidity(t);var e=!t&&!this.isFocused&&!!this.getValue();this.adapter.hasLabel()&&this.adapter.shakeLabel(e)},e.prototype.setValidateOnValueChange=function(t){this.validateOnValueChange=t},e.prototype.getValidateOnValueChange=function(){return this.validateOnValueChange},e.prototype.setUseNativeValidation=function(t){this.useNativeValidation=t},e.prototype.isDisabled=function(){return this.getNativeInput().disabled},e.prototype.setDisabled=function(t){this.getNativeInput().disabled=t,this.styleDisabled(t)},e.prototype.setHelperTextContent=function(t){this.helperText&&this.helperText.setContent(t)},e.prototype.setLeadingIconAriaLabel=function(t){this.leadingIcon&&this.leadingIcon.setAriaLabel(t)},e.prototype.setLeadingIconContent=function(t){this.leadingIcon&&this.leadingIcon.setContent(t)},e.prototype.setTrailingIconAriaLabel=function(t){this.trailingIcon&&this.trailingIcon.setAriaLabel(t)},e.prototype.setTrailingIconContent=function(t){this.trailingIcon&&this.trailingIcon.setContent(t)},e.prototype.setcharacterCounter=function(t){if(this.characterCounter){var e=this.getNativeInput().maxLength;if(-1===e)throw new Error("MDCTextFieldFoundation: Expected maxlength html property on text input or textarea.");this.characterCounter.setCounterValue(t,e)}},e.prototype.isBadInput=function(){return this.getNativeInput().validity.badInput||!1},e.prototype.isNativeInputValid=function(){return this.getNativeInput().validity.valid},e.prototype.styleValidity=function(t){var i=e.cssClasses.INVALID;if(t?this.adapter.removeClass(i):this.adapter.addClass(i),this.helperText){if(this.helperText.setValidity(t),!this.helperText.isValidation())return;var n=this.helperText.isVisible(),o=this.helperText.getId();n&&o?this.adapter.setInputAttr(En.ARIA_DESCRIBEDBY,o):this.adapter.removeInputAttr(En.ARIA_DESCRIBEDBY)}},e.prototype.styleFocused=function(t){var i=e.cssClasses.FOCUSED;t?this.adapter.addClass(i):this.adapter.removeClass(i)},e.prototype.styleDisabled=function(t){var i=e.cssClasses,n=i.DISABLED,o=i.INVALID;t?(this.adapter.addClass(n),this.adapter.removeClass(o)):this.adapter.removeClass(n),this.leadingIcon&&this.leadingIcon.setDisabled(t),this.trailingIcon&&this.trailingIcon.setDisabled(t)},e.prototype.styleFloating=function(t){var i=e.cssClasses.LABEL_FLOATING;t?this.adapter.addClass(i):this.adapter.removeClass(i)},e.prototype.getNativeInput=function(){return(this.adapter?this.adapter.getNativeInput():null)||{disabled:!1,maxLength:-1,required:!1,type:"input",validity:{badInput:!1,valid:!0},value:""}},e}(ee); -/** - * @license - * Copyright 2020 Google LLC * SPDX-License-Identifier: BSD-3-Clause - */ -const Rn={},Pn=xe(class extends _e{constructor(t){if(super(t),t.type!==ye&&t.type!==ge&&t.type!==be)throw Error("The `live` directive is not allowed on child or event bindings");if(!(t=>void 0===t.strings)(t))throw Error("`live` bindings can only contain a single expression")}render(t){return t}update(t,[e]){if(e===U||e===W)return e;const i=t.element,n=t.name;if(t.type===ye){if(e===i[n])return U}else if(t.type===be){if(!!e===i.hasAttribute(n))return U}else if(t.type===ge&&i.getAttribute(n)===e+"")return U;return((t,e=Rn)=>{t._$AH=e; -/** - * @license - * Copyright 2020 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */})(t),e}}),Dn=["touchstart","touchmove","scroll","mousewheel"],Mn=(t={})=>{const e={};for(const i in t)e[i]=t[i];return Object.assign({badInput:!1,customError:!1,patternMismatch:!1,rangeOverflow:!1,rangeUnderflow:!1,stepMismatch:!1,tooLong:!1,tooShort:!1,typeMismatch:!1,valid:!0,valueMissing:!1},e)};class Fn extends me{constructor(){super(...arguments),this.mdcFoundationClass=An,this.value="",this.type="text",this.placeholder="",this.label="",this.icon="",this.iconTrailing="",this.disabled=!1,this.required=!1,this.minLength=-1,this.maxLength=-1,this.outlined=!1,this.helper="",this.validateOnInitialRender=!1,this.validationMessage="",this.autoValidate=!1,this.pattern="",this.min="",this.max="",this.step=null,this.size=null,this.helperPersistent=!1,this.charCounter=!1,this.endAligned=!1,this.prefix="",this.suffix="",this.name="",this.readOnly=!1,this.autocapitalize="",this.outlineOpen=!1,this.outlineWidth=0,this.isUiValid=!0,this.focused=!1,this._validity=Mn(),this.validityTransform=null}get validity(){return this._checkValidity(this.value),this._validity}get willValidate(){return this.formElement.willValidate}get selectionStart(){return this.formElement.selectionStart}get selectionEnd(){return this.formElement.selectionEnd}focus(){const t=new CustomEvent("focus");this.formElement.dispatchEvent(t),this.formElement.focus()}blur(){const t=new CustomEvent("blur");this.formElement.dispatchEvent(t),this.formElement.blur()}select(){this.formElement.select()}setSelectionRange(t,e,i){this.formElement.setSelectionRange(t,e,i)}update(t){t.has("autoValidate")&&this.mdcFoundation&&this.mdcFoundation.setValidateOnValueChange(this.autoValidate),t.has("value")&&"string"!=typeof this.value&&(this.value=`${this.value}`),super.update(t)}setFormData(t){this.name&&t.append(this.name,this.value)}render(){const t=this.charCounter&&-1!==this.maxLength,e=!!this.helper||!!this.validationMessage||t,i={"mdc-text-field--disabled":this.disabled,"mdc-text-field--no-label":!this.label,"mdc-text-field--filled":!this.outlined,"mdc-text-field--outlined":this.outlined,"mdc-text-field--with-leading-icon":this.icon,"mdc-text-field--with-trailing-icon":this.iconTrailing,"mdc-text-field--end-aligned":this.endAligned};return $` - - ${this.renderHelperText(e,t)} - `}updated(t){t.has("value")&&void 0!==t.get("value")&&(this.mdcFoundation.setValue(this.value),this.autoValidate&&this.reportValidity())}renderRipple(){return this.outlined?"":$` - - `}renderOutline(){return this.outlined?$` - - ${this.renderLabel()} - `:""}renderLabel(){return this.label?$` - ${this.label} - `:""}renderLeadingIcon(){return this.icon?this.renderIcon(this.icon):""}renderTrailingIcon(){return this.iconTrailing?this.renderIcon(this.iconTrailing,!0):""}renderIcon(t,e=!1){return $`${t}`}renderPrefix(){return this.prefix?this.renderAffix(this.prefix):""}renderSuffix(){return this.suffix?this.renderAffix(this.suffix,!0):""}renderAffix(t,e=!1){return $` - ${t}`}renderInput(t){const e=-1===this.minLength?void 0:this.minLength,i=-1===this.maxLength?void 0:this.maxLength,n=this.autocapitalize?this.autocapitalize:void 0,o=this.validationMessage&&!this.isUiValid,r=this.label?"label":void 0,s=t?"helper-text":void 0,a=this.focused||this.helperPersistent||o?"helper-text":void 0;return $` - `}renderLineRipple(){return this.outlined?"":$` - - `}renderHelperText(t,e){const i=this.validationMessage&&!this.isUiValid,n={"mdc-text-field-helper-text--persistent":this.helperPersistent,"mdc-text-field-helper-text--validation-msg":i},o=this.focused||this.helperPersistent||i?void 0:"true",r=i?this.validationMessage:this.helper;return t?$` -
-
${r}
- ${this.renderCharCounter(e)} -
`:""}renderCharCounter(t){const e=Math.min(this.value.length,this.maxLength);return t?$` - ${e} / ${this.maxLength}`:""}onInputFocus(){this.focused=!0}onInputBlur(){this.focused=!1,this.reportValidity()}checkValidity(){const t=this._checkValidity(this.value);if(!t){const t=new Event("invalid",{bubbles:!1,cancelable:!0});this.dispatchEvent(t)}return t}reportValidity(){const t=this.checkValidity();return this.mdcFoundation.setValid(t),this.isUiValid=t,t}_checkValidity(t){const e=this.formElement.validity;let i=Mn(e);if(this.validityTransform){const e=this.validityTransform(t,i);i=Object.assign(Object.assign({},i),e),this.mdcFoundation.setUseNativeValidation(!1)}else this.mdcFoundation.setUseNativeValidation(!0);return this._validity=i,this._validity.valid}setCustomValidity(t){this.validationMessage=t,this.formElement.setCustomValidity(t)}handleInputChange(){this.value=this.formElement.value}createAdapter(){return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},this.getRootAdapterMethods()),this.getInputAdapterMethods()),this.getLabelAdapterMethods()),this.getLineRippleAdapterMethods()),this.getOutlineAdapterMethods())}getRootAdapterMethods(){return Object.assign({registerTextFieldInteractionHandler:(t,e)=>this.addEventListener(t,e),deregisterTextFieldInteractionHandler:(t,e)=>this.removeEventListener(t,e),registerValidationAttributeChangeHandler:t=>{const e=new MutationObserver((e=>{t((t=>t.map((t=>t.attributeName)).filter((t=>t)))(e))}));return e.observe(this.formElement,{attributes:!0}),e},deregisterValidationAttributeChangeHandler:t=>t.disconnect()},se(this.mdcRoot))}getInputAdapterMethods(){return{getNativeInput:()=>this.formElement,setInputAttr:()=>{},removeInputAttr:()=>{},isFocused:()=>!!this.shadowRoot&&this.shadowRoot.activeElement===this.formElement,registerInputInteractionHandler:(t,e)=>this.formElement.addEventListener(t,e,{passive:t in Dn}),deregisterInputInteractionHandler:(t,e)=>this.formElement.removeEventListener(t,e)}}getLabelAdapterMethods(){return{floatLabel:t=>this.labelElement&&this.labelElement.floatingLabelFoundation.float(t),getLabelWidth:()=>this.labelElement?this.labelElement.floatingLabelFoundation.getWidth():0,hasLabel:()=>Boolean(this.labelElement),shakeLabel:t=>this.labelElement&&this.labelElement.floatingLabelFoundation.shake(t),setLabelRequired:t=>{this.labelElement&&this.labelElement.floatingLabelFoundation.setRequired(t)}}}getLineRippleAdapterMethods(){return{activateLineRipple:()=>{this.lineRippleElement&&this.lineRippleElement.lineRippleFoundation.activate()},deactivateLineRipple:()=>{this.lineRippleElement&&this.lineRippleElement.lineRippleFoundation.deactivate()},setLineRippleTransformOrigin:t=>{this.lineRippleElement&&this.lineRippleElement.lineRippleFoundation.setRippleCenter(t)}}}async getUpdateComplete(){var t;const e=await super.getUpdateComplete();return await(null===(t=this.outlineElement)||void 0===t?void 0:t.updateComplete),e}firstUpdated(){var t;super.firstUpdated(),this.mdcFoundation.setValidateOnValueChange(this.autoValidate),this.validateOnInitialRender&&this.reportValidity(),null===(t=this.outlineElement)||void 0===t||t.updateComplete.then((()=>{var t;this.outlineWidth=(null===(t=this.labelElement)||void 0===t?void 0:t.floatingLabelFoundation.getWidth())||0}))}getOutlineAdapterMethods(){return{closeOutline:()=>this.outlineElement&&(this.outlineOpen=!1),hasOutline:()=>Boolean(this.outlineElement),notchOutline:t=>{this.outlineElement&&!this.outlineOpen&&(this.outlineWidth=t,this.outlineOpen=!0)}}}async layout(){await this.updateComplete;const t=this.labelElement;if(!t)return void(this.outlineOpen=!1);const e=!!this.label&&!!this.value;if(t.floatingLabelFoundation.float(e),!this.outlined)return;this.outlineOpen=e,await this.updateComplete;const i=t.floatingLabelFoundation.getWidth();this.outlineOpen&&(this.outlineWidth=i,await this.updateComplete)}}o([Mt(".mdc-text-field")],Fn.prototype,"mdcRoot",void 0),o([Mt("input")],Fn.prototype,"formElement",void 0),o([Mt(".mdc-floating-label")],Fn.prototype,"labelElement",void 0),o([Mt(".mdc-line-ripple")],Fn.prototype,"lineRippleElement",void 0),o([Mt("mwc-notched-outline")],Fn.prototype,"outlineElement",void 0),o([Mt(".mdc-notched-outline__notch")],Fn.prototype,"notchElement",void 0),o([At({type:String})],Fn.prototype,"value",void 0),o([At({type:String})],Fn.prototype,"type",void 0),o([At({type:String})],Fn.prototype,"placeholder",void 0),o([At({type:String}),ve((function(t,e){void 0!==e&&this.label!==e&&this.layout()}))],Fn.prototype,"label",void 0),o([At({type:String})],Fn.prototype,"icon",void 0),o([At({type:String})],Fn.prototype,"iconTrailing",void 0),o([At({type:Boolean,reflect:!0})],Fn.prototype,"disabled",void 0),o([At({type:Boolean})],Fn.prototype,"required",void 0),o([At({type:Number})],Fn.prototype,"minLength",void 0),o([At({type:Number})],Fn.prototype,"maxLength",void 0),o([At({type:Boolean,reflect:!0}),ve((function(t,e){void 0!==e&&this.outlined!==e&&this.layout()}))],Fn.prototype,"outlined",void 0),o([At({type:String})],Fn.prototype,"helper",void 0),o([At({type:Boolean})],Fn.prototype,"validateOnInitialRender",void 0),o([At({type:String})],Fn.prototype,"validationMessage",void 0),o([At({type:Boolean})],Fn.prototype,"autoValidate",void 0),o([At({type:String})],Fn.prototype,"pattern",void 0),o([At({type:String})],Fn.prototype,"min",void 0),o([At({type:String})],Fn.prototype,"max",void 0),o([At({type:String})],Fn.prototype,"step",void 0),o([At({type:Number})],Fn.prototype,"size",void 0),o([At({type:Boolean})],Fn.prototype,"helperPersistent",void 0),o([At({type:Boolean})],Fn.prototype,"charCounter",void 0),o([At({type:Boolean})],Fn.prototype,"endAligned",void 0),o([At({type:String})],Fn.prototype,"prefix",void 0),o([At({type:String})],Fn.prototype,"suffix",void 0),o([At({type:String})],Fn.prototype,"name",void 0),o([At({type:String})],Fn.prototype,"inputMode",void 0),o([At({type:Boolean})],Fn.prototype,"readOnly",void 0),o([At({type:String})],Fn.prototype,"autocapitalize",void 0),o([Rt()],Fn.prototype,"outlineOpen",void 0),o([Rt()],Fn.prototype,"outlineWidth",void 0),o([Rt()],Fn.prototype,"isUiValid",void 0),o([Rt()],Fn.prototype,"focused",void 0),o([Dt({passive:!0})],Fn.prototype,"handleInputChange",null); -/** - * @license - * Copyright 2021 Google LLC - * SPDX-LIcense-Identifier: Apache-2.0 - */ -const Nn=ht`.mdc-floating-label{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-subtitle1-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:1rem;font-size:var(--mdc-typography-subtitle1-font-size, 1rem);font-weight:400;font-weight:var(--mdc-typography-subtitle1-font-weight, 400);letter-spacing:0.009375em;letter-spacing:var(--mdc-typography-subtitle1-letter-spacing, 0.009375em);text-decoration:inherit;text-decoration:var(--mdc-typography-subtitle1-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-subtitle1-text-transform, inherit);position:absolute;left:0;-webkit-transform-origin:left top;transform-origin:left top;line-height:1.15rem;text-align:left;text-overflow:ellipsis;white-space:nowrap;cursor:text;overflow:hidden;will-change:transform;transition:transform 150ms cubic-bezier(0.4, 0, 0.2, 1),color 150ms cubic-bezier(0.4, 0, 0.2, 1)}[dir=rtl] .mdc-floating-label,.mdc-floating-label[dir=rtl]{right:0;left:auto;-webkit-transform-origin:right top;transform-origin:right top;text-align:right}.mdc-floating-label--float-above{cursor:auto}.mdc-floating-label--required::after{margin-left:1px;margin-right:0px;content:"*"}[dir=rtl] .mdc-floating-label--required::after,.mdc-floating-label--required[dir=rtl]::after{margin-left:0;margin-right:1px}.mdc-floating-label--float-above{transform:translateY(-106%) scale(0.75)}.mdc-floating-label--shake{animation:mdc-floating-label-shake-float-above-standard 250ms 1}@keyframes mdc-floating-label-shake-float-above-standard{0%{transform:translateX(calc(0 - 0%)) translateY(-106%) scale(0.75)}33%{animation-timing-function:cubic-bezier(0.5, 0, 0.701732, 0.495819);transform:translateX(calc(4% - 0%)) translateY(-106%) scale(0.75)}66%{animation-timing-function:cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);transform:translateX(calc(-4% - 0%)) translateY(-106%) scale(0.75)}100%{transform:translateX(calc(0 - 0%)) translateY(-106%) scale(0.75)}}.mdc-line-ripple::before,.mdc-line-ripple::after{position:absolute;bottom:0;left:0;width:100%;border-bottom-style:solid;content:""}.mdc-line-ripple::before{border-bottom-width:1px}.mdc-line-ripple::before{z-index:1}.mdc-line-ripple::after{transform:scaleX(0);border-bottom-width:2px;opacity:0;z-index:2}.mdc-line-ripple::after{transition:transform 180ms cubic-bezier(0.4, 0, 0.2, 1),opacity 180ms cubic-bezier(0.4, 0, 0.2, 1)}.mdc-line-ripple--active::after{transform:scaleX(1);opacity:1}.mdc-line-ripple--deactivating::after{opacity:0}.mdc-notched-outline{display:flex;position:absolute;top:0;right:0;left:0;box-sizing:border-box;width:100%;max-width:100%;height:100%;text-align:left;pointer-events:none}[dir=rtl] .mdc-notched-outline,.mdc-notched-outline[dir=rtl]{text-align:right}.mdc-notched-outline__leading,.mdc-notched-outline__notch,.mdc-notched-outline__trailing{box-sizing:border-box;height:100%;border-top:1px solid;border-bottom:1px solid;pointer-events:none}.mdc-notched-outline__leading{border-left:1px solid;border-right:none;width:12px}[dir=rtl] .mdc-notched-outline__leading,.mdc-notched-outline__leading[dir=rtl]{border-left:none;border-right:1px solid}.mdc-notched-outline__trailing{border-left:none;border-right:1px solid;flex-grow:1}[dir=rtl] .mdc-notched-outline__trailing,.mdc-notched-outline__trailing[dir=rtl]{border-left:1px solid;border-right:none}.mdc-notched-outline__notch{flex:0 0 auto;width:auto;max-width:calc(100% - 12px * 2)}.mdc-notched-outline .mdc-floating-label{display:inline-block;position:relative;max-width:100%}.mdc-notched-outline .mdc-floating-label--float-above{text-overflow:clip}.mdc-notched-outline--upgraded .mdc-floating-label--float-above{max-width:calc(100% / 0.75)}.mdc-notched-outline--notched .mdc-notched-outline__notch{padding-left:0;padding-right:8px;border-top:none}[dir=rtl] .mdc-notched-outline--notched .mdc-notched-outline__notch,.mdc-notched-outline--notched .mdc-notched-outline__notch[dir=rtl]{padding-left:8px;padding-right:0}.mdc-notched-outline--no-label .mdc-notched-outline__notch{display:none}@keyframes mdc-ripple-fg-radius-in{from{animation-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transform:translate(var(--mdc-ripple-fg-translate-start, 0)) scale(1)}to{transform:translate(var(--mdc-ripple-fg-translate-end, 0)) scale(var(--mdc-ripple-fg-scale, 1))}}@keyframes mdc-ripple-fg-opacity-in{from{animation-timing-function:linear;opacity:0}to{opacity:var(--mdc-ripple-fg-opacity, 0)}}@keyframes mdc-ripple-fg-opacity-out{from{animation-timing-function:linear;opacity:var(--mdc-ripple-fg-opacity, 0)}to{opacity:0}}.mdc-text-field--filled{--mdc-ripple-fg-size: 0;--mdc-ripple-left: 0;--mdc-ripple-top: 0;--mdc-ripple-fg-scale: 1;--mdc-ripple-fg-translate-end: 0;--mdc-ripple-fg-translate-start: 0;-webkit-tap-highlight-color:rgba(0,0,0,0);will-change:transform,opacity}.mdc-text-field--filled .mdc-text-field__ripple::before,.mdc-text-field--filled .mdc-text-field__ripple::after{position:absolute;border-radius:50%;opacity:0;pointer-events:none;content:""}.mdc-text-field--filled .mdc-text-field__ripple::before{transition:opacity 15ms linear,background-color 15ms linear;z-index:1;z-index:var(--mdc-ripple-z-index, 1)}.mdc-text-field--filled .mdc-text-field__ripple::after{z-index:0;z-index:var(--mdc-ripple-z-index, 0)}.mdc-text-field--filled.mdc-ripple-upgraded .mdc-text-field__ripple::before{transform:scale(var(--mdc-ripple-fg-scale, 1))}.mdc-text-field--filled.mdc-ripple-upgraded .mdc-text-field__ripple::after{top:0;left:0;transform:scale(0);transform-origin:center center}.mdc-text-field--filled.mdc-ripple-upgraded--unbounded .mdc-text-field__ripple::after{top:var(--mdc-ripple-top, 0);left:var(--mdc-ripple-left, 0)}.mdc-text-field--filled.mdc-ripple-upgraded--foreground-activation .mdc-text-field__ripple::after{animation:mdc-ripple-fg-radius-in 225ms forwards,mdc-ripple-fg-opacity-in 75ms forwards}.mdc-text-field--filled.mdc-ripple-upgraded--foreground-deactivation .mdc-text-field__ripple::after{animation:mdc-ripple-fg-opacity-out 150ms;transform:translate(var(--mdc-ripple-fg-translate-end, 0)) scale(var(--mdc-ripple-fg-scale, 1))}.mdc-text-field--filled .mdc-text-field__ripple::before,.mdc-text-field--filled .mdc-text-field__ripple::after{top:calc(50% - 100%);left:calc(50% - 100%);width:200%;height:200%}.mdc-text-field--filled.mdc-ripple-upgraded .mdc-text-field__ripple::after{width:var(--mdc-ripple-fg-size, 100%);height:var(--mdc-ripple-fg-size, 100%)}.mdc-text-field__ripple{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none}.mdc-text-field{border-top-left-radius:4px;border-top-left-radius:var(--mdc-shape-small, 4px);border-top-right-radius:4px;border-top-right-radius:var(--mdc-shape-small, 4px);border-bottom-right-radius:0;border-bottom-left-radius:0;display:inline-flex;align-items:baseline;padding:0 16px;position:relative;box-sizing:border-box;overflow:hidden;will-change:opacity,transform,color}.mdc-text-field:not(.mdc-text-field--disabled) .mdc-floating-label{color:rgba(0, 0, 0, 0.6)}.mdc-text-field:not(.mdc-text-field--disabled) .mdc-text-field__input{color:rgba(0, 0, 0, 0.87)}@media all{.mdc-text-field:not(.mdc-text-field--disabled) .mdc-text-field__input::placeholder{color:rgba(0, 0, 0, 0.54)}}@media all{.mdc-text-field:not(.mdc-text-field--disabled) .mdc-text-field__input:-ms-input-placeholder{color:rgba(0, 0, 0, 0.54)}}.mdc-text-field .mdc-text-field__input{caret-color:#6200ee;caret-color:var(--mdc-theme-primary, #6200ee)}.mdc-text-field:not(.mdc-text-field--disabled)+.mdc-text-field-helper-line .mdc-text-field-helper-text{color:rgba(0, 0, 0, 0.6)}.mdc-text-field:not(.mdc-text-field--disabled) .mdc-text-field-character-counter,.mdc-text-field:not(.mdc-text-field--disabled)+.mdc-text-field-helper-line .mdc-text-field-character-counter{color:rgba(0, 0, 0, 0.6)}.mdc-text-field:not(.mdc-text-field--disabled) .mdc-text-field__icon--leading{color:rgba(0, 0, 0, 0.54)}.mdc-text-field:not(.mdc-text-field--disabled) .mdc-text-field__icon--trailing{color:rgba(0, 0, 0, 0.54)}.mdc-text-field:not(.mdc-text-field--disabled) .mdc-text-field__affix--prefix{color:rgba(0, 0, 0, 0.6)}.mdc-text-field:not(.mdc-text-field--disabled) .mdc-text-field__affix--suffix{color:rgba(0, 0, 0, 0.6)}.mdc-text-field .mdc-floating-label{top:50%;transform:translateY(-50%);pointer-events:none}.mdc-text-field__input{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-subtitle1-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:1rem;font-size:var(--mdc-typography-subtitle1-font-size, 1rem);font-weight:400;font-weight:var(--mdc-typography-subtitle1-font-weight, 400);letter-spacing:0.009375em;letter-spacing:var(--mdc-typography-subtitle1-letter-spacing, 0.009375em);text-decoration:inherit;text-decoration:var(--mdc-typography-subtitle1-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-subtitle1-text-transform, inherit);height:28px;transition:opacity 150ms 0ms cubic-bezier(0.4, 0, 0.2, 1);width:100%;min-width:0;border:none;border-radius:0;background:none;appearance:none;padding:0}.mdc-text-field__input::-ms-clear{display:none}.mdc-text-field__input::-webkit-calendar-picker-indicator{display:none}.mdc-text-field__input:focus{outline:none}.mdc-text-field__input:invalid{box-shadow:none}@media all{.mdc-text-field__input::placeholder{transition:opacity 67ms 0ms cubic-bezier(0.4, 0, 0.2, 1);opacity:0}}@media all{.mdc-text-field__input:-ms-input-placeholder{transition:opacity 67ms 0ms cubic-bezier(0.4, 0, 0.2, 1);opacity:0}}@media all{.mdc-text-field--no-label .mdc-text-field__input::placeholder,.mdc-text-field--focused .mdc-text-field__input::placeholder{transition-delay:40ms;transition-duration:110ms;opacity:1}}@media all{.mdc-text-field--no-label .mdc-text-field__input:-ms-input-placeholder,.mdc-text-field--focused .mdc-text-field__input:-ms-input-placeholder{transition-delay:40ms;transition-duration:110ms;opacity:1}}.mdc-text-field__affix{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-subtitle1-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:1rem;font-size:var(--mdc-typography-subtitle1-font-size, 1rem);font-weight:400;font-weight:var(--mdc-typography-subtitle1-font-weight, 400);letter-spacing:0.009375em;letter-spacing:var(--mdc-typography-subtitle1-letter-spacing, 0.009375em);text-decoration:inherit;text-decoration:var(--mdc-typography-subtitle1-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-subtitle1-text-transform, inherit);height:28px;transition:opacity 150ms 0ms cubic-bezier(0.4, 0, 0.2, 1);opacity:0;white-space:nowrap}.mdc-text-field--label-floating .mdc-text-field__affix,.mdc-text-field--no-label .mdc-text-field__affix{opacity:1}@supports(-webkit-hyphens: none){.mdc-text-field--outlined .mdc-text-field__affix{align-items:center;align-self:center;display:inline-flex;height:100%}}.mdc-text-field__affix--prefix{padding-left:0;padding-right:2px}[dir=rtl] .mdc-text-field__affix--prefix,.mdc-text-field__affix--prefix[dir=rtl]{padding-left:2px;padding-right:0}.mdc-text-field--end-aligned .mdc-text-field__affix--prefix{padding-left:0;padding-right:12px}[dir=rtl] .mdc-text-field--end-aligned .mdc-text-field__affix--prefix,.mdc-text-field--end-aligned .mdc-text-field__affix--prefix[dir=rtl]{padding-left:12px;padding-right:0}.mdc-text-field__affix--suffix{padding-left:12px;padding-right:0}[dir=rtl] .mdc-text-field__affix--suffix,.mdc-text-field__affix--suffix[dir=rtl]{padding-left:0;padding-right:12px}.mdc-text-field--end-aligned .mdc-text-field__affix--suffix{padding-left:2px;padding-right:0}[dir=rtl] .mdc-text-field--end-aligned .mdc-text-field__affix--suffix,.mdc-text-field--end-aligned .mdc-text-field__affix--suffix[dir=rtl]{padding-left:0;padding-right:2px}.mdc-text-field--filled{height:56px}.mdc-text-field--filled .mdc-text-field__ripple::before,.mdc-text-field--filled .mdc-text-field__ripple::after{background-color:rgba(0, 0, 0, 0.87);background-color:var(--mdc-ripple-color, rgba(0, 0, 0, 0.87))}.mdc-text-field--filled:hover .mdc-text-field__ripple::before,.mdc-text-field--filled.mdc-ripple-surface--hover .mdc-text-field__ripple::before{opacity:0.04;opacity:var(--mdc-ripple-hover-opacity, 0.04)}.mdc-text-field--filled.mdc-ripple-upgraded--background-focused .mdc-text-field__ripple::before,.mdc-text-field--filled:not(.mdc-ripple-upgraded):focus .mdc-text-field__ripple::before{transition-duration:75ms;opacity:0.12;opacity:var(--mdc-ripple-focus-opacity, 0.12)}.mdc-text-field--filled::before{display:inline-block;width:0;height:40px;content:"";vertical-align:0}.mdc-text-field--filled:not(.mdc-text-field--disabled){background-color:whitesmoke}.mdc-text-field--filled:not(.mdc-text-field--disabled) .mdc-line-ripple::before{border-bottom-color:rgba(0, 0, 0, 0.42)}.mdc-text-field--filled:not(.mdc-text-field--disabled):hover .mdc-line-ripple::before{border-bottom-color:rgba(0, 0, 0, 0.87)}.mdc-text-field--filled .mdc-line-ripple::after{border-bottom-color:#6200ee;border-bottom-color:var(--mdc-theme-primary, #6200ee)}.mdc-text-field--filled .mdc-floating-label{left:16px;right:initial}[dir=rtl] .mdc-text-field--filled .mdc-floating-label,.mdc-text-field--filled .mdc-floating-label[dir=rtl]{left:initial;right:16px}.mdc-text-field--filled .mdc-floating-label--float-above{transform:translateY(-106%) scale(0.75)}.mdc-text-field--filled.mdc-text-field--no-label .mdc-text-field__input{height:100%}.mdc-text-field--filled.mdc-text-field--no-label .mdc-floating-label{display:none}.mdc-text-field--filled.mdc-text-field--no-label::before{display:none}@supports(-webkit-hyphens: none){.mdc-text-field--filled.mdc-text-field--no-label .mdc-text-field__affix{align-items:center;align-self:center;display:inline-flex;height:100%}}.mdc-text-field--outlined{height:56px;overflow:visible}.mdc-text-field--outlined .mdc-floating-label--float-above{transform:translateY(-37.25px) scale(1)}.mdc-text-field--outlined .mdc-floating-label--float-above{font-size:.75rem}.mdc-text-field--outlined.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{transform:translateY(-34.75px) scale(0.75)}.mdc-text-field--outlined.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{font-size:1rem}.mdc-text-field--outlined .mdc-floating-label--shake{animation:mdc-floating-label-shake-float-above-text-field-outlined 250ms 1}@keyframes mdc-floating-label-shake-float-above-text-field-outlined{0%{transform:translateX(calc(0 - 0%)) translateY(-34.75px) scale(0.75)}33%{animation-timing-function:cubic-bezier(0.5, 0, 0.701732, 0.495819);transform:translateX(calc(4% - 0%)) translateY(-34.75px) scale(0.75)}66%{animation-timing-function:cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);transform:translateX(calc(-4% - 0%)) translateY(-34.75px) scale(0.75)}100%{transform:translateX(calc(0 - 0%)) translateY(-34.75px) scale(0.75)}}.mdc-text-field--outlined .mdc-text-field__input{height:100%}.mdc-text-field--outlined:not(.mdc-text-field--disabled) .mdc-notched-outline__leading,.mdc-text-field--outlined:not(.mdc-text-field--disabled) .mdc-notched-outline__notch,.mdc-text-field--outlined:not(.mdc-text-field--disabled) .mdc-notched-outline__trailing{border-color:rgba(0, 0, 0, 0.38)}.mdc-text-field--outlined:not(.mdc-text-field--disabled):not(.mdc-text-field--focused):hover .mdc-notched-outline .mdc-notched-outline__leading,.mdc-text-field--outlined:not(.mdc-text-field--disabled):not(.mdc-text-field--focused):hover .mdc-notched-outline .mdc-notched-outline__notch,.mdc-text-field--outlined:not(.mdc-text-field--disabled):not(.mdc-text-field--focused):hover .mdc-notched-outline .mdc-notched-outline__trailing{border-color:rgba(0, 0, 0, 0.87)}.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-notched-outline__leading,.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-notched-outline__notch,.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-notched-outline__trailing{border-color:#6200ee;border-color:var(--mdc-theme-primary, #6200ee)}.mdc-text-field--outlined .mdc-notched-outline .mdc-notched-outline__leading{border-top-left-radius:4px;border-top-left-radius:var(--mdc-shape-small, 4px);border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:4px;border-bottom-left-radius:var(--mdc-shape-small, 4px)}[dir=rtl] .mdc-text-field--outlined .mdc-notched-outline .mdc-notched-outline__leading,.mdc-text-field--outlined .mdc-notched-outline .mdc-notched-outline__leading[dir=rtl]{border-top-left-radius:0;border-top-right-radius:4px;border-top-right-radius:var(--mdc-shape-small, 4px);border-bottom-right-radius:4px;border-bottom-right-radius:var(--mdc-shape-small, 4px);border-bottom-left-radius:0}@supports(top: max(0%)){.mdc-text-field--outlined .mdc-notched-outline .mdc-notched-outline__leading{width:max(12px, var(--mdc-shape-small, 4px))}}@supports(top: max(0%)){.mdc-text-field--outlined .mdc-notched-outline .mdc-notched-outline__notch{max-width:calc(100% - max(12px, var(--mdc-shape-small, 4px)) * 2)}}.mdc-text-field--outlined .mdc-notched-outline .mdc-notched-outline__trailing{border-top-left-radius:0;border-top-right-radius:4px;border-top-right-radius:var(--mdc-shape-small, 4px);border-bottom-right-radius:4px;border-bottom-right-radius:var(--mdc-shape-small, 4px);border-bottom-left-radius:0}[dir=rtl] .mdc-text-field--outlined .mdc-notched-outline .mdc-notched-outline__trailing,.mdc-text-field--outlined .mdc-notched-outline .mdc-notched-outline__trailing[dir=rtl]{border-top-left-radius:4px;border-top-left-radius:var(--mdc-shape-small, 4px);border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:4px;border-bottom-left-radius:var(--mdc-shape-small, 4px)}@supports(top: max(0%)){.mdc-text-field--outlined{padding-left:max(16px, calc(var(--mdc-shape-small, 4px) + 4px))}}@supports(top: max(0%)){.mdc-text-field--outlined{padding-right:max(16px, var(--mdc-shape-small, 4px))}}@supports(top: max(0%)){.mdc-text-field--outlined+.mdc-text-field-helper-line{padding-left:max(16px, calc(var(--mdc-shape-small, 4px) + 4px))}}@supports(top: max(0%)){.mdc-text-field--outlined+.mdc-text-field-helper-line{padding-right:max(16px, var(--mdc-shape-small, 4px))}}.mdc-text-field--outlined.mdc-text-field--with-leading-icon{padding-left:0}@supports(top: max(0%)){.mdc-text-field--outlined.mdc-text-field--with-leading-icon{padding-right:max(16px, var(--mdc-shape-small, 4px))}}[dir=rtl] .mdc-text-field--outlined.mdc-text-field--with-leading-icon,.mdc-text-field--outlined.mdc-text-field--with-leading-icon[dir=rtl]{padding-right:0}@supports(top: max(0%)){[dir=rtl] .mdc-text-field--outlined.mdc-text-field--with-leading-icon,.mdc-text-field--outlined.mdc-text-field--with-leading-icon[dir=rtl]{padding-left:max(16px, var(--mdc-shape-small, 4px))}}.mdc-text-field--outlined.mdc-text-field--with-trailing-icon{padding-right:0}@supports(top: max(0%)){.mdc-text-field--outlined.mdc-text-field--with-trailing-icon{padding-left:max(16px, calc(var(--mdc-shape-small, 4px) + 4px))}}[dir=rtl] .mdc-text-field--outlined.mdc-text-field--with-trailing-icon,.mdc-text-field--outlined.mdc-text-field--with-trailing-icon[dir=rtl]{padding-left:0}@supports(top: max(0%)){[dir=rtl] .mdc-text-field--outlined.mdc-text-field--with-trailing-icon,.mdc-text-field--outlined.mdc-text-field--with-trailing-icon[dir=rtl]{padding-right:max(16px, calc(var(--mdc-shape-small, 4px) + 4px))}}.mdc-text-field--outlined.mdc-text-field--with-leading-icon.mdc-text-field--with-trailing-icon{padding-left:0;padding-right:0}.mdc-text-field--outlined .mdc-notched-outline--notched .mdc-notched-outline__notch{padding-top:1px}.mdc-text-field--outlined .mdc-text-field__ripple::before,.mdc-text-field--outlined .mdc-text-field__ripple::after{background-color:transparent;background-color:var(--mdc-ripple-color, transparent)}.mdc-text-field--outlined .mdc-floating-label{left:4px;right:initial}[dir=rtl] .mdc-text-field--outlined .mdc-floating-label,.mdc-text-field--outlined .mdc-floating-label[dir=rtl]{left:initial;right:4px}.mdc-text-field--outlined .mdc-text-field__input{display:flex;border:none !important;background-color:transparent}.mdc-text-field--outlined .mdc-notched-outline{z-index:1}.mdc-text-field--textarea{flex-direction:column;align-items:center;width:auto;height:auto;padding:0;transition:none}.mdc-text-field--textarea .mdc-floating-label{top:19px}.mdc-text-field--textarea .mdc-floating-label:not(.mdc-floating-label--float-above){transform:none}.mdc-text-field--textarea .mdc-text-field__input{flex-grow:1;height:auto;min-height:1.5rem;overflow-x:hidden;overflow-y:auto;box-sizing:border-box;resize:none;padding:0 16px;line-height:1.5rem}.mdc-text-field--textarea.mdc-text-field--filled::before{display:none}.mdc-text-field--textarea.mdc-text-field--filled .mdc-floating-label--float-above{transform:translateY(-10.25px) scale(0.75)}.mdc-text-field--textarea.mdc-text-field--filled .mdc-floating-label--shake{animation:mdc-floating-label-shake-float-above-textarea-filled 250ms 1}@keyframes mdc-floating-label-shake-float-above-textarea-filled{0%{transform:translateX(calc(0 - 0%)) translateY(-10.25px) scale(0.75)}33%{animation-timing-function:cubic-bezier(0.5, 0, 0.701732, 0.495819);transform:translateX(calc(4% - 0%)) translateY(-10.25px) scale(0.75)}66%{animation-timing-function:cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);transform:translateX(calc(-4% - 0%)) translateY(-10.25px) scale(0.75)}100%{transform:translateX(calc(0 - 0%)) translateY(-10.25px) scale(0.75)}}.mdc-text-field--textarea.mdc-text-field--filled .mdc-text-field__input{margin-top:23px;margin-bottom:9px}.mdc-text-field--textarea.mdc-text-field--filled.mdc-text-field--no-label .mdc-text-field__input{margin-top:16px;margin-bottom:16px}.mdc-text-field--textarea.mdc-text-field--outlined .mdc-notched-outline--notched .mdc-notched-outline__notch{padding-top:0}.mdc-text-field--textarea.mdc-text-field--outlined .mdc-floating-label--float-above{transform:translateY(-27.25px) scale(1)}.mdc-text-field--textarea.mdc-text-field--outlined .mdc-floating-label--float-above{font-size:.75rem}.mdc-text-field--textarea.mdc-text-field--outlined.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-text-field--textarea.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{transform:translateY(-24.75px) scale(0.75)}.mdc-text-field--textarea.mdc-text-field--outlined.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-text-field--textarea.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{font-size:1rem}.mdc-text-field--textarea.mdc-text-field--outlined .mdc-floating-label--shake{animation:mdc-floating-label-shake-float-above-textarea-outlined 250ms 1}@keyframes mdc-floating-label-shake-float-above-textarea-outlined{0%{transform:translateX(calc(0 - 0%)) translateY(-24.75px) scale(0.75)}33%{animation-timing-function:cubic-bezier(0.5, 0, 0.701732, 0.495819);transform:translateX(calc(4% - 0%)) translateY(-24.75px) scale(0.75)}66%{animation-timing-function:cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);transform:translateX(calc(-4% - 0%)) translateY(-24.75px) scale(0.75)}100%{transform:translateX(calc(0 - 0%)) translateY(-24.75px) scale(0.75)}}.mdc-text-field--textarea.mdc-text-field--outlined .mdc-text-field__input{margin-top:16px;margin-bottom:16px}.mdc-text-field--textarea.mdc-text-field--outlined .mdc-floating-label{top:18px}.mdc-text-field--textarea.mdc-text-field--with-internal-counter .mdc-text-field__input{margin-bottom:2px}.mdc-text-field--textarea.mdc-text-field--with-internal-counter .mdc-text-field-character-counter{align-self:flex-end;padding:0 16px}.mdc-text-field--textarea.mdc-text-field--with-internal-counter .mdc-text-field-character-counter::after{display:inline-block;width:0;height:16px;content:"";vertical-align:-16px}.mdc-text-field--textarea.mdc-text-field--with-internal-counter .mdc-text-field-character-counter::before{display:none}.mdc-text-field__resizer{align-self:stretch;display:inline-flex;flex-direction:column;flex-grow:1;max-height:100%;max-width:100%;min-height:56px;min-width:fit-content;min-width:-moz-available;min-width:-webkit-fill-available;overflow:hidden;resize:both}.mdc-text-field--filled .mdc-text-field__resizer{transform:translateY(-1px)}.mdc-text-field--filled .mdc-text-field__resizer .mdc-text-field__input,.mdc-text-field--filled .mdc-text-field__resizer .mdc-text-field-character-counter{transform:translateY(1px)}.mdc-text-field--outlined .mdc-text-field__resizer{transform:translateX(-1px) translateY(-1px)}[dir=rtl] .mdc-text-field--outlined .mdc-text-field__resizer,.mdc-text-field--outlined .mdc-text-field__resizer[dir=rtl]{transform:translateX(1px) translateY(-1px)}.mdc-text-field--outlined .mdc-text-field__resizer .mdc-text-field__input,.mdc-text-field--outlined .mdc-text-field__resizer .mdc-text-field-character-counter{transform:translateX(1px) translateY(1px)}[dir=rtl] .mdc-text-field--outlined .mdc-text-field__resizer .mdc-text-field__input,[dir=rtl] .mdc-text-field--outlined .mdc-text-field__resizer .mdc-text-field-character-counter,.mdc-text-field--outlined .mdc-text-field__resizer .mdc-text-field__input[dir=rtl],.mdc-text-field--outlined .mdc-text-field__resizer .mdc-text-field-character-counter[dir=rtl]{transform:translateX(-1px) translateY(1px)}.mdc-text-field--with-leading-icon{padding-left:0;padding-right:16px}[dir=rtl] .mdc-text-field--with-leading-icon,.mdc-text-field--with-leading-icon[dir=rtl]{padding-left:16px;padding-right:0}.mdc-text-field--with-leading-icon.mdc-text-field--filled .mdc-floating-label{max-width:calc(100% - 48px);left:48px;right:initial}[dir=rtl] .mdc-text-field--with-leading-icon.mdc-text-field--filled .mdc-floating-label,.mdc-text-field--with-leading-icon.mdc-text-field--filled .mdc-floating-label[dir=rtl]{left:initial;right:48px}.mdc-text-field--with-leading-icon.mdc-text-field--filled .mdc-floating-label--float-above{max-width:calc(100% / 0.75 - 64px / 0.75)}.mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-floating-label{left:36px;right:initial}[dir=rtl] .mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-floating-label,.mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-floating-label[dir=rtl]{left:initial;right:36px}.mdc-text-field--with-leading-icon.mdc-text-field--outlined :not(.mdc-notched-outline--notched) .mdc-notched-outline__notch{max-width:calc(100% - 60px)}.mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-floating-label--float-above{transform:translateY(-37.25px) translateX(-32px) scale(1)}[dir=rtl] .mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-floating-label--float-above,.mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-floating-label--float-above[dir=rtl]{transform:translateY(-37.25px) translateX(32px) scale(1)}.mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-floating-label--float-above{font-size:.75rem}.mdc-text-field--with-leading-icon.mdc-text-field--outlined.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{transform:translateY(-34.75px) translateX(-32px) scale(0.75)}[dir=rtl] .mdc-text-field--with-leading-icon.mdc-text-field--outlined.mdc-notched-outline--upgraded .mdc-floating-label--float-above,[dir=rtl] .mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-text-field--with-leading-icon.mdc-text-field--outlined.mdc-notched-outline--upgraded .mdc-floating-label--float-above[dir=rtl],.mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above[dir=rtl]{transform:translateY(-34.75px) translateX(32px) scale(0.75)}.mdc-text-field--with-leading-icon.mdc-text-field--outlined.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{font-size:1rem}.mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-floating-label--shake{animation:mdc-floating-label-shake-float-above-text-field-outlined-leading-icon 250ms 1}@keyframes mdc-floating-label-shake-float-above-text-field-outlined-leading-icon{0%{transform:translateX(calc(0 - 32px)) translateY(-34.75px) scale(0.75)}33%{animation-timing-function:cubic-bezier(0.5, 0, 0.701732, 0.495819);transform:translateX(calc(4% - 32px)) translateY(-34.75px) scale(0.75)}66%{animation-timing-function:cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);transform:translateX(calc(-4% - 32px)) translateY(-34.75px) scale(0.75)}100%{transform:translateX(calc(0 - 32px)) translateY(-34.75px) scale(0.75)}}[dir=rtl] .mdc-text-field--with-leading-icon.mdc-text-field--outlined .mdc-floating-label--shake,.mdc-text-field--with-leading-icon.mdc-text-field--outlined[dir=rtl] .mdc-floating-label--shake{animation:mdc-floating-label-shake-float-above-text-field-outlined-leading-icon 250ms 1}@keyframes mdc-floating-label-shake-float-above-text-field-outlined-leading-icon-rtl{0%{transform:translateX(calc(0 - -32px)) translateY(-34.75px) scale(0.75)}33%{animation-timing-function:cubic-bezier(0.5, 0, 0.701732, 0.495819);transform:translateX(calc(4% - -32px)) translateY(-34.75px) scale(0.75)}66%{animation-timing-function:cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);transform:translateX(calc(-4% - -32px)) translateY(-34.75px) scale(0.75)}100%{transform:translateX(calc(0 - -32px)) translateY(-34.75px) scale(0.75)}}.mdc-text-field--with-trailing-icon{padding-left:16px;padding-right:0}[dir=rtl] .mdc-text-field--with-trailing-icon,.mdc-text-field--with-trailing-icon[dir=rtl]{padding-left:0;padding-right:16px}.mdc-text-field--with-trailing-icon.mdc-text-field--filled .mdc-floating-label{max-width:calc(100% - 64px)}.mdc-text-field--with-trailing-icon.mdc-text-field--filled .mdc-floating-label--float-above{max-width:calc(100% / 0.75 - 64px / 0.75)}.mdc-text-field--with-trailing-icon.mdc-text-field--outlined :not(.mdc-notched-outline--notched) .mdc-notched-outline__notch{max-width:calc(100% - 60px)}.mdc-text-field--with-leading-icon.mdc-text-field--with-trailing-icon{padding-left:0;padding-right:0}.mdc-text-field--with-leading-icon.mdc-text-field--with-trailing-icon.mdc-text-field--filled .mdc-floating-label{max-width:calc(100% - 96px)}.mdc-text-field--with-leading-icon.mdc-text-field--with-trailing-icon.mdc-text-field--filled .mdc-floating-label--float-above{max-width:calc(100% / 0.75 - 96px / 0.75)}.mdc-text-field-helper-line{display:flex;justify-content:space-between;box-sizing:border-box}.mdc-text-field+.mdc-text-field-helper-line{padding-right:16px;padding-left:16px}.mdc-form-field>.mdc-text-field+label{align-self:flex-start}.mdc-text-field--focused:not(.mdc-text-field--disabled) .mdc-floating-label{color:rgba(98, 0, 238, 0.87)}.mdc-text-field--focused .mdc-notched-outline__leading,.mdc-text-field--focused .mdc-notched-outline__notch,.mdc-text-field--focused .mdc-notched-outline__trailing{border-width:2px}.mdc-text-field--focused+.mdc-text-field-helper-line .mdc-text-field-helper-text:not(.mdc-text-field-helper-text--validation-msg){opacity:1}.mdc-text-field--focused.mdc-text-field--outlined .mdc-notched-outline--notched .mdc-notched-outline__notch{padding-top:2px}.mdc-text-field--focused.mdc-text-field--outlined.mdc-text-field--textarea .mdc-notched-outline--notched .mdc-notched-outline__notch{padding-top:0}.mdc-text-field--invalid:not(.mdc-text-field--disabled):hover .mdc-line-ripple::before{border-bottom-color:#b00020;border-bottom-color:var(--mdc-theme-error, #b00020)}.mdc-text-field--invalid:not(.mdc-text-field--disabled) .mdc-line-ripple::after{border-bottom-color:#b00020;border-bottom-color:var(--mdc-theme-error, #b00020)}.mdc-text-field--invalid:not(.mdc-text-field--disabled) .mdc-floating-label{color:#b00020;color:var(--mdc-theme-error, #b00020)}.mdc-text-field--invalid:not(.mdc-text-field--disabled).mdc-text-field--invalid+.mdc-text-field-helper-line .mdc-text-field-helper-text--validation-msg{color:#b00020;color:var(--mdc-theme-error, #b00020)}.mdc-text-field--invalid .mdc-text-field__input{caret-color:#b00020;caret-color:var(--mdc-theme-error, #b00020)}.mdc-text-field--invalid:not(.mdc-text-field--disabled) .mdc-text-field__icon--trailing{color:#b00020;color:var(--mdc-theme-error, #b00020)}.mdc-text-field--invalid:not(.mdc-text-field--disabled) .mdc-line-ripple::before{border-bottom-color:#b00020;border-bottom-color:var(--mdc-theme-error, #b00020)}.mdc-text-field--invalid:not(.mdc-text-field--disabled) .mdc-notched-outline__leading,.mdc-text-field--invalid:not(.mdc-text-field--disabled) .mdc-notched-outline__notch,.mdc-text-field--invalid:not(.mdc-text-field--disabled) .mdc-notched-outline__trailing{border-color:#b00020;border-color:var(--mdc-theme-error, #b00020)}.mdc-text-field--invalid:not(.mdc-text-field--disabled):not(.mdc-text-field--focused):hover .mdc-notched-outline .mdc-notched-outline__leading,.mdc-text-field--invalid:not(.mdc-text-field--disabled):not(.mdc-text-field--focused):hover .mdc-notched-outline .mdc-notched-outline__notch,.mdc-text-field--invalid:not(.mdc-text-field--disabled):not(.mdc-text-field--focused):hover .mdc-notched-outline .mdc-notched-outline__trailing{border-color:#b00020;border-color:var(--mdc-theme-error, #b00020)}.mdc-text-field--invalid:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-notched-outline__leading,.mdc-text-field--invalid:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-notched-outline__notch,.mdc-text-field--invalid:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-notched-outline__trailing{border-color:#b00020;border-color:var(--mdc-theme-error, #b00020)}.mdc-text-field--invalid+.mdc-text-field-helper-line .mdc-text-field-helper-text--validation-msg{opacity:1}.mdc-text-field--disabled{pointer-events:none}.mdc-text-field--disabled .mdc-text-field__input{color:rgba(0, 0, 0, 0.38)}@media all{.mdc-text-field--disabled .mdc-text-field__input::placeholder{color:rgba(0, 0, 0, 0.38)}}@media all{.mdc-text-field--disabled .mdc-text-field__input:-ms-input-placeholder{color:rgba(0, 0, 0, 0.38)}}.mdc-text-field--disabled .mdc-floating-label{color:rgba(0, 0, 0, 0.38)}.mdc-text-field--disabled+.mdc-text-field-helper-line .mdc-text-field-helper-text{color:rgba(0, 0, 0, 0.38)}.mdc-text-field--disabled .mdc-text-field-character-counter,.mdc-text-field--disabled+.mdc-text-field-helper-line .mdc-text-field-character-counter{color:rgba(0, 0, 0, 0.38)}.mdc-text-field--disabled .mdc-text-field__icon--leading{color:rgba(0, 0, 0, 0.3)}.mdc-text-field--disabled .mdc-text-field__icon--trailing{color:rgba(0, 0, 0, 0.3)}.mdc-text-field--disabled .mdc-text-field__affix--prefix{color:rgba(0, 0, 0, 0.38)}.mdc-text-field--disabled .mdc-text-field__affix--suffix{color:rgba(0, 0, 0, 0.38)}.mdc-text-field--disabled .mdc-line-ripple::before{border-bottom-color:rgba(0, 0, 0, 0.06)}.mdc-text-field--disabled .mdc-notched-outline__leading,.mdc-text-field--disabled .mdc-notched-outline__notch,.mdc-text-field--disabled .mdc-notched-outline__trailing{border-color:rgba(0, 0, 0, 0.06)}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-text-field--disabled .mdc-text-field__input::placeholder{color:GrayText}}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-text-field--disabled .mdc-text-field__input:-ms-input-placeholder{color:GrayText}}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-text-field--disabled .mdc-floating-label{color:GrayText}}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-text-field--disabled+.mdc-text-field-helper-line .mdc-text-field-helper-text{color:GrayText}}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-text-field--disabled .mdc-text-field-character-counter,.mdc-text-field--disabled+.mdc-text-field-helper-line .mdc-text-field-character-counter{color:GrayText}}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-text-field--disabled .mdc-text-field__icon--leading{color:GrayText}}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-text-field--disabled .mdc-text-field__icon--trailing{color:GrayText}}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-text-field--disabled .mdc-text-field__affix--prefix{color:GrayText}}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-text-field--disabled .mdc-text-field__affix--suffix{color:GrayText}}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-text-field--disabled .mdc-line-ripple::before{border-bottom-color:GrayText}}@media screen and (forced-colors: active),(-ms-high-contrast: active){.mdc-text-field--disabled .mdc-notched-outline__leading,.mdc-text-field--disabled .mdc-notched-outline__notch,.mdc-text-field--disabled .mdc-notched-outline__trailing{border-color:GrayText}}@media screen and (forced-colors: active){.mdc-text-field--disabled .mdc-text-field__input{background-color:Window}.mdc-text-field--disabled .mdc-floating-label{z-index:1}}.mdc-text-field--disabled .mdc-floating-label{cursor:default}.mdc-text-field--disabled.mdc-text-field--filled{background-color:#fafafa}.mdc-text-field--disabled.mdc-text-field--filled .mdc-text-field__ripple{display:none}.mdc-text-field--disabled .mdc-text-field__input{pointer-events:auto}.mdc-text-field--end-aligned .mdc-text-field__input{text-align:right}[dir=rtl] .mdc-text-field--end-aligned .mdc-text-field__input,.mdc-text-field--end-aligned .mdc-text-field__input[dir=rtl]{text-align:left}[dir=rtl] .mdc-text-field--ltr-text .mdc-text-field__input,[dir=rtl] .mdc-text-field--ltr-text .mdc-text-field__affix,.mdc-text-field--ltr-text[dir=rtl] .mdc-text-field__input,.mdc-text-field--ltr-text[dir=rtl] .mdc-text-field__affix{direction:ltr}[dir=rtl] .mdc-text-field--ltr-text .mdc-text-field__affix--prefix,.mdc-text-field--ltr-text[dir=rtl] .mdc-text-field__affix--prefix{padding-left:0;padding-right:2px}[dir=rtl] .mdc-text-field--ltr-text .mdc-text-field__affix--suffix,.mdc-text-field--ltr-text[dir=rtl] .mdc-text-field__affix--suffix{padding-left:12px;padding-right:0}[dir=rtl] .mdc-text-field--ltr-text .mdc-text-field__icon--leading,.mdc-text-field--ltr-text[dir=rtl] .mdc-text-field__icon--leading{order:1}[dir=rtl] .mdc-text-field--ltr-text .mdc-text-field__affix--suffix,.mdc-text-field--ltr-text[dir=rtl] .mdc-text-field__affix--suffix{order:2}[dir=rtl] .mdc-text-field--ltr-text .mdc-text-field__input,.mdc-text-field--ltr-text[dir=rtl] .mdc-text-field__input{order:3}[dir=rtl] .mdc-text-field--ltr-text .mdc-text-field__affix--prefix,.mdc-text-field--ltr-text[dir=rtl] .mdc-text-field__affix--prefix{order:4}[dir=rtl] .mdc-text-field--ltr-text .mdc-text-field__icon--trailing,.mdc-text-field--ltr-text[dir=rtl] .mdc-text-field__icon--trailing{order:5}[dir=rtl] .mdc-text-field--ltr-text.mdc-text-field--end-aligned .mdc-text-field__input,.mdc-text-field--ltr-text.mdc-text-field--end-aligned[dir=rtl] .mdc-text-field__input{text-align:right}[dir=rtl] .mdc-text-field--ltr-text.mdc-text-field--end-aligned .mdc-text-field__affix--prefix,.mdc-text-field--ltr-text.mdc-text-field--end-aligned[dir=rtl] .mdc-text-field__affix--prefix{padding-right:12px}[dir=rtl] .mdc-text-field--ltr-text.mdc-text-field--end-aligned .mdc-text-field__affix--suffix,.mdc-text-field--ltr-text.mdc-text-field--end-aligned[dir=rtl] .mdc-text-field__affix--suffix{padding-left:2px}.mdc-text-field-helper-text{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-caption-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:0.75rem;font-size:var(--mdc-typography-caption-font-size, 0.75rem);line-height:1.25rem;line-height:var(--mdc-typography-caption-line-height, 1.25rem);font-weight:400;font-weight:var(--mdc-typography-caption-font-weight, 400);letter-spacing:0.0333333333em;letter-spacing:var(--mdc-typography-caption-letter-spacing, 0.0333333333em);text-decoration:inherit;text-decoration:var(--mdc-typography-caption-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-caption-text-transform, inherit);display:block;margin-top:0;line-height:normal;margin:0;opacity:0;will-change:opacity;transition:opacity 150ms 0ms cubic-bezier(0.4, 0, 0.2, 1)}.mdc-text-field-helper-text::before{display:inline-block;width:0;height:16px;content:"";vertical-align:0}.mdc-text-field-helper-text--persistent{transition:none;opacity:1;will-change:initial}.mdc-text-field-character-counter{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto, sans-serif;font-family:var(--mdc-typography-caption-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:0.75rem;font-size:var(--mdc-typography-caption-font-size, 0.75rem);line-height:1.25rem;line-height:var(--mdc-typography-caption-line-height, 1.25rem);font-weight:400;font-weight:var(--mdc-typography-caption-font-weight, 400);letter-spacing:0.0333333333em;letter-spacing:var(--mdc-typography-caption-letter-spacing, 0.0333333333em);text-decoration:inherit;text-decoration:var(--mdc-typography-caption-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-caption-text-transform, inherit);display:block;margin-top:0;line-height:normal;margin-left:auto;margin-right:0;padding-left:16px;padding-right:0;white-space:nowrap}.mdc-text-field-character-counter::before{display:inline-block;width:0;height:16px;content:"";vertical-align:0}[dir=rtl] .mdc-text-field-character-counter,.mdc-text-field-character-counter[dir=rtl]{margin-left:0;margin-right:auto}[dir=rtl] .mdc-text-field-character-counter,.mdc-text-field-character-counter[dir=rtl]{padding-left:0;padding-right:16px}.mdc-text-field__icon{align-self:center;cursor:pointer}.mdc-text-field__icon:not([tabindex]),.mdc-text-field__icon[tabindex="-1"]{cursor:default;pointer-events:none}.mdc-text-field__icon svg{display:block}.mdc-text-field__icon--leading{margin-left:16px;margin-right:8px}[dir=rtl] .mdc-text-field__icon--leading,.mdc-text-field__icon--leading[dir=rtl]{margin-left:8px;margin-right:16px}.mdc-text-field__icon--trailing{padding:12px;margin-left:0px;margin-right:0px}[dir=rtl] .mdc-text-field__icon--trailing,.mdc-text-field__icon--trailing[dir=rtl]{margin-left:0px;margin-right:0px}.material-icons{font-family:var(--mdc-icon-font, "Material Icons");font-weight:normal;font-style:normal;font-size:var(--mdc-icon-size, 24px);line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;-moz-osx-font-smoothing:grayscale;font-feature-settings:"liga"}:host{display:inline-flex;flex-direction:column;outline:none}.mdc-text-field{width:100%}.mdc-text-field:not(.mdc-text-field--disabled) .mdc-line-ripple::before{border-bottom-color:rgba(0, 0, 0, 0.42);border-bottom-color:var(--mdc-text-field-idle-line-color, rgba(0, 0, 0, 0.42))}.mdc-text-field:not(.mdc-text-field--disabled):hover .mdc-line-ripple::before{border-bottom-color:rgba(0, 0, 0, 0.87);border-bottom-color:var(--mdc-text-field-hover-line-color, rgba(0, 0, 0, 0.87))}.mdc-text-field.mdc-text-field--disabled .mdc-line-ripple::before{border-bottom-color:rgba(0, 0, 0, 0.06);border-bottom-color:var(--mdc-text-field-disabled-line-color, rgba(0, 0, 0, 0.06))}.mdc-text-field.mdc-text-field--invalid:not(.mdc-text-field--disabled) .mdc-line-ripple::before{border-bottom-color:#b00020;border-bottom-color:var(--mdc-theme-error, #b00020)}.mdc-text-field__input{direction:inherit}mwc-notched-outline{--mdc-notched-outline-border-color: var( --mdc-text-field-outlined-idle-border-color, rgba(0, 0, 0, 0.38) )}:host(:not([disabled]):hover) :not(.mdc-text-field--invalid):not(.mdc-text-field--focused) mwc-notched-outline{--mdc-notched-outline-border-color: var( --mdc-text-field-outlined-hover-border-color, rgba(0, 0, 0, 0.87) )}:host(:not([disabled])) .mdc-text-field:not(.mdc-text-field--outlined){background-color:var(--mdc-text-field-fill-color, whitesmoke)}:host(:not([disabled])) .mdc-text-field.mdc-text-field--invalid mwc-notched-outline{--mdc-notched-outline-border-color: var( --mdc-text-field-error-color, var(--mdc-theme-error, #b00020) )}:host(:not([disabled])) .mdc-text-field.mdc-text-field--invalid+.mdc-text-field-helper-line .mdc-text-field-character-counter,:host(:not([disabled])) .mdc-text-field.mdc-text-field--invalid .mdc-text-field__icon{color:var(--mdc-text-field-error-color, var(--mdc-theme-error, #b00020))}:host(:not([disabled])) .mdc-text-field:not(.mdc-text-field--invalid):not(.mdc-text-field--focused) .mdc-floating-label,:host(:not([disabled])) .mdc-text-field:not(.mdc-text-field--invalid):not(.mdc-text-field--focused) .mdc-floating-label::after{color:var(--mdc-text-field-label-ink-color, rgba(0, 0, 0, 0.6))}:host(:not([disabled])) .mdc-text-field.mdc-text-field--focused mwc-notched-outline{--mdc-notched-outline-stroke-width: 2px}:host(:not([disabled])) .mdc-text-field.mdc-text-field--focused:not(.mdc-text-field--invalid) mwc-notched-outline{--mdc-notched-outline-border-color: var( --mdc-text-field-focused-label-color, var(--mdc-theme-primary, rgba(98, 0, 238, 0.87)) )}:host(:not([disabled])) .mdc-text-field.mdc-text-field--focused:not(.mdc-text-field--invalid) .mdc-floating-label{color:#6200ee;color:var(--mdc-theme-primary, #6200ee)}:host(:not([disabled])) .mdc-text-field .mdc-text-field__input{color:var(--mdc-text-field-ink-color, rgba(0, 0, 0, 0.87))}:host(:not([disabled])) .mdc-text-field .mdc-text-field__input::placeholder{color:var(--mdc-text-field-label-ink-color, rgba(0, 0, 0, 0.6))}:host(:not([disabled])) .mdc-text-field-helper-line .mdc-text-field-helper-text:not(.mdc-text-field-helper-text--validation-msg),:host(:not([disabled])) .mdc-text-field-helper-line:not(.mdc-text-field--invalid) .mdc-text-field-character-counter{color:var(--mdc-text-field-label-ink-color, rgba(0, 0, 0, 0.6))}:host([disabled]) .mdc-text-field:not(.mdc-text-field--outlined){background-color:var(--mdc-text-field-disabled-fill-color, #fafafa)}:host([disabled]) .mdc-text-field.mdc-text-field--outlined mwc-notched-outline{--mdc-notched-outline-border-color: var( --mdc-text-field-outlined-disabled-border-color, rgba(0, 0, 0, 0.06) )}:host([disabled]) .mdc-text-field:not(.mdc-text-field--invalid):not(.mdc-text-field--focused) .mdc-floating-label,:host([disabled]) .mdc-text-field:not(.mdc-text-field--invalid):not(.mdc-text-field--focused) .mdc-floating-label::after{color:var(--mdc-text-field-disabled-ink-color, rgba(0, 0, 0, 0.38))}:host([disabled]) .mdc-text-field .mdc-text-field__input,:host([disabled]) .mdc-text-field .mdc-text-field__input::placeholder{color:var(--mdc-text-field-disabled-ink-color, rgba(0, 0, 0, 0.38))}:host([disabled]) .mdc-text-field-helper-line .mdc-text-field-helper-text,:host([disabled]) .mdc-text-field-helper-line .mdc-text-field-character-counter{color:var(--mdc-text-field-disabled-ink-color, rgba(0, 0, 0, 0.38))}`,Bn={"mwc-textfield":class extends Fn{static get styles(){return Nn}},"mwc-notched-outline":class extends an{static get styles(){return fn}}};let Ln=class extends(te(Ot)){constructor(){super(...arguments),this._initialized=!1}setConfig(t){this._config=t,null==this._config.auto_update&&(this._config=Object.assign(Object.assign({},this._config),{auto_update:!0})),this.loadCardHelpers()}connectedCallback(){super.connectedCallback();const t=this.save_layout.bind(this);window.addEventListener("wiser-zigbee-save-layout",t)}disconnectedCallback(){window.removeEventListener("wiser-zigbee-save-layout",this.save_layout),super.disconnectedCallback()}shouldUpdate(){return this._initialized||this._initialize(),!0}get _name(){var t;return(null===(t=this._config)||void 0===t?void 0:t.name)||""}get _hub(){var t;return(null===(t=this._config)||void 0===t?void 0:t.hub)||""}get _auto_update(){var t;return(null===(t=this._config)||void 0===t?void 0:t.auto_update)||!1}async loadData(){var t;this.hass&&(this._hubs=await(t=this.hass,t.callWS({type:"wiser/hubs"})))}render(){return this.hass&&this._helpers&&this._config&&this._hubs?$` - ${this.hubSelector()} - - - - -
-
Version: ${$t}
- `:$``}hubSelector(){var t;const e=this._hubs?this._hubs:[];return e.length>1?$` - t.stopPropagation()} - > - ${null===(t=this._hubs)||void 0===t?void 0:t.map((t=>$`${t}`))} - - `:$``}_initialize(){void 0!==this.hass&&void 0!==this._config&&void 0!==this._helpers&&(this._initialized=!0)}async loadCardHelpers(){this._helpers=await window.loadCardHelpers(),await this.loadData()}save_layout(t){this._config&&(this._config=Object.assign(Object.assign({},this._config),{layout_data:t.detail.layout_data}),Ht(this,"config-changed",{config:this._config}))}_valueChanged(t){if(!this._config||!this.hass)return;const e=t.target;if(this[`_${e.configValue}`]!==e.value){if(e.configValue)if("hub"==e.configValue&&(this._config=Object.assign(Object.assign({},this._config),{layout_data:""})),""===e.value){const t=Object.assign({},this._config);delete t[e.configValue],this._config=t}else this._config=Object.assign(Object.assign({},this._config),{[e.configValue]:void 0!==e.checked?e.checked:e.value});Ht(this,"config-changed",{config:this._config})}}}; + */var Ht,Vt,Wt;null===(Ht=window.HTMLSlotElement)||void 0===Ht||Ht.prototype.assignedElements,function(t){t.language="language",t.system="system",t.comma_decimal="comma_decimal",t.decimal_comma="decimal_comma",t.space_comma="space_comma",t.none="none"}(Vt||(Vt={})),function(t){t.language="language",t.system="system",t.am_pm="12",t.twenty_four="24"}(Wt||(Wt={}));var Gt=function(t,e,i,o){o=o||{},i=null==i?{}:i;var n=new Event(e,{bubbles:void 0===o.bubbles||o.bubbles,cancelable:Boolean(o.cancelable),composed:void 0===o.composed||o.composed});return n.detail=i,t.dispatchEvent(n),n /** * vis-data * http://visjs.org/ @@ -1016,28 +88,14 @@ const Nn=ht`.mdc-floating-label{-moz-osx-font-smoothing:grayscale;-webkit-font-s * http://opensource.org/licenses/MIT * * vis.js may be distributed under either license. - */ -function zn(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}Ln.elementDefinitions=Object.assign(Object.assign(Object.assign(Object.assign({},Bn),mn),wn),Oe),Ln.styles=ht` - mwc-select, - mwc-textfield { - margin-bottom: 16px; - display: block; - } - mwc-formfield { - padding-bottom: 20px; - display: flex; - } - mwc-switch { - --mdc-theme-secondary: var(--switch-checked-color); - } - `,o([At({attribute:!1})],Ln.prototype,"hass",void 0),o([Rt()],Ln.prototype,"_config",void 0),o([Rt()],Ln.prototype,"_helpers",void 0),o([Rt()],Ln.prototype,"_hubs",void 0),Ln=o([St("wiser-zigbee-card-editor")],Ln);var jn="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function Hn(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var $n={exports:{}},Un=function(t){return t&&t.Math===Math&&t},Wn=Un("object"==typeof globalThis&&globalThis)||Un("object"==typeof window&&window)||Un("object"==typeof self&&self)||Un("object"==typeof jn&&jn)||function(){return this}()||jn||Function("return this")(),Vn=function(t){try{return!!t()}catch(t){return!0}},qn=!Vn((function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")})),Xn=qn,Yn=Function.prototype,Gn=Yn.apply,Kn=Yn.call,Zn="object"==typeof Reflect&&Reflect.apply||(Xn?Kn.bind(Gn):function(){return Kn.apply(Gn,arguments)}),Qn=qn,Jn=Function.prototype,to=Jn.call,eo=Qn&&Jn.bind.bind(to,to),io=Qn?eo:function(t){return function(){return to.apply(t,arguments)}},no=io,oo=no({}.toString),ro=no("".slice),so=function(t){return ro(oo(t),8,-1)},ao=so,lo=io,co=function(t){if("Function"===ao(t))return lo(t)},ho="object"==typeof document&&document.all,uo={all:ho,IS_HTMLDDA:void 0===ho&&void 0!==ho},po=uo.all,fo=uo.IS_HTMLDDA?function(t){return"function"==typeof t||t===po}:function(t){return"function"==typeof t},mo={},vo=!Vn((function(){return 7!==Object.defineProperty({},1,{get:function(){return 7}})[1]})),go=qn,yo=Function.prototype.call,bo=go?yo.bind(yo):function(){return yo.apply(yo,arguments)},xo={},_o={}.propertyIsEnumerable,wo=Object.getOwnPropertyDescriptor,Eo=wo&&!_o.call({1:2},1);xo.f=Eo?function(t){var e=wo(this,t);return!!e&&e.enumerable}:_o;var ko,Oo,Co=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}},So=Vn,To=so,Io=Object,Ao=io("".split),Ro=So((function(){return!Io("z").propertyIsEnumerable(0)}))?function(t){return"String"===To(t)?Ao(t,""):Io(t)}:Io,Po=function(t){return null==t},Do=Po,Mo=TypeError,Fo=function(t){if(Do(t))throw new Mo("Can't call method on "+t);return t},No=Ro,Bo=Fo,Lo=function(t){return No(Bo(t))},zo=fo,jo=uo.all,Ho=uo.IS_HTMLDDA?function(t){return"object"==typeof t?null!==t:zo(t)||t===jo}:function(t){return"object"==typeof t?null!==t:zo(t)},$o={},Uo=$o,Wo=Wn,Vo=fo,qo=function(t){return Vo(t)?t:void 0},Xo=function(t,e){return arguments.length<2?qo(Uo[t])||qo(Wo[t]):Uo[t]&&Uo[t][e]||Wo[t]&&Wo[t][e]},Yo=io({}.isPrototypeOf),Go="undefined"!=typeof navigator&&String(navigator.userAgent)||"",Ko=Wn,Zo=Go,Qo=Ko.process,Jo=Ko.Deno,tr=Qo&&Qo.versions||Jo&&Jo.version,er=tr&&tr.v8;er&&(Oo=(ko=er.split("."))[0]>0&&ko[0]<4?1:+(ko[0]+ko[1])),!Oo&&Zo&&(!(ko=Zo.match(/Edge\/(\d+)/))||ko[1]>=74)&&(ko=Zo.match(/Chrome\/(\d+)/))&&(Oo=+ko[1]);var ir=Oo,nr=ir,or=Vn,rr=Wn.String,sr=!!Object.getOwnPropertySymbols&&!or((function(){var t=Symbol("symbol detection");return!rr(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&nr&&nr<41})),ar=sr&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,dr=Xo,lr=fo,cr=Yo,hr=Object,ur=ar?function(t){return"symbol"==typeof t}:function(t){var e=dr("Symbol");return lr(e)&&cr(e.prototype,hr(t))},pr=String,fr=function(t){try{return pr(t)}catch(t){return"Object"}},mr=fo,vr=fr,gr=TypeError,yr=function(t){if(mr(t))return t;throw new gr(vr(t)+" is not a function")},br=yr,xr=Po,_r=function(t,e){var i=t[e];return xr(i)?void 0:br(i)},wr=bo,Er=fo,kr=Ho,Or=TypeError,Cr={exports:{}},Sr=Wn,Tr=Object.defineProperty,Ir=function(t,e){try{Tr(Sr,t,{value:e,configurable:!0,writable:!0})}catch(i){Sr[t]=e}return e},Ar="__core-js_shared__",Rr=Wn[Ar]||Ir(Ar,{}),Pr=Rr;(Cr.exports=function(t,e){return Pr[t]||(Pr[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.33.2",mode:"pure",copyright:"© 2014-2023 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.33.2/LICENSE",source:"https://github.com/zloirock/core-js"});var Dr=Cr.exports,Mr=Fo,Fr=Object,Nr=function(t){return Fr(Mr(t))},Br=Nr,Lr=io({}.hasOwnProperty),zr=Object.hasOwn||function(t,e){return Lr(Br(t),e)},jr=io,Hr=0,$r=Math.random(),Ur=jr(1..toString),Wr=function(t){return"Symbol("+(void 0===t?"":t)+")_"+Ur(++Hr+$r,36)},Vr=Dr,qr=zr,Xr=Wr,Yr=sr,Gr=ar,Kr=Wn.Symbol,Zr=Vr("wks"),Qr=Gr?Kr.for||Kr:Kr&&Kr.withoutSetter||Xr,Jr=function(t){return qr(Zr,t)||(Zr[t]=Yr&&qr(Kr,t)?Kr[t]:Qr("Symbol."+t)),Zr[t]},ts=bo,es=Ho,is=ur,ns=_r,os=function(t,e){var i,n;if("string"===e&&Er(i=t.toString)&&!kr(n=wr(i,t)))return n;if(Er(i=t.valueOf)&&!kr(n=wr(i,t)))return n;if("string"!==e&&Er(i=t.toString)&&!kr(n=wr(i,t)))return n;throw new Or("Can't convert object to primitive value")},rs=TypeError,ss=Jr("toPrimitive"),as=function(t,e){if(!es(t)||is(t))return t;var i,n=ns(t,ss);if(n){if(void 0===e&&(e="default"),i=ts(n,t,e),!es(i)||is(i))return i;throw new rs("Can't convert object to primitive value")}return void 0===e&&(e="number"),os(t,e)},ds=ur,ls=function(t){var e=as(t,"string");return ds(e)?e:e+""},cs=Ho,hs=Wn.document,us=cs(hs)&&cs(hs.createElement),ps=function(t){return us?hs.createElement(t):{}},fs=ps,ms=!vo&&!Vn((function(){return 7!==Object.defineProperty(fs("div"),"a",{get:function(){return 7}}).a})),vs=vo,gs=bo,ys=xo,bs=Co,xs=Lo,_s=ls,ws=zr,Es=ms,ks=Object.getOwnPropertyDescriptor;mo.f=vs?ks:function(t,e){if(t=xs(t),e=_s(e),Es)try{return ks(t,e)}catch(t){}if(ws(t,e))return bs(!gs(ys.f,t,e),t[e])};var Os=Vn,Cs=fo,Ss=/#|\.prototype\./,Ts=function(t,e){var i=As[Is(t)];return i===Ps||i!==Rs&&(Cs(e)?Os(e):!!e)},Is=Ts.normalize=function(t){return String(t).replace(Ss,".").toLowerCase()},As=Ts.data={},Rs=Ts.NATIVE="N",Ps=Ts.POLYFILL="P",Ds=Ts,Ms=yr,Fs=qn,Ns=co(co.bind),Bs=function(t,e){return Ms(t),void 0===e?t:Fs?Ns(t,e):function(){return t.apply(e,arguments)}},Ls={},zs=vo&&Vn((function(){return 42!==Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype})),js=Ho,Hs=String,$s=TypeError,Us=function(t){if(js(t))return t;throw new $s(Hs(t)+" is not an object")},Ws=vo,Vs=ms,qs=zs,Xs=Us,Ys=ls,Gs=TypeError,Ks=Object.defineProperty,Zs=Object.getOwnPropertyDescriptor,Qs="enumerable",Js="configurable",ta="writable";Ls.f=Ws?qs?function(t,e,i){if(Xs(t),e=Ys(e),Xs(i),"function"==typeof t&&"prototype"===e&&"value"in i&&ta in i&&!i[ta]){var n=Zs(t,e);n&&n[ta]&&(t[e]=i.value,i={configurable:Js in i?i[Js]:n[Js],enumerable:Qs in i?i[Qs]:n[Qs],writable:!1})}return Ks(t,e,i)}:Ks:function(t,e,i){if(Xs(t),e=Ys(e),Xs(i),Vs)try{return Ks(t,e,i)}catch(t){}if("get"in i||"set"in i)throw new Gs("Accessors not supported");return"value"in i&&(t[e]=i.value),t};var ea=Ls,ia=Co,na=vo?function(t,e,i){return ea.f(t,e,ia(1,i))}:function(t,e,i){return t[e]=i,t},oa=Wn,ra=Zn,sa=co,aa=fo,da=mo.f,la=Ds,ca=$o,ha=Bs,ua=na,pa=zr,fa=function(t){var e=function(i,n,o){if(this instanceof e){switch(arguments.length){case 0:return new t;case 1:return new t(i);case 2:return new t(i,n)}return new t(i,n,o)}return ra(t,this,arguments)};return e.prototype=t.prototype,e},ma=function(t,e){var i,n,o,r,s,a,d,l,c,h=t.target,u=t.global,p=t.stat,f=t.proto,m=u?oa:p?oa[h]:(oa[h]||{}).prototype,v=u?ca:ca[h]||ua(ca,h,{})[h],g=v.prototype;for(r in e)n=!(i=la(u?r:h+(p?".":"#")+r,t.forced))&&m&&pa(m,r),a=v[r],n&&(d=t.dontCallGetSet?(c=da(m,r))&&c.value:m[r]),s=n&&d?d:e[r],n&&typeof a==typeof s||(l=t.bind&&n?ha(s,oa):t.wrap&&n?fa(s):f&&aa(s)?sa(s):s,(t.sham||s&&s.sham||a&&a.sham)&&ua(l,"sham",!0),ua(v,r,l),f&&(pa(ca,o=h+"Prototype")||ua(ca,o,{}),ua(ca[o],r,s),t.real&&g&&(i||!g[r])&&ua(g,r,s)))},va=ma,ga=vo,ya=Ls.f;va({target:"Object",stat:!0,forced:Object.defineProperty!==ya,sham:!ga},{defineProperty:ya});var ba=$o.Object,xa=$n.exports=function(t,e,i){return ba.defineProperty(t,e,i)};ba.defineProperty.sham&&(xa.sham=!0);var _a=$n.exports,wa=_a,Ea=Hn(wa),ka=so,Oa=Array.isArray||function(t){return"Array"===ka(t)},Ca=Math.ceil,Sa=Math.floor,Ta=Math.trunc||function(t){var e=+t;return(e>0?Sa:Ca)(e)},Ia=Ta,Aa=function(t){var e=+t;return e!=e||0===e?0:Ia(e)},Ra=Aa,Pa=Math.min,Da=function(t){return t>0?Pa(Ra(t),9007199254740991):0},Ma=function(t){return Da(t.length)},Fa=TypeError,Na=function(t){if(t>9007199254740991)throw Fa("Maximum allowed index exceeded");return t},Ba=ls,La=Ls,za=Co,ja=function(t,e,i){var n=Ba(e);n in t?La.f(t,n,za(0,i)):t[n]=i},Ha={};Ha[Jr("toStringTag")]="z";var $a="[object z]"===String(Ha),Ua=$a,Wa=fo,Va=so,qa=Jr("toStringTag"),Xa=Object,Ya="Arguments"===Va(function(){return arguments}()),Ga=Ua?Va:function(t){var e,i,n;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(i=function(t,e){try{return t[e]}catch(t){}}(e=Xa(t),qa))?i:Ya?Va(e):"Object"===(n=Va(e))&&Wa(e.callee)?"Arguments":n},Ka=fo,Za=Rr,Qa=io(Function.toString);Ka(Za.inspectSource)||(Za.inspectSource=function(t){return Qa(t)});var Ja=Za.inspectSource,td=io,ed=Vn,id=fo,nd=Ga,od=Ja,rd=function(){},sd=[],ad=Xo("Reflect","construct"),dd=/^\s*(?:class|function)\b/,ld=td(dd.exec),cd=!dd.test(rd),hd=function(t){if(!id(t))return!1;try{return ad(rd,sd,t),!0}catch(t){return!1}},ud=function(t){if(!id(t))return!1;switch(nd(t)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}try{return cd||!!ld(dd,od(t))}catch(t){return!0}};ud.sham=!0;var pd=!ad||ed((function(){var t;return hd(hd.call)||!hd(Object)||!hd((function(){t=!0}))||t}))?ud:hd,fd=Oa,md=pd,vd=Ho,gd=Jr("species"),yd=Array,bd=function(t){var e;return fd(t)&&(e=t.constructor,(md(e)&&(e===yd||fd(e.prototype))||vd(e)&&null===(e=e[gd]))&&(e=void 0)),void 0===e?yd:e},xd=function(t,e){return new(bd(t))(0===e?0:e)},_d=Vn,wd=ir,Ed=Jr("species"),kd=function(t){return wd>=51||!_d((function(){var e=[];return(e.constructor={})[Ed]=function(){return{foo:1}},1!==e[t](Boolean).foo}))},Od=ma,Cd=Vn,Sd=Oa,Td=Ho,Id=Nr,Ad=Ma,Rd=Na,Pd=ja,Dd=xd,Md=kd,Fd=ir,Nd=Jr("isConcatSpreadable"),Bd=Fd>=51||!Cd((function(){var t=[];return t[Nd]=!1,t.concat()[0]!==t})),Ld=function(t){if(!Td(t))return!1;var e=t[Nd];return void 0!==e?!!e:Sd(t)};Od({target:"Array",proto:!0,arity:1,forced:!Bd||!Md("concat")},{concat:function(t){var e,i,n,o,r,s=Id(this),a=Dd(s,0),d=0;for(e=-1,n=arguments.length;ea;)if((o=r[a++])!=o)return!0}else for(;s>a;a++)if((t||a in r)&&r[a]===i)return t||a||0;return!t&&-1}},Zd={includes:Kd(!0),indexOf:Kd(!1)},Qd={},Jd=zr,tl=Lo,el=Zd.indexOf,il=Qd,nl=io([].push),ol=function(t,e){var i,n=tl(t),o=0,r=[];for(i in n)!Jd(il,i)&&Jd(n,i)&&nl(r,i);for(;e.length>o;)Jd(n,i=e[o++])&&(~el(r,i)||nl(r,i));return r},rl=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],sl=ol,al=rl,dl=Object.keys||function(t){return sl(t,al)},ll=vo,cl=zs,hl=Ls,ul=Us,pl=Lo,fl=dl;$d.f=ll&&!cl?Object.defineProperties:function(t,e){ul(t);for(var i,n=pl(e),o=fl(e),r=o.length,s=0;r>s;)hl.f(t,i=o[s++],n[i]);return t};var ml,vl=Xo("document","documentElement"),gl=Wr,yl=Dr("keys"),bl=function(t){return yl[t]||(yl[t]=gl(t))},xl=Us,_l=$d,wl=rl,El=Qd,kl=vl,Ol=ps,Cl="prototype",Sl="script",Tl=bl("IE_PROTO"),Il=function(){},Al=function(t){return"<"+Sl+">"+t+""},Rl=function(t){t.write(Al("")),t.close();var e=t.parentWindow.Object;return t=null,e},Pl=function(){try{ml=new ActiveXObject("htmlfile")}catch(t){}var t,e,i;Pl="undefined"!=typeof document?document.domain&&ml?Rl(ml):(e=Ol("iframe"),i="java"+Sl+":",e.style.display="none",kl.appendChild(e),e.src=String(i),(t=e.contentWindow.document).open(),t.write(Al("document.F=Object")),t.close(),t.F):Rl(ml);for(var n=wl.length;n--;)delete Pl[Cl][wl[n]];return Pl()};El[Tl]=!0;var Dl=Object.create||function(t,e){var i;return null!==t?(Il[Cl]=xl(t),i=new Il,Il[Cl]=null,i[Tl]=t):i=Pl(),void 0===e?i:_l.f(i,e)},Ml={},Fl=ol,Nl=rl.concat("length","prototype");Ml.f=Object.getOwnPropertyNames||function(t){return Fl(t,Nl)};var Bl={},Ll=qd,zl=Ma,jl=ja,Hl=Array,$l=Math.max,Ul=function(t,e,i){for(var n=zl(t),o=Ll(e,n),r=Ll(void 0===i?n:i,n),s=Hl($l(r-o,0)),a=0;oy;y++)if((a||y in m)&&(p=v(u=m[y],y,f),t))if(e)x[y]=p;else if(p)switch(t){case 3:return!0;case 5:return u;case 6:return y;case 2:Vc(x,u)}else switch(t){case 4:return!1;case 7:Vc(x,u)}return r?-1:n||o?o:x}},Xc={forEach:qc(0),map:qc(1),filter:qc(2),some:qc(3),every:qc(4),find:qc(5),findIndex:qc(6),filterReject:qc(7)},Yc=ma,Gc=Wn,Kc=bo,Zc=io,Qc=vo,Jc=sr,th=Vn,eh=zr,ih=Yo,nh=Us,oh=Lo,rh=ls,sh=Hd,ah=Co,dh=Dl,lh=dl,ch=Ml,hh=Bl,uh=Gl,ph=mo,fh=Ls,mh=$d,vh=xo,gh=Zl,yh=Jl,bh=Dr,xh=Qd,_h=Wr,wh=Jr,Eh=tc,kh=lc,Oh=fc,Ch=Ec,Sh=zc,Th=Xc.forEach,Ih=bl("hidden"),Ah="Symbol",Rh="prototype",Ph=Sh.set,Dh=Sh.getterFor(Ah),Mh=Object[Rh],Fh=Gc.Symbol,Nh=Fh&&Fh[Rh],Bh=Gc.RangeError,Lh=Gc.TypeError,zh=Gc.QObject,jh=ph.f,Hh=fh.f,$h=hh.f,Uh=vh.f,Wh=Zc([].push),Vh=bh("symbols"),qh=bh("op-symbols"),Xh=bh("wks"),Yh=!zh||!zh[Rh]||!zh[Rh].findChild,Gh=function(t,e,i){var n=jh(Mh,e);n&&delete Mh[e],Hh(t,e,i),n&&t!==Mh&&Hh(Mh,e,n)},Kh=Qc&&th((function(){return 7!==dh(Hh({},"a",{get:function(){return Hh(this,"a",{value:7}).a}})).a}))?Gh:Hh,Zh=function(t,e){var i=Vh[t]=dh(Nh);return Ph(i,{type:Ah,tag:t,description:e}),Qc||(i.description=e),i},Qh=function(t,e,i){t===Mh&&Qh(qh,e,i),nh(t);var n=rh(e);return nh(i),eh(Vh,n)?(i.enumerable?(eh(t,Ih)&&t[Ih][n]&&(t[Ih][n]=!1),i=dh(i,{enumerable:ah(0,!1)})):(eh(t,Ih)||Hh(t,Ih,ah(1,{})),t[Ih][n]=!0),Kh(t,n,i)):Hh(t,n,i)},Jh=function(t,e){nh(t);var i=oh(e),n=lh(i).concat(nu(i));return Th(n,(function(e){Qc&&!Kc(tu,i,e)||Qh(t,e,i[e])})),t},tu=function(t){var e=rh(t),i=Kc(Uh,this,e);return!(this===Mh&&eh(Vh,e)&&!eh(qh,e))&&(!(i||!eh(this,e)||!eh(Vh,e)||eh(this,Ih)&&this[Ih][e])||i)},eu=function(t,e){var i=oh(t),n=rh(e);if(i!==Mh||!eh(Vh,n)||eh(qh,n)){var o=jh(i,n);return!o||!eh(Vh,n)||eh(i,Ih)&&i[Ih][n]||(o.enumerable=!0),o}},iu=function(t){var e=$h(oh(t)),i=[];return Th(e,(function(t){eh(Vh,t)||eh(xh,t)||Wh(i,t)})),i},nu=function(t){var e=t===Mh,i=$h(e?qh:oh(t)),n=[];return Th(i,(function(t){!eh(Vh,t)||e&&!eh(Mh,t)||Wh(n,Vh[t])})),n};Jc||(Fh=function(){if(ih(Nh,this))throw new Lh("Symbol is not a constructor");var t=arguments.length&&void 0!==arguments[0]?sh(arguments[0]):void 0,e=_h(t),i=function(t){var n=void 0===this?Gc:this;n===Mh&&Kc(i,qh,t),eh(n,Ih)&&eh(n[Ih],e)&&(n[Ih][e]=!1);var o=ah(1,t);try{Kh(n,e,o)}catch(t){if(!(t instanceof Bh))throw t;Gh(n,e,o)}};return Qc&&Yh&&Kh(Mh,e,{configurable:!0,set:i}),Zh(e,t)},gh(Nh=Fh[Rh],"toString",(function(){return Dh(this).tag})),gh(Fh,"withoutSetter",(function(t){return Zh(_h(t),t)})),vh.f=tu,fh.f=Qh,mh.f=Jh,ph.f=eu,ch.f=hh.f=iu,uh.f=nu,Eh.f=function(t){return Zh(wh(t),t)},Qc&&yh(Nh,"description",{configurable:!0,get:function(){return Dh(this).description}})),Yc({global:!0,constructor:!0,wrap:!0,forced:!Jc,sham:!Jc},{Symbol:Fh}),Th(lh(Xh),(function(t){kh(t)})),Yc({target:Ah,stat:!0,forced:!Jc},{useSetter:function(){Yh=!0},useSimple:function(){Yh=!1}}),Yc({target:"Object",stat:!0,forced:!Jc,sham:!Qc},{create:function(t,e){return void 0===e?dh(t):Jh(dh(t),e)},defineProperty:Qh,defineProperties:Jh,getOwnPropertyDescriptor:eu}),Yc({target:"Object",stat:!0,forced:!Jc},{getOwnPropertyNames:iu}),Oh(),Ch(Fh,Ah),xh[Ih]=!0;var ou=sr&&!!Symbol.for&&!!Symbol.keyFor,ru=ma,su=Xo,au=zr,du=Hd,lu=Dr,cu=ou,hu=lu("string-to-symbol-registry"),uu=lu("symbol-to-string-registry");ru({target:"Symbol",stat:!0,forced:!cu},{for:function(t){var e=du(t);if(au(hu,e))return hu[e];var i=su("Symbol")(e);return hu[e]=i,uu[i]=e,i}});var pu=ma,fu=zr,mu=ur,vu=fr,gu=ou,yu=Dr("symbol-to-string-registry");pu({target:"Symbol",stat:!0,forced:!gu},{keyFor:function(t){if(!mu(t))throw new TypeError(vu(t)+" is not a symbol");if(fu(yu,t))return yu[t]}});var bu=io([].slice),xu=Oa,_u=fo,wu=so,Eu=Hd,ku=io([].push),Ou=ma,Cu=Xo,Su=Zn,Tu=bo,Iu=io,Au=Vn,Ru=fo,Pu=ur,Du=bu,Mu=function(t){if(_u(t))return t;if(xu(t)){for(var e=t.length,i=[],n=0;n=e.length)return t.target=void 0,pf(void 0,!0);switch(t.kind){case"keys":return pf(i,!1);case"values":return pf(e[i],!1)}return pf([i,e[i]],!1)}),"values"),cf.Arguments=cf.Array;var gf={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0},yf=Wn,bf=Ga,xf=na,_f=rp,wf=Jr("toStringTag");for(var Ef in gf){var kf=yf[Ef],Of=kf&&kf.prototype;Of&&bf(Of)!==wf&&xf(Of,wf,Ef),_f[Ef]=_f.Array}var Cf=op,Sf=Jr,Tf=Ls.f,If=Sf("metadata"),Af=Function.prototype;void 0===Af[If]&&Tf(Af,If,{value:null}),lc("asyncDispose"),lc("dispose"),lc("metadata");var Rf=Cf,Pf=io,Df=Xo("Symbol"),Mf=Df.keyFor,Ff=Pf(Df.prototype.valueOf),Nf=Df.isRegisteredSymbol||function(t){try{return void 0!==Mf(Ff(t))}catch(t){return!1}};ma({target:"Symbol",stat:!0},{isRegisteredSymbol:Nf});for(var Bf=Dr,Lf=Xo,zf=io,jf=ur,Hf=Jr,$f=Lf("Symbol"),Uf=$f.isWellKnownSymbol,Wf=Lf("Object","getOwnPropertyNames"),Vf=zf($f.prototype.valueOf),qf=Bf("wks"),Xf=0,Yf=Wf($f),Gf=Yf.length;Xf=a?t?"":void 0:(n=rm(r,s))<55296||n>56319||s+1===a||(o=rm(r,s+1))<56320||o>57343?t?om(r,s):n:t?sm(r,s,s+2):o-56320+(n-55296<<10)+65536}},dm={codeAt:am(!1),charAt:am(!0)}.charAt,lm=Hd,cm=zc,hm=af,um=df,pm="String Iterator",fm=cm.set,mm=cm.getterFor(pm);hm(String,"String",(function(t){fm(this,{type:pm,string:lm(t),index:0})}),(function(){var t,e=mm(this),i=e.string,n=e.index;return n>=i.length?um(void 0,!0):(t=dm(i,n),e.index+=t.length,um(t,!1))}));var vm=tc.f("iterator"),gm=vm,ym=Hn(gm);function bm(t){return bm="function"==typeof Jf&&"symbol"==typeof ym?function(t){return typeof t}:function(t){return t&&"function"==typeof Jf&&t.constructor===Jf&&t!==Jf.prototype?"symbol":typeof t},bm(t)}var xm=Hn(tc.f("toPrimitive"));function _m(t){var e=function(t,e){if("object"!==bm(t)||null===t)return t;var i=t[xm];if(void 0!==i){var n=i.call(t,e||"default");if("object"!==bm(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(t,"string");return"symbol"===bm(e)?e:String(e)}function wm(t,e){for(var i=0;i=0:a>d;d+=l)d in s&&(o=i(o,s[d],d,r));return o}},Jm={left:Qm(!1),right:Qm(!0)},tv=Vn,ev=function(t,e){var i=[][t];return!!i&&tv((function(){i.call(null,e||function(){return 1},1)}))},iv="process"===so(Wn.process),nv=Jm.left;ma({target:"Array",proto:!0,forced:!iv&&ir>79&&ir<83||!ev("reduce")},{reduce:function(t){var e=arguments.length;return nv(this,t,e,e>1?arguments[1]:void 0)}});var ov=zm("Array","reduce"),rv=Yo,sv=ov,av=Array.prototype,dv=function(t){var e=t.reduce;return t===av||rv(av,t)&&e===av.reduce?sv:e},lv=Hn(dv),cv=Xc.filter;ma({target:"Array",proto:!0,forced:!kd("filter")},{filter:function(t){return cv(this,t,arguments.length>1?arguments[1]:void 0)}});var hv=zm("Array","filter"),uv=Yo,pv=hv,fv=Array.prototype,mv=function(t){var e=t.filter;return t===fv||uv(fv,t)&&e===fv.filter?pv:e},vv=Hn(mv),gv=Xc.map;ma({target:"Array",proto:!0,forced:!kd("map")},{map:function(t){return gv(this,t,arguments.length>1?arguments[1]:void 0)}});var yv=zm("Array","map"),bv=Yo,xv=yv,_v=Array.prototype,wv=function(t){var e=t.map;return t===_v||bv(_v,t)&&e===_v.map?xv:e},Ev=Hn(wv),kv=Oa,Ov=Ma,Cv=Na,Sv=Bs,Tv=function(t,e,i,n,o,r,s,a){for(var d,l,c=o,h=0,u=!!s&&Sv(s,a);h0&&kv(d)?(l=Ov(d),c=Tv(t,e,d,l,c,r-1)-1):(Cv(c+1),t[c]=d),c++),h++;return c},Iv=Tv,Av=yr,Rv=Nr,Pv=Ma,Dv=xd;ma({target:"Array",proto:!0},{flatMap:function(t){var e,i=Rv(this),n=Pv(i);return Av(t),(e=Dv(i,0)).length=Iv(e,i,i,n,0,1,t,arguments.length>1?arguments[1]:void 0),e}}),zm("Array","flatMap");var Mv=bo,Fv=Us,Nv=_r,Bv=function(t,e,i){var n,o;Fv(t);try{if(!(n=Nv(t,"return"))){if("throw"===e)throw i;return i}n=Mv(n,t)}catch(t){o=!0,n=t}if("throw"===e)throw i;if(o)throw n;return Fv(n),i},Lv=Us,zv=Bv,jv=rp,Hv=Jr("iterator"),$v=Array.prototype,Uv=function(t){return void 0!==t&&(jv.Array===t||$v[Hv]===t)},Wv=Ga,Vv=_r,qv=Po,Xv=rp,Yv=Jr("iterator"),Gv=function(t){if(!qv(t))return Vv(t,Yv)||Vv(t,"@@iterator")||Xv[Wv(t)]},Kv=bo,Zv=yr,Qv=Us,Jv=fr,tg=Gv,eg=TypeError,ig=function(t,e){var i=arguments.length<2?tg(t):e;if(Zv(i))return Qv(Kv(i,t));throw new eg(Jv(t)+" is not iterable")},ng=Bs,og=bo,rg=Nr,sg=function(t,e,i,n){try{return n?e(Lv(i)[0],i[1]):e(i)}catch(e){zv(t,"throw",e)}},ag=Uv,dg=pd,lg=Ma,cg=ja,hg=ig,ug=Gv,pg=Array,fg=Jr("iterator"),mg=!1;try{var vg=0,gg={next:function(){return{done:!!vg++}},return:function(){mg=!0}};gg[fg]=function(){return this},Array.from(gg,(function(){throw 2}))}catch(t){}var yg=function(t,e){try{if(!e&&!mg)return!1}catch(t){return!1}var i=!1;try{var n={};n[fg]=function(){return{next:function(){return{done:i=!0}}}},t(n)}catch(t){}return i},bg=function(t){var e=rg(t),i=dg(this),n=arguments.length,o=n>1?arguments[1]:void 0,r=void 0!==o;r&&(o=ng(o,n>2?arguments[2]:void 0));var s,a,d,l,c,h,u=ug(e),p=0;if(!u||this===pg&&ag(u))for(s=lg(e),a=i?new this(s):pg(s);s>p;p++)h=r?o(e[p],p):e[p],cg(a,p,h);else for(c=(l=hg(e,u)).next,a=i?new this:[];!(d=og(c,l)).done;p++)h=r?sg(l,o,[d.value,p],!0):d.value,cg(a,p,h);return a.length=p,a};ma({target:"Array",stat:!0,forced:!yg((function(t){Array.from(t)}))},{from:bg});var xg=$o.Array.from,_g=Hn(xg),wg=Gv,Eg=Hn(wg),kg=Hn(wg);ma({target:"Array",stat:!0},{isArray:Oa});var Og=$o.Array.isArray,Cg=Hn(Og);var Sg=vo,Tg=Oa,Ig=TypeError,Ag=Object.getOwnPropertyDescriptor,Rg=Sg&&!function(){if(void 0!==this)return!0;try{Object.defineProperty([],"length",{writable:!1}).length=1}catch(t){return t instanceof TypeError}}()?function(t,e){if(Tg(t)&&!Ag(t,"length").writable)throw new Ig("Cannot set read only .length");return t.length=e}:function(t,e){return t.length=e},Pg=Nr,Dg=Ma,Mg=Rg,Fg=Na;ma({target:"Array",proto:!0,arity:1,forced:Vn((function(){return 4294967297!==[].push.call({length:4294967296},1)}))||!function(){try{Object.defineProperty([],"length",{writable:!1}).push()}catch(t){return t instanceof TypeError}}()},{push:function(t){var e=Pg(this),i=Dg(e),n=arguments.length;Fg(i+n);for(var o=0;ot.length)&&(e=t.length);for(var i=0,n=new Array(e);i1?arguments[1]:void 0)};ma({target:"Array",proto:!0,forced:[].forEach!==Ny},{forEach:Ny});var By=zm("Array","forEach"),Ly=Ga,zy=zr,jy=Yo,Hy=By,$y=Array.prototype,Uy={DOMTokenList:!0,NodeList:!0},Wy=function(t){var e=t.forEach;return t===$y||jy($y,t)&&e===$y.forEach||zy(Uy,Ly(t))?Hy:e},Vy=Hn(Wy),qy=ma,Xy=Oa,Yy=io([].reverse),Gy=[1,2];qy({target:"Array",proto:!0,forced:String(Gy)===String(Gy.reverse())},{reverse:function(){return Xy(this)&&(this.length=this.length),Yy(this)}});var Ky=zm("Array","reverse"),Zy=Yo,Qy=Ky,Jy=Array.prototype,tb=function(t){var e=t.reverse;return t===Jy||Zy(Jy,t)&&e===Jy.reverse?Qy:e},eb=tb,ib=Hn(eb),nb=fr,ob=TypeError,rb=function(t,e){if(!delete t[e])throw new ob("Cannot delete property "+nb(e)+" of "+nb(t))},sb=ma,ab=Nr,db=qd,lb=Aa,cb=Ma,hb=Rg,ub=Na,pb=xd,fb=ja,mb=rb,vb=kd("splice"),gb=Math.max,yb=Math.min;sb({target:"Array",proto:!0,forced:!vb},{splice:function(t,e){var i,n,o,r,s,a,d=ab(this),l=cb(d),c=db(t,l),h=arguments.length;for(0===h?i=n=0:1===h?(i=0,n=l-c):(i=h-2,n=yb(gb(lb(e),0),l-c)),ub(l+i-n),o=pb(d,n),r=0;rl-n+i;r--)mb(d,r-1)}else if(i>n)for(r=l-n;r>c;r--)a=r+i-1,(s=r+n-1)in d?d[a]=d[s]:mb(d,a);for(r=0;ro;)for(var a,d=Db(arguments[o++]),l=r?Nb(Ib(d),r(d)):Ib(d),c=l.length,h=0;c>h;)a=l[h++],Ob&&!Sb(s,d,a)||(i[a]=d[a]);return i}:Mb,Lb=Bb;ma({target:"Object",stat:!0,arity:2,forced:Object.assign!==Lb},{assign:Lb});var zb=Hn($o.Object.assign),jb=Nr,Hb=xp,$b=up;ma({target:"Object",stat:!0,forced:Vn((function(){Hb(1)})),sham:!$b},{getPrototypeOf:function(t){return Hb(jb(t))}});var Ub=$o.Object.getPrototypeOf;ma({target:"Object",stat:!0,sham:!vo},{create:Dl});var Wb=$o.Object,Vb=function(t,e){return Wb.create(t,e)},qb=Vb,Xb=Hn(qb),Yb=$o,Gb=Zn;Yb.JSON||(Yb.JSON={stringify:JSON.stringify});var Kb=function(t,e,i){return Gb(Yb.JSON.stringify,null,arguments)},Zb=Hn(Kb),Qb="function"==typeof Bun&&Bun&&"string"==typeof Bun.version,Jb=TypeError,tx=function(t,e){if(ti,s=nx(n)?n:dx(n),a=r?sx(arguments,i):[],d=r?function(){ix(s,this,a)}:s;return e?t(d,o):t(d)}:t},hx=ma,ux=Wn,px=cx(ux.setInterval,!0);hx({global:!0,bind:!0,forced:ux.setInterval!==px},{setInterval:px});var fx=ma,mx=Wn,vx=cx(mx.setTimeout,!0);fx({global:!0,bind:!0,forced:mx.setTimeout!==vx},{setTimeout:vx});var gx=Hn($o.setTimeout),yx={exports:{}};!function(t){function e(t){if(t)return function(t){return Object.assign(t,e.prototype),t._callbacks=new Map,t}(t);this._callbacks=new Map}e.prototype.on=function(t,e){const i=this._callbacks.get(t)??[];return i.push(e),this._callbacks.set(t,i),this},e.prototype.once=function(t,e){const i=(...n)=>{this.off(t,i),e.apply(this,n)};return i.fn=e,this.on(t,i),this},e.prototype.off=function(t,e){if(void 0===t&&void 0===e)return this._callbacks.clear(),this;if(void 0===e)return this._callbacks.delete(t),this;const i=this._callbacks.get(t);if(i){for(const[t,n]of i.entries())if(n===e||n.fn===e){i.splice(t,1);break}0===i.length?this._callbacks.delete(t):this._callbacks.set(t,i)}return this},e.prototype.emit=function(t,...e){const i=this._callbacks.get(t);if(i){const t=[...i];for(const i of t)i.apply(this,e)}return this},e.prototype.listeners=function(t){return this._callbacks.get(t)??[]},e.prototype.listenerCount=function(t){if(t)return this.listeners(t).length;let e=0;for(const t of this._callbacks.values())e+=t.length;return e},e.prototype.hasListeners=function(t){return this.listenerCount(t)>0},e.prototype.addEventListener=e.prototype.on,e.prototype.removeListener=e.prototype.off,e.prototype.removeEventListener=e.prototype.off,e.prototype.removeAllListeners=e.prototype.off,t.exports=e}(yx);var bx,xx=Hn(yx.exports); + */};function Kt(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var qt="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function Yt(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var Zt={exports:{}},Jt=function(t){return t&&t.Math===Math&&t},Xt=Jt("object"==typeof globalThis&&globalThis)||Jt("object"==typeof window&&window)||Jt("object"==typeof self&&self)||Jt("object"==typeof qt&&qt)||function(){return this}()||qt||Function("return this")(),_t=function(t){try{return!!t()}catch(t){return!0}},$t=!_t((function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")})),te=$t,ee=Function.prototype,ie=ee.apply,oe=ee.call,ne="object"==typeof Reflect&&Reflect.apply||(te?oe.bind(ie):function(){return oe.apply(ie,arguments)}),re=$t,se=Function.prototype,ae=se.call,le=re&&se.bind.bind(ae,ae),he=re?le:function(t){return function(){return ae.apply(t,arguments)}},ce=he,de=ce({}.toString),ue=ce("".slice),fe=function(t){return ue(de(t),8,-1)},pe=fe,ve=he,ge=function(t){if("Function"===pe(t))return ve(t)},ye="object"==typeof document&&document.all,me={all:ye,IS_HTMLDDA:void 0===ye&&void 0!==ye},be=me.all,we=me.IS_HTMLDDA?function(t){return"function"==typeof t||t===be}:function(t){return"function"==typeof t},Ae={},Ee=!_t((function(){return 7!==Object.defineProperty({},1,{get:function(){return 7}})[1]})),ke=$t,Ce=Function.prototype.call,xe=ke?Ce.bind(Ce):function(){return Ce.apply(Ce,arguments)},Se={},Ie={}.propertyIsEnumerable,Me=Object.getOwnPropertyDescriptor,Oe=Me&&!Ie.call({1:2},1);Se.f=Oe?function(t){var e=Me(this,t);return!!e&&e.enumerable}:Ie;var De,Re,Be=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}},ze=_t,Pe=fe,Fe=Object,Te=he("".split),Ne=ze((function(){return!Fe("z").propertyIsEnumerable(0)}))?function(t){return"String"===Pe(t)?Te(t,""):Fe(t)}:Fe,je=function(t){return null==t},Ue=je,Le=TypeError,Qe=function(t){if(Ue(t))throw new Le("Can't call method on "+t);return t},He=Ne,Ve=Qe,We=function(t){return He(Ve(t))},Ge=we,Ke=me.all,qe=me.IS_HTMLDDA?function(t){return"object"==typeof t?null!==t:Ge(t)||t===Ke}:function(t){return"object"==typeof t?null!==t:Ge(t)},Ye={},Ze=Ye,Je=Xt,Xe=we,_e=function(t){return Xe(t)?t:void 0},$e=function(t,e){return arguments.length<2?_e(Ze[t])||_e(Je[t]):Ze[t]&&Ze[t][e]||Je[t]&&Je[t][e]},ti=he({}.isPrototypeOf),ei="undefined"!=typeof navigator&&String(navigator.userAgent)||"",ii=Xt,oi=ei,ni=ii.process,ri=ii.Deno,si=ni&&ni.versions||ri&&ri.version,ai=si&&si.v8;ai&&(Re=(De=ai.split("."))[0]>0&&De[0]<4?1:+(De[0]+De[1])),!Re&&oi&&(!(De=oi.match(/Edge\/(\d+)/))||De[1]>=74)&&(De=oi.match(/Chrome\/(\d+)/))&&(Re=+De[1]);var li=Re,hi=li,ci=_t,di=Xt.String,ui=!!Object.getOwnPropertySymbols&&!ci((function(){var t=Symbol("symbol detection");return!di(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&hi&&hi<41})),fi=ui&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,pi=$e,vi=we,gi=ti,yi=Object,mi=fi?function(t){return"symbol"==typeof t}:function(t){var e=pi("Symbol");return vi(e)&&gi(e.prototype,yi(t))},bi=String,wi=function(t){try{return bi(t)}catch(t){return"Object"}},Ai=we,Ei=wi,ki=TypeError,Ci=function(t){if(Ai(t))return t;throw new ki(Ei(t)+" is not a function")},xi=Ci,Si=je,Ii=function(t,e){var i=t[e];return Si(i)?void 0:xi(i)},Mi=xe,Oi=we,Di=qe,Ri=TypeError,Bi={exports:{}},zi=Xt,Pi=Object.defineProperty,Fi=function(t,e){try{Pi(zi,t,{value:e,configurable:!0,writable:!0})}catch(i){zi[t]=e}return e},Ti="__core-js_shared__",Ni=Xt[Ti]||Fi(Ti,{}),ji=Ni;(Bi.exports=function(t,e){return ji[t]||(ji[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.33.2",mode:"pure",copyright:"© 2014-2023 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.33.2/LICENSE",source:"https://github.com/zloirock/core-js"});var Ui=Bi.exports,Li=Qe,Qi=Object,Hi=function(t){return Qi(Li(t))},Vi=Hi,Wi=he({}.hasOwnProperty),Gi=Object.hasOwn||function(t,e){return Wi(Vi(t),e)},Ki=he,qi=0,Yi=Math.random(),Zi=Ki(1..toString),Ji=function(t){return"Symbol("+(void 0===t?"":t)+")_"+Zi(++qi+Yi,36)},Xi=Ui,_i=Gi,$i=Ji,to=ui,eo=fi,io=Xt.Symbol,oo=Xi("wks"),no=eo?io.for||io:io&&io.withoutSetter||$i,ro=function(t){return _i(oo,t)||(oo[t]=to&&_i(io,t)?io[t]:no("Symbol."+t)),oo[t]},so=xe,ao=qe,lo=mi,ho=Ii,co=function(t,e){var i,o;if("string"===e&&Oi(i=t.toString)&&!Di(o=Mi(i,t)))return o;if(Oi(i=t.valueOf)&&!Di(o=Mi(i,t)))return o;if("string"!==e&&Oi(i=t.toString)&&!Di(o=Mi(i,t)))return o;throw new Ri("Can't convert object to primitive value")},uo=TypeError,fo=ro("toPrimitive"),po=function(t,e){if(!ao(t)||lo(t))return t;var i,o=ho(t,fo);if(o){if(void 0===e&&(e="default"),i=so(o,t,e),!ao(i)||lo(i))return i;throw new uo("Can't convert object to primitive value")}return void 0===e&&(e="number"),co(t,e)},vo=mi,go=function(t){var e=po(t,"string");return vo(e)?e:e+""},yo=qe,mo=Xt.document,bo=yo(mo)&&yo(mo.createElement),wo=function(t){return bo?mo.createElement(t):{}},Ao=wo,Eo=!Ee&&!_t((function(){return 7!==Object.defineProperty(Ao("div"),"a",{get:function(){return 7}}).a})),ko=Ee,Co=xe,xo=Se,So=Be,Io=We,Mo=go,Oo=Gi,Do=Eo,Ro=Object.getOwnPropertyDescriptor;Ae.f=ko?Ro:function(t,e){if(t=Io(t),e=Mo(e),Do)try{return Ro(t,e)}catch(t){}if(Oo(t,e))return So(!Co(xo.f,t,e),t[e])};var Bo=_t,zo=we,Po=/#|\.prototype\./,Fo=function(t,e){var i=No[To(t)];return i===Uo||i!==jo&&(zo(e)?Bo(e):!!e)},To=Fo.normalize=function(t){return String(t).replace(Po,".").toLowerCase()},No=Fo.data={},jo=Fo.NATIVE="N",Uo=Fo.POLYFILL="P",Lo=Fo,Qo=Ci,Ho=$t,Vo=ge(ge.bind),Wo=function(t,e){return Qo(t),void 0===e?t:Ho?Vo(t,e):function(){return t.apply(e,arguments)}},Go={},Ko=Ee&&_t((function(){return 42!==Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype})),qo=qe,Yo=String,Zo=TypeError,Jo=function(t){if(qo(t))return t;throw new Zo(Yo(t)+" is not an object")},Xo=Ee,_o=Eo,$o=Ko,tn=Jo,en=go,on=TypeError,nn=Object.defineProperty,rn=Object.getOwnPropertyDescriptor,sn="enumerable",an="configurable",ln="writable";Go.f=Xo?$o?function(t,e,i){if(tn(t),e=en(e),tn(i),"function"==typeof t&&"prototype"===e&&"value"in i&&ln in i&&!i[ln]){var o=rn(t,e);o&&o[ln]&&(t[e]=i.value,i={configurable:an in i?i[an]:o[an],enumerable:sn in i?i[sn]:o[sn],writable:!1})}return nn(t,e,i)}:nn:function(t,e,i){if(tn(t),e=en(e),tn(i),_o)try{return nn(t,e,i)}catch(t){}if("get"in i||"set"in i)throw new on("Accessors not supported");return"value"in i&&(t[e]=i.value),t};var hn=Go,cn=Be,dn=Ee?function(t,e,i){return hn.f(t,e,cn(1,i))}:function(t,e,i){return t[e]=i,t},un=Xt,fn=ne,pn=ge,vn=we,gn=Ae.f,yn=Lo,mn=Ye,bn=Wo,wn=dn,An=Gi,En=function(t){var e=function(i,o,n){if(this instanceof e){switch(arguments.length){case 0:return new t;case 1:return new t(i);case 2:return new t(i,o)}return new t(i,o,n)}return fn(t,this,arguments)};return e.prototype=t.prototype,e},kn=function(t,e){var i,o,n,r,s,a,l,h,c,d=t.target,u=t.global,f=t.stat,p=t.proto,v=u?un:f?un[d]:(un[d]||{}).prototype,g=u?mn:mn[d]||wn(mn,d,{})[d],y=g.prototype;for(r in e)o=!(i=yn(u?r:d+(f?".":"#")+r,t.forced))&&v&&An(v,r),a=g[r],o&&(l=t.dontCallGetSet?(c=gn(v,r))&&c.value:v[r]),s=o&&l?l:e[r],o&&typeof a==typeof s||(h=t.bind&&o?bn(s,un):t.wrap&&o?En(s):p&&vn(s)?pn(s):s,(t.sham||s&&s.sham||a&&a.sham)&&wn(h,"sham",!0),wn(g,r,h),p&&(An(mn,n=d+"Prototype")||wn(mn,n,{}),wn(mn[n],r,s),t.real&&y&&(i||!y[r])&&wn(y,r,s)))},Cn=kn,xn=Ee,Sn=Go.f;Cn({target:"Object",stat:!0,forced:Object.defineProperty!==Sn,sham:!xn},{defineProperty:Sn});var In=Ye.Object,Mn=Zt.exports=function(t,e,i){return In.defineProperty(t,e,i)};In.defineProperty.sham&&(Mn.sham=!0);var On=Zt.exports,Dn=On,Rn=Yt(Dn),Bn=fe,zn=Array.isArray||function(t){return"Array"===Bn(t)},Pn=Math.ceil,Fn=Math.floor,Tn=Math.trunc||function(t){var e=+t;return(e>0?Fn:Pn)(e)},Nn=Tn,jn=function(t){var e=+t;return e!=e||0===e?0:Nn(e)},Un=jn,Ln=Math.min,Qn=function(t){return t>0?Ln(Un(t),9007199254740991):0},Hn=function(t){return Qn(t.length)},Vn=TypeError,Wn=function(t){if(t>9007199254740991)throw Vn("Maximum allowed index exceeded");return t},Gn=go,Kn=Go,qn=Be,Yn=function(t,e,i){var o=Gn(e);o in t?Kn.f(t,o,qn(0,i)):t[o]=i},Zn={};Zn[ro("toStringTag")]="z";var Jn="[object z]"===String(Zn),Xn=Jn,_n=we,$n=fe,tr=ro("toStringTag"),er=Object,ir="Arguments"===$n(function(){return arguments}()),or=Xn?$n:function(t){var e,i,o;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(i=function(t,e){try{return t[e]}catch(t){}}(e=er(t),tr))?i:ir?$n(e):"Object"===(o=$n(e))&&_n(e.callee)?"Arguments":o},nr=we,rr=Ni,sr=he(Function.toString);nr(rr.inspectSource)||(rr.inspectSource=function(t){return sr(t)});var ar=rr.inspectSource,lr=he,hr=_t,cr=we,dr=or,ur=ar,fr=function(){},pr=[],vr=$e("Reflect","construct"),gr=/^\s*(?:class|function)\b/,yr=lr(gr.exec),mr=!gr.test(fr),br=function(t){if(!cr(t))return!1;try{return vr(fr,pr,t),!0}catch(t){return!1}},wr=function(t){if(!cr(t))return!1;switch(dr(t)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}try{return mr||!!yr(gr,ur(t))}catch(t){return!0}};wr.sham=!0;var Ar=!vr||hr((function(){var t;return br(br.call)||!br(Object)||!br((function(){t=!0}))||t}))?wr:br,Er=zn,kr=Ar,Cr=qe,xr=ro("species"),Sr=Array,Ir=function(t){var e;return Er(t)&&(e=t.constructor,(kr(e)&&(e===Sr||Er(e.prototype))||Cr(e)&&null===(e=e[xr]))&&(e=void 0)),void 0===e?Sr:e},Mr=function(t,e){return new(Ir(t))(0===e?0:e)},Or=_t,Dr=li,Rr=ro("species"),Br=function(t){return Dr>=51||!Or((function(){var e=[];return(e.constructor={})[Rr]=function(){return{foo:1}},1!==e[t](Boolean).foo}))},zr=kn,Pr=_t,Fr=zn,Tr=qe,Nr=Hi,jr=Hn,Ur=Wn,Lr=Yn,Qr=Mr,Hr=Br,Vr=li,Wr=ro("isConcatSpreadable"),Gr=Vr>=51||!Pr((function(){var t=[];return t[Wr]=!1,t.concat()[0]!==t})),Kr=function(t){if(!Tr(t))return!1;var e=t[Wr];return void 0!==e?!!e:Fr(t)};zr({target:"Array",proto:!0,arity:1,forced:!Gr||!Hr("concat")},{concat:function(t){var e,i,o,n,r,s=Nr(this),a=Qr(s,0),l=0;for(e=-1,o=arguments.length;ea;)if((n=r[a++])!=n)return!0}else for(;s>a;a++)if((t||a in r)&&r[a]===i)return t||a||0;return!t&&-1}},rs={includes:ns(!0),indexOf:ns(!1)},ss={},as=Gi,ls=We,hs=rs.indexOf,cs=ss,ds=he([].push),us=function(t,e){var i,o=ls(t),n=0,r=[];for(i in o)!as(cs,i)&&as(o,i)&&ds(r,i);for(;e.length>n;)as(o,i=e[n++])&&(~hs(r,i)||ds(r,i));return r},fs=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],ps=us,vs=fs,gs=Object.keys||function(t){return ps(t,vs)},ys=Ee,ms=Ko,bs=Go,ws=Jo,As=We,Es=gs;Jr.f=ys&&!ms?Object.defineProperties:function(t,e){ws(t);for(var i,o=As(e),n=Es(e),r=n.length,s=0;r>s;)bs.f(t,i=n[s++],o[i]);return t};var ks,Cs=$e("document","documentElement"),xs=Ji,Ss=Ui("keys"),Is=function(t){return Ss[t]||(Ss[t]=xs(t))},Ms=Jo,Os=Jr,Ds=fs,Rs=ss,Bs=Cs,zs=wo,Ps="prototype",Fs="script",Ts=Is("IE_PROTO"),Ns=function(){},js=function(t){return"<"+Fs+">"+t+""},Us=function(t){t.write(js("")),t.close();var e=t.parentWindow.Object;return t=null,e},Ls=function(){try{ks=new ActiveXObject("htmlfile")}catch(t){}var t,e,i;Ls="undefined"!=typeof document?document.domain&&ks?Us(ks):(e=zs("iframe"),i="java"+Fs+":",e.style.display="none",Bs.appendChild(e),e.src=String(i),(t=e.contentWindow.document).open(),t.write(js("document.F=Object")),t.close(),t.F):Us(ks);for(var o=Ds.length;o--;)delete Ls[Ps][Ds[o]];return Ls()};Rs[Ts]=!0;var Qs=Object.create||function(t,e){var i;return null!==t?(Ns[Ps]=Ms(t),i=new Ns,Ns[Ps]=null,i[Ts]=t):i=Ls(),void 0===e?i:Os.f(i,e)},Hs={},Vs=us,Ws=fs.concat("length","prototype");Hs.f=Object.getOwnPropertyNames||function(t){return Vs(t,Ws)};var Gs={},Ks=ts,qs=Hn,Ys=Yn,Zs=Array,Js=Math.max,Xs=function(t,e,i){for(var o=qs(t),n=Ks(e,o),r=Ks(void 0===i?o:i,o),s=Zs(Js(r-n,0)),a=0;nm;m++)if((a||m in v)&&(f=g(u=v[m],m,p),t))if(e)w[m]=f;else if(f)switch(t){case 3:return!0;case 5:return u;case 6:return m;case 2:$a(w,u)}else switch(t){case 4:return!1;case 7:$a(w,u)}return r?-1:o||n?n:w}},el={forEach:tl(0),map:tl(1),filter:tl(2),some:tl(3),every:tl(4),find:tl(5),findIndex:tl(6),filterReject:tl(7)},il=kn,ol=Xt,nl=xe,rl=he,sl=Ee,al=ui,ll=_t,hl=Gi,cl=ti,dl=Jo,ul=We,fl=go,pl=Zr,vl=Be,gl=Qs,yl=gs,ml=Hs,bl=Gs,wl=oa,Al=Ae,El=Go,kl=Jr,Cl=Se,xl=ra,Sl=aa,Il=Ui,Ml=ss,Ol=Ji,Dl=ro,Rl=la,Bl=ya,zl=Ea,Pl=Ra,Fl=qa,Tl=el.forEach,Nl=Is("hidden"),jl="Symbol",Ul="prototype",Ll=Fl.set,Ql=Fl.getterFor(jl),Hl=Object[Ul],Vl=ol.Symbol,Wl=Vl&&Vl[Ul],Gl=ol.RangeError,Kl=ol.TypeError,ql=ol.QObject,Yl=Al.f,Zl=El.f,Jl=bl.f,Xl=Cl.f,_l=rl([].push),$l=Il("symbols"),th=Il("op-symbols"),eh=Il("wks"),ih=!ql||!ql[Ul]||!ql[Ul].findChild,oh=function(t,e,i){var o=Yl(Hl,e);o&&delete Hl[e],Zl(t,e,i),o&&t!==Hl&&Zl(Hl,e,o)},nh=sl&&ll((function(){return 7!==gl(Zl({},"a",{get:function(){return Zl(this,"a",{value:7}).a}})).a}))?oh:Zl,rh=function(t,e){var i=$l[t]=gl(Wl);return Ll(i,{type:jl,tag:t,description:e}),sl||(i.description=e),i},sh=function(t,e,i){t===Hl&&sh(th,e,i),dl(t);var o=fl(e);return dl(i),hl($l,o)?(i.enumerable?(hl(t,Nl)&&t[Nl][o]&&(t[Nl][o]=!1),i=gl(i,{enumerable:vl(0,!1)})):(hl(t,Nl)||Zl(t,Nl,vl(1,{})),t[Nl][o]=!0),nh(t,o,i)):Zl(t,o,i)},ah=function(t,e){dl(t);var i=ul(e),o=yl(i).concat(dh(i));return Tl(o,(function(e){sl&&!nl(lh,i,e)||sh(t,e,i[e])})),t},lh=function(t){var e=fl(t),i=nl(Xl,this,e);return!(this===Hl&&hl($l,e)&&!hl(th,e))&&(!(i||!hl(this,e)||!hl($l,e)||hl(this,Nl)&&this[Nl][e])||i)},hh=function(t,e){var i=ul(t),o=fl(e);if(i!==Hl||!hl($l,o)||hl(th,o)){var n=Yl(i,o);return!n||!hl($l,o)||hl(i,Nl)&&i[Nl][o]||(n.enumerable=!0),n}},ch=function(t){var e=Jl(ul(t)),i=[];return Tl(e,(function(t){hl($l,t)||hl(Ml,t)||_l(i,t)})),i},dh=function(t){var e=t===Hl,i=Jl(e?th:ul(t)),o=[];return Tl(i,(function(t){!hl($l,t)||e&&!hl(Hl,t)||_l(o,$l[t])})),o};al||(Vl=function(){if(cl(Wl,this))throw new Kl("Symbol is not a constructor");var t=arguments.length&&void 0!==arguments[0]?pl(arguments[0]):void 0,e=Ol(t),i=function(t){var o=void 0===this?ol:this;o===Hl&&nl(i,th,t),hl(o,Nl)&&hl(o[Nl],e)&&(o[Nl][e]=!1);var n=vl(1,t);try{nh(o,e,n)}catch(t){if(!(t instanceof Gl))throw t;oh(o,e,n)}};return sl&&ih&&nh(Hl,e,{configurable:!0,set:i}),rh(e,t)},xl(Wl=Vl[Ul],"toString",(function(){return Ql(this).tag})),xl(Vl,"withoutSetter",(function(t){return rh(Ol(t),t)})),Cl.f=lh,El.f=sh,kl.f=ah,Al.f=hh,ml.f=bl.f=ch,wl.f=dh,Rl.f=function(t){return rh(Dl(t),t)},sl&&Sl(Wl,"description",{configurable:!0,get:function(){return Ql(this).description}})),il({global:!0,constructor:!0,wrap:!0,forced:!al,sham:!al},{Symbol:Vl}),Tl(yl(eh),(function(t){Bl(t)})),il({target:jl,stat:!0,forced:!al},{useSetter:function(){ih=!0},useSimple:function(){ih=!1}}),il({target:"Object",stat:!0,forced:!al,sham:!sl},{create:function(t,e){return void 0===e?gl(t):ah(gl(t),e)},defineProperty:sh,defineProperties:ah,getOwnPropertyDescriptor:hh}),il({target:"Object",stat:!0,forced:!al},{getOwnPropertyNames:ch}),zl(),Pl(Vl,jl),Ml[Nl]=!0;var uh=ui&&!!Symbol.for&&!!Symbol.keyFor,fh=kn,ph=$e,vh=Gi,gh=Zr,yh=Ui,mh=uh,bh=yh("string-to-symbol-registry"),wh=yh("symbol-to-string-registry");fh({target:"Symbol",stat:!0,forced:!mh},{for:function(t){var e=gh(t);if(vh(bh,e))return bh[e];var i=ph("Symbol")(e);return bh[e]=i,wh[i]=e,i}});var Ah=kn,Eh=Gi,kh=mi,Ch=wi,xh=uh,Sh=Ui("symbol-to-string-registry");Ah({target:"Symbol",stat:!0,forced:!xh},{keyFor:function(t){if(!kh(t))throw new TypeError(Ch(t)+" is not a symbol");if(Eh(Sh,t))return Sh[t]}});var Ih=he([].slice),Mh=zn,Oh=we,Dh=fe,Rh=Zr,Bh=he([].push),zh=kn,Ph=$e,Fh=ne,Th=xe,Nh=he,jh=_t,Uh=we,Lh=mi,Qh=Ih,Hh=function(t){if(Oh(t))return t;if(Mh(t)){for(var e=t.length,i=[],o=0;o=e.length)return t.target=void 0,wd(void 0,!0);switch(t.kind){case"keys":return wd(i,!1);case"values":return wd(e[i],!1)}return wd([i,e[i]],!1)}),"values"),yd.Arguments=yd.Array;var Cd={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0},xd=Xt,Sd=or,Id=dn,Md=fc,Od=ro("toStringTag");for(var Dd in Cd){var Rd=xd[Dd],Bd=Rd&&Rd.prototype;Bd&&Sd(Bd)!==Od&&Id(Bd,Od,Dd),Md[Dd]=Md.Array}var zd=uc,Pd=ro,Fd=Go.f,Td=Pd("metadata"),Nd=Function.prototype;void 0===Nd[Td]&&Fd(Nd,Td,{value:null}),ya("asyncDispose"),ya("dispose"),ya("metadata");var jd=zd,Ud=he,Ld=$e("Symbol"),Qd=Ld.keyFor,Hd=Ud(Ld.prototype.valueOf),Vd=Ld.isRegisteredSymbol||function(t){try{return void 0!==Qd(Hd(t))}catch(t){return!1}};kn({target:"Symbol",stat:!0},{isRegisteredSymbol:Vd});for(var Wd=Ui,Gd=$e,Kd=he,qd=mi,Yd=ro,Zd=Gd("Symbol"),Jd=Zd.isWellKnownSymbol,Xd=Gd("Object","getOwnPropertyNames"),_d=Kd(Zd.prototype.valueOf),$d=Wd("wks"),tu=0,eu=Xd(Zd),iu=eu.length;tu=a?t?"":void 0:(o=uu(r,s))<55296||o>56319||s+1===a||(n=uu(r,s+1))<56320||n>57343?t?du(r,s):o:t?fu(r,s,s+2):n-56320+(o-55296<<10)+65536}},vu={codeAt:pu(!1),charAt:pu(!0)}.charAt,gu=Zr,yu=qa,mu=pd,bu=vd,wu="String Iterator",Au=yu.set,Eu=yu.getterFor(wu);mu(String,"String",(function(t){Au(this,{type:wu,string:gu(t),index:0})}),(function(){var t,e=Eu(this),i=e.string,o=e.index;return o>=i.length?bu(void 0,!0):(t=vu(i,o),e.index+=t.length,bu(t,!1))}));var ku=la.f("iterator"),Cu=ku,xu=Yt(Cu);function Su(t){return Su="function"==typeof su&&"symbol"==typeof xu?function(t){return typeof t}:function(t){return t&&"function"==typeof su&&t.constructor===su&&t!==su.prototype?"symbol":typeof t},Su(t)}var Iu=Yt(la.f("toPrimitive"));function Mu(t){var e=function(t,e){if("object"!==Su(t)||null===t)return t;var i=t[Iu];if(void 0!==i){var o=i.call(t,e||"default");if("object"!==Su(o))return o;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(t,"string");return"symbol"===Su(e)?e:String(e)}function Ou(t,e){for(var i=0;i=0:a>l;l+=h)l in s&&(n=i(n,s[l],l,r));return n}},af={left:sf(!1),right:sf(!0)},lf=_t,hf=function(t,e){var i=[][t];return!!i&&lf((function(){i.call(null,e||function(){return 1},1)}))},cf="process"===fe(Xt.process),df=af.left;kn({target:"Array",proto:!0,forced:!cf&&li>79&&li<83||!hf("reduce")},{reduce:function(t){var e=arguments.length;return df(this,t,e,e>1?arguments[1]:void 0)}});var uf=Ku("Array","reduce"),ff=ti,pf=uf,vf=Array.prototype,gf=function(t){var e=t.reduce;return t===vf||ff(vf,t)&&e===vf.reduce?pf:e},yf=Yt(gf),mf=el.filter;kn({target:"Array",proto:!0,forced:!Br("filter")},{filter:function(t){return mf(this,t,arguments.length>1?arguments[1]:void 0)}});var bf=Ku("Array","filter"),wf=ti,Af=bf,Ef=Array.prototype,kf=function(t){var e=t.filter;return t===Ef||wf(Ef,t)&&e===Ef.filter?Af:e},Cf=Yt(kf),xf=el.map;kn({target:"Array",proto:!0,forced:!Br("map")},{map:function(t){return xf(this,t,arguments.length>1?arguments[1]:void 0)}});var Sf=Ku("Array","map"),If=ti,Mf=Sf,Of=Array.prototype,Df=function(t){var e=t.map;return t===Of||If(Of,t)&&e===Of.map?Mf:e},Rf=Yt(Df),Bf=zn,zf=Hn,Pf=Wn,Ff=Wo,Tf=function(t,e,i,o,n,r,s,a){for(var l,h,c=n,d=0,u=!!s&&Ff(s,a);d0&&Bf(l)?(h=zf(l),c=Tf(t,e,l,h,c,r-1)-1):(Pf(c+1),t[c]=l),c++),d++;return c},Nf=Tf,jf=Ci,Uf=Hi,Lf=Hn,Qf=Mr;kn({target:"Array",proto:!0},{flatMap:function(t){var e,i=Uf(this),o=Lf(i);return jf(t),(e=Qf(i,0)).length=Nf(e,i,i,o,0,1,t,arguments.length>1?arguments[1]:void 0),e}}),Ku("Array","flatMap");var Hf=xe,Vf=Jo,Wf=Ii,Gf=function(t,e,i){var o,n;Vf(t);try{if(!(o=Wf(t,"return"))){if("throw"===e)throw i;return i}o=Hf(o,t)}catch(t){n=!0,o=t}if("throw"===e)throw i;if(n)throw o;return Vf(o),i},Kf=Jo,qf=Gf,Yf=fc,Zf=ro("iterator"),Jf=Array.prototype,Xf=function(t){return void 0!==t&&(Yf.Array===t||Jf[Zf]===t)},_f=or,$f=Ii,tp=je,ep=fc,ip=ro("iterator"),op=function(t){if(!tp(t))return $f(t,ip)||$f(t,"@@iterator")||ep[_f(t)]},np=xe,rp=Ci,sp=Jo,ap=wi,lp=op,hp=TypeError,cp=function(t,e){var i=arguments.length<2?lp(t):e;if(rp(i))return sp(np(i,t));throw new hp(ap(t)+" is not iterable")},dp=Wo,up=xe,fp=Hi,pp=function(t,e,i,o){try{return o?e(Kf(i)[0],i[1]):e(i)}catch(e){qf(t,"throw",e)}},vp=Xf,gp=Ar,yp=Hn,mp=Yn,bp=cp,wp=op,Ap=Array,Ep=ro("iterator"),kp=!1;try{var Cp=0,xp={next:function(){return{done:!!Cp++}},return:function(){kp=!0}};xp[Ep]=function(){return this},Array.from(xp,(function(){throw 2}))}catch(t){}var Sp=function(t,e){try{if(!e&&!kp)return!1}catch(t){return!1}var i=!1;try{var o={};o[Ep]=function(){return{next:function(){return{done:i=!0}}}},t(o)}catch(t){}return i},Ip=function(t){var e=fp(t),i=gp(this),o=arguments.length,n=o>1?arguments[1]:void 0,r=void 0!==n;r&&(n=dp(n,o>2?arguments[2]:void 0));var s,a,l,h,c,d,u=wp(e),f=0;if(!u||this===Ap&&vp(u))for(s=yp(e),a=i?new this(s):Ap(s);s>f;f++)d=r?n(e[f],f):e[f],mp(a,f,d);else for(c=(h=bp(e,u)).next,a=i?new this:[];!(l=up(c,h)).done;f++)d=r?pp(h,n,[l.value,f],!0):l.value,mp(a,f,d);return a.length=f,a};kn({target:"Array",stat:!0,forced:!Sp((function(t){Array.from(t)}))},{from:Ip});var Mp=Ye.Array.from,Op=Yt(Mp),Dp=op,Rp=Yt(Dp),Bp=Yt(Dp);kn({target:"Array",stat:!0},{isArray:zn});var zp=Ye.Array.isArray,Pp=Yt(zp);var Fp=Ee,Tp=zn,Np=TypeError,jp=Object.getOwnPropertyDescriptor,Up=Fp&&!function(){if(void 0!==this)return!0;try{Object.defineProperty([],"length",{writable:!1}).length=1}catch(t){return t instanceof TypeError}}()?function(t,e){if(Tp(t)&&!jp(t,"length").writable)throw new Np("Cannot set read only .length");return t.length=e}:function(t,e){return t.length=e},Lp=Hi,Qp=Hn,Hp=Up,Vp=Wn;kn({target:"Array",proto:!0,arity:1,forced:_t((function(){return 4294967297!==[].push.call({length:4294967296},1)}))||!function(){try{Object.defineProperty([],"length",{writable:!1}).push()}catch(t){return t instanceof TypeError}}()},{push:function(t){var e=Lp(this),i=Qp(e),o=arguments.length;Vp(i+o);for(var n=0;nt.length)&&(e=t.length);for(var i=0,o=new Array(e);i1?arguments[1]:void 0)};kn({target:"Array",proto:!0,forced:[].forEach!==Wv},{forEach:Wv});var Gv=Ku("Array","forEach"),Kv=or,qv=Gi,Yv=ti,Zv=Gv,Jv=Array.prototype,Xv={DOMTokenList:!0,NodeList:!0},_v=function(t){var e=t.forEach;return t===Jv||Yv(Jv,t)&&e===Jv.forEach||qv(Xv,Kv(t))?Zv:e},$v=Yt(_v),tg=kn,eg=zn,ig=he([].reverse),og=[1,2];tg({target:"Array",proto:!0,forced:String(og)===String(og.reverse())},{reverse:function(){return eg(this)&&(this.length=this.length),ig(this)}});var ng=Ku("Array","reverse"),rg=ti,sg=ng,ag=Array.prototype,lg=function(t){var e=t.reverse;return t===ag||rg(ag,t)&&e===ag.reverse?sg:e},hg=lg,cg=Yt(hg),dg=wi,ug=TypeError,fg=function(t,e){if(!delete t[e])throw new ug("Cannot delete property "+dg(e)+" of "+dg(t))},pg=kn,vg=Hi,gg=ts,yg=jn,mg=Hn,bg=Up,wg=Wn,Ag=Mr,Eg=Yn,kg=fg,Cg=Br("splice"),xg=Math.max,Sg=Math.min;pg({target:"Array",proto:!0,forced:!Cg},{splice:function(t,e){var i,o,n,r,s,a,l=vg(this),h=mg(l),c=gg(t,h),d=arguments.length;for(0===d?i=o=0:1===d?(i=0,o=h-c):(i=d-2,o=Sg(xg(yg(e),0),h-c)),wg(h+i-o),n=Ag(l,o),r=0;rh-o+i;r--)kg(l,r-1)}else if(i>o)for(r=h-o;r>c;r--)a=r+i-1,(s=r+o-1)in l?l[a]=l[s]:kg(l,a);for(r=0;rn;)for(var a,l=Qg(arguments[n++]),h=r?Wg(Ng(l),r(l)):Ng(l),c=h.length,d=0;c>d;)a=h[d++],zg&&!Fg(s,l,a)||(i[a]=l[a]);return i}:Hg,Kg=Gg;kn({target:"Object",stat:!0,arity:2,forced:Object.assign!==Kg},{assign:Kg});var qg=Yt(Ye.Object.assign),Yg=Hi,Zg=Mc,Jg=wc;kn({target:"Object",stat:!0,forced:_t((function(){Zg(1)})),sham:!Jg},{getPrototypeOf:function(t){return Zg(Yg(t))}});var Xg=Ye.Object.getPrototypeOf;kn({target:"Object",stat:!0,sham:!Ee},{create:Qs});var _g=Ye.Object,$g=function(t,e){return _g.create(t,e)},ty=$g,ey=Yt(ty),iy=Ye,oy=ne;iy.JSON||(iy.JSON={stringify:JSON.stringify});var ny=function(t,e,i){return oy(iy.JSON.stringify,null,arguments)},ry=Yt(ny),sy="function"==typeof Bun&&Bun&&"string"==typeof Bun.version,ay=TypeError,ly=function(t,e){if(ti,s=dy(o)?o:gy(o),a=r?py(arguments,i):[],l=r?function(){cy(s,this,a)}:s;return e?t(l,n):t(l)}:t},by=kn,wy=Xt,Ay=my(wy.setInterval,!0);by({global:!0,bind:!0,forced:wy.setInterval!==Ay},{setInterval:Ay});var Ey=kn,ky=Xt,Cy=my(ky.setTimeout,!0);Ey({global:!0,bind:!0,forced:ky.setTimeout!==Cy},{setTimeout:Cy});var xy=Yt(Ye.setTimeout),Sy={exports:{}};!function(t){function e(t){if(t)return function(t){return Object.assign(t,e.prototype),t._callbacks=new Map,t}(t);this._callbacks=new Map}e.prototype.on=function(t,e){const i=this._callbacks.get(t)??[];return i.push(e),this._callbacks.set(t,i),this},e.prototype.once=function(t,e){const i=(...o)=>{this.off(t,i),e.apply(this,o)};return i.fn=e,this.on(t,i),this},e.prototype.off=function(t,e){if(void 0===t&&void 0===e)return this._callbacks.clear(),this;if(void 0===e)return this._callbacks.delete(t),this;const i=this._callbacks.get(t);if(i){for(const[t,o]of i.entries())if(o===e||o.fn===e){i.splice(t,1);break}0===i.length?this._callbacks.delete(t):this._callbacks.set(t,i)}return this},e.prototype.emit=function(t,...e){const i=this._callbacks.get(t);if(i){const t=[...i];for(const i of t)i.apply(this,e)}return this},e.prototype.listeners=function(t){return this._callbacks.get(t)??[]},e.prototype.listenerCount=function(t){if(t)return this.listeners(t).length;let e=0;for(const t of this._callbacks.values())e+=t.length;return e},e.prototype.hasListeners=function(t){return this.listenerCount(t)>0},e.prototype.addEventListener=e.prototype.on,e.prototype.removeListener=e.prototype.off,e.prototype.removeEventListener=e.prototype.off,e.prototype.removeAllListeners=e.prototype.off,t.exports=e}(Sy);var Iy,My=Yt(Sy.exports); /*! Hammer.JS - v2.0.17-rc - 2019-12-16 * http://naver.github.io/egjs * * Forked By Naver egjs * Copyright (c) hammerjs * Licensed under the MIT license */ -function _x(){return _x=Object.assign||function(t){for(var e=1;e-1}var l_=function(){function t(t,e){this.manager=t,this.set(e)}var e=t.prototype;return e.set=function(t){t===Mx&&(t=this.compute()),Dx&&this.manager.element.style&&jx[t]&&(this.manager.element.style[Px]=t),this.actions=t.toLowerCase().trim()},e.update=function(){this.set(this.manager.options.touchAction)},e.compute=function(){var t=[];return s_(this.manager.recognizers,(function(e){a_(e.options.enable,[e])&&(t=t.concat(e.getTouchAction()))})),function(t){if(d_(t,Bx))return Bx;var e=d_(t,Lx),i=d_(t,zx);return e&&i?Bx:e||i?e?Lx:zx:d_(t,Nx)?Nx:Fx}(t.join(" "))},e.preventDefaults=function(t){var e=t.srcEvent,i=t.offsetDirection;if(this.manager.session.prevented)e.preventDefault();else{var n=this.actions,o=d_(n,Bx)&&!jx[Bx],r=d_(n,zx)&&!jx[zx],s=d_(n,Lx)&&!jx[Lx];if(o){var a=1===t.pointers.length,d=t.distance<2,l=t.deltaTime<250;if(a&&d&&l)return}if(!s||!r)return o||r&&i&e_||s&&i&i_?this.preventSrc(e):void 0}},e.preventSrc=function(t){this.manager.session.prevented=!0,t.preventDefault()},t}();function c_(t,e){for(;t;){if(t===e)return!0;t=t.parentNode}return!1}function h_(t){var e=t.length;if(1===e)return{x:Tx(t[0].clientX),y:Tx(t[0].clientY)};for(var i=0,n=0,o=0;o=Ix(e)?t<0?Zx:Qx:e<0?Jx:t_}function v_(t,e,i){return{x:e/t||0,y:i/t||0}}function g_(t,e){var i=t.session,n=e.pointers,o=n.length;i.firstInput||(i.firstInput=u_(e)),o>1&&!i.firstMultiple?i.firstMultiple=u_(e):1===o&&(i.firstMultiple=!1);var r=i.firstInput,s=i.firstMultiple,a=s?s.center:r.center,d=e.center=h_(n);e.timeStamp=Ax(),e.deltaTime=e.timeStamp-r.timeStamp,e.angle=f_(a,d),e.distance=p_(a,d),function(t,e){var i=e.center,n=t.offsetDelta||{},o=t.prevDelta||{},r=t.prevInput||{};e.eventType!==Xx&&r.eventType!==Yx||(o=t.prevDelta={x:r.deltaX||0,y:r.deltaY||0},n=t.offsetDelta={x:i.x,y:i.y}),e.deltaX=o.x+(i.x-n.x),e.deltaY=o.y+(i.y-n.y)}(i,e),e.offsetDirection=m_(e.deltaX,e.deltaY);var l,c,h=v_(e.deltaTime,e.deltaX,e.deltaY);e.overallVelocityX=h.x,e.overallVelocityY=h.y,e.overallVelocity=Ix(h.x)>Ix(h.y)?h.x:h.y,e.scale=s?(l=s.pointers,p_((c=n)[0],c[1],r_)/p_(l[0],l[1],r_)):1,e.rotation=s?function(t,e){return f_(e[1],e[0],r_)+f_(t[1],t[0],r_)}(s.pointers,n):0,e.maxPointers=i.prevInput?e.pointers.length>i.prevInput.maxPointers?e.pointers.length:i.prevInput.maxPointers:e.pointers.length,function(t,e){var i,n,o,r,s=t.lastInterval||e,a=e.timeStamp-s.timeStamp;if(e.eventType!==Gx&&(a>qx||void 0===s.velocity)){var d=e.deltaX-s.deltaX,l=e.deltaY-s.deltaY,c=v_(a,d,l);n=c.x,o=c.y,i=Ix(c.x)>Ix(c.y)?c.x:c.y,r=m_(d,l),t.lastInterval=e}else i=s.velocity,n=s.velocityX,o=s.velocityY,r=s.direction;e.velocity=i,e.velocityX=n,e.velocityY=o,e.direction=r}(i,e);var u,p=t.element,f=e.srcEvent;c_(u=f.composedPath?f.composedPath()[0]:f.path?f.path[0]:f.target,p)&&(p=u),e.target=p}function y_(t,e,i){var n=i.pointers.length,o=i.changedPointers.length,r=e&Xx&&n-o==0,s=e&(Yx|Gx)&&n-o==0;i.isFirst=!!r,i.isFinal=!!s,r&&(t.session={}),i.eventType=e,g_(t,i),t.emit("hammer.input",i),t.recognize(i),t.session.prevInput=i}function b_(t){return t.trim().split(/\s+/g)}function x_(t,e,i){s_(b_(e),(function(e){t.addEventListener(e,i,!1)}))}function __(t,e,i){s_(b_(e),(function(e){t.removeEventListener(e,i,!1)}))}function w_(t){var e=t.ownerDocument||t;return e.defaultView||e.parentWindow||window}var E_=function(){function t(t,e){var i=this;this.manager=t,this.callback=e,this.element=t.element,this.target=t.options.inputTarget,this.domHandler=function(e){a_(t.options.enable,[t])&&i.handler(e)},this.init()}var e=t.prototype;return e.handler=function(){},e.init=function(){this.evEl&&x_(this.element,this.evEl,this.domHandler),this.evTarget&&x_(this.target,this.evTarget,this.domHandler),this.evWin&&x_(w_(this.element),this.evWin,this.domHandler)},e.destroy=function(){this.evEl&&__(this.element,this.evEl,this.domHandler),this.evTarget&&__(this.target,this.evTarget,this.domHandler),this.evWin&&__(w_(this.element),this.evWin,this.domHandler)},t}();function k_(t,e,i){if(t.indexOf&&!i)return t.indexOf(e);for(var n=0;ni[e]})):n.sort()),n}var P_={touchstart:Xx,touchmove:2,touchend:Yx,touchcancel:Gx},D_=function(t){function e(){var i;return e.prototype.evTarget="touchstart touchmove touchend touchcancel",(i=t.apply(this,arguments)||this).targetIds={},i}return wx(e,t),e.prototype.handler=function(t){var e=P_[t.type],i=M_.call(this,t,e);i&&this.callback(this.manager,e,{pointers:i[0],changedPointers:i[1],pointerType:Wx,srcEvent:t})},e}(E_);function M_(t,e){var i,n,o=A_(t.touches),r=this.targetIds;if(e&(2|Xx)&&1===o.length)return r[o[0].identifier]=!0,[o,o];var s=A_(t.changedTouches),a=[],d=this.target;if(n=o.filter((function(t){return c_(t.target,d)})),e===Xx)for(i=0;i-1&&n.splice(t,1)}),B_)}}function z_(t,e){t&Xx?(this.primaryTouch=e.changedPointers[0].identifier,L_.call(this,e)):t&(Yx|Gx)&&L_.call(this,e)}function j_(t){for(var e=t.srcEvent.clientX,i=t.srcEvent.clientY,n=0;n-1&&this.requireFail.splice(e,1),this},e.hasRequireFailures=function(){return this.requireFail.length>0},e.canRecognizeWith=function(t){return!!this.simultaneous[t.id]},e.emit=function(t){var e=this,i=this.state;function n(i){e.manager.emit(i,t)}i<8&&n(e.options.event+q_(i)),n(e.options.event),t.additionalEvent&&n(t.additionalEvent),i>=8&&n(e.options.event+q_(i))},e.tryEmit=function(t){if(this.canEmit())return this.emit(t);this.state=U_},e.canEmit=function(){for(var t=0;te.threshold&&o&e.direction},i.attrTest=function(t){return G_.prototype.attrTest.call(this,t)&&(2&this.state||!(2&this.state)&&this.directionTest(t))},i.emit=function(e){this.pX=e.deltaX,this.pY=e.deltaY;var i=K_(e.direction);i&&(e.additionalEvent=this.options.event+i),t.prototype.emit.call(this,e)},e}(G_),Q_=function(t){function e(e){return void 0===e&&(e={}),t.call(this,_x({event:"swipe",threshold:10,velocity:.3,direction:e_|i_,pointers:1},e))||this}wx(e,t);var i=e.prototype;return i.getTouchAction=function(){return Z_.prototype.getTouchAction.call(this)},i.attrTest=function(e){var i,n=this.options.direction;return n&(e_|i_)?i=e.overallVelocity:n&e_?i=e.overallVelocityX:n&i_&&(i=e.overallVelocityY),t.prototype.attrTest.call(this,e)&&n&e.offsetDirection&&e.distance>this.options.threshold&&e.maxPointers===this.options.pointers&&Ix(i)>this.options.velocity&&e.eventType&Yx},i.emit=function(t){var e=K_(t.offsetDirection);e&&this.manager.emit(this.options.event+e,t),this.manager.emit(this.options.event,t)},e}(G_),J_=function(t){function e(e){return void 0===e&&(e={}),t.call(this,_x({event:"pinch",threshold:0,pointers:2},e))||this}wx(e,t);var i=e.prototype;return i.getTouchAction=function(){return[Bx]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.scale-1)>this.options.threshold||2&this.state)},i.emit=function(e){if(1!==e.scale){var i=e.scale<1?"in":"out";e.additionalEvent=this.options.event+i}t.prototype.emit.call(this,e)},e}(G_),tw=function(t){function e(e){return void 0===e&&(e={}),t.call(this,_x({event:"rotate",threshold:0,pointers:2},e))||this}wx(e,t);var i=e.prototype;return i.getTouchAction=function(){return[Bx]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.rotation)>this.options.threshold||2&this.state)},e}(G_),ew=function(t){function e(e){var i;return void 0===e&&(e={}),(i=t.call(this,_x({event:"press",pointers:1,time:251,threshold:9},e))||this)._timer=null,i._input=null,i}wx(e,t);var i=e.prototype;return i.getTouchAction=function(){return[Fx]},i.process=function(t){var e=this,i=this.options,n=t.pointers.length===i.pointers,o=t.distancei.time;if(this._input=t,!o||!n||t.eventType&(Yx|Gx)&&!r)this.reset();else if(t.eventType&Xx)this.reset(),this._timer=setTimeout((function(){e.state=8,e.tryEmit()}),i.time);else if(t.eventType&Yx)return 8;return U_},i.reset=function(){clearTimeout(this._timer)},i.emit=function(t){8===this.state&&(t&&t.eventType&Yx?this.manager.emit(this.options.event+"up",t):(this._input.timeStamp=Ax(),this.manager.emit(this.options.event,this._input)))},e}(X_),iw={domEvents:!1,touchAction:Mx,enable:!0,inputTarget:null,inputClass:null,cssProps:{userSelect:"none",touchSelect:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}},nw=[[tw,{enable:!1}],[J_,{enable:!1},["rotate"]],[Q_,{direction:e_}],[Z_,{direction:e_},["swipe"]],[Y_],[Y_,{event:"doubletap",taps:2},["tap"]],[ew]];function ow(t,e){var i,n=t.element;n.style&&(s_(t.options.cssProps,(function(o,r){i=Rx(n.style,r),e?(t.oldCssProps[i]=n.style[i],n.style[i]=o):n.style[i]=t.oldCssProps[i]||""})),e||(t.oldCssProps={}))}var rw=function(){function t(t,e){var i,n=this;this.options=Ox({},iw,e||{}),this.options.inputTarget=this.options.inputTarget||t,this.handlers={},this.session={},this.recognizers=[],this.oldCssProps={},this.element=t,this.input=new((i=this).options.inputClass||($x?I_:Ux?D_:Hx?H_:N_))(i,y_),this.touchAction=new l_(this,this.options.touchAction),ow(this,!0),s_(this.options.recognizers,(function(t){var e=n.add(new t[0](t[1]));t[2]&&e.recognizeWith(t[2]),t[3]&&e.requireFailure(t[3])}),this)}var e=t.prototype;return e.set=function(t){return Ox(this.options,t),t.touchAction&&this.touchAction.update(),t.inputTarget&&(this.input.destroy(),this.input.target=t.inputTarget,this.input.init()),this},e.stop=function(t){this.session.stopped=t?2:1},e.recognize=function(t){var e=this.session;if(!e.stopped){var i;this.touchAction.preventDefaults(t);var n=this.recognizers,o=e.curRecognizer;(!o||o&&8&o.state)&&(e.curRecognizer=null,o=null);for(var r=0;r\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",o=window.console&&(window.console.warn||window.console.log);return o&&o.call(window.console,n,i),t.apply(this,arguments)}}var cw=lw((function(t,e,i){for(var n=Object.keys(e),o=0;o=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function gw(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i2)return xw.apply(void 0,wy(n=[bw(e[0],e[1])]).call(n,my(Ey(e).call(e,2))));var o=e[0],r=e[1];if(o instanceof Date&&r instanceof Date)return o.setTime(r.getTime()),o;var s,a=vw(Ay(r));try{for(a.s();!(s=a.n()).done;){var d=s.value;Object.prototype.propertyIsEnumerable.call(r,d)&&(r[d]===yw?delete o[d]:null===o[d]||null===r[d]||"object"!=typeof o[d]||"object"!=typeof r[d]||Ry(o[d])||Ry(r[d])?o[d]=_w(r[d]):o[d]=xw(o[d],r[d]))}}catch(t){a.e(t)}finally{a.f()}return o}function _w(t){return Ry(t)?Ev(t).call(t,(function(t){return _w(t)})):"object"==typeof t&&null!==t?t instanceof Date?new Date(t.getTime()):xw({},t):t}function ww(t){for(var e=0,i=My(t);e({set:t})}}()};function kw(t){var e,i=this;this._cleanupQueue=[],this.active=!1,this._dom={container:t,overlay:document.createElement("div")},this._dom.overlay.classList.add("vis-overlay"),this._dom.container.appendChild(this._dom.overlay),this._cleanupQueue.push((function(){i._dom.overlay.parentNode.removeChild(i._dom.overlay)}));var n=Ew(this._dom.overlay);n.on("tap",qm(e=this._onTapOverlay).call(e,this)),this._cleanupQueue.push((function(){n.destroy()}));var o=["tap","doubletap","press","pinch","pan","panstart","panmove","panend"];Vy(o).call(o,(function(t){n.on(t,(function(t){t.srcEvent.stopPropagation()}))})),document&&document.body&&(this._onClick=function(e){(function(t,e){for(;t;){if(t===e)return!0;t=t.parentNode}return!1})(e.target,t)||i.deactivate()},document.body.addEventListener("click",this._onClick),this._cleanupQueue.push((function(){document.body.removeEventListener("click",i._onClick)}))),this._escListener=function(t){("key"in t?"Escape"===t.key:27===t.keyCode)&&i.deactivate()}}xx(kw.prototype),kw.current=null,kw.prototype.destroy=function(){var t,e;this.deactivate();var i,n=vw(ib(t=kb(e=this._cleanupQueue).call(e,0)).call(t));try{for(n.s();!(i=n.n()).done;){(0,i.value)()}}catch(t){n.e(t)}finally{n.f()}},kw.prototype.activate=function(){kw.current&&kw.current.deactivate(),kw.current=this,this.active=!0,this._dom.overlay.style.display="none",this._dom.container.classList.add("vis-active"),this.emit("change"),this.emit("activate"),document.body.addEventListener("keydown",this._escListener)},kw.prototype.deactivate=function(){this.active=!1,this._dom.overlay.style.display="block",this._dom.container.classList.remove("vis-active"),document.body.removeEventListener("keydown",this._escListener),this.emit("change"),this.emit("deactivate")},kw.prototype._onTapOverlay=function(t){this.activate(),t.srcEvent.stopPropagation()};var Ow=pd,Cw=fr,Sw=TypeError,Tw=function(t){if(Ow(t))return t;throw new Sw(Cw(t)+" is not a constructor")},Iw=ma,Aw=Zn,Rw=Fm,Pw=Tw,Dw=Us,Mw=Ho,Fw=Dl,Nw=Vn,Bw=Xo("Reflect","construct"),Lw=Object.prototype,zw=[].push,jw=Nw((function(){function t(){}return!(Bw((function(){}),[],t)instanceof t)})),Hw=!Nw((function(){Bw((function(){}))})),$w=jw||Hw;Iw({target:"Reflect",stat:!0,forced:$w,sham:$w},{construct:function(t,e){Pw(t),Dw(e);var i=arguments.length<3?t:Pw(arguments[2]);if(Hw&&!jw)return Bw(t,e,i);if(t===i){switch(e.length){case 0:return new t;case 1:return new t(e[0]);case 2:return new t(e[0],e[1]);case 3:return new t(e[0],e[1],e[2]);case 4:return new t(e[0],e[1],e[2],e[3])}var n=[null];return Aw(zw,n,e),new(Aw(Rw,t,n))}var o=i.prototype,r=Fw(Mw(o)?o:Lw),s=Aw(t,r,e);return Mw(s)?s:r}});var Uw=Hn($o.Reflect.construct),Ww=Hn($o.Object.getOwnPropertySymbols),Vw={exports:{}},qw=ma,Xw=Vn,Yw=Lo,Gw=mo.f,Kw=vo;qw({target:"Object",stat:!0,forced:!Kw||Xw((function(){Gw(1)})),sham:!Kw},{getOwnPropertyDescriptor:function(t,e){return Gw(Yw(t),e)}});var Zw=$o.Object,Qw=Vw.exports=function(t,e){return Zw.getOwnPropertyDescriptor(t,e)};Zw.getOwnPropertyDescriptor.sham&&(Qw.sham=!0);var Jw=Hn(Vw.exports),tE=Iy,eE=Lo,iE=mo,nE=ja;ma({target:"Object",stat:!0,sham:!vo},{getOwnPropertyDescriptors:function(t){for(var e,i,n=eE(t),o=iE.f,r=tE(n),s={},a=0;r.length>a;)void 0!==(i=o(n,e=r[a++]))&&nE(s,e,i);return s}});var oE=Hn($o.Object.getOwnPropertyDescriptors),rE={exports:{}},sE=ma,aE=vo,dE=$d.f;sE({target:"Object",stat:!0,forced:Object.defineProperties!==dE,sham:!aE},{defineProperties:dE});var lE=$o.Object,cE=rE.exports=function(t,e){return lE.defineProperties(t,e)};lE.defineProperties.sham&&(cE.sham=!0);var hE=Hn(rE.exports),uE=Hn(_a);function pE(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}var fE=qb,mE=Hn(fE);ma({target:"Object",stat:!0},{setPrototypeOf:Vp});var vE=$o.Object.setPrototypeOf,gE=Hn(vE),yE=Hn(Vm);function bE(t,e){var i;return bE=gE?yE(i=gE).call(i):function(t,e){return t.__proto__=e,t},bE(t,e)}var xE=Ub,_E=Hn(xE);function wE(t){var e;return wE=gE?yE(e=_E).call(e):function(t){return t.__proto__||_E(t)},wE(t)}var EE={exports:{}},kE={exports:{}};!function(t){var e=Qf,i=gm;function n(o){return t.exports=n="function"==typeof e&&"symbol"==typeof i?function(t){return typeof t}:function(t){return t&&"function"==typeof e&&t.constructor===e&&t!==e.prototype?"symbol":typeof t},t.exports.__esModule=!0,t.exports.default=t.exports,n(o)}t.exports=n,t.exports.__esModule=!0,t.exports.default=t.exports}(kE);var OE=kE.exports,CE=Wy,SE=zr,TE=Iy,IE=mo,AE=Ls,RE=Ho,PE=na,DE=Error,ME=io("".replace),FE=String(new DE("zxcasd").stack),NE=/\n\s*at [^:]*:[^\n]*/,BE=NE.test(FE),LE=Co,zE=!Vn((function(){var t=new Error("a");return!("stack"in t)||(Object.defineProperty(t,"stack",LE(1,7)),7!==t.stack)})),jE=na,HE=function(t,e){if(BE&&"string"==typeof t&&!DE.prepareStackTrace)for(;e--;)t=ME(t,NE,"");return t},$E=zE,UE=Error.captureStackTrace,WE=Bs,VE=bo,qE=Us,XE=fr,YE=Uv,GE=Ma,KE=Yo,ZE=ig,QE=Gv,JE=Bv,tk=TypeError,ek=function(t,e){this.stopped=t,this.result=e},ik=ek.prototype,nk=function(t,e,i){var n,o,r,s,a,d,l,c=i&&i.that,h=!(!i||!i.AS_ENTRIES),u=!(!i||!i.IS_RECORD),p=!(!i||!i.IS_ITERATOR),f=!(!i||!i.INTERRUPTED),m=WE(e,c),v=function(t){return n&&JE(n,"normal",t),new ek(!0,t)},g=function(t){return h?(qE(t),f?m(t[0],t[1],v):m(t[0],t[1])):f?m(t,v):m(t)};if(u)n=t.iterator;else if(p)n=t;else{if(!(o=QE(t)))throw new tk(XE(t)+" is not iterable");if(YE(o)){for(r=0,s=GE(t);s>r;r++)if((a=g(t[r]))&&KE(ik,a))return a;return new ek(!1)}n=ZE(t,o)}for(d=u?t.next:n.next;!(l=VE(d,n)).done;){try{a=g(l.value)}catch(t){JE(n,"throw",t)}if("object"==typeof a&&a&&KE(ik,a))return a}return new ek(!1)},ok=Hd,rk=ma,sk=Yo,ak=xp,dk=Vp,lk=function(t,e,i){for(var n=TE(e),o=AE.f,r=IE.f,s=0;s2&&pk(i,arguments[2]);var o=[];return mk(t,bk,{that:o}),hk(i,"errors",o),i};dk?dk(xk,yk):lk(xk,yk,{name:!0});var _k=xk.prototype=ck(yk.prototype,{constructor:uk(1,xk),message:uk(1,""),name:uk(1,"AggregateError")});rk({global:!0,constructor:!0,arity:2},{AggregateError:xk});var wk,Ek,kk,Ok,Ck=Xo,Sk=Jl,Tk=vo,Ik=Jr("species"),Ak=function(t){var e=Ck(t);Tk&&e&&!e[Ik]&&Sk(e,Ik,{configurable:!0,get:function(){return this}})},Rk=Yo,Pk=TypeError,Dk=function(t,e){if(Rk(e,t))return t;throw new Pk("Incorrect invocation")},Mk=Us,Fk=Tw,Nk=Po,Bk=Jr("species"),Lk=function(t,e){var i,n=Mk(t).constructor;return void 0===n||Nk(i=Mk(n)[Bk])?e:Fk(i)},zk=/(?:ipad|iphone|ipod).*applewebkit/i.test(Go),jk=Wn,Hk=Zn,$k=Bs,Uk=fo,Wk=zr,Vk=Vn,qk=vl,Xk=bu,Yk=ps,Gk=tx,Kk=zk,Zk=iv,Qk=jk.setImmediate,Jk=jk.clearImmediate,tO=jk.process,eO=jk.Dispatch,iO=jk.Function,nO=jk.MessageChannel,oO=jk.String,rO=0,sO={},aO="onreadystatechange";Vk((function(){wk=jk.location}));var dO=function(t){if(Wk(sO,t)){var e=sO[t];delete sO[t],e()}},lO=function(t){return function(){dO(t)}},cO=function(t){dO(t.data)},hO=function(t){jk.postMessage(oO(t),wk.protocol+"//"+wk.host)};Qk&&Jk||(Qk=function(t){Gk(arguments.length,1);var e=Uk(t)?t:iO(t),i=Xk(arguments,1);return sO[++rO]=function(){Hk(e,void 0,i)},Ek(rO),rO},Jk=function(t){delete sO[t]},Zk?Ek=function(t){tO.nextTick(lO(t))}:eO&&eO.now?Ek=function(t){eO.now(lO(t))}:nO&&!Kk?(Ok=(kk=new nO).port2,kk.port1.onmessage=cO,Ek=$k(Ok.postMessage,Ok)):jk.addEventListener&&Uk(jk.postMessage)&&!jk.importScripts&&wk&&"file:"!==wk.protocol&&!Vk(hO)?(Ek=hO,jk.addEventListener("message",cO,!1)):Ek=aO in Yk("script")?function(t){qk.appendChild(Yk("script"))[aO]=function(){qk.removeChild(this),dO(t)}}:function(t){setTimeout(lO(t),0)});var uO={set:Qk,clear:Jk},pO=function(){this.head=null,this.tail=null};pO.prototype={add:function(t){var e={item:t,next:null},i=this.tail;i?i.next=e:this.head=e,this.tail=e},get:function(){var t=this.head;if(t)return null===(this.head=t.next)&&(this.tail=null),t.item}};var fO,mO,vO,gO,yO,bO=pO,xO=/ipad|iphone|ipod/i.test(Go)&&"undefined"!=typeof Pebble,_O=/web0s(?!.*chrome)/i.test(Go),wO=Wn,EO=Bs,kO=mo.f,OO=uO.set,CO=bO,SO=zk,TO=xO,IO=_O,AO=iv,RO=wO.MutationObserver||wO.WebKitMutationObserver,PO=wO.document,DO=wO.process,MO=wO.Promise,FO=kO(wO,"queueMicrotask"),NO=FO&&FO.value;if(!NO){var BO=new CO,LO=function(){var t,e;for(AO&&(t=DO.domain)&&t.exit();e=BO.get();)try{e()}catch(t){throw BO.head&&fO(),t}t&&t.enter()};SO||AO||IO||!RO||!PO?!TO&&MO&&MO.resolve?((gO=MO.resolve(void 0)).constructor=MO,yO=EO(gO.then,gO),fO=function(){yO(LO)}):AO?fO=function(){DO.nextTick(LO)}:(OO=EO(OO,wO),fO=function(){OO(LO)}):(mO=!0,vO=PO.createTextNode(""),new RO(LO).observe(vO,{characterData:!0}),fO=function(){vO.data=mO=!mO}),NO=function(t){BO.head||fO(),BO.add(t)}}var zO=NO,jO=function(t){try{return{error:!1,value:t()}}catch(t){return{error:!0,value:t}}},HO=Wn.Promise,$O="object"==typeof Deno&&Deno&&"object"==typeof Deno.version,UO=!$O&&!iv&&"object"==typeof window&&"object"==typeof document,WO=Wn,VO=HO,qO=fo,XO=Ds,YO=Ja,GO=Jr,KO=UO,ZO=$O,QO=ir,JO=VO&&VO.prototype,tC=GO("species"),eC=!1,iC=qO(WO.PromiseRejectionEvent),nC=XO("Promise",(function(){var t=YO(VO),e=t!==String(VO);if(!e&&66===QO)return!0;if(!JO.catch||!JO.finally)return!0;if(!QO||QO<51||!/native code/.test(t)){var i=new VO((function(t){t(1)})),n=function(t){t((function(){}),(function(){}))};if((i.constructor={})[tC]=n,!(eC=i.then((function(){}))instanceof n))return!0}return!e&&(KO||ZO)&&!iC})),oC={CONSTRUCTOR:nC,REJECTION_EVENT:iC,SUBCLASSING:eC},rC={},sC=yr,aC=TypeError,dC=function(t){var e,i;this.promise=new t((function(t,n){if(void 0!==e||void 0!==i)throw new aC("Bad Promise constructor");e=t,i=n})),this.resolve=sC(e),this.reject=sC(i)};rC.f=function(t){return new dC(t)};var lC,cC,hC=ma,uC=iv,pC=Wn,fC=bo,mC=Zl,vC=Ec,gC=Ak,yC=yr,bC=fo,xC=Ho,_C=Dk,wC=Lk,EC=uO.set,kC=zO,OC=function(t,e){try{1===arguments.length?console.error(t):console.error(t,e)}catch(t){}},CC=jO,SC=bO,TC=zc,IC=HO,AC=rC,RC="Promise",PC=oC.CONSTRUCTOR,DC=oC.REJECTION_EVENT,MC=TC.getterFor(RC),FC=TC.set,NC=IC&&IC.prototype,BC=IC,LC=NC,zC=pC.TypeError,jC=pC.document,HC=pC.process,$C=AC.f,UC=$C,WC=!!(jC&&jC.createEvent&&pC.dispatchEvent),VC="unhandledrejection",qC=function(t){var e;return!(!xC(t)||!bC(e=t.then))&&e},XC=function(t,e){var i,n,o,r=e.value,s=1===e.state,a=s?t.ok:t.fail,d=t.resolve,l=t.reject,c=t.domain;try{a?(s||(2===e.rejection&&QC(e),e.rejection=1),!0===a?i=r:(c&&c.enter(),i=a(r),c&&(c.exit(),o=!0)),i===t.promise?l(new zC("Promise-chain cycle")):(n=qC(i))?fC(n,i,d,l):d(i)):l(r)}catch(t){c&&!o&&c.exit(),l(t)}},YC=function(t,e){t.notified||(t.notified=!0,kC((function(){for(var i,n=t.reactions;i=n.get();)XC(i,t);t.notified=!1,e&&!t.rejection&&KC(t)})))},GC=function(t,e,i){var n,o;WC?((n=jC.createEvent("Event")).promise=e,n.reason=i,n.initEvent(t,!1,!0),pC.dispatchEvent(n)):n={promise:e,reason:i},!DC&&(o=pC["on"+t])?o(n):t===VC&&OC("Unhandled promise rejection",i)},KC=function(t){fC(EC,pC,(function(){var e,i=t.facade,n=t.value;if(ZC(t)&&(e=CC((function(){uC?HC.emit("unhandledRejection",n,i):GC(VC,i,n)})),t.rejection=uC||ZC(t)?2:1,e.error))throw e.value}))},ZC=function(t){return 1!==t.rejection&&!t.parent},QC=function(t){fC(EC,pC,(function(){var e=t.facade;uC?HC.emit("rejectionHandled",e):GC("rejectionhandled",e,t.value)}))},JC=function(t,e,i){return function(n){t(e,n,i)}},tS=function(t,e,i){t.done||(t.done=!0,i&&(t=i),t.value=e,t.state=2,YC(t,!0))},eS=function(t,e,i){if(!t.done){t.done=!0,i&&(t=i);try{if(t.facade===e)throw new zC("Promise can't be resolved itself");var n=qC(e);n?kC((function(){var i={done:!1};try{fC(n,e,JC(eS,i,t),JC(tS,i,t))}catch(e){tS(i,e,t)}})):(t.value=e,t.state=1,YC(t,!1))}catch(e){tS({done:!1},e,t)}}};PC&&(LC=(BC=function(t){_C(this,LC),yC(t),fC(lC,this);var e=MC(this);try{t(JC(eS,e),JC(tS,e))}catch(t){tS(e,t)}}).prototype,(lC=function(t){FC(this,{type:RC,done:!1,notified:!1,parent:!1,reactions:new SC,rejection:!1,state:0,value:void 0})}).prototype=mC(LC,"then",(function(t,e){var i=MC(this),n=$C(wC(this,BC));return i.parent=!0,n.ok=!bC(t)||t,n.fail=bC(e)&&e,n.domain=uC?HC.domain:void 0,0===i.state?i.reactions.add(n):kC((function(){XC(n,i)})),n.promise})),cC=function(){var t=new lC,e=MC(t);this.promise=t,this.resolve=JC(eS,e),this.reject=JC(tS,e)},AC.f=$C=function(t){return t===BC||undefined===t?new cC(t):UC(t)}),hC({global:!0,constructor:!0,wrap:!0,forced:PC},{Promise:BC}),vC(BC,RC,!1,!0),gC(RC);var iS=HO,nS=oC.CONSTRUCTOR||!yg((function(t){iS.all(t).then(void 0,(function(){}))})),oS=bo,rS=yr,sS=rC,aS=jO,dS=nk;ma({target:"Promise",stat:!0,forced:nS},{all:function(t){var e=this,i=sS.f(e),n=i.resolve,o=i.reject,r=aS((function(){var i=rS(e.resolve),r=[],s=0,a=1;dS(t,(function(t){var d=s++,l=!1;a++,oS(i,e,t).then((function(t){l||(l=!0,r[d]=t,--a||n(r))}),o)})),--a||n(r)}));return r.error&&o(r.value),i.promise}});var lS=ma,cS=oC.CONSTRUCTOR;HO&&HO.prototype,lS({target:"Promise",proto:!0,forced:cS,real:!0},{catch:function(t){return this.then(void 0,t)}});var hS=bo,uS=yr,pS=rC,fS=jO,mS=nk;ma({target:"Promise",stat:!0,forced:nS},{race:function(t){var e=this,i=pS.f(e),n=i.reject,o=fS((function(){var o=uS(e.resolve);mS(t,(function(t){hS(o,e,t).then(i.resolve,n)}))}));return o.error&&n(o.value),i.promise}});var vS=bo,gS=rC;ma({target:"Promise",stat:!0,forced:oC.CONSTRUCTOR},{reject:function(t){var e=gS.f(this);return vS(e.reject,void 0,t),e.promise}});var yS=Us,bS=Ho,xS=rC,_S=function(t,e){if(yS(t),bS(e)&&e.constructor===t)return e;var i=xS.f(t);return(0,i.resolve)(e),i.promise},wS=ma,ES=HO,kS=oC.CONSTRUCTOR,OS=_S,CS=Xo("Promise"),SS=!kS;wS({target:"Promise",stat:!0,forced:true},{resolve:function(t){return OS(SS&&this===CS?ES:this,t)}});var TS=bo,IS=yr,AS=rC,RS=jO,PS=nk;ma({target:"Promise",stat:!0,forced:nS},{allSettled:function(t){var e=this,i=AS.f(e),n=i.resolve,o=i.reject,r=RS((function(){var i=IS(e.resolve),o=[],r=0,s=1;PS(t,(function(t){var a=r++,d=!1;s++,TS(i,e,t).then((function(t){d||(d=!0,o[a]={status:"fulfilled",value:t},--s||n(o))}),(function(t){d||(d=!0,o[a]={status:"rejected",reason:t},--s||n(o))}))})),--s||n(o)}));return r.error&&o(r.value),i.promise}});var DS=bo,MS=yr,FS=Xo,NS=rC,BS=jO,LS=nk,zS="No one promise resolved";ma({target:"Promise",stat:!0,forced:nS},{any:function(t){var e=this,i=FS("AggregateError"),n=NS.f(e),o=n.resolve,r=n.reject,s=BS((function(){var n=MS(e.resolve),s=[],a=0,d=1,l=!1;LS(t,(function(t){var c=a++,h=!1;d++,DS(n,e,t).then((function(t){h||l||(l=!0,o(t))}),(function(t){h||l||(h=!0,s[c]=t,--d||r(new i(s,zS)))}))})),--d||r(new i(s,zS))}));return s.error&&r(s.value),n.promise}});var jS=ma,HS=HO,$S=Vn,US=Xo,WS=fo,VS=Lk,qS=_S,XS=HS&&HS.prototype;jS({target:"Promise",proto:!0,real:!0,forced:!!HS&&$S((function(){XS.finally.call({then:function(){}},(function(){}))}))},{finally:function(t){var e=VS(this,US("Promise")),i=WS(t);return this.then(i?function(i){return qS(e,t()).then((function(){return i}))}:t,i?function(i){return qS(e,t()).then((function(){throw i}))}:t)}});var YS=$o.Promise,GS=rC;ma({target:"Promise",stat:!0},{withResolvers:function(){var t=GS.f(this);return{promise:t.promise,resolve:t.resolve,reject:t.reject}}});var KS=YS,ZS=rC,QS=jO;ma({target:"Promise",stat:!0,forced:!0},{try:function(t){var e=ZS.f(this),i=QS(t);return(i.error?e.reject:e.resolve)(i.value),e.promise}});var JS=KS,tT=eb;!function(t){var e=OE.default,i=wa,n=Qf,o=fE,r=xE,s=CE,a=Hg,d=vE,l=JS,c=tT,h=ly;function u(){t.exports=u=function(){return f},t.exports.__esModule=!0,t.exports.default=t.exports;var p,f={},m=Object.prototype,v=m.hasOwnProperty,g=i||function(t,e,i){t[e]=i.value},y="function"==typeof n?n:{},b=y.iterator||"@@iterator",x=y.asyncIterator||"@@asyncIterator",_=y.toStringTag||"@@toStringTag";function w(t,e,n){return i(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{w({},"")}catch(p){w=function(t,e,i){return t[e]=i}}function E(t,e,i,n){var r=e&&e.prototype instanceof A?e:A,s=o(r.prototype),a=new $(n||[]);return g(s,"_invoke",{value:L(t,i,a)}),s}function k(t,e,i){try{return{type:"normal",arg:t.call(e,i)}}catch(t){return{type:"throw",arg:t}}}f.wrap=E;var O="suspendedStart",C="suspendedYield",S="executing",T="completed",I={};function A(){}function R(){}function P(){}var D={};w(D,b,(function(){return this}));var M=r&&r(r(U([])));M&&M!==m&&v.call(M,b)&&(D=M);var F=P.prototype=A.prototype=o(D);function N(t){var e;s(e=["next","throw","return"]).call(e,(function(e){w(t,e,(function(t){return this._invoke(e,t)}))}))}function B(t,i){function n(o,r,s,a){var d=k(t[o],t,r);if("throw"!==d.type){var l=d.arg,c=l.value;return c&&"object"==e(c)&&v.call(c,"__await")?i.resolve(c.__await).then((function(t){n("next",t,s,a)}),(function(t){n("throw",t,s,a)})):i.resolve(c).then((function(t){l.value=t,s(l)}),(function(t){return n("throw",t,s,a)}))}a(d.arg)}var o;g(this,"_invoke",{value:function(t,e){function r(){return new i((function(i,o){n(t,e,i,o)}))}return o=o?o.then(r,r):r()}})}function L(t,e,i){var n=O;return function(o,r){if(n===S)throw new Error("Generator is already running");if(n===T){if("throw"===o)throw r;return{value:p,done:!0}}for(i.method=o,i.arg=r;;){var s=i.delegate;if(s){var a=z(s,i);if(a){if(a===I)continue;return a}}if("next"===i.method)i.sent=i._sent=i.arg;else if("throw"===i.method){if(n===O)throw n=T,i.arg;i.dispatchException(i.arg)}else"return"===i.method&&i.abrupt("return",i.arg);n=S;var d=k(t,e,i);if("normal"===d.type){if(n=i.done?T:C,d.arg===I)continue;return{value:d.arg,done:i.done}}"throw"===d.type&&(n=T,i.method="throw",i.arg=d.arg)}}}function z(t,e){var i=e.method,n=t.iterator[i];if(n===p)return e.delegate=null,"throw"===i&&t.iterator.return&&(e.method="return",e.arg=p,z(t,e),"throw"===e.method)||"return"!==i&&(e.method="throw",e.arg=new TypeError("The iterator does not provide a '"+i+"' method")),I;var o=k(n,t.iterator,e.arg);if("throw"===o.type)return e.method="throw",e.arg=o.arg,e.delegate=null,I;var r=o.arg;return r?r.done?(e[t.resultName]=r.value,e.next=t.nextLoc,"return"!==e.method&&(e.method="next",e.arg=p),e.delegate=null,I):r:(e.method="throw",e.arg=new TypeError("iterator result is not an object"),e.delegate=null,I)}function j(t){var e,i={tryLoc:t[0]};1 in t&&(i.catchLoc=t[1]),2 in t&&(i.finallyLoc=t[2],i.afterLoc=t[3]),a(e=this.tryEntries).call(e,i)}function H(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function $(t){this.tryEntries=[{tryLoc:"root"}],s(t).call(t,j,this),this.reset(!0)}function U(t){if(t||""===t){var i=t[b];if(i)return i.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var n=-1,o=function e(){for(;++n=0;--n){var o=this.tryEntries[n],r=o.completion;if("root"===o.tryLoc)return i("end");if(o.tryLoc<=this.prev){var s=v.call(o,"catchLoc"),a=v.call(o,"finallyLoc");if(s&&a){if(this.prev=0;--i){var n=this.tryEntries[i];if(n.tryLoc<=this.prev&&v.call(n,"finallyLoc")&&this.prev=0;--e){var i=this.tryEntries[e];if(i.finallyLoc===t)return this.complete(i.completion,i.afterLoc),H(i),I}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var i=this.tryEntries[e];if(i.tryLoc===t){var n=i.completion;if("throw"===n.type){var o=n.arg;H(i)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,e,i){return this.delegate={iterator:U(t),resultName:e,nextLoc:i},"next"===this.method&&(this.arg=p),I}},f}t.exports=u,t.exports.__esModule=!0,t.exports.default=t.exports}(EE);var eT=(0,EE.exports)(),iT=eT;try{regeneratorRuntime=eT}catch(t){"object"==typeof globalThis?globalThis.regeneratorRuntime=eT:Function("r","regeneratorRuntime = r")(eT)}var nT=Hn(iT),oT={exports:{}},rT=Vn((function(){if("function"==typeof ArrayBuffer){var t=new ArrayBuffer(8);Object.isExtensible(t)&&Object.defineProperty(t,"a",{value:8})}})),sT=Vn,aT=Ho,dT=so,lT=rT,cT=Object.isExtensible,hT=sT((function(){cT(1)}))||lT?function(t){return!!aT(t)&&((!lT||"ArrayBuffer"!==dT(t))&&(!cT||cT(t)))}:cT,uT=!Vn((function(){return Object.isExtensible(Object.preventExtensions({}))})),pT=ma,fT=io,mT=Qd,vT=Ho,gT=zr,yT=Ls.f,bT=Ml,xT=Bl,_T=hT,wT=uT,ET=!1,kT=Wr("meta"),OT=0,CT=function(t){yT(t,kT,{value:{objectID:"O"+OT++,weakData:{}}})},ST=oT.exports={enable:function(){ST.enable=function(){},ET=!0;var t=bT.f,e=fT([].splice),i={};i[kT]=1,t(i).length&&(bT.f=function(i){for(var n=t(i),o=0,r=n.length;o1?arguments[1]:void 0);e=e?e.next:i.first;)for(n(e.value,e.key,this);e&&e.removed;)e=e.previous},has:function(t){return!!d(this,t)}}),GT(r,i?{get:function(t){var e=d(this,t);return e&&e.value},set:function(t,e){return a(this,0===t?0:t,e)}}:{add:function(t){return a(this,t=0===t?0:t,t)}}),nI&&YT(r,"size",{configurable:!0,get:function(){return s(this).size}}),o},setStrong:function(t,e,i){var n=e+" Iterator",o=sI(e),r=sI(n);tI(t,e,(function(t,e){rI(this,{type:n,target:t,state:o(t),kind:e,last:void 0})}),(function(){for(var t=r(this),e=t.kind,i=t.last;i&&i.removed;)i=i.previous;return t.target&&(t.last=i=i?i.next:t.state.first)?eI("keys"===e?i.key:"values"===e?i.value:[i.key,i.value],!1):(t.target=void 0,eI(void 0,!0))}),i?"entries":"values",!i,!0),iI(e)}};VT("Map",(function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}}),aI);var dI=Hn($o.Map),lI=Xc.some;ma({target:"Array",proto:!0,forced:!ev("some")},{some:function(t){return lI(this,t,arguments.length>1?arguments[1]:void 0)}});var cI=zm("Array","some"),hI=Yo,uI=cI,pI=Array.prototype,fI=function(t){var e=t.some;return t===pI||hI(pI,t)&&e===pI.some?uI:e},mI=Hn(fI),vI=zm("Array","keys"),gI=Ga,yI=zr,bI=Yo,xI=vI,_I=Array.prototype,wI={DOMTokenList:!0,NodeList:!0},EI=function(t){var e=t.keys;return t===_I||bI(_I,t)&&e===_I.keys||yI(wI,gI(t))?xI:e},kI=Hn(EI),OI=Ul,CI=Math.floor,SI=function(t,e){var i=t.length,n=CI(i/2);return i<8?TI(t,e):II(t,SI(OI(t,0,n),e),SI(OI(t,n),e),e)},TI=function(t,e){for(var i,n,o=t.length,r=1;r0;)t[n]=t[--n];n!==r++&&(t[n]=i)}return t},II=function(t,e,i,n){for(var o=e.length,r=i.length,s=0,a=0;s3)){if(XI)return!0;if(GI)return GI<603;var t,e,i,n,o="";for(t=65;t<76;t++){switch(e=String.fromCharCode(t),t){case 66:case 69:case 70:case 72:i=3;break;case 68:case 71:i=4;break;default:i=2}for(n=0;n<47;n++)KI.push({k:e+n,v:i})}for(KI.sort((function(t,e){return e.v-t.v})),n=0;n$I(i)?1:-1}}(t)),i=jI(o),n=0;nthis.max&&this.flush(),null!=this._timeout&&(clearTimeout(this._timeout),this._timeout=null),this.queue.length>0&&"number"==typeof this.delay&&(this._timeout=gx((function(){t.flush()}),this.delay))}},{key:"flush",value:function(){var t,e;Vy(t=kb(e=this._queue).call(e,0)).call(t,(function(t){t.fn.apply(t.context||t.fn,t.args||[])}))}}],[{key:"extend",value:function(e,i){var n=new t(i);if(void 0!==e.flush)throw new Error("Target object already has a property flush");e.flush=function(){n.flush()};var o=[{name:"flush",original:void 0}];if(i&&i.replace)for(var r=0;r=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function jA(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);inT.mark((function e(){var n,o,r,s,a;return nT.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:n=zA(i),e.prev=1,n.s();case 3:if((o=n.n()).done){e.next=10;break}if(r=fy(o.value,2),s=r[0],a=r[1],!t(a,s)){e.next=8;break}return e.next=8,[s,a];case 8:e.next=3;break;case 10:e.next=15;break;case 12:e.prev=12,e.t0=e.catch(1),n.e(e.t0);case 15:return e.prev=15,n.f(),e.finish(15);case 18:case"end":return e.stop()}}),e,null,[[1,12,15,18]])}))()})}},{key:"forEach",value:function(t){var e,i=zA(this._pairs);try{for(i.s();!(e=i.n()).done;){var n=fy(e.value,2),o=n[0];t(n[1],o)}}catch(t){i.e(t)}finally{i.f()}}},{key:"map",value:function(t){var i=this._pairs;return new e({[yA]:()=>nT.mark((function e(){var n,o,r,s,a;return nT.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:n=zA(i),e.prev=1,n.s();case 3:if((o=n.n()).done){e.next=9;break}return r=fy(o.value,2),s=r[0],a=r[1],e.next=7,[s,t(a,s)];case 7:e.next=3;break;case 9:e.next=14;break;case 11:e.prev=11,e.t0=e.catch(1),n.e(e.t0);case 14:return e.prev=14,n.f(),e.finish(14);case 17:case"end":return e.stop()}}),e,null,[[1,11,14,17]])}))()})}},{key:"max",value:function(t){var e=LA(this._pairs),i=e.next();if(i.done)return null;for(var n=i.value[1],o=t(i.value[1],i.value[0]);!(i=e.next()).done;){var r=fy(i.value,2),s=r[0],a=r[1],d=t(a,s);d>o&&(o=d,n=a)}return n}},{key:"min",value:function(t){var e=LA(this._pairs),i=e.next();if(i.done)return null;for(var n=i.value[1],o=t(i.value[1],i.value[0]);!(i=e.next()).done;){var r=fy(i.value,2),s=r[0],a=r[1],d=t(a,s);d=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function VA(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i1?i-1:0),o=1;oo?1:no)&&(n=s,o=a)}}catch(t){r.e(t)}finally{r.f()}return n||null}},{key:"min",value:function(t){var e,i,n=null,o=null,r=WA(gA(e=this._data).call(e));try{for(r.s();!(i=r.n()).done;){var s=i.value,a=s[t];"number"==typeof a&&(null==o||anT.mark((function i(){var n,o,r,s;return nT.wrap((function(i){for(;;)switch(i.prev=i.next){case 0:n=WA(t),i.prev=1,n.s();case 3:if((o=n.n()).done){i.next=11;break}if(r=o.value,null==(s=e.get(r))){i.next=9;break}return i.next=9,[r,s];case 9:i.next=3;break;case 11:i.next=16;break;case 13:i.prev=13,i.t0=i.catch(1),n.e(i.t0);case 16:return i.prev=16,n.f(),i.finish(16);case 19:case"end":return i.stop()}}),i,null,[[1,13,16,19]])}))()})}var i;return new HA({[yA]:qm(i=SA(this._data)).call(i,this._data)})}}]),i}(NA);function YA(t,e){return"object"==typeof e&&null!==e&&t===e.idProp&&"function"==typeof Vy(e)&&"function"==typeof e.get&&"function"==typeof e.getDataSet&&"function"==typeof e.getIds&&"number"==typeof e.length&&"function"==typeof Ev(e)&&"function"==typeof e.off&&"function"==typeof e.on&&"function"==typeof e.stream&&function(t,e){return"object"==typeof e&&null!==e&&t===e.idProp&&"function"==typeof e.add&&"function"==typeof e.clear&&"function"==typeof e.distinct&&"function"==typeof Vy(e)&&"function"==typeof e.get&&"function"==typeof e.getDataSet&&"function"==typeof e.getIds&&"number"==typeof e.length&&"function"==typeof Ev(e)&&"function"==typeof e.max&&"function"==typeof e.min&&"function"==typeof e.off&&"function"==typeof e.on&&"function"==typeof e.remove&&"function"==typeof e.setOptions&&"function"==typeof e.stream&&"function"==typeof e.update&&"function"==typeof e.updateOnly}(t,e.getDataSet())} +function Oy(){return Oy=Object.assign||function(t){for(var e=1;e-1}var ym=function(){function t(t,e){this.manager=t,this.set(e)}var e=t.prototype;return e.set=function(t){t===Hy&&(t=this.compute()),Qy&&this.manager.element.style&&Yy[t]&&(this.manager.element.style[Ly]=t),this.actions=t.toLowerCase().trim()},e.update=function(){this.set(this.manager.options.touchAction)},e.compute=function(){var t=[];return pm(this.manager.recognizers,(function(e){vm(e.options.enable,[e])&&(t=t.concat(e.getTouchAction()))})),function(t){if(gm(t,Gy))return Gy;var e=gm(t,Ky),i=gm(t,qy);return e&&i?Gy:e||i?e?Ky:qy:gm(t,Wy)?Wy:Vy}(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=gm(o,Gy)&&!Yy[Gy],r=gm(o,qy)&&!Yy[qy],s=gm(o,Ky)&&!Yy[Ky];if(n){var a=1===t.pointers.length,l=t.distance<2,h=t.deltaTime<250;if(a&&l&&h)return}if(!s||!r)return n||r&&i&hm||s&&i&cm?this.preventSrc(e):void 0}},e.preventSrc=function(t){this.manager.session.prevented=!0,t.preventDefault()},t}();function mm(t,e){for(;t;){if(t===e)return!0;t=t.parentNode}return!1}function bm(t){var e=t.length;if(1===e)return{x:Ty(t[0].clientX),y:Ty(t[0].clientY)};for(var i=0,o=0,n=0;n=Ny(e)?t<0?rm:sm:e<0?am:lm}function Cm(t,e,i){return{x:e/t||0,y:i/t||0}}function xm(t,e){var i=t.session,o=e.pointers,n=o.length;i.firstInput||(i.firstInput=wm(e)),n>1&&!i.firstMultiple?i.firstMultiple=wm(e):1===n&&(i.firstMultiple=!1);var r=i.firstInput,s=i.firstMultiple,a=s?s.center:r.center,l=e.center=bm(o);e.timeStamp=jy(),e.deltaTime=e.timeStamp-r.timeStamp,e.angle=Em(a,l),e.distance=Am(a,l),function(t,e){var i=e.center,o=t.offsetDelta||{},n=t.prevDelta||{},r=t.prevInput||{};e.eventType!==em&&r.eventType!==im||(n=t.prevDelta={x:r.deltaX||0,y:r.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=km(e.deltaX,e.deltaY);var h,c,d=Cm(e.deltaTime,e.deltaX,e.deltaY);e.overallVelocityX=d.x,e.overallVelocityY=d.y,e.overallVelocity=Ny(d.x)>Ny(d.y)?d.x:d.y,e.scale=s?(h=s.pointers,Am((c=o)[0],c[1],fm)/Am(h[0],h[1],fm)):1,e.rotation=s?function(t,e){return Em(e[1],e[0],fm)+Em(t[1],t[0],fm)}(s.pointers,o):0,e.maxPointers=i.prevInput?e.pointers.length>i.prevInput.maxPointers?e.pointers.length:i.prevInput.maxPointers:e.pointers.length,function(t,e){var i,o,n,r,s=t.lastInterval||e,a=e.timeStamp-s.timeStamp;if(e.eventType!==om&&(a>tm||void 0===s.velocity)){var l=e.deltaX-s.deltaX,h=e.deltaY-s.deltaY,c=Cm(a,l,h);o=c.x,n=c.y,i=Ny(c.x)>Ny(c.y)?c.x:c.y,r=km(l,h),t.lastInterval=e}else i=s.velocity,o=s.velocityX,n=s.velocityY,r=s.direction;e.velocity=i,e.velocityX=o,e.velocityY=n,e.direction=r}(i,e);var u,f=t.element,p=e.srcEvent;mm(u=p.composedPath?p.composedPath()[0]:p.path?p.path[0]:p.target,f)&&(f=u),e.target=f}function Sm(t,e,i){var o=i.pointers.length,n=i.changedPointers.length,r=e&em&&o-n==0,s=e&(im|om)&&o-n==0;i.isFirst=!!r,i.isFinal=!!s,r&&(t.session={}),i.eventType=e,xm(t,i),t.emit("hammer.input",i),t.recognize(i),t.session.prevInput=i}function Im(t){return t.trim().split(/\s+/g)}function Mm(t,e,i){pm(Im(e),(function(e){t.addEventListener(e,i,!1)}))}function Om(t,e,i){pm(Im(e),(function(e){t.removeEventListener(e,i,!1)}))}function Dm(t){var e=t.ownerDocument||t;return e.defaultView||e.parentWindow||window}var Rm=function(){function t(t,e){var i=this;this.manager=t,this.callback=e,this.element=t.element,this.target=t.options.inputTarget,this.domHandler=function(e){vm(t.options.enable,[t])&&i.handler(e)},this.init()}var e=t.prototype;return e.handler=function(){},e.init=function(){this.evEl&&Mm(this.element,this.evEl,this.domHandler),this.evTarget&&Mm(this.target,this.evTarget,this.domHandler),this.evWin&&Mm(Dm(this.element),this.evWin,this.domHandler)},e.destroy=function(){this.evEl&&Om(this.element,this.evEl,this.domHandler),this.evTarget&&Om(this.target,this.evTarget,this.domHandler),this.evWin&&Om(Dm(this.element),this.evWin,this.domHandler)},t}();function Bm(t,e,i){if(t.indexOf&&!i)return t.indexOf(e);for(var o=0;oi[e]})):o.sort()),o}var Lm={touchstart:em,touchmove:2,touchend:im,touchcancel:om},Qm=function(t){function e(){var i;return e.prototype.evTarget="touchstart touchmove touchend touchcancel",(i=t.apply(this,arguments)||this).targetIds={},i}return Dy(e,t),e.prototype.handler=function(t){var e=Lm[t.type],i=Hm.call(this,t,e);i&&this.callback(this.manager,e,{pointers:i[0],changedPointers:i[1],pointerType:_y,srcEvent:t})},e}(Rm);function Hm(t,e){var i,o,n=jm(t.touches),r=this.targetIds;if(e&(2|em)&&1===n.length)return r[n[0].identifier]=!0,[n,n];var s=jm(t.changedTouches),a=[],l=this.target;if(o=n.filter((function(t){return mm(t.target,l)})),e===em)for(i=0;i-1&&o.splice(t,1)}),Gm)}}function qm(t,e){t&em?(this.primaryTouch=e.changedPointers[0].identifier,Km.call(this,e)):t&(im|om)&&Km.call(this,e)}function Ym(t){for(var e=t.srcEvent.clientX,i=t.srcEvent.clientY,o=0;o-1&&this.requireFail.splice(e,1),this},e.hasRequireFailures=function(){return this.requireFail.length>0},e.canRecognizeWith=function(t){return!!this.simultaneous[t.id]},e.emit=function(t){var e=this,i=this.state;function o(i){e.manager.emit(i,t)}i<8&&o(e.options.event+tb(i)),o(e.options.event),t.additionalEvent&&o(t.additionalEvent),i>=8&&o(e.options.event+tb(i))},e.tryEmit=function(t){if(this.canEmit())return this.emit(t);this.state=Xm},e.canEmit=function(){for(var t=0;te.threshold&&n&e.direction},i.attrTest=function(t){return ob.prototype.attrTest.call(this,t)&&(2&this.state||!(2&this.state)&&this.directionTest(t))},i.emit=function(e){this.pX=e.deltaX,this.pY=e.deltaY;var i=nb(e.direction);i&&(e.additionalEvent=this.options.event+i),t.prototype.emit.call(this,e)},e}(ob),sb=function(t){function e(e){return void 0===e&&(e={}),t.call(this,Oy({event:"swipe",threshold:10,velocity:.3,direction:hm|cm,pointers:1},e))||this}Dy(e,t);var i=e.prototype;return i.getTouchAction=function(){return rb.prototype.getTouchAction.call(this)},i.attrTest=function(e){var i,o=this.options.direction;return o&(hm|cm)?i=e.overallVelocity:o&hm?i=e.overallVelocityX:o&cm&&(i=e.overallVelocityY),t.prototype.attrTest.call(this,e)&&o&e.offsetDirection&&e.distance>this.options.threshold&&e.maxPointers===this.options.pointers&&Ny(i)>this.options.velocity&&e.eventType&im},i.emit=function(t){var e=nb(t.offsetDirection);e&&this.manager.emit(this.options.event+e,t),this.manager.emit(this.options.event,t)},e}(ob),ab=function(t){function e(e){return void 0===e&&(e={}),t.call(this,Oy({event:"pinch",threshold:0,pointers:2},e))||this}Dy(e,t);var i=e.prototype;return i.getTouchAction=function(){return[Gy]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.scale-1)>this.options.threshold||2&this.state)},i.emit=function(e){if(1!==e.scale){var i=e.scale<1?"in":"out";e.additionalEvent=this.options.event+i}t.prototype.emit.call(this,e)},e}(ob),lb=function(t){function e(e){return void 0===e&&(e={}),t.call(this,Oy({event:"rotate",threshold:0,pointers:2},e))||this}Dy(e,t);var i=e.prototype;return i.getTouchAction=function(){return[Gy]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.rotation)>this.options.threshold||2&this.state)},e}(ob),hb=function(t){function e(e){var i;return void 0===e&&(e={}),(i=t.call(this,Oy({event:"press",pointers:1,time:251,threshold:9},e))||this)._timer=null,i._input=null,i}Dy(e,t);var i=e.prototype;return i.getTouchAction=function(){return[Vy]},i.process=function(t){var e=this,i=this.options,o=t.pointers.length===i.pointers,n=t.distancei.time;if(this._input=t,!n||!o||t.eventType&(im|om)&&!r)this.reset();else if(t.eventType&em)this.reset(),this._timer=setTimeout((function(){e.state=8,e.tryEmit()}),i.time);else if(t.eventType&im)return 8;return Xm},i.reset=function(){clearTimeout(this._timer)},i.emit=function(t){8===this.state&&(t&&t.eventType&im?this.manager.emit(this.options.event+"up",t):(this._input.timeStamp=jy(),this.manager.emit(this.options.event,this._input)))},e}(eb),cb={domEvents:!1,touchAction:Hy,enable:!0,inputTarget:null,inputClass:null,cssProps:{userSelect:"none",touchSelect:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}},db=[[lb,{enable:!1}],[ab,{enable:!1},["rotate"]],[sb,{direction:hm}],[rb,{direction:hm},["swipe"]],[ib],[ib,{event:"doubletap",taps:2},["tap"]],[hb]];function ub(t,e){var i,o=t.element;o.style&&(pm(t.options.cssProps,(function(n,r){i=Uy(o.style,r),e?(t.oldCssProps[i]=o.style[i],o.style[i]=n):o.style[i]=t.oldCssProps[i]||""})),e||(t.oldCssProps={}))}var fb=function(){function t(t,e){var i,o=this;this.options=zy({},cb,e||{}),this.options.inputTarget=this.options.inputTarget||t,this.handlers={},this.session={},this.recognizers=[],this.oldCssProps={},this.element=t,this.input=new((i=this).options.inputClass||(Jy?Nm:Xy?Qm:Zy?Zm:Wm))(i,Sm),this.touchAction=new ym(this,this.options.touchAction),ub(this,!0),pm(this.options.recognizers,(function(t){var e=o.add(new t[0](t[1]));t[2]&&e.recognizeWith(t[2]),t[3]&&e.requireFailure(t[3])}),this)}var e=t.prototype;return e.set=function(t){return zy(this.options,t),t.touchAction&&this.touchAction.update(),t.inputTarget&&(this.input.destroy(),this.input.target=t.inputTarget,this.input.init()),this},e.stop=function(t){this.session.stopped=t?2:1},e.recognize=function(t){var e=this.session;if(!e.stopped){var i;this.touchAction.preventDefaults(t);var o=this.recognizers,n=e.curRecognizer;(!n||n&&8&n.state)&&(e.curRecognizer=null,n=null);for(var r=0;r\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",n=window.console&&(window.console.warn||window.console.log);return n&&n.call(window.console,o,i),t.apply(this,arguments)}}var mb=yb((function(t,e,i){for(var o=Object.keys(e),n=0;n=t.length?{done:!0}:{done:!1,value:t[o++]}},e:function(t){throw t},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function xb(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,o=new Array(e);i2)return Mb.apply(void 0,Dv(o=[Ib(e[0],e[1])]).call(o,kv(Rv(e).call(e,2))));var n=e[0],r=e[1];if(n instanceof Date&&r instanceof Date)return n.setTime(r.getTime()),n;var s,a=Cb(jv(r));try{for(a.s();!(s=a.n()).done;){var l=s.value;Object.prototype.propertyIsEnumerable.call(r,l)&&(r[l]===Sb?delete n[l]:null===n[l]||null===r[l]||"object"!=typeof n[l]||"object"!=typeof r[l]||Uv(n[l])||Uv(r[l])?n[l]=Ob(r[l]):n[l]=Mb(n[l],r[l]))}}catch(t){a.e(t)}finally{a.f()}return n}function Ob(t){return Uv(t)?Rf(t).call(t,(function(t){return Ob(t)})):"object"==typeof t&&null!==t?t instanceof Date?new Date(t.getTime()):Mb({},t):t}function Db(t){for(var e=0,i=Hv(t);e({set:t})}}()};function Bb(t){var e,i=this;this._cleanupQueue=[],this.active=!1,this._dom={container:t,overlay:document.createElement("div")},this._dom.overlay.classList.add("vis-overlay"),this._dom.container.appendChild(this._dom.overlay),this._cleanupQueue.push((function(){i._dom.overlay.parentNode.removeChild(i._dom.overlay)}));var o=Rb(this._dom.overlay);o.on("tap",$u(e=this._onTapOverlay).call(e,this)),this._cleanupQueue.push((function(){o.destroy()}));var n=["tap","doubletap","press","pinch","pan","panstart","panmove","panend"];$v(n).call(n,(function(t){o.on(t,(function(t){t.srcEvent.stopPropagation()}))})),document&&document.body&&(this._onClick=function(e){(function(t,e){for(;t;){if(t===e)return!0;t=t.parentNode}return!1})(e.target,t)||i.deactivate()},document.body.addEventListener("click",this._onClick),this._cleanupQueue.push((function(){document.body.removeEventListener("click",i._onClick)}))),this._escListener=function(t){("key"in t?"Escape"===t.key:27===t.keyCode)&&i.deactivate()}}My(Bb.prototype),Bb.current=null,Bb.prototype.destroy=function(){var t,e;this.deactivate();var i,o=Cb(cg(t=Bg(e=this._cleanupQueue).call(e,0)).call(t));try{for(o.s();!(i=o.n()).done;){(0,i.value)()}}catch(t){o.e(t)}finally{o.f()}},Bb.prototype.activate=function(){Bb.current&&Bb.current.deactivate(),Bb.current=this,this.active=!0,this._dom.overlay.style.display="none",this._dom.container.classList.add("vis-active"),this.emit("change"),this.emit("activate"),document.body.addEventListener("keydown",this._escListener)},Bb.prototype.deactivate=function(){this.active=!1,this._dom.overlay.style.display="block",this._dom.container.classList.remove("vis-active"),document.body.removeEventListener("keydown",this._escListener),this.emit("change"),this.emit("deactivate")},Bb.prototype._onTapOverlay=function(t){this.activate(),t.srcEvent.stopPropagation()};var zb=Ar,Pb=wi,Fb=TypeError,Tb=function(t){if(zb(t))return t;throw new Fb(Pb(t)+" is not a constructor")},Nb=kn,jb=ne,Ub=Hu,Lb=Tb,Qb=Jo,Hb=qe,Vb=Qs,Wb=_t,Gb=$e("Reflect","construct"),Kb=Object.prototype,qb=[].push,Yb=Wb((function(){function t(){}return!(Gb((function(){}),[],t)instanceof t)})),Zb=!Wb((function(){Gb((function(){}))})),Jb=Yb||Zb;Nb({target:"Reflect",stat:!0,forced:Jb,sham:Jb},{construct:function(t,e){Lb(t),Qb(e);var i=arguments.length<3?t:Lb(arguments[2]);if(Zb&&!Yb)return Gb(t,e,i);if(t===i){switch(e.length){case 0:return new t;case 1:return new t(e[0]);case 2:return new t(e[0],e[1]);case 3:return new t(e[0],e[1],e[2]);case 4:return new t(e[0],e[1],e[2],e[3])}var o=[null];return jb(qb,o,e),new(jb(Ub,t,o))}var n=i.prototype,r=Vb(Hb(n)?n:Kb),s=jb(t,r,e);return Hb(s)?s:r}});var Xb=Yt(Ye.Reflect.construct),_b=Yt(Ye.Object.getOwnPropertySymbols),$b={exports:{}},tw=kn,ew=_t,iw=We,ow=Ae.f,nw=Ee;tw({target:"Object",stat:!0,forced:!nw||ew((function(){ow(1)})),sham:!nw},{getOwnPropertyDescriptor:function(t,e){return ow(iw(t),e)}});var rw=Ye.Object,sw=$b.exports=function(t,e){return rw.getOwnPropertyDescriptor(t,e)};rw.getOwnPropertyDescriptor.sham&&(sw.sham=!0);var aw=Yt($b.exports),lw=Nv,hw=We,cw=Ae,dw=Yn;kn({target:"Object",stat:!0,sham:!Ee},{getOwnPropertyDescriptors:function(t){for(var e,i,o=hw(t),n=cw.f,r=lw(o),s={},a=0;r.length>a;)void 0!==(i=n(o,e=r[a++]))&&dw(s,e,i);return s}});var uw=Yt(Ye.Object.getOwnPropertyDescriptors),fw={exports:{}},pw=kn,vw=Ee,gw=Jr.f;pw({target:"Object",stat:!0,forced:Object.defineProperties!==gw,sham:!vw},{defineProperties:gw});var yw=Ye.Object,mw=fw.exports=function(t,e){return yw.defineProperties(t,e)};yw.defineProperties.sham&&(mw.sham=!0);var bw=Yt(fw.exports),ww=Yt(On);function Aw(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}var Ew=ty,kw=Yt(Ew);kn({target:"Object",stat:!0},{setPrototypeOf:$c});var Cw=Ye.Object.setPrototypeOf,xw=Yt(Cw),Sw=Yt(_u);function Iw(t,e){var i;return Iw=xw?Sw(i=xw).call(i):function(t,e){return t.__proto__=e,t},Iw(t,e)}var Mw=Xg,Ow=Yt(Mw);function Dw(t){var e;return Dw=xw?Sw(e=Ow).call(e):function(t){return t.__proto__||Ow(t)},Dw(t)}var Rw={exports:{}},Bw={exports:{}};!function(t){var e=ru,i=Cu;function o(n){return t.exports=o="function"==typeof e&&"symbol"==typeof i?function(t){return typeof t}:function(t){return t&&"function"==typeof e&&t.constructor===e&&t!==e.prototype?"symbol":typeof t},t.exports.__esModule=!0,t.exports.default=t.exports,o(n)}t.exports=o,t.exports.__esModule=!0,t.exports.default=t.exports}(Bw);var zw=Bw.exports,Pw=_v,Fw=Gi,Tw=Nv,Nw=Ae,jw=Go,Uw=qe,Lw=dn,Qw=Error,Hw=he("".replace),Vw=String(new Qw("zxcasd").stack),Ww=/\n\s*at [^:]*:[^\n]*/,Gw=Ww.test(Vw),Kw=Be,qw=!_t((function(){var t=new Error("a");return!("stack"in t)||(Object.defineProperty(t,"stack",Kw(1,7)),7!==t.stack)})),Yw=dn,Zw=function(t,e){if(Gw&&"string"==typeof t&&!Qw.prepareStackTrace)for(;e--;)t=Hw(t,Ww,"");return t},Jw=qw,Xw=Error.captureStackTrace,_w=Wo,$w=xe,tA=Jo,eA=wi,iA=Xf,oA=Hn,nA=ti,rA=cp,sA=op,aA=Gf,lA=TypeError,hA=function(t,e){this.stopped=t,this.result=e},cA=hA.prototype,dA=function(t,e,i){var o,n,r,s,a,l,h,c=i&&i.that,d=!(!i||!i.AS_ENTRIES),u=!(!i||!i.IS_RECORD),f=!(!i||!i.IS_ITERATOR),p=!(!i||!i.INTERRUPTED),v=_w(e,c),g=function(t){return o&&aA(o,"normal",t),new hA(!0,t)},y=function(t){return d?(tA(t),p?v(t[0],t[1],g):v(t[0],t[1])):p?v(t,g):v(t)};if(u)o=t.iterator;else if(f)o=t;else{if(!(n=sA(t)))throw new lA(eA(t)+" is not iterable");if(iA(n)){for(r=0,s=oA(t);s>r;r++)if((a=y(t[r]))&&nA(cA,a))return a;return new hA(!1)}o=rA(t,n)}for(l=u?t.next:o.next;!(h=$w(l,o)).done;){try{a=y(h.value)}catch(t){aA(o,"throw",t)}if("object"==typeof a&&a&&nA(cA,a))return a}return new hA(!1)},uA=Zr,fA=kn,pA=ti,vA=Mc,gA=$c,yA=function(t,e,i){for(var o=Tw(e),n=jw.f,r=Nw.f,s=0;s2&&AA(i,arguments[2]);var n=[];return kA(t,IA,{that:n}),bA(i,"errors",n),i};gA?gA(MA,SA):yA(MA,SA,{name:!0});var OA=MA.prototype=mA(SA.prototype,{constructor:wA(1,MA),message:wA(1,""),name:wA(1,"AggregateError")});fA({global:!0,constructor:!0,arity:2},{AggregateError:MA});var DA,RA,BA,zA,PA=$e,FA=aa,TA=Ee,NA=ro("species"),jA=function(t){var e=PA(t);TA&&e&&!e[NA]&&FA(e,NA,{configurable:!0,get:function(){return this}})},UA=ti,LA=TypeError,QA=function(t,e){if(UA(e,t))return t;throw new LA("Incorrect invocation")},HA=Jo,VA=Tb,WA=je,GA=ro("species"),KA=function(t,e){var i,o=HA(t).constructor;return void 0===o||WA(i=HA(o)[GA])?e:VA(i)},qA=/(?:ipad|iphone|ipod).*applewebkit/i.test(ei),YA=Xt,ZA=ne,JA=Wo,XA=we,_A=Gi,$A=_t,tE=Cs,eE=Ih,iE=wo,oE=ly,nE=qA,rE=cf,sE=YA.setImmediate,aE=YA.clearImmediate,lE=YA.process,hE=YA.Dispatch,cE=YA.Function,dE=YA.MessageChannel,uE=YA.String,fE=0,pE={},vE="onreadystatechange";$A((function(){DA=YA.location}));var gE=function(t){if(_A(pE,t)){var e=pE[t];delete pE[t],e()}},yE=function(t){return function(){gE(t)}},mE=function(t){gE(t.data)},bE=function(t){YA.postMessage(uE(t),DA.protocol+"//"+DA.host)};sE&&aE||(sE=function(t){oE(arguments.length,1);var e=XA(t)?t:cE(t),i=eE(arguments,1);return pE[++fE]=function(){ZA(e,void 0,i)},RA(fE),fE},aE=function(t){delete pE[t]},rE?RA=function(t){lE.nextTick(yE(t))}:hE&&hE.now?RA=function(t){hE.now(yE(t))}:dE&&!nE?(zA=(BA=new dE).port2,BA.port1.onmessage=mE,RA=JA(zA.postMessage,zA)):YA.addEventListener&&XA(YA.postMessage)&&!YA.importScripts&&DA&&"file:"!==DA.protocol&&!$A(bE)?(RA=bE,YA.addEventListener("message",mE,!1)):RA=vE in iE("script")?function(t){tE.appendChild(iE("script"))[vE]=function(){tE.removeChild(this),gE(t)}}:function(t){setTimeout(yE(t),0)});var wE={set:sE,clear:aE},AE=function(){this.head=null,this.tail=null};AE.prototype={add:function(t){var e={item:t,next:null},i=this.tail;i?i.next=e:this.head=e,this.tail=e},get:function(){var t=this.head;if(t)return null===(this.head=t.next)&&(this.tail=null),t.item}};var EE,kE,CE,xE,SE,IE=AE,ME=/ipad|iphone|ipod/i.test(ei)&&"undefined"!=typeof Pebble,OE=/web0s(?!.*chrome)/i.test(ei),DE=Xt,RE=Wo,BE=Ae.f,zE=wE.set,PE=IE,FE=qA,TE=ME,NE=OE,jE=cf,UE=DE.MutationObserver||DE.WebKitMutationObserver,LE=DE.document,QE=DE.process,HE=DE.Promise,VE=BE(DE,"queueMicrotask"),WE=VE&&VE.value;if(!WE){var GE=new PE,KE=function(){var t,e;for(jE&&(t=QE.domain)&&t.exit();e=GE.get();)try{e()}catch(t){throw GE.head&&EE(),t}t&&t.enter()};FE||jE||NE||!UE||!LE?!TE&&HE&&HE.resolve?((xE=HE.resolve(void 0)).constructor=HE,SE=RE(xE.then,xE),EE=function(){SE(KE)}):jE?EE=function(){QE.nextTick(KE)}:(zE=RE(zE,DE),EE=function(){zE(KE)}):(kE=!0,CE=LE.createTextNode(""),new UE(KE).observe(CE,{characterData:!0}),EE=function(){CE.data=kE=!kE}),WE=function(t){GE.head||EE(),GE.add(t)}}var qE=WE,YE=function(t){try{return{error:!1,value:t()}}catch(t){return{error:!0,value:t}}},ZE=Xt.Promise,JE="object"==typeof Deno&&Deno&&"object"==typeof Deno.version,XE=!JE&&!cf&&"object"==typeof window&&"object"==typeof document,_E=Xt,$E=ZE,tk=we,ek=Lo,ik=ar,ok=ro,nk=XE,rk=JE,sk=li,ak=$E&&$E.prototype,lk=ok("species"),hk=!1,ck=tk(_E.PromiseRejectionEvent),dk=ek("Promise",(function(){var t=ik($E),e=t!==String($E);if(!e&&66===sk)return!0;if(!ak.catch||!ak.finally)return!0;if(!sk||sk<51||!/native code/.test(t)){var i=new $E((function(t){t(1)})),o=function(t){t((function(){}),(function(){}))};if((i.constructor={})[lk]=o,!(hk=i.then((function(){}))instanceof o))return!0}return!e&&(nk||rk)&&!ck})),uk={CONSTRUCTOR:dk,REJECTION_EVENT:ck,SUBCLASSING:hk},fk={},pk=Ci,vk=TypeError,gk=function(t){var e,i;this.promise=new t((function(t,o){if(void 0!==e||void 0!==i)throw new vk("Bad Promise constructor");e=t,i=o})),this.resolve=pk(e),this.reject=pk(i)};fk.f=function(t){return new gk(t)};var yk,mk,bk=kn,wk=cf,Ak=Xt,Ek=xe,kk=ra,Ck=Ra,xk=jA,Sk=Ci,Ik=we,Mk=qe,Ok=QA,Dk=KA,Rk=wE.set,Bk=qE,zk=function(t,e){try{1===arguments.length?console.error(t):console.error(t,e)}catch(t){}},Pk=YE,Fk=IE,Tk=qa,Nk=ZE,jk=fk,Uk="Promise",Lk=uk.CONSTRUCTOR,Qk=uk.REJECTION_EVENT,Hk=Tk.getterFor(Uk),Vk=Tk.set,Wk=Nk&&Nk.prototype,Gk=Nk,Kk=Wk,qk=Ak.TypeError,Yk=Ak.document,Zk=Ak.process,Jk=jk.f,Xk=Jk,_k=!!(Yk&&Yk.createEvent&&Ak.dispatchEvent),$k="unhandledrejection",tC=function(t){var e;return!(!Mk(t)||!Ik(e=t.then))&&e},eC=function(t,e){var i,o,n,r=e.value,s=1===e.state,a=s?t.ok:t.fail,l=t.resolve,h=t.reject,c=t.domain;try{a?(s||(2===e.rejection&&sC(e),e.rejection=1),!0===a?i=r:(c&&c.enter(),i=a(r),c&&(c.exit(),n=!0)),i===t.promise?h(new qk("Promise-chain cycle")):(o=tC(i))?Ek(o,i,l,h):l(i)):h(r)}catch(t){c&&!n&&c.exit(),h(t)}},iC=function(t,e){t.notified||(t.notified=!0,Bk((function(){for(var i,o=t.reactions;i=o.get();)eC(i,t);t.notified=!1,e&&!t.rejection&&nC(t)})))},oC=function(t,e,i){var o,n;_k?((o=Yk.createEvent("Event")).promise=e,o.reason=i,o.initEvent(t,!1,!0),Ak.dispatchEvent(o)):o={promise:e,reason:i},!Qk&&(n=Ak["on"+t])?n(o):t===$k&&zk("Unhandled promise rejection",i)},nC=function(t){Ek(Rk,Ak,(function(){var e,i=t.facade,o=t.value;if(rC(t)&&(e=Pk((function(){wk?Zk.emit("unhandledRejection",o,i):oC($k,i,o)})),t.rejection=wk||rC(t)?2:1,e.error))throw e.value}))},rC=function(t){return 1!==t.rejection&&!t.parent},sC=function(t){Ek(Rk,Ak,(function(){var e=t.facade;wk?Zk.emit("rejectionHandled",e):oC("rejectionhandled",e,t.value)}))},aC=function(t,e,i){return function(o){t(e,o,i)}},lC=function(t,e,i){t.done||(t.done=!0,i&&(t=i),t.value=e,t.state=2,iC(t,!0))},hC=function(t,e,i){if(!t.done){t.done=!0,i&&(t=i);try{if(t.facade===e)throw new qk("Promise can't be resolved itself");var o=tC(e);o?Bk((function(){var i={done:!1};try{Ek(o,e,aC(hC,i,t),aC(lC,i,t))}catch(e){lC(i,e,t)}})):(t.value=e,t.state=1,iC(t,!1))}catch(e){lC({done:!1},e,t)}}};Lk&&(Kk=(Gk=function(t){Ok(this,Kk),Sk(t),Ek(yk,this);var e=Hk(this);try{t(aC(hC,e),aC(lC,e))}catch(t){lC(e,t)}}).prototype,(yk=function(t){Vk(this,{type:Uk,done:!1,notified:!1,parent:!1,reactions:new Fk,rejection:!1,state:0,value:void 0})}).prototype=kk(Kk,"then",(function(t,e){var i=Hk(this),o=Jk(Dk(this,Gk));return i.parent=!0,o.ok=!Ik(t)||t,o.fail=Ik(e)&&e,o.domain=wk?Zk.domain:void 0,0===i.state?i.reactions.add(o):Bk((function(){eC(o,i)})),o.promise})),mk=function(){var t=new yk,e=Hk(t);this.promise=t,this.resolve=aC(hC,e),this.reject=aC(lC,e)},jk.f=Jk=function(t){return t===Gk||undefined===t?new mk(t):Xk(t)}),bk({global:!0,constructor:!0,wrap:!0,forced:Lk},{Promise:Gk}),Ck(Gk,Uk,!1,!0),xk(Uk);var cC=ZE,dC=uk.CONSTRUCTOR||!Sp((function(t){cC.all(t).then(void 0,(function(){}))})),uC=xe,fC=Ci,pC=fk,vC=YE,gC=dA;kn({target:"Promise",stat:!0,forced:dC},{all:function(t){var e=this,i=pC.f(e),o=i.resolve,n=i.reject,r=vC((function(){var i=fC(e.resolve),r=[],s=0,a=1;gC(t,(function(t){var l=s++,h=!1;a++,uC(i,e,t).then((function(t){h||(h=!0,r[l]=t,--a||o(r))}),n)})),--a||o(r)}));return r.error&&n(r.value),i.promise}});var yC=kn,mC=uk.CONSTRUCTOR;ZE&&ZE.prototype,yC({target:"Promise",proto:!0,forced:mC,real:!0},{catch:function(t){return this.then(void 0,t)}});var bC=xe,wC=Ci,AC=fk,EC=YE,kC=dA;kn({target:"Promise",stat:!0,forced:dC},{race:function(t){var e=this,i=AC.f(e),o=i.reject,n=EC((function(){var n=wC(e.resolve);kC(t,(function(t){bC(n,e,t).then(i.resolve,o)}))}));return n.error&&o(n.value),i.promise}});var CC=xe,xC=fk;kn({target:"Promise",stat:!0,forced:uk.CONSTRUCTOR},{reject:function(t){var e=xC.f(this);return CC(e.reject,void 0,t),e.promise}});var SC=Jo,IC=qe,MC=fk,OC=function(t,e){if(SC(t),IC(e)&&e.constructor===t)return e;var i=MC.f(t);return(0,i.resolve)(e),i.promise},DC=kn,RC=ZE,BC=uk.CONSTRUCTOR,zC=OC,PC=$e("Promise"),FC=!BC;DC({target:"Promise",stat:!0,forced:true},{resolve:function(t){return zC(FC&&this===PC?RC:this,t)}});var TC=xe,NC=Ci,jC=fk,UC=YE,LC=dA;kn({target:"Promise",stat:!0,forced:dC},{allSettled:function(t){var e=this,i=jC.f(e),o=i.resolve,n=i.reject,r=UC((function(){var i=NC(e.resolve),n=[],r=0,s=1;LC(t,(function(t){var a=r++,l=!1;s++,TC(i,e,t).then((function(t){l||(l=!0,n[a]={status:"fulfilled",value:t},--s||o(n))}),(function(t){l||(l=!0,n[a]={status:"rejected",reason:t},--s||o(n))}))})),--s||o(n)}));return r.error&&n(r.value),i.promise}});var QC=xe,HC=Ci,VC=$e,WC=fk,GC=YE,KC=dA,qC="No one promise resolved";kn({target:"Promise",stat:!0,forced:dC},{any:function(t){var e=this,i=VC("AggregateError"),o=WC.f(e),n=o.resolve,r=o.reject,s=GC((function(){var o=HC(e.resolve),s=[],a=0,l=1,h=!1;KC(t,(function(t){var c=a++,d=!1;l++,QC(o,e,t).then((function(t){d||h||(h=!0,n(t))}),(function(t){d||h||(d=!0,s[c]=t,--l||r(new i(s,qC)))}))})),--l||r(new i(s,qC))}));return s.error&&r(s.value),o.promise}});var YC=kn,ZC=ZE,JC=_t,XC=$e,_C=we,$C=KA,tx=OC,ex=ZC&&ZC.prototype;YC({target:"Promise",proto:!0,real:!0,forced:!!ZC&&JC((function(){ex.finally.call({then:function(){}},(function(){}))}))},{finally:function(t){var e=$C(this,XC("Promise")),i=_C(t);return this.then(i?function(i){return tx(e,t()).then((function(){return i}))}:t,i?function(i){return tx(e,t()).then((function(){throw i}))}:t)}});var ix=Ye.Promise,ox=fk;kn({target:"Promise",stat:!0},{withResolvers:function(){var t=ox.f(this);return{promise:t.promise,resolve:t.resolve,reject:t.reject}}});var nx=ix,rx=fk,sx=YE;kn({target:"Promise",stat:!0,forced:!0},{try:function(t){var e=rx.f(this),i=sx(t);return(i.error?e.reject:e.resolve)(i.value),e.promise}});var ax=nx,lx=hg;!function(t){var e=zw.default,i=Dn,o=ru,n=Ew,r=Mw,s=Pw,a=Zp,l=Cw,h=ax,c=lx,d=yv;function u(){t.exports=u=function(){return p},t.exports.__esModule=!0,t.exports.default=t.exports;var f,p={},v=Object.prototype,g=v.hasOwnProperty,y=i||function(t,e,i){t[e]=i.value},m="function"==typeof o?o:{},b=m.iterator||"@@iterator",w=m.asyncIterator||"@@asyncIterator",A=m.toStringTag||"@@toStringTag";function E(t,e,o){return i(t,e,{value:o,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{E({},"")}catch(f){E=function(t,e,i){return t[e]=i}}function k(t,e,i,o){var r=e&&e.prototype instanceof D?e:D,s=n(r.prototype),a=new H(o||[]);return y(s,"_invoke",{value:j(t,i,a)}),s}function C(t,e,i){try{return{type:"normal",arg:t.call(e,i)}}catch(t){return{type:"throw",arg:t}}}p.wrap=k;var x="suspendedStart",S="suspendedYield",I="executing",M="completed",O={};function D(){}function R(){}function B(){}var z={};E(z,b,(function(){return this}));var P=r&&r(r(V([])));P&&P!==v&&g.call(P,b)&&(z=P);var F=B.prototype=D.prototype=n(z);function T(t){var e;s(e=["next","throw","return"]).call(e,(function(e){E(t,e,(function(t){return this._invoke(e,t)}))}))}function N(t,i){function o(n,r,s,a){var l=C(t[n],t,r);if("throw"!==l.type){var h=l.arg,c=h.value;return c&&"object"==e(c)&&g.call(c,"__await")?i.resolve(c.__await).then((function(t){o("next",t,s,a)}),(function(t){o("throw",t,s,a)})):i.resolve(c).then((function(t){h.value=t,s(h)}),(function(t){return o("throw",t,s,a)}))}a(l.arg)}var n;y(this,"_invoke",{value:function(t,e){function r(){return new i((function(i,n){o(t,e,i,n)}))}return n=n?n.then(r,r):r()}})}function j(t,e,i){var o=x;return function(n,r){if(o===I)throw new Error("Generator is already running");if(o===M){if("throw"===n)throw r;return{value:f,done:!0}}for(i.method=n,i.arg=r;;){var s=i.delegate;if(s){var a=U(s,i);if(a){if(a===O)continue;return a}}if("next"===i.method)i.sent=i._sent=i.arg;else if("throw"===i.method){if(o===x)throw o=M,i.arg;i.dispatchException(i.arg)}else"return"===i.method&&i.abrupt("return",i.arg);o=I;var l=C(t,e,i);if("normal"===l.type){if(o=i.done?M:S,l.arg===O)continue;return{value:l.arg,done:i.done}}"throw"===l.type&&(o=M,i.method="throw",i.arg=l.arg)}}}function U(t,e){var i=e.method,o=t.iterator[i];if(o===f)return e.delegate=null,"throw"===i&&t.iterator.return&&(e.method="return",e.arg=f,U(t,e),"throw"===e.method)||"return"!==i&&(e.method="throw",e.arg=new TypeError("The iterator does not provide a '"+i+"' method")),O;var n=C(o,t.iterator,e.arg);if("throw"===n.type)return e.method="throw",e.arg=n.arg,e.delegate=null,O;var r=n.arg;return r?r.done?(e[t.resultName]=r.value,e.next=t.nextLoc,"return"!==e.method&&(e.method="next",e.arg=f),e.delegate=null,O):r:(e.method="throw",e.arg=new TypeError("iterator result is not an object"),e.delegate=null,O)}function L(t){var e,i={tryLoc:t[0]};1 in t&&(i.catchLoc=t[1]),2 in t&&(i.finallyLoc=t[2],i.afterLoc=t[3]),a(e=this.tryEntries).call(e,i)}function Q(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function H(t){this.tryEntries=[{tryLoc:"root"}],s(t).call(t,L,this),this.reset(!0)}function V(t){if(t||""===t){var i=t[b];if(i)return i.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var o=-1,n=function e(){for(;++o=0;--o){var n=this.tryEntries[o],r=n.completion;if("root"===n.tryLoc)return i("end");if(n.tryLoc<=this.prev){var s=g.call(n,"catchLoc"),a=g.call(n,"finallyLoc");if(s&&a){if(this.prev=0;--i){var o=this.tryEntries[i];if(o.tryLoc<=this.prev&&g.call(o,"finallyLoc")&&this.prev=0;--e){var i=this.tryEntries[e];if(i.finallyLoc===t)return this.complete(i.completion,i.afterLoc),Q(i),O}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var i=this.tryEntries[e];if(i.tryLoc===t){var o=i.completion;if("throw"===o.type){var n=o.arg;Q(i)}return n}}throw new Error("illegal catch attempt")},delegateYield:function(t,e,i){return this.delegate={iterator:V(t),resultName:e,nextLoc:i},"next"===this.method&&(this.arg=f),O}},p}t.exports=u,t.exports.__esModule=!0,t.exports.default=t.exports}(Rw);var hx=(0,Rw.exports)(),cx=hx;try{regeneratorRuntime=hx}catch(t){"object"==typeof globalThis?globalThis.regeneratorRuntime=hx:Function("r","regeneratorRuntime = r")(hx)}var dx=Yt(cx),ux={exports:{}},fx=_t((function(){if("function"==typeof ArrayBuffer){var t=new ArrayBuffer(8);Object.isExtensible(t)&&Object.defineProperty(t,"a",{value:8})}})),px=_t,vx=qe,gx=fe,yx=fx,mx=Object.isExtensible,bx=px((function(){mx(1)}))||yx?function(t){return!!vx(t)&&((!yx||"ArrayBuffer"!==gx(t))&&(!mx||mx(t)))}:mx,wx=!_t((function(){return Object.isExtensible(Object.preventExtensions({}))})),Ax=kn,Ex=he,kx=ss,Cx=qe,xx=Gi,Sx=Go.f,Ix=Hs,Mx=Gs,Ox=bx,Dx=wx,Rx=!1,Bx=Ji("meta"),zx=0,Px=function(t){Sx(t,Bx,{value:{objectID:"O"+zx++,weakData:{}}})},Fx=ux.exports={enable:function(){Fx.enable=function(){},Rx=!0;var t=Ix.f,e=Ex([].splice),i={};i[Bx]=1,t(i).length&&(Ix.f=function(i){for(var o=t(i),n=0,r=o.length;n1?arguments[1]:void 0);e=e?e.next:i.first;)for(o(e.value,e.key,this);e&&e.removed;)e=e.previous},has:function(t){return!!l(this,t)}}),oS(r,i?{get:function(t){var e=l(this,t);return e&&e.value},set:function(t,e){return a(this,0===t?0:t,e)}}:{add:function(t){return a(this,t=0===t?0:t,t)}}),dS&&iS(r,"size",{configurable:!0,get:function(){return s(this).size}}),n},setStrong:function(t,e,i){var o=e+" Iterator",n=pS(e),r=pS(o);lS(t,e,(function(t,e){fS(this,{type:o,target:t,state:n(t),kind:e,last:void 0})}),(function(){for(var t=r(this),e=t.kind,i=t.last;i&&i.removed;)i=i.previous;return t.target&&(t.last=i=i?i.next:t.state.first)?hS("keys"===e?i.key:"values"===e?i.value:[i.key,i.value],!1):(t.target=void 0,hS(void 0,!0))}),i?"entries":"values",!i,!0),cS(e)}};$x("Map",(function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}}),vS);var gS=Yt(Ye.Map),yS=el.some;kn({target:"Array",proto:!0,forced:!hf("some")},{some:function(t){return yS(this,t,arguments.length>1?arguments[1]:void 0)}});var mS=Ku("Array","some"),bS=ti,wS=mS,AS=Array.prototype,ES=function(t){var e=t.some;return t===AS||bS(AS,t)&&e===AS.some?wS:e},kS=Yt(ES),CS=Ku("Array","keys"),xS=or,SS=Gi,IS=ti,MS=CS,OS=Array.prototype,DS={DOMTokenList:!0,NodeList:!0},RS=function(t){var e=t.keys;return t===OS||IS(OS,t)&&e===OS.keys||SS(DS,xS(t))?MS:e},BS=Yt(RS),zS=Xs,PS=Math.floor,FS=function(t,e){var i=t.length,o=PS(i/2);return i<8?TS(t,e):NS(t,FS(zS(t,0,o),e),FS(zS(t,o),e),e)},TS=function(t,e){for(var i,o,n=t.length,r=1;r0;)t[o]=t[--o];o!==r++&&(t[o]=i)}return t},NS=function(t,e,i,o){for(var n=e.length,r=i.length,s=0,a=0;s3)){if(eI)return!0;if(oI)return oI<603;var t,e,i,o,n="";for(t=65;t<76;t++){switch(e=String.fromCharCode(t),t){case 66:case 69:case 70:case 72:i=3;break;case 68:case 71:i=4;break;default:i=2}for(o=0;o<47;o++)nI.push({k:e+o,v:i})}for(nI.sort((function(t,e){return e.v-t.v})),o=0;oJS(i)?1:-1}}(t)),i=YS(n),o=0;othis.max&&this.flush(),null!=this._timeout&&(clearTimeout(this._timeout),this._timeout=null),this.queue.length>0&&"number"==typeof this.delay&&(this._timeout=xy((function(){t.flush()}),this.delay))}},{key:"flush",value:function(){var t,e;$v(t=Bg(e=this._queue).call(e,0)).call(t,(function(t){t.fn.apply(t.context||t.fn,t.args||[])}))}}],[{key:"extend",value:function(e,i){var o=new t(i);if(void 0!==e.flush)throw new Error("Target object already has a property flush");e.flush=function(){o.flush()};var n=[{name:"flush",original:void 0}];if(i&&i.replace)for(var r=0;r=t.length?{done:!0}:{done:!1,value:t[o++]}},e:function(t){throw t},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function YI(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,o=new Array(e);idx.mark((function e(){var o,n,r,s,a;return dx.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:o=qI(i),e.prev=1,o.s();case 3:if((n=o.n()).done){e.next=10;break}if(r=Ev(n.value,2),s=r[0],a=r[1],!t(a,s)){e.next=8;break}return e.next=8,[s,a];case 8:e.next=3;break;case 10:e.next=15;break;case 12:e.prev=12,e.t0=e.catch(1),o.e(e.t0);case 15:return e.prev=15,o.f(),e.finish(15);case 18:case"end":return e.stop()}}),e,null,[[1,12,15,18]])}))()})}},{key:"forEach",value:function(t){var e,i=qI(this._pairs);try{for(i.s();!(e=i.n()).done;){var o=Ev(e.value,2),n=o[0];t(o[1],n)}}catch(t){i.e(t)}finally{i.f()}}},{key:"map",value:function(t){var i=this._pairs;return new e({[SI]:()=>dx.mark((function e(){var o,n,r,s,a;return dx.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:o=qI(i),e.prev=1,o.s();case 3:if((n=o.n()).done){e.next=9;break}return r=Ev(n.value,2),s=r[0],a=r[1],e.next=7,[s,t(a,s)];case 7:e.next=3;break;case 9:e.next=14;break;case 11:e.prev=11,e.t0=e.catch(1),o.e(e.t0);case 14:return e.prev=14,o.f(),e.finish(14);case 17:case"end":return e.stop()}}),e,null,[[1,11,14,17]])}))()})}},{key:"max",value:function(t){var e=KI(this._pairs),i=e.next();if(i.done)return null;for(var o=i.value[1],n=t(i.value[1],i.value[0]);!(i=e.next()).done;){var r=Ev(i.value,2),s=r[0],a=r[1],l=t(a,s);l>n&&(n=l,o=a)}return o}},{key:"min",value:function(t){var e=KI(this._pairs),i=e.next();if(i.done)return null;for(var o=i.value[1],n=t(i.value[1],i.value[0]);!(i=e.next()).done;){var r=Ev(i.value,2),s=r[0],a=r[1],l=t(a,s);l=t.length?{done:!0}:{done:!1,value:t[o++]}},e:function(t){throw t},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function $I(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,o=new Array(e);i1?i-1:0),n=1;nn?1:on)&&(o=s,n=a)}}catch(t){r.e(t)}finally{r.f()}return o||null}},{key:"min",value:function(t){var e,i,o=null,n=null,r=_I(xI(e=this._data).call(e));try{for(r.s();!(i=r.n()).done;){var s=i.value,a=s[t];"number"==typeof a&&(null==n||adx.mark((function i(){var o,n,r,s;return dx.wrap((function(i){for(;;)switch(i.prev=i.next){case 0:o=_I(t),i.prev=1,o.s();case 3:if((n=o.n()).done){i.next=11;break}if(r=n.value,null==(s=e.get(r))){i.next=9;break}return i.next=9,[r,s];case 9:i.next=3;break;case 11:i.next=16;break;case 13:i.prev=13,i.t0=i.catch(1),o.e(i.t0);case 16:return i.prev=16,o.f(),i.finish(16);case 19:case"end":return i.stop()}}),i,null,[[1,13,16,19]])}))()})}var i;return new ZI({[SI]:$u(i=FI(this._data)).call(i,this._data)})}}]),i}(WI);function iM(t,e){return"object"==typeof e&&null!==e&&t===e.idProp&&"function"==typeof $v(e)&&"function"==typeof e.get&&"function"==typeof e.getDataSet&&"function"==typeof e.getIds&&"number"==typeof e.length&&"function"==typeof Rf(e)&&"function"==typeof e.off&&"function"==typeof e.on&&"function"==typeof e.stream&&function(t,e){return"object"==typeof e&&null!==e&&t===e.idProp&&"function"==typeof e.add&&"function"==typeof e.clear&&"function"==typeof e.distinct&&"function"==typeof $v(e)&&"function"==typeof e.get&&"function"==typeof e.getDataSet&&"function"==typeof e.getIds&&"number"==typeof e.length&&"function"==typeof Rf(e)&&"function"==typeof e.max&&"function"==typeof e.min&&"function"==typeof e.off&&"function"==typeof e.on&&"function"==typeof e.remove&&"function"==typeof e.setOptions&&"function"==typeof e.stream&&"function"==typeof e.update&&"function"==typeof e.updateOnly}(t,e.getDataSet())} /** * vis-network * https://visjs.github.io/vis-network/ @@ -1062,41 +120,488 @@ function _x(){return _x=Object.assign||function(t){for(var e=1;e0&&RR[0]<4?1:+(RR[0]+RR[1])),!PR&&oP&&(!(RR=oP.match(/Edge\/(\d+)/))||RR[1]>=74)&&(RR=oP.match(/Chrome\/(\d+)/))&&(PR=+RR[1]);var lP=PR,cP=lP,hP=JA,uP=QA.String,pP=!!Object.getOwnPropertySymbols&&!hP((function(){var t=Symbol("symbol detection");return!uP(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&cP&&cP<41})),fP=pP&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,mP=tP,vP=_R,gP=eP,yP=Object,bP=fP?function(t){return"symbol"==typeof t}:function(t){var e=mP("Symbol");return vP(e)&&gP(e.prototype,yP(t))},xP=String,_P=function(t){try{return xP(t)}catch(t){return"Object"}},wP=_R,EP=_P,kP=TypeError,OP=function(t){if(wP(t))return t;throw new kP(EP(t)+" is not a function")},CP=OP,SP=zR,TP=function(t,e){var i=t[e];return SP(i)?void 0:CP(i)},IP=CR,AP=_R,RP=YR,PP=TypeError,DP={exports:{}},MP=QA,FP=Object.defineProperty,NP=function(t,e){try{FP(MP,t,{value:e,configurable:!0,writable:!0})}catch(i){MP[t]=e}return e},BP="__core-js_shared__",LP=QA[BP]||NP(BP,{}),zP=LP;(DP.exports=function(t,e){return zP[t]||(zP[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.33.0",mode:"pure",copyright:"© 2014-2023 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.33.0/LICENSE",source:"https://github.com/zloirock/core-js"});var jP=DP.exports,HP=$R,$P=Object,UP=function(t){return $P(HP(t))},WP=UP,VP=cR({}.hasOwnProperty),qP=Object.hasOwn||function(t,e){return VP(WP(t),e)},XP=cR,YP=0,GP=Math.random(),KP=XP(1..toString),ZP=function(t){return"Symbol("+(void 0===t?"":t)+")_"+KP(++YP+GP,36)},QP=jP,JP=qP,tD=ZP,eD=pP,iD=fP,nD=QA.Symbol,oD=QP("wks"),rD=iD?nD.for||nD:nD&&nD.withoutSetter||tD,sD=function(t){return JP(oD,t)||(oD[t]=eD&&JP(nD,t)?nD[t]:rD("Symbol."+t)),oD[t]},aD=CR,dD=YR,lD=bP,cD=TP,hD=function(t,e){var i,n;if("string"===e&&AP(i=t.toString)&&!RP(n=IP(i,t)))return n;if(AP(i=t.valueOf)&&!RP(n=IP(i,t)))return n;if("string"!==e&&AP(i=t.toString)&&!RP(n=IP(i,t)))return n;throw new PP("Can't convert object to primitive value")},uD=TypeError,pD=sD("toPrimitive"),fD=function(t,e){if(!dD(t)||lD(t))return t;var i,n=cD(t,pD);if(n){if(void 0===e&&(e="default"),i=aD(n,t,e),!dD(i)||lD(i))return i;throw new uD("Can't convert object to primitive value")}return void 0===e&&(e="number"),hD(t,e)},mD=bP,vD=function(t){var e=fD(t,"string");return mD(e)?e:e+""},gD=YR,yD=QA.document,bD=gD(yD)&&gD(yD.createElement),xD=function(t){return bD?yD.createElement(t):{}},_D=xD,wD=!ER&&!JA((function(){return 7!==Object.defineProperty(_D("div"),"a",{get:function(){return 7}}).a})),ED=ER,kD=CR,OD=SR,CD=DR,SD=VR,TD=vD,ID=qP,AD=wD,RD=Object.getOwnPropertyDescriptor;wR.f=ED?RD:function(t,e){if(t=SD(t),e=TD(e),AD)try{return RD(t,e)}catch(t){}if(ID(t,e))return CD(!kD(OD.f,t,e),t[e])};var PD=JA,DD=_R,MD=/#|\.prototype\./,FD=function(t,e){var i=BD[ND(t)];return i===zD||i!==LD&&(DD(e)?PD(e):!!e)},ND=FD.normalize=function(t){return String(t).replace(MD,".").toLowerCase()},BD=FD.data={},LD=FD.NATIVE="N",zD=FD.POLYFILL="P",jD=FD,HD=OP,$D=tR,UD=gR(gR.bind),WD=function(t,e){return HD(t),void 0===e?t:$D?UD(t,e):function(){return t.apply(e,arguments)}},VD={},qD=ER&&JA((function(){return 42!==Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype})),XD=YR,YD=String,GD=TypeError,KD=function(t){if(XD(t))return t;throw new GD(YD(t)+" is not an object")},ZD=ER,QD=wD,JD=qD,tM=KD,eM=vD,iM=TypeError,nM=Object.defineProperty,oM=Object.getOwnPropertyDescriptor,rM="enumerable",sM="configurable",aM="writable";VD.f=ZD?JD?function(t,e,i){if(tM(t),e=eM(e),tM(i),"function"==typeof t&&"prototype"===e&&"value"in i&&aM in i&&!i[aM]){var n=oM(t,e);n&&n[aM]&&(t[e]=i.value,i={configurable:sM in i?i[sM]:n[sM],enumerable:rM in i?i[rM]:n[rM],writable:!1})}return nM(t,e,i)}:nM:function(t,e,i){if(tM(t),e=eM(e),tM(i),QD)try{return nM(t,e,i)}catch(t){}if("get"in i||"set"in i)throw new iM("Accessors not supported");return"value"in i&&(t[e]=i.value),t};var dM=VD,lM=DR,cM=ER?function(t,e,i){return dM.f(t,e,lM(1,i))}:function(t,e,i){return t[e]=i,t},hM=QA,uM=rR,pM=gR,fM=_R,mM=wR.f,vM=jD,gM=GR,yM=WD,bM=cM,xM=qP,_M=function(t){var e=function(i,n,o){if(this instanceof e){switch(arguments.length){case 0:return new t;case 1:return new t(i);case 2:return new t(i,n)}return new t(i,n,o)}return uM(t,this,arguments)};return e.prototype=t.prototype,e},wM=function(t,e){var i,n,o,r,s,a,d,l,c,h=t.target,u=t.global,p=t.stat,f=t.proto,m=u?hM:p?hM[h]:(hM[h]||{}).prototype,v=u?gM:gM[h]||bM(gM,h,{})[h],g=v.prototype;for(r in e)n=!(i=vM(u?r:h+(p?".":"#")+r,t.forced))&&m&&xM(m,r),a=v[r],n&&(d=t.dontCallGetSet?(c=mM(m,r))&&c.value:m[r]),s=n&&d?d:e[r],n&&typeof a==typeof s||(l=t.bind&&n?yM(s,hM):t.wrap&&n?_M(s):f&&fM(s)?pM(s):s,(t.sham||s&&s.sham||a&&a.sham)&&bM(l,"sham",!0),bM(v,r,l),f&&(xM(gM,o=h+"Prototype")||bM(gM,o,{}),bM(gM[o],r,s),t.real&&g&&(i||!g[r])&&bM(g,r,s)))},EM=Math.ceil,kM=Math.floor,OM=Math.trunc||function(t){var e=+t;return(e>0?kM:EM)(e)},CM=OM,SM=function(t){var e=+t;return e!=e||0===e?0:CM(e)},TM=SM,IM=Math.max,AM=Math.min,RM=function(t,e){var i=TM(t);return i<0?IM(i+e,0):AM(i,e)},PM=SM,DM=Math.min,MM=function(t){return t>0?DM(PM(t),9007199254740991):0},FM=function(t){return MM(t.length)},NM=VR,BM=RM,LM=FM,zM=function(t){return function(e,i,n){var o,r=NM(e),s=LM(r),a=BM(n,s);if(t&&i!=i){for(;s>a;)if((o=r[a++])!=o)return!0}else for(;s>a;a++)if((t||a in r)&&r[a]===i)return t||a||0;return!t&&-1}},jM={includes:zM(!0),indexOf:zM(!1)},HM={},$M=qP,UM=VR,WM=jM.indexOf,VM=HM,qM=cR([].push),XM=function(t,e){var i,n=UM(t),o=0,r=[];for(i in n)!$M(VM,i)&&$M(n,i)&&qM(r,i);for(;e.length>o;)$M(n,i=e[o++])&&(~WM(r,i)||qM(r,i));return r},YM=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],GM=XM,KM=YM,ZM=Object.keys||function(t){return GM(t,KM)},QM={};QM.f=Object.getOwnPropertySymbols;var JM=ER,tF=cR,eF=CR,iF=JA,nF=ZM,oF=QM,rF=SR,sF=UP,aF=LR,dF=Object.assign,lF=Object.defineProperty,cF=tF([].concat),hF=!dF||iF((function(){if(JM&&1!==dF({b:1},dF(lF({},"a",{enumerable:!0,get:function(){lF(this,"b",{value:3,enumerable:!1})}}),{b:2})).b)return!0;var t={},e={},i=Symbol("assign detection"),n="abcdefghijklmnopqrst";return t[i]=7,n.split("").forEach((function(t){e[t]=t})),7!==dF({},t)[i]||nF(dF({},e)).join("")!==n}))?function(t,e){for(var i=sF(t),n=arguments.length,o=1,r=oF.f,s=rF.f;n>o;)for(var a,d=aF(arguments[o++]),l=r?cF(nF(d),r(d)):nF(d),c=l.length,h=0;c>h;)a=l[h++],JM&&!eF(s,d,a)||(i[a]=d[a]);return i}:dF,uF=hF;wM({target:"Object",stat:!0,arity:2,forced:Object.assign!==uF},{assign:uF});var pF=KA(GR.Object.assign),fF=cR([].slice),mF=cR,vF=OP,gF=YR,yF=qP,bF=fF,xF=tR,_F=Function,wF=mF([].concat),EF=mF([].join),kF={},OF=xF?_F.bind:function(t){var e=vF(this),i=e.prototype,n=bF(arguments,1),o=function(){var i=wF(n,bF(arguments));return this instanceof o?function(t,e,i){if(!yF(kF,e)){for(var n=[],o=0;o=.1;)(f=+r[h++%s])>c&&(f=c),p=Math.sqrt(f*f/(1+l*l)),e+=p=a<0?-p:p,i+=l*p,!0===u?t.lineTo(e,i):t.moveTo(e,i),c-=f,u=!u}var HF={circle:NF,dashedLine:jF,database:zF,diamond:function(t,e,i,n){t.beginPath(),t.lineTo(e,i+n),t.lineTo(e+n,i),t.lineTo(e,i-n),t.lineTo(e-n,i),t.closePath()},ellipse:LF,ellipse_vis:LF,hexagon:function(t,e,i,n){t.beginPath();var o=2*Math.PI/6;t.moveTo(e+n,i);for(var r=1;r<6;r++)t.lineTo(e+n*Math.cos(o*r),i+n*Math.sin(o*r));t.closePath()},roundRect:BF,square:function(t,e,i,n){t.beginPath(),t.rect(e-n,i-n,2*n,2*n),t.closePath()},star:function(t,e,i,n){t.beginPath(),i+=.1*(n*=.82);for(var o=0;o<10;o++){var r=o%2==0?1.3*n:.5*n;t.lineTo(e+r*Math.sin(2*o*Math.PI/10),i-r*Math.cos(2*o*Math.PI/10))}t.closePath()},triangle:function(t,e,i,n){t.beginPath(),i+=.275*(n*=1.15);var o=2*n,r=o/2,s=Math.sqrt(3)/6*o,a=Math.sqrt(o*o-r*r);t.moveTo(e,i-(a-s)),t.lineTo(e+r,i+s),t.lineTo(e-r,i+s),t.lineTo(e,i-(a-s)),t.closePath()},triangleDown:function(t,e,i,n){t.beginPath(),i-=.275*(n*=1.15);var o=2*n,r=o/2,s=Math.sqrt(3)/6*o,a=Math.sqrt(o*o-r*r);t.moveTo(e,i+(a-s)),t.lineTo(e+r,i-s),t.lineTo(e-r,i-s),t.lineTo(e,i+(a-s)),t.closePath()}};var $F={exports:{}};!function(t){function e(t){if(t)return function(t){for(var i in e.prototype)t[i]=e.prototype[i];return t}(t)}t.exports=e,e.prototype.on=e.prototype.addEventListener=function(t,e){return this._callbacks=this._callbacks||{},(this._callbacks["$"+t]=this._callbacks["$"+t]||[]).push(e),this},e.prototype.once=function(t,e){function i(){this.off(t,i),e.apply(this,arguments)}return i.fn=e,this.on(t,i),this},e.prototype.off=e.prototype.removeListener=e.prototype.removeAllListeners=e.prototype.removeEventListener=function(t,e){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var i,n=this._callbacks["$"+t];if(!n)return this;if(1==arguments.length)return delete this._callbacks["$"+t],this;for(var o=0;o=a?t?"":void 0:(n=cN(r,s))<55296||n>56319||s+1===a||(o=cN(r,s+1))<56320||o>57343?t?lN(r,s):n:t?hN(r,s,s+2):o-56320+(n-55296<<10)+65536}},pN={codeAt:uN(!1),charAt:uN(!0)},fN=_R,mN=QA.WeakMap,vN=fN(mN)&&/native code/.test(String(mN)),gN=ZP,yN=jP("keys"),bN=function(t){return yN[t]||(yN[t]=gN(t))},xN=vN,_N=QA,wN=YR,EN=cM,kN=qP,ON=LP,CN=bN,SN=HM,TN="Object already initialized",IN=_N.TypeError,AN=_N.WeakMap;if(xN||ON.state){var RN=ON.state||(ON.state=new AN);RN.get=RN.get,RN.has=RN.has,RN.set=RN.set,VF=function(t,e){if(RN.has(t))throw new IN(TN);return e.facade=t,RN.set(t,e),e},qF=function(t){return RN.get(t)||{}},XF=function(t){return RN.has(t)}}else{var PN=CN("state");SN[PN]=!0,VF=function(t,e){if(kN(t,PN))throw new IN(TN);return e.facade=t,EN(t,PN,e),e},qF=function(t){return kN(t,PN)?t[PN]:{}},XF=function(t){return kN(t,PN)}}var DN={set:VF,get:qF,has:XF,enforce:function(t){return XF(t)?qF(t):VF(t,{})},getterFor:function(t){return function(e){var i;if(!wN(e)||(i=qF(e)).type!==t)throw new IN("Incompatible receiver, "+t+" required");return i}}},MN=ER,FN=qP,NN=Function.prototype,BN=MN&&Object.getOwnPropertyDescriptor,LN=FN(NN,"name"),zN={EXISTS:LN,PROPER:LN&&"something"===function(){}.name,CONFIGURABLE:LN&&(!MN||MN&&BN(NN,"name").configurable)},jN={},HN=ER,$N=qD,UN=VD,WN=KD,VN=VR,qN=ZM;jN.f=HN&&!$N?Object.defineProperties:function(t,e){WN(t);for(var i,n=VN(e),o=qN(e),r=o.length,s=0;r>s;)UN.f(t,i=o[s++],n[i]);return t};var XN,YN=tP("document","documentElement"),GN=KD,KN=jN,ZN=YM,QN=HM,JN=YN,tB=xD,eB="prototype",iB="script",nB=bN("IE_PROTO"),oB=function(){},rB=function(t){return"<"+iB+">"+t+""},sB=function(t){t.write(rB("")),t.close();var e=t.parentWindow.Object;return t=null,e},aB=function(){try{XN=new ActiveXObject("htmlfile")}catch(t){}var t,e,i;aB="undefined"!=typeof document?document.domain&&XN?sB(XN):(e=tB("iframe"),i="java"+iB+":",e.style.display="none",JN.appendChild(e),e.src=String(i),(t=e.contentWindow.document).open(),t.write(rB("document.F=Object")),t.close(),t.F):sB(XN);for(var n=ZN.length;n--;)delete aB[eB][ZN[n]];return aB()};QN[nB]=!0;var dB,lB,cB,hB=Object.create||function(t,e){var i;return null!==t?(oB[eB]=GN(t),i=new oB,oB[eB]=null,i[nB]=t):i=aB(),void 0===e?i:KN.f(i,e)},uB=!JA((function(){function t(){}return t.prototype.constructor=null,Object.getPrototypeOf(new t)!==t.prototype})),pB=qP,fB=_R,mB=UP,vB=uB,gB=bN("IE_PROTO"),yB=Object,bB=yB.prototype,xB=vB?yB.getPrototypeOf:function(t){var e=mB(t);if(pB(e,gB))return e[gB];var i=e.constructor;return fB(i)&&e instanceof i?i.prototype:e instanceof yB?bB:null},_B=cM,wB=function(t,e,i,n){return n&&n.enumerable?t[e]=i:_B(t,e,i),t},EB=JA,kB=_R,OB=YR,CB=hB,SB=xB,TB=wB,IB=sD("iterator"),AB=!1;[].keys&&("next"in(cB=[].keys())?(lB=SB(SB(cB)))!==Object.prototype&&(dB=lB):AB=!0);var RB=!OB(dB)||EB((function(){var t={};return dB[IB].call(t)!==t}));kB((dB=RB?{}:CB(dB))[IB])||TB(dB,IB,(function(){return this}));var PB={IteratorPrototype:dB,BUGGY_SAFARI_ITERATORS:AB},DB=eN,MB=YF?{}.toString:function(){return"[object "+DB(this)+"]"},FB=YF,NB=VD.f,BB=cM,LB=qP,zB=MB,jB=sD("toStringTag"),HB=function(t,e,i,n){if(t){var o=i?t:t.prototype;LB(o,jB)||NB(o,jB,{configurable:!0,value:e}),n&&!FB&&BB(o,"toString",zB)}},$B={},UB=PB.IteratorPrototype,WB=hB,VB=DR,qB=HB,XB=$B,YB=function(){return this},GB=cR,KB=OP,ZB=_R,QB=String,JB=TypeError,tL=function(t,e,i){try{return GB(KB(Object.getOwnPropertyDescriptor(t,e)[i]))}catch(t){}},eL=KD,iL=function(t){if("object"==typeof t||ZB(t))return t;throw new JB("Can't set "+QB(t)+" as a prototype")},nL=Object.setPrototypeOf||("__proto__"in{}?function(){var t,e=!1,i={};try{(t=tL(Object.prototype,"__proto__","set"))(i,[]),e=i instanceof Array}catch(t){}return function(i,n){return eL(i),iL(n),e?t(i,n):i.__proto__=n,i}}():void 0),oL=wM,rL=CR,sL=function(t,e,i,n){var o=e+" Iterator";return t.prototype=WB(UB,{next:VB(+!n,i)}),qB(t,o,!1,!0),XB[o]=YB,t},aL=xB,dL=HB,lL=wB,cL=$B,hL=zN.PROPER,uL=PB.BUGGY_SAFARI_ITERATORS,pL=sD("iterator"),fL="keys",mL="values",vL="entries",gL=function(){return this},yL=function(t,e,i,n,o,r,s){sL(i,e,n);var a,d,l,c=function(t){if(t===o&&m)return m;if(!uL&&t&&t in p)return p[t];switch(t){case fL:case mL:case vL:return function(){return new i(this,t)}}return function(){return new i(this)}},h=e+" Iterator",u=!1,p=t.prototype,f=p[pL]||p["@@iterator"]||o&&p[o],m=!uL&&f||c(o),v="Array"===e&&p.entries||f;if(v&&(a=aL(v.call(new t)))!==Object.prototype&&a.next&&(dL(a,h,!0,!0),cL[h]=gL),hL&&o===mL&&f&&f.name!==mL&&(u=!0,m=function(){return rL(f,this)}),o)if(d={values:c(mL),keys:r?m:c(fL),entries:c(vL)},s)for(l in d)(uL||u||!(l in p))&&lL(p,l,d[l]);else oL({target:e,proto:!0,forced:uL||u},d);return s&&p[pL]!==m&&lL(p,pL,m,{name:o}),cL[e]=m,d},bL=function(t,e){return{value:t,done:e}},xL=pN.charAt,_L=oN,wL=DN,EL=yL,kL=bL,OL="String Iterator",CL=wL.set,SL=wL.getterFor(OL);EL(String,"String",(function(t){CL(this,{type:OL,string:_L(t),index:0})}),(function(){var t,e=SL(this),i=e.string,n=e.index;return n>=i.length?kL(void 0,!0):(t=xL(i,n),e.index+=t.length,kL(t,!1))}));var TL=CR,IL=KD,AL=TP,RL=function(t,e,i){var n,o;IL(t);try{if(!(n=AL(t,"return"))){if("throw"===e)throw i;return i}n=TL(n,t)}catch(t){o=!0,n=t}if("throw"===e)throw i;if(o)throw n;return IL(n),i},PL=KD,DL=RL,ML=$B,FL=sD("iterator"),NL=Array.prototype,BL=function(t){return void 0!==t&&(ML.Array===t||NL[FL]===t)},LL=_R,zL=LP,jL=cR(Function.toString);LL(zL.inspectSource)||(zL.inspectSource=function(t){return jL(t)});var HL=zL.inspectSource,$L=cR,UL=JA,WL=_R,VL=eN,qL=HL,XL=function(){},YL=[],GL=tP("Reflect","construct"),KL=/^\s*(?:class|function)\b/,ZL=$L(KL.exec),QL=!KL.test(XL),JL=function(t){if(!WL(t))return!1;try{return GL(XL,YL,t),!0}catch(t){return!1}},tz=function(t){if(!WL(t))return!1;switch(VL(t)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}try{return QL||!!ZL(KL,qL(t))}catch(t){return!0}};tz.sham=!0;var ez=!GL||UL((function(){var t;return JL(JL.call)||!JL(Object)||!JL((function(){t=!0}))||t}))?tz:JL,iz=vD,nz=VD,oz=DR,rz=function(t,e,i){var n=iz(e);n in t?nz.f(t,n,oz(0,i)):t[n]=i},sz=eN,az=TP,dz=zR,lz=$B,cz=sD("iterator"),hz=function(t){if(!dz(t))return az(t,cz)||az(t,"@@iterator")||lz[sz(t)]},uz=CR,pz=OP,fz=KD,mz=_P,vz=hz,gz=TypeError,yz=function(t,e){var i=arguments.length<2?vz(t):e;if(pz(i))return fz(uz(i,t));throw new gz(mz(t)+" is not iterable")},bz=WD,xz=CR,_z=UP,wz=function(t,e,i,n){try{return n?e(PL(i)[0],i[1]):e(i)}catch(e){DL(t,"throw",e)}},Ez=BL,kz=ez,Oz=FM,Cz=rz,Sz=yz,Tz=hz,Iz=Array,Az=sD("iterator"),Rz=!1;try{var Pz=0,Dz={next:function(){return{done:!!Pz++}},return:function(){Rz=!0}};Dz[Az]=function(){return this},Array.from(Dz,(function(){throw 2}))}catch(t){}var Mz=function(t){var e=_z(t),i=kz(this),n=arguments.length,o=n>1?arguments[1]:void 0,r=void 0!==o;r&&(o=bz(o,n>2?arguments[2]:void 0));var s,a,d,l,c,h,u=Tz(e),p=0;if(!u||this===Iz&&Ez(u))for(s=Oz(e),a=i?new this(s):Iz(s);s>p;p++)h=r?o(e[p],p):e[p],Cz(a,p,h);else for(c=(l=Sz(e,u)).next,a=i?new this:[];!(d=xz(c,l)).done;p++)h=r?wz(l,o,[d.value,p],!0):d.value,Cz(a,p,h);return a.length=p,a},Fz=function(t,e){try{if(!e&&!Rz)return!1}catch(t){return!1}var i=!1;try{var n={};n[Az]=function(){return{next:function(){return{done:i=!0}}}},t(n)}catch(t){}return i};wM({target:"Array",stat:!0,forced:!Fz((function(t){Array.from(t)}))},{from:Mz});var Nz=GR.Array.from,Bz=KA(Nz),Lz=VR,zz=$B,jz=DN;VD.f;var Hz=yL,$z=bL,Uz="Array Iterator",Wz=jz.set,Vz=jz.getterFor(Uz);Hz(Array,"Array",(function(t,e){Wz(this,{type:Uz,target:Lz(t),index:0,kind:e})}),(function(){var t=Vz(this),e=t.target,i=t.kind,n=t.index++;if(!e||n>=e.length)return t.target=void 0,$z(void 0,!0);switch(i){case"keys":return $z(n,!1);case"values":return $z(e[n],!1)}return $z([n,e[n]],!1)}),"values"),zz.Arguments=zz.Array;var qz=hz,Xz={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0},Yz=QA,Gz=eN,Kz=cM,Zz=$B,Qz=sD("toStringTag");for(var Jz in Xz){var tj=Yz[Jz],ej=tj&&tj.prototype;ej&&Gz(ej)!==Qz&&Kz(ej,Qz,Jz),Zz[Jz]=Zz.Array}var ij=qz,nj=KA(ij),oj=KA(ij);function rj(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var sj={exports:{}},aj=wM,dj=ER,lj=VD.f;aj({target:"Object",stat:!0,forced:Object.defineProperty!==lj,sham:!dj},{defineProperty:lj});var cj=GR.Object,hj=sj.exports=function(t,e,i){return cj.defineProperty(t,e,i)};cj.defineProperty.sham&&(hj.sham=!0);var uj=sj.exports,pj=KA(uj),fj=fR,mj=Array.isArray||function(t){return"Array"===fj(t)},vj=TypeError,gj=function(t){if(t>9007199254740991)throw vj("Maximum allowed index exceeded");return t},yj=mj,bj=ez,xj=YR,_j=sD("species"),wj=Array,Ej=function(t){var e;return yj(t)&&(e=t.constructor,(bj(e)&&(e===wj||yj(e.prototype))||xj(e)&&null===(e=e[_j]))&&(e=void 0)),void 0===e?wj:e},kj=function(t,e){return new(Ej(t))(0===e?0:e)},Oj=JA,Cj=lP,Sj=sD("species"),Tj=function(t){return Cj>=51||!Oj((function(){var e=[];return(e.constructor={})[Sj]=function(){return{foo:1}},1!==e[t](Boolean).foo}))},Ij=wM,Aj=JA,Rj=mj,Pj=YR,Dj=UP,Mj=FM,Fj=gj,Nj=rz,Bj=kj,Lj=Tj,zj=lP,jj=sD("isConcatSpreadable"),Hj=zj>=51||!Aj((function(){var t=[];return t[jj]=!1,t.concat()[0]!==t})),$j=function(t){if(!Pj(t))return!1;var e=t[jj];return void 0!==e?!!e:Rj(t)};Ij({target:"Array",proto:!0,arity:1,forced:!Hj||!Lj("concat")},{concat:function(t){var e,i,n,o,r,s=Dj(this),a=Bj(s,0),d=0;for(e=-1,n=arguments.length;ey;y++)if((a||y in m)&&(p=v(u=m[y],y,f),t))if(e)x[y]=p;else if(p)switch(t){case 3:return!0;case 5:return u;case 6:return y;case 2:EH(x,u)}else switch(t){case 4:return!1;case 7:EH(x,u)}return r?-1:n||o?o:x}},OH={forEach:kH(0),map:kH(1),filter:kH(2),some:kH(3),every:kH(4),find:kH(5),findIndex:kH(6),filterReject:kH(7)},CH=wM,SH=QA,TH=CR,IH=cR,AH=ER,RH=pP,PH=JA,DH=qP,MH=eP,FH=KD,NH=VR,BH=vD,LH=oN,zH=DR,jH=hB,HH=ZM,$H=Uj,UH=qj,WH=QM,VH=wR,qH=VD,XH=jN,YH=SR,GH=wB,KH=rH,ZH=jP,QH=HM,JH=ZP,t$=sD,e$=sH,i$=uH,n$=gH,o$=HB,r$=DN,s$=OH.forEach,a$=bN("hidden"),d$="Symbol",l$="prototype",c$=r$.set,h$=r$.getterFor(d$),u$=Object[l$],p$=SH.Symbol,f$=p$&&p$[l$],m$=SH.RangeError,v$=SH.TypeError,g$=SH.QObject,y$=VH.f,b$=qH.f,x$=UH.f,_$=YH.f,w$=IH([].push),E$=ZH("symbols"),k$=ZH("op-symbols"),O$=ZH("wks"),C$=!g$||!g$[l$]||!g$[l$].findChild,S$=function(t,e,i){var n=y$(u$,e);n&&delete u$[e],b$(t,e,i),n&&t!==u$&&b$(u$,e,n)},T$=AH&&PH((function(){return 7!==jH(b$({},"a",{get:function(){return b$(this,"a",{value:7}).a}})).a}))?S$:b$,I$=function(t,e){var i=E$[t]=jH(f$);return c$(i,{type:d$,tag:t,description:e}),AH||(i.description=e),i},A$=function(t,e,i){t===u$&&A$(k$,e,i),FH(t);var n=BH(e);return FH(i),DH(E$,n)?(i.enumerable?(DH(t,a$)&&t[a$][n]&&(t[a$][n]=!1),i=jH(i,{enumerable:zH(0,!1)})):(DH(t,a$)||b$(t,a$,zH(1,{})),t[a$][n]=!0),T$(t,n,i)):b$(t,n,i)},R$=function(t,e){FH(t);var i=NH(e),n=HH(i).concat(F$(i));return s$(n,(function(e){AH&&!TH(P$,i,e)||A$(t,e,i[e])})),t},P$=function(t){var e=BH(t),i=TH(_$,this,e);return!(this===u$&&DH(E$,e)&&!DH(k$,e))&&(!(i||!DH(this,e)||!DH(E$,e)||DH(this,a$)&&this[a$][e])||i)},D$=function(t,e){var i=NH(t),n=BH(e);if(i!==u$||!DH(E$,n)||DH(k$,n)){var o=y$(i,n);return!o||!DH(E$,n)||DH(i,a$)&&i[a$][n]||(o.enumerable=!0),o}},M$=function(t){var e=x$(NH(t)),i=[];return s$(e,(function(t){DH(E$,t)||DH(QH,t)||w$(i,t)})),i},F$=function(t){var e=t===u$,i=x$(e?k$:NH(t)),n=[];return s$(i,(function(t){!DH(E$,t)||e&&!DH(u$,t)||w$(n,E$[t])})),n};RH||(p$=function(){if(MH(f$,this))throw new v$("Symbol is not a constructor");var t=arguments.length&&void 0!==arguments[0]?LH(arguments[0]):void 0,e=JH(t),i=function(t){this===u$&&TH(i,k$,t),DH(this,a$)&&DH(this[a$],e)&&(this[a$][e]=!1);var n=zH(1,t);try{T$(this,e,n)}catch(t){if(!(t instanceof m$))throw t;S$(this,e,n)}};return AH&&C$&&T$(u$,e,{configurable:!0,set:i}),I$(e,t)},GH(f$=p$[l$],"toString",(function(){return h$(this).tag})),GH(p$,"withoutSetter",(function(t){return I$(JH(t),t)})),YH.f=P$,qH.f=A$,XH.f=R$,VH.f=D$,$H.f=UH.f=M$,WH.f=F$,e$.f=function(t){return I$(t$(t),t)},AH&&KH(f$,"description",{configurable:!0,get:function(){return h$(this).description}})),CH({global:!0,constructor:!0,wrap:!0,forced:!RH,sham:!RH},{Symbol:p$}),s$(HH(O$),(function(t){i$(t)})),CH({target:d$,stat:!0,forced:!RH},{useSetter:function(){C$=!0},useSimple:function(){C$=!1}}),CH({target:"Object",stat:!0,forced:!RH,sham:!AH},{create:function(t,e){return void 0===e?jH(t):R$(jH(t),e)},defineProperty:A$,defineProperties:R$,getOwnPropertyDescriptor:D$}),CH({target:"Object",stat:!0,forced:!RH},{getOwnPropertyNames:M$}),n$(),o$(p$,d$),QH[a$]=!0;var N$=pP&&!!Symbol.for&&!!Symbol.keyFor,B$=wM,L$=tP,z$=qP,j$=oN,H$=jP,$$=N$,U$=H$("string-to-symbol-registry"),W$=H$("symbol-to-string-registry");B$({target:"Symbol",stat:!0,forced:!$$},{for:function(t){var e=j$(t);if(z$(U$,e))return U$[e];var i=L$("Symbol")(e);return U$[e]=i,W$[i]=e,i}});var V$=wM,q$=qP,X$=bP,Y$=_P,G$=N$,K$=jP("symbol-to-string-registry");V$({target:"Symbol",stat:!0,forced:!G$},{keyFor:function(t){if(!X$(t))throw new TypeError(Y$(t)+" is not a symbol");if(q$(K$,t))return K$[t]}});var Z$=mj,Q$=_R,J$=fR,tU=oN,eU=cR([].push),iU=wM,nU=tP,oU=rR,rU=CR,sU=cR,aU=JA,dU=_R,lU=bP,cU=fF,hU=function(t){if(Q$(t))return t;if(Z$(t)){for(var e=t.length,i=[],n=0;nt.length)&&(e=t.length);for(var i=0,n=new Array(e);i1?arguments[1]:void 0)}});var vV=TF("Array").map,gV=eP,yV=vV,bV=Array.prototype,xV=function(t){var e=t.map;return t===bV||gV(bV,t)&&e===bV.map?yV:e},_V=KA(xV),wV=UP,EV=ZM;wM({target:"Object",stat:!0,forced:JA((function(){EV(1)}))},{keys:function(t){return EV(wV(t))}});var kV=KA(GR.Object.keys),OV=wM,CV=Date,SV=cR(CV.prototype.getTime);OV({target:"Date",stat:!0},{now:function(){return SV(new CV)}});var TV=KA(GR.Date.now),IV=JA,AV=function(t,e){var i=[][t];return!!i&&IV((function(){i.call(null,e||function(){return 1},1)}))},RV=OH.forEach,PV=AV("forEach")?[].forEach:function(t){return RV(this,t,arguments.length>1?arguments[1]:void 0)};wM({target:"Array",proto:!0,forced:[].forEach!==PV},{forEach:PV});var DV=TF("Array").forEach,MV=eN,FV=qP,NV=eP,BV=DV,LV=Array.prototype,zV={DOMTokenList:!0,NodeList:!0},jV=function(t){var e=t.forEach;return t===LV||NV(LV,t)&&e===LV.forEach||FV(zV,MV(t))?BV:e},HV=KA(jV),$V=wM,UV=mj,WV=cR([].reverse),VV=[1,2];$V({target:"Array",proto:!0,forced:String(VV)===String(VV.reverse())},{reverse:function(){return UV(this)&&(this.length=this.length),WV(this)}});var qV=TF("Array").reverse,XV=eP,YV=qV,GV=Array.prototype,KV=function(t){var e=t.reverse;return t===GV||XV(GV,t)&&e===GV.reverse?YV:e},ZV=KA(KV),QV=_P,JV=TypeError,tq=function(t,e){if(!delete t[e])throw new JV("Cannot delete property "+QV(e)+" of "+QV(t))},eq=wM,iq=UP,nq=RM,oq=SM,rq=FM,sq=gW,aq=gj,dq=kj,lq=rz,cq=tq,hq=Tj("splice"),uq=Math.max,pq=Math.min;eq({target:"Array",proto:!0,forced:!hq},{splice:function(t,e){var i,n,o,r,s,a,d=iq(this),l=rq(d),c=nq(t,l),h=arguments.length;for(0===h?i=n=0:1===h?(i=0,n=l-c):(i=h-2,n=pq(uq(oq(e),0),l-c)),aq(l+i-n),o=dq(d,n),r=0;rl-n+i;r--)cq(d,r-1)}else if(i>n)for(r=l-n;r>c;r--)a=r+i-1,(s=r+n-1)in d?d[a]=d[s]:cq(d,a);for(r=0;r1?arguments[1]:void 0)}});var _q=TF("Array").includes,wq=YR,Eq=fR,kq=sD("match"),Oq=function(t){var e;return wq(t)&&(void 0!==(e=t[kq])?!!e:"RegExp"===Eq(t))},Cq=TypeError,Sq=sD("match"),Tq=wM,Iq=function(t){if(Oq(t))throw new Cq("The method doesn't accept regular expressions");return t},Aq=$R,Rq=oN,Pq=function(t){var e=/./;try{"/./"[t](e)}catch(i){try{return e[Sq]=!1,"/./"[t](e)}catch(t){}}return!1},Dq=cR("".indexOf);Tq({target:"String",proto:!0,forced:!Pq("includes")},{includes:function(t){return!!~Dq(Rq(Aq(this)),Rq(Iq(t)),arguments.length>1?arguments[1]:void 0)}});var Mq=TF("String").includes,Fq=eP,Nq=_q,Bq=Mq,Lq=Array.prototype,zq=String.prototype,jq=function(t){var e=t.includes;return t===Lq||Fq(Lq,t)&&e===Lq.includes?Nq:"string"==typeof t||t===zq||Fq(zq,t)&&e===zq.includes?Bq:e},Hq=KA(jq),$q=UP,Uq=xB,Wq=uB;wM({target:"Object",stat:!0,forced:JA((function(){Uq(1)})),sham:!Wq},{getPrototypeOf:function(t){return Uq($q(t))}});var Vq=GR.Object.getPrototypeOf,qq=KA(Vq),Xq=OH.filter;wM({target:"Array",proto:!0,forced:!Tj("filter")},{filter:function(t){return Xq(this,t,arguments.length>1?arguments[1]:void 0)}});var Yq=TF("Array").filter,Gq=eP,Kq=Yq,Zq=Array.prototype,Qq=function(t){var e=t.filter;return t===Zq||Gq(Zq,t)&&e===Zq.filter?Kq:e},Jq=KA(Qq),tX="\t\n\v\f\r                 \u2028\u2029\ufeff",eX=$R,iX=oN,nX=tX,oX=cR("".replace),rX=RegExp("^["+nX+"]+"),sX=RegExp("(^|[^"+nX+"])["+nX+"]+$"),aX=function(t){return function(e){var i=iX(eX(e));return 1&t&&(i=oX(i,rX,"")),2&t&&(i=oX(i,sX,"$1")),i}},dX={start:aX(1),end:aX(2),trim:aX(3)},lX=QA,cX=JA,hX=cR,uX=oN,pX=dX.trim,fX=tX,mX=lX.parseInt,vX=lX.Symbol,gX=vX&&vX.iterator,yX=/^[+-]?0x/i,bX=hX(yX.exec),xX=8!==mX(fX+"08")||22!==mX(fX+"0x16")||gX&&!cX((function(){mX(Object(gX))}))?function(t,e){var i=pX(uX(t));return mX(i,e>>>0||(bX(yX,i)?16:10))}:mX;wM({global:!0,forced:parseInt!==xX},{parseInt:xX});var _X=KA(GR.parseInt),wX=wM,EX=jM.indexOf,kX=AV,OX=gR([].indexOf),CX=!!OX&&1/OX([1],1,-0)<0;wX({target:"Array",proto:!0,forced:CX||!kX("indexOf")},{indexOf:function(t){var e=arguments.length>1?arguments[1]:void 0;return CX?OX(this,t,e)||0:EX(this,t,e)}});var SX=TF("Array").indexOf,TX=eP,IX=SX,AX=Array.prototype,RX=function(t){var e=t.indexOf;return t===AX||TX(AX,t)&&e===AX.indexOf?IX:e},PX=KA(RX);wM({target:"Object",stat:!0,sham:!ER},{create:hB});var DX=GR.Object,MX=function(t,e){return DX.create(t,e)},FX=MX,NX=KA(FX),BX=GR,LX=rR;BX.JSON||(BX.JSON={stringify:JSON.stringify});var zX=function(t,e,i){return LX(BX.JSON.stringify,null,arguments)},jX=KA(zX),HX="function"==typeof Bun&&Bun&&"string"==typeof Bun.version,$X=TypeError,UX=QA,WX=rR,VX=_R,qX=HX,XX=iP,YX=fF,GX=function(t,e){if(ti,s=VX(n)?n:KX(n),a=r?YX(arguments,i):[],d=r?function(){WX(s,this,a)}:s;return e?t(d,o):t(d)}:t},JX=wM,tY=QA,eY=QX(tY.setInterval,!0);JX({global:!0,bind:!0,forced:tY.setInterval!==eY},{setInterval:eY});var iY=wM,nY=QA,oY=QX(nY.setTimeout,!0);iY({global:!0,bind:!0,forced:nY.setTimeout!==oY},{setTimeout:oY});var rY=KA(GR.setTimeout),sY=UP,aY=RM,dY=FM,lY=function(t){for(var e=sY(this),i=dY(e),n=arguments.length,o=aY(n>1?arguments[1]:void 0,i),r=n>2?arguments[2]:void 0,s=void 0===r?i:aY(r,i);s>o;)e[o++]=t;return e};wM({target:"Array",proto:!0},{fill:lY});var cY,hY=TF("Array").fill,uY=eP,pY=hY,fY=Array.prototype,mY=function(t){var e=t.fill;return t===fY||uY(fY,t)&&e===fY.fill?pY:e},vY=KA(mY); + */var oM="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function nM(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var rM=function(t){return t&&t.Math===Math&&t},sM=rM("object"==typeof globalThis&&globalThis)||rM("object"==typeof window&&window)||rM("object"==typeof self&&self)||rM("object"==typeof oM&&oM)||function(){return this}()||oM||Function("return this")(),aM=function(t){try{return!!t()}catch(t){return!0}},lM=!aM((function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")})),hM=lM,cM=Function.prototype,dM=cM.apply,uM=cM.call,fM="object"==typeof Reflect&&Reflect.apply||(hM?uM.bind(dM):function(){return uM.apply(dM,arguments)}),pM=lM,vM=Function.prototype,gM=vM.call,yM=pM&&vM.bind.bind(gM,gM),mM=pM?yM:function(t){return function(){return gM.apply(t,arguments)}},bM=mM,wM=bM({}.toString),AM=bM("".slice),EM=function(t){return AM(wM(t),8,-1)},kM=EM,CM=mM,xM=function(t){if("Function"===kM(t))return CM(t)},SM="object"==typeof document&&document.all,IM={all:SM,IS_HTMLDDA:void 0===SM&&void 0!==SM},MM=IM.all,OM=IM.IS_HTMLDDA?function(t){return"function"==typeof t||t===MM}:function(t){return"function"==typeof t},DM={},RM=!aM((function(){return 7!==Object.defineProperty({},1,{get:function(){return 7}})[1]})),BM=lM,zM=Function.prototype.call,PM=BM?zM.bind(zM):function(){return zM.apply(zM,arguments)},FM={},TM={}.propertyIsEnumerable,NM=Object.getOwnPropertyDescriptor,jM=NM&&!TM.call({1:2},1);FM.f=jM?function(t){var e=NM(this,t);return!!e&&e.enumerable}:TM;var UM,LM,QM=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}},HM=aM,VM=EM,WM=Object,GM=mM("".split),KM=HM((function(){return!WM("z").propertyIsEnumerable(0)}))?function(t){return"String"===VM(t)?GM(t,""):WM(t)}:WM,qM=function(t){return null==t},YM=qM,ZM=TypeError,JM=function(t){if(YM(t))throw new ZM("Can't call method on "+t);return t},XM=KM,_M=JM,$M=function(t){return XM(_M(t))},tO=OM,eO=IM.all,iO=IM.IS_HTMLDDA?function(t){return"object"==typeof t?null!==t:tO(t)||t===eO}:function(t){return"object"==typeof t?null!==t:tO(t)},oO={},nO=oO,rO=sM,sO=OM,aO=function(t){return sO(t)?t:void 0},lO=function(t,e){return arguments.length<2?aO(nO[t])||aO(rO[t]):nO[t]&&nO[t][e]||rO[t]&&rO[t][e]},hO=mM({}.isPrototypeOf),cO="undefined"!=typeof navigator&&String(navigator.userAgent)||"",dO=sM,uO=cO,fO=dO.process,pO=dO.Deno,vO=fO&&fO.versions||pO&&pO.version,gO=vO&&vO.v8;gO&&(LM=(UM=gO.split("."))[0]>0&&UM[0]<4?1:+(UM[0]+UM[1])),!LM&&uO&&(!(UM=uO.match(/Edge\/(\d+)/))||UM[1]>=74)&&(UM=uO.match(/Chrome\/(\d+)/))&&(LM=+UM[1]);var yO=LM,mO=yO,bO=aM,wO=sM.String,AO=!!Object.getOwnPropertySymbols&&!bO((function(){var t=Symbol("symbol detection");return!wO(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&mO&&mO<41})),EO=AO&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,kO=lO,CO=OM,xO=hO,SO=Object,IO=EO?function(t){return"symbol"==typeof t}:function(t){var e=kO("Symbol");return CO(e)&&xO(e.prototype,SO(t))},MO=String,OO=function(t){try{return MO(t)}catch(t){return"Object"}},DO=OM,RO=OO,BO=TypeError,zO=function(t){if(DO(t))return t;throw new BO(RO(t)+" is not a function")},PO=zO,FO=qM,TO=function(t,e){var i=t[e];return FO(i)?void 0:PO(i)},NO=PM,jO=OM,UO=iO,LO=TypeError,QO={exports:{}},HO=sM,VO=Object.defineProperty,WO=function(t,e){try{VO(HO,t,{value:e,configurable:!0,writable:!0})}catch(i){HO[t]=e}return e},GO="__core-js_shared__",KO=sM[GO]||WO(GO,{}),qO=KO;(QO.exports=function(t,e){return qO[t]||(qO[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.33.0",mode:"pure",copyright:"© 2014-2023 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.33.0/LICENSE",source:"https://github.com/zloirock/core-js"});var YO=QO.exports,ZO=JM,JO=Object,XO=function(t){return JO(ZO(t))},_O=XO,$O=mM({}.hasOwnProperty),tD=Object.hasOwn||function(t,e){return $O(_O(t),e)},eD=mM,iD=0,oD=Math.random(),nD=eD(1..toString),rD=function(t){return"Symbol("+(void 0===t?"":t)+")_"+nD(++iD+oD,36)},sD=YO,aD=tD,lD=rD,hD=AO,cD=EO,dD=sM.Symbol,uD=sD("wks"),fD=cD?dD.for||dD:dD&&dD.withoutSetter||lD,pD=function(t){return aD(uD,t)||(uD[t]=hD&&aD(dD,t)?dD[t]:fD("Symbol."+t)),uD[t]},vD=PM,gD=iO,yD=IO,mD=TO,bD=function(t,e){var i,o;if("string"===e&&jO(i=t.toString)&&!UO(o=NO(i,t)))return o;if(jO(i=t.valueOf)&&!UO(o=NO(i,t)))return o;if("string"!==e&&jO(i=t.toString)&&!UO(o=NO(i,t)))return o;throw new LO("Can't convert object to primitive value")},wD=TypeError,AD=pD("toPrimitive"),ED=function(t,e){if(!gD(t)||yD(t))return t;var i,o=mD(t,AD);if(o){if(void 0===e&&(e="default"),i=vD(o,t,e),!gD(i)||yD(i))return i;throw new wD("Can't convert object to primitive value")}return void 0===e&&(e="number"),bD(t,e)},kD=IO,CD=function(t){var e=ED(t,"string");return kD(e)?e:e+""},xD=iO,SD=sM.document,ID=xD(SD)&&xD(SD.createElement),MD=function(t){return ID?SD.createElement(t):{}},OD=MD,DD=!RM&&!aM((function(){return 7!==Object.defineProperty(OD("div"),"a",{get:function(){return 7}}).a})),RD=RM,BD=PM,zD=FM,PD=QM,FD=$M,TD=CD,ND=tD,jD=DD,UD=Object.getOwnPropertyDescriptor;DM.f=RD?UD:function(t,e){if(t=FD(t),e=TD(e),jD)try{return UD(t,e)}catch(t){}if(ND(t,e))return PD(!BD(zD.f,t,e),t[e])};var LD=aM,QD=OM,HD=/#|\.prototype\./,VD=function(t,e){var i=GD[WD(t)];return i===qD||i!==KD&&(QD(e)?LD(e):!!e)},WD=VD.normalize=function(t){return String(t).replace(HD,".").toLowerCase()},GD=VD.data={},KD=VD.NATIVE="N",qD=VD.POLYFILL="P",YD=VD,ZD=zO,JD=lM,XD=xM(xM.bind),_D=function(t,e){return ZD(t),void 0===e?t:JD?XD(t,e):function(){return t.apply(e,arguments)}},$D={},tR=RM&&aM((function(){return 42!==Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype})),eR=iO,iR=String,oR=TypeError,nR=function(t){if(eR(t))return t;throw new oR(iR(t)+" is not an object")},rR=RM,sR=DD,aR=tR,lR=nR,hR=CD,cR=TypeError,dR=Object.defineProperty,uR=Object.getOwnPropertyDescriptor,fR="enumerable",pR="configurable",vR="writable";$D.f=rR?aR?function(t,e,i){if(lR(t),e=hR(e),lR(i),"function"==typeof t&&"prototype"===e&&"value"in i&&vR in i&&!i[vR]){var o=uR(t,e);o&&o[vR]&&(t[e]=i.value,i={configurable:pR in i?i[pR]:o[pR],enumerable:fR in i?i[fR]:o[fR],writable:!1})}return dR(t,e,i)}:dR:function(t,e,i){if(lR(t),e=hR(e),lR(i),sR)try{return dR(t,e,i)}catch(t){}if("get"in i||"set"in i)throw new cR("Accessors not supported");return"value"in i&&(t[e]=i.value),t};var gR=$D,yR=QM,mR=RM?function(t,e,i){return gR.f(t,e,yR(1,i))}:function(t,e,i){return t[e]=i,t},bR=sM,wR=fM,AR=xM,ER=OM,kR=DM.f,CR=YD,xR=oO,SR=_D,IR=mR,MR=tD,OR=function(t){var e=function(i,o,n){if(this instanceof e){switch(arguments.length){case 0:return new t;case 1:return new t(i);case 2:return new t(i,o)}return new t(i,o,n)}return wR(t,this,arguments)};return e.prototype=t.prototype,e},DR=function(t,e){var i,o,n,r,s,a,l,h,c,d=t.target,u=t.global,f=t.stat,p=t.proto,v=u?bR:f?bR[d]:(bR[d]||{}).prototype,g=u?xR:xR[d]||IR(xR,d,{})[d],y=g.prototype;for(r in e)o=!(i=CR(u?r:d+(f?".":"#")+r,t.forced))&&v&&MR(v,r),a=g[r],o&&(l=t.dontCallGetSet?(c=kR(v,r))&&c.value:v[r]),s=o&&l?l:e[r],o&&typeof a==typeof s||(h=t.bind&&o?SR(s,bR):t.wrap&&o?OR(s):p&&ER(s)?AR(s):s,(t.sham||s&&s.sham||a&&a.sham)&&IR(h,"sham",!0),IR(g,r,h),p&&(MR(xR,n=d+"Prototype")||IR(xR,n,{}),IR(xR[n],r,s),t.real&&y&&(i||!y[r])&&IR(y,r,s)))},RR=Math.ceil,BR=Math.floor,zR=Math.trunc||function(t){var e=+t;return(e>0?BR:RR)(e)},PR=zR,FR=function(t){var e=+t;return e!=e||0===e?0:PR(e)},TR=FR,NR=Math.max,jR=Math.min,UR=function(t,e){var i=TR(t);return i<0?NR(i+e,0):jR(i,e)},LR=FR,QR=Math.min,HR=function(t){return t>0?QR(LR(t),9007199254740991):0},VR=function(t){return HR(t.length)},WR=$M,GR=UR,KR=VR,qR=function(t){return function(e,i,o){var n,r=WR(e),s=KR(r),a=GR(o,s);if(t&&i!=i){for(;s>a;)if((n=r[a++])!=n)return!0}else for(;s>a;a++)if((t||a in r)&&r[a]===i)return t||a||0;return!t&&-1}},YR={includes:qR(!0),indexOf:qR(!1)},ZR={},JR=tD,XR=$M,_R=YR.indexOf,$R=ZR,tB=mM([].push),eB=function(t,e){var i,o=XR(t),n=0,r=[];for(i in o)!JR($R,i)&&JR(o,i)&&tB(r,i);for(;e.length>n;)JR(o,i=e[n++])&&(~_R(r,i)||tB(r,i));return r},iB=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],oB=eB,nB=iB,rB=Object.keys||function(t){return oB(t,nB)},sB={};sB.f=Object.getOwnPropertySymbols;var aB=RM,lB=mM,hB=PM,cB=aM,dB=rB,uB=sB,fB=FM,pB=XO,vB=KM,gB=Object.assign,yB=Object.defineProperty,mB=lB([].concat),bB=!gB||cB((function(){if(aB&&1!==gB({b:1},gB(yB({},"a",{enumerable:!0,get:function(){yB(this,"b",{value:3,enumerable:!1})}}),{b:2})).b)return!0;var t={},e={},i=Symbol("assign detection"),o="abcdefghijklmnopqrst";return t[i]=7,o.split("").forEach((function(t){e[t]=t})),7!==gB({},t)[i]||dB(gB({},e)).join("")!==o}))?function(t,e){for(var i=pB(t),o=arguments.length,n=1,r=uB.f,s=fB.f;o>n;)for(var a,l=vB(arguments[n++]),h=r?mB(dB(l),r(l)):dB(l),c=h.length,d=0;c>d;)a=h[d++],aB&&!hB(s,l,a)||(i[a]=l[a]);return i}:gB,wB=bB;DR({target:"Object",stat:!0,arity:2,forced:Object.assign!==wB},{assign:wB});var AB=nM(oO.Object.assign),EB=mM([].slice),kB=mM,CB=zO,xB=iO,SB=tD,IB=EB,MB=lM,OB=Function,DB=kB([].concat),RB=kB([].join),BB={},zB=MB?OB.bind:function(t){var e=CB(this),i=e.prototype,o=IB(arguments,1),n=function(){var i=DB(o,IB(arguments));return this instanceof n?function(t,e,i){if(!SB(BB,e)){for(var o=[],n=0;n=.1;)(p=+r[d++%s])>c&&(p=c),f=Math.sqrt(p*p/(1+h*h)),e+=f=a<0?-f:f,i+=h*f,!0===u?t.lineTo(e,i):t.moveTo(e,i),c-=p,u=!u}var ZB={circle:WB,dashedLine:YB,database:qB,diamond:function(t,e,i,o){t.beginPath(),t.lineTo(e,i+o),t.lineTo(e+o,i),t.lineTo(e,i-o),t.lineTo(e-o,i),t.closePath()},ellipse:KB,ellipse_vis:KB,hexagon:function(t,e,i,o){t.beginPath();var n=2*Math.PI/6;t.moveTo(e+o,i);for(var r=1;r<6;r++)t.lineTo(e+o*Math.cos(n*r),i+o*Math.sin(n*r));t.closePath()},roundRect:GB,square:function(t,e,i,o){t.beginPath(),t.rect(e-o,i-o,2*o,2*o),t.closePath()},star:function(t,e,i,o){t.beginPath(),i+=.1*(o*=.82);for(var n=0;n<10;n++){var r=n%2==0?1.3*o:.5*o;t.lineTo(e+r*Math.sin(2*n*Math.PI/10),i-r*Math.cos(2*n*Math.PI/10))}t.closePath()},triangle:function(t,e,i,o){t.beginPath(),i+=.275*(o*=1.15);var n=2*o,r=n/2,s=Math.sqrt(3)/6*n,a=Math.sqrt(n*n-r*r);t.moveTo(e,i-(a-s)),t.lineTo(e+r,i+s),t.lineTo(e-r,i+s),t.lineTo(e,i-(a-s)),t.closePath()},triangleDown:function(t,e,i,o){t.beginPath(),i-=.275*(o*=1.15);var n=2*o,r=n/2,s=Math.sqrt(3)/6*n,a=Math.sqrt(n*n-r*r);t.moveTo(e,i+(a-s)),t.lineTo(e+r,i-s),t.lineTo(e-r,i-s),t.lineTo(e,i+(a-s)),t.closePath()}};var JB={exports:{}};!function(t){function e(t){if(t)return function(t){for(var i in e.prototype)t[i]=e.prototype[i];return t}(t)}t.exports=e,e.prototype.on=e.prototype.addEventListener=function(t,e){return this._callbacks=this._callbacks||{},(this._callbacks["$"+t]=this._callbacks["$"+t]||[]).push(e),this},e.prototype.once=function(t,e){function i(){this.off(t,i),e.apply(this,arguments)}return i.fn=e,this.on(t,i),this},e.prototype.off=e.prototype.removeListener=e.prototype.removeAllListeners=e.prototype.removeEventListener=function(t,e){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var i,o=this._callbacks["$"+t];if(!o)return this;if(1==arguments.length)return delete this._callbacks["$"+t],this;for(var n=0;n=a?t?"":void 0:(o=mz(r,s))<55296||o>56319||s+1===a||(n=mz(r,s+1))<56320||n>57343?t?yz(r,s):o:t?bz(r,s,s+2):n-56320+(o-55296<<10)+65536}},Az={codeAt:wz(!1),charAt:wz(!0)},Ez=OM,kz=sM.WeakMap,Cz=Ez(kz)&&/native code/.test(String(kz)),xz=rD,Sz=YO("keys"),Iz=function(t){return Sz[t]||(Sz[t]=xz(t))},Mz=Cz,Oz=sM,Dz=iO,Rz=mR,Bz=tD,zz=KO,Pz=Iz,Fz=ZR,Tz="Object already initialized",Nz=Oz.TypeError,jz=Oz.WeakMap;if(Mz||zz.state){var Uz=zz.state||(zz.state=new jz);Uz.get=Uz.get,Uz.has=Uz.has,Uz.set=Uz.set,$B=function(t,e){if(Uz.has(t))throw new Nz(Tz);return e.facade=t,Uz.set(t,e),e},tz=function(t){return Uz.get(t)||{}},ez=function(t){return Uz.has(t)}}else{var Lz=Pz("state");Fz[Lz]=!0,$B=function(t,e){if(Bz(t,Lz))throw new Nz(Tz);return e.facade=t,Rz(t,Lz,e),e},tz=function(t){return Bz(t,Lz)?t[Lz]:{}},ez=function(t){return Bz(t,Lz)}}var Qz={set:$B,get:tz,has:ez,enforce:function(t){return ez(t)?tz(t):$B(t,{})},getterFor:function(t){return function(e){var i;if(!Dz(e)||(i=tz(e)).type!==t)throw new Nz("Incompatible receiver, "+t+" required");return i}}},Hz=RM,Vz=tD,Wz=Function.prototype,Gz=Hz&&Object.getOwnPropertyDescriptor,Kz=Vz(Wz,"name"),qz={EXISTS:Kz,PROPER:Kz&&"something"===function(){}.name,CONFIGURABLE:Kz&&(!Hz||Hz&&Gz(Wz,"name").configurable)},Yz={},Zz=RM,Jz=tR,Xz=$D,_z=nR,$z=$M,tP=rB;Yz.f=Zz&&!Jz?Object.defineProperties:function(t,e){_z(t);for(var i,o=$z(e),n=tP(e),r=n.length,s=0;r>s;)Xz.f(t,i=n[s++],o[i]);return t};var eP,iP=lO("document","documentElement"),oP=nR,nP=Yz,rP=iB,sP=ZR,aP=iP,lP=MD,hP="prototype",cP="script",dP=Iz("IE_PROTO"),uP=function(){},fP=function(t){return"<"+cP+">"+t+""},pP=function(t){t.write(fP("")),t.close();var e=t.parentWindow.Object;return t=null,e},vP=function(){try{eP=new ActiveXObject("htmlfile")}catch(t){}var t,e,i;vP="undefined"!=typeof document?document.domain&&eP?pP(eP):(e=lP("iframe"),i="java"+cP+":",e.style.display="none",aP.appendChild(e),e.src=String(i),(t=e.contentWindow.document).open(),t.write(fP("document.F=Object")),t.close(),t.F):pP(eP);for(var o=rP.length;o--;)delete vP[hP][rP[o]];return vP()};sP[dP]=!0;var gP,yP,mP,bP=Object.create||function(t,e){var i;return null!==t?(uP[hP]=oP(t),i=new uP,uP[hP]=null,i[dP]=t):i=vP(),void 0===e?i:nP.f(i,e)},wP=!aM((function(){function t(){}return t.prototype.constructor=null,Object.getPrototypeOf(new t)!==t.prototype})),AP=tD,EP=OM,kP=XO,CP=wP,xP=Iz("IE_PROTO"),SP=Object,IP=SP.prototype,MP=CP?SP.getPrototypeOf:function(t){var e=kP(t);if(AP(e,xP))return e[xP];var i=e.constructor;return EP(i)&&e instanceof i?i.prototype:e instanceof SP?IP:null},OP=mR,DP=function(t,e,i,o){return o&&o.enumerable?t[e]=i:OP(t,e,i),t},RP=aM,BP=OM,zP=iO,PP=bP,FP=MP,TP=DP,NP=pD("iterator"),jP=!1;[].keys&&("next"in(mP=[].keys())?(yP=FP(FP(mP)))!==Object.prototype&&(gP=yP):jP=!0);var UP=!zP(gP)||RP((function(){var t={};return gP[NP].call(t)!==t}));BP((gP=UP?{}:PP(gP))[NP])||TP(gP,NP,(function(){return this}));var LP={IteratorPrototype:gP,BUGGY_SAFARI_ITERATORS:jP},QP=hz,HP=iz?{}.toString:function(){return"[object "+QP(this)+"]"},VP=iz,WP=$D.f,GP=mR,KP=tD,qP=HP,YP=pD("toStringTag"),ZP=function(t,e,i,o){if(t){var n=i?t:t.prototype;KP(n,YP)||WP(n,YP,{configurable:!0,value:e}),o&&!VP&&GP(n,"toString",qP)}},JP={},XP=LP.IteratorPrototype,_P=bP,$P=QM,tF=ZP,eF=JP,iF=function(){return this},oF=mM,nF=zO,rF=OM,sF=String,aF=TypeError,lF=function(t,e,i){try{return oF(nF(Object.getOwnPropertyDescriptor(t,e)[i]))}catch(t){}},hF=nR,cF=function(t){if("object"==typeof t||rF(t))return t;throw new aF("Can't set "+sF(t)+" as a prototype")},dF=Object.setPrototypeOf||("__proto__"in{}?function(){var t,e=!1,i={};try{(t=lF(Object.prototype,"__proto__","set"))(i,[]),e=i instanceof Array}catch(t){}return function(i,o){return hF(i),cF(o),e?t(i,o):i.__proto__=o,i}}():void 0),uF=DR,fF=PM,pF=function(t,e,i,o){var n=e+" Iterator";return t.prototype=_P(XP,{next:$P(+!o,i)}),tF(t,n,!1,!0),eF[n]=iF,t},vF=MP,gF=ZP,yF=DP,mF=JP,bF=qz.PROPER,wF=LP.BUGGY_SAFARI_ITERATORS,AF=pD("iterator"),EF="keys",kF="values",CF="entries",xF=function(){return this},SF=function(t,e,i,o,n,r,s){pF(i,e,o);var a,l,h,c=function(t){if(t===n&&v)return v;if(!wF&&t&&t in f)return f[t];switch(t){case EF:case kF:case CF:return function(){return new i(this,t)}}return function(){return new i(this)}},d=e+" Iterator",u=!1,f=t.prototype,p=f[AF]||f["@@iterator"]||n&&f[n],v=!wF&&p||c(n),g="Array"===e&&f.entries||p;if(g&&(a=vF(g.call(new t)))!==Object.prototype&&a.next&&(gF(a,d,!0,!0),mF[d]=xF),bF&&n===kF&&p&&p.name!==kF&&(u=!0,v=function(){return fF(p,this)}),n)if(l={values:c(kF),keys:r?v:c(EF),entries:c(CF)},s)for(h in l)(wF||u||!(h in f))&&yF(f,h,l[h]);else uF({target:e,proto:!0,forced:wF||u},l);return s&&f[AF]!==v&&yF(f,AF,v,{name:n}),mF[e]=v,l},IF=function(t,e){return{value:t,done:e}},MF=Az.charAt,OF=uz,DF=Qz,RF=SF,BF=IF,zF="String Iterator",PF=DF.set,FF=DF.getterFor(zF);RF(String,"String",(function(t){PF(this,{type:zF,string:OF(t),index:0})}),(function(){var t,e=FF(this),i=e.string,o=e.index;return o>=i.length?BF(void 0,!0):(t=MF(i,o),e.index+=t.length,BF(t,!1))}));var TF=PM,NF=nR,jF=TO,UF=function(t,e,i){var o,n;NF(t);try{if(!(o=jF(t,"return"))){if("throw"===e)throw i;return i}o=TF(o,t)}catch(t){n=!0,o=t}if("throw"===e)throw i;if(n)throw o;return NF(o),i},LF=nR,QF=UF,HF=JP,VF=pD("iterator"),WF=Array.prototype,GF=function(t){return void 0!==t&&(HF.Array===t||WF[VF]===t)},KF=OM,qF=KO,YF=mM(Function.toString);KF(qF.inspectSource)||(qF.inspectSource=function(t){return YF(t)});var ZF=qF.inspectSource,JF=mM,XF=aM,_F=OM,$F=hz,tT=ZF,eT=function(){},iT=[],oT=lO("Reflect","construct"),nT=/^\s*(?:class|function)\b/,rT=JF(nT.exec),sT=!nT.test(eT),aT=function(t){if(!_F(t))return!1;try{return oT(eT,iT,t),!0}catch(t){return!1}},lT=function(t){if(!_F(t))return!1;switch($F(t)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}try{return sT||!!rT(nT,tT(t))}catch(t){return!0}};lT.sham=!0;var hT=!oT||XF((function(){var t;return aT(aT.call)||!aT(Object)||!aT((function(){t=!0}))||t}))?lT:aT,cT=CD,dT=$D,uT=QM,fT=function(t,e,i){var o=cT(e);o in t?dT.f(t,o,uT(0,i)):t[o]=i},pT=hz,vT=TO,gT=qM,yT=JP,mT=pD("iterator"),bT=function(t){if(!gT(t))return vT(t,mT)||vT(t,"@@iterator")||yT[pT(t)]},wT=PM,AT=zO,ET=nR,kT=OO,CT=bT,xT=TypeError,ST=function(t,e){var i=arguments.length<2?CT(t):e;if(AT(i))return ET(wT(i,t));throw new xT(kT(t)+" is not iterable")},IT=_D,MT=PM,OT=XO,DT=function(t,e,i,o){try{return o?e(LF(i)[0],i[1]):e(i)}catch(e){QF(t,"throw",e)}},RT=GF,BT=hT,zT=VR,PT=fT,FT=ST,TT=bT,NT=Array,jT=pD("iterator"),UT=!1;try{var LT=0,QT={next:function(){return{done:!!LT++}},return:function(){UT=!0}};QT[jT]=function(){return this},Array.from(QT,(function(){throw 2}))}catch(t){}var HT=function(t){var e=OT(t),i=BT(this),o=arguments.length,n=o>1?arguments[1]:void 0,r=void 0!==n;r&&(n=IT(n,o>2?arguments[2]:void 0));var s,a,l,h,c,d,u=TT(e),f=0;if(!u||this===NT&&RT(u))for(s=zT(e),a=i?new this(s):NT(s);s>f;f++)d=r?n(e[f],f):e[f],PT(a,f,d);else for(c=(h=FT(e,u)).next,a=i?new this:[];!(l=MT(c,h)).done;f++)d=r?DT(h,n,[l.value,f],!0):l.value,PT(a,f,d);return a.length=f,a},VT=function(t,e){try{if(!e&&!UT)return!1}catch(t){return!1}var i=!1;try{var o={};o[jT]=function(){return{next:function(){return{done:i=!0}}}},t(o)}catch(t){}return i};DR({target:"Array",stat:!0,forced:!VT((function(t){Array.from(t)}))},{from:HT});var WT=oO.Array.from,GT=nM(WT),KT=$M,qT=JP,YT=Qz;$D.f;var ZT=SF,JT=IF,XT="Array Iterator",_T=YT.set,$T=YT.getterFor(XT);ZT(Array,"Array",(function(t,e){_T(this,{type:XT,target:KT(t),index:0,kind:e})}),(function(){var t=$T(this),e=t.target,i=t.kind,o=t.index++;if(!e||o>=e.length)return t.target=void 0,JT(void 0,!0);switch(i){case"keys":return JT(o,!1);case"values":return JT(e[o],!1)}return JT([o,e[o]],!1)}),"values"),qT.Arguments=qT.Array;var tN=bT,eN={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0},iN=sM,oN=hz,nN=mR,rN=JP,sN=pD("toStringTag");for(var aN in eN){var lN=iN[aN],hN=lN&&lN.prototype;hN&&oN(hN)!==sN&&nN(hN,sN,aN),rN[aN]=rN.Array}var cN=tN,dN=nM(cN),uN=nM(cN);function fN(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var pN={exports:{}},vN=DR,gN=RM,yN=$D.f;vN({target:"Object",stat:!0,forced:Object.defineProperty!==yN,sham:!gN},{defineProperty:yN});var mN=oO.Object,bN=pN.exports=function(t,e,i){return mN.defineProperty(t,e,i)};mN.defineProperty.sham&&(bN.sham=!0);var wN=pN.exports,AN=nM(wN),EN=EM,kN=Array.isArray||function(t){return"Array"===EN(t)},CN=TypeError,xN=function(t){if(t>9007199254740991)throw CN("Maximum allowed index exceeded");return t},SN=kN,IN=hT,MN=iO,ON=pD("species"),DN=Array,RN=function(t){var e;return SN(t)&&(e=t.constructor,(IN(e)&&(e===DN||SN(e.prototype))||MN(e)&&null===(e=e[ON]))&&(e=void 0)),void 0===e?DN:e},BN=function(t,e){return new(RN(t))(0===e?0:e)},zN=aM,PN=yO,FN=pD("species"),TN=function(t){return PN>=51||!zN((function(){var e=[];return(e.constructor={})[FN]=function(){return{foo:1}},1!==e[t](Boolean).foo}))},NN=DR,jN=aM,UN=kN,LN=iO,QN=XO,HN=VR,VN=xN,WN=fT,GN=BN,KN=TN,qN=yO,YN=pD("isConcatSpreadable"),ZN=qN>=51||!jN((function(){var t=[];return t[YN]=!1,t.concat()[0]!==t})),JN=function(t){if(!LN(t))return!1;var e=t[YN];return void 0!==e?!!e:UN(t)};NN({target:"Array",proto:!0,arity:1,forced:!ZN||!KN("concat")},{concat:function(t){var e,i,o,n,r,s=QN(this),a=GN(s,0),l=0;for(e=-1,o=arguments.length;em;m++)if((a||m in v)&&(f=g(u=v[m],m,p),t))if(e)w[m]=f;else if(f)switch(t){case 3:return!0;case 5:return u;case 6:return m;case 2:Rj(w,u)}else switch(t){case 4:return!1;case 7:Rj(w,u)}return r?-1:o||n?n:w}},zj={forEach:Bj(0),map:Bj(1),filter:Bj(2),some:Bj(3),every:Bj(4),find:Bj(5),findIndex:Bj(6),filterReject:Bj(7)},Pj=DR,Fj=sM,Tj=PM,Nj=mM,jj=RM,Uj=AO,Lj=aM,Qj=tD,Hj=hO,Vj=nR,Wj=$M,Gj=CD,Kj=uz,qj=QM,Yj=bP,Zj=rB,Jj=XN,Xj=tj,_j=sB,$j=DM,tU=$D,eU=Yz,iU=FM,oU=DP,nU=fj,rU=YO,sU=ZR,aU=rD,lU=pD,hU=pj,cU=wj,dU=xj,uU=ZP,fU=Qz,pU=zj.forEach,vU=Iz("hidden"),gU="Symbol",yU="prototype",mU=fU.set,bU=fU.getterFor(gU),wU=Object[yU],AU=Fj.Symbol,EU=AU&&AU[yU],kU=Fj.RangeError,CU=Fj.TypeError,xU=Fj.QObject,SU=$j.f,IU=tU.f,MU=Xj.f,OU=iU.f,DU=Nj([].push),RU=rU("symbols"),BU=rU("op-symbols"),zU=rU("wks"),PU=!xU||!xU[yU]||!xU[yU].findChild,FU=function(t,e,i){var o=SU(wU,e);o&&delete wU[e],IU(t,e,i),o&&t!==wU&&IU(wU,e,o)},TU=jj&&Lj((function(){return 7!==Yj(IU({},"a",{get:function(){return IU(this,"a",{value:7}).a}})).a}))?FU:IU,NU=function(t,e){var i=RU[t]=Yj(EU);return mU(i,{type:gU,tag:t,description:e}),jj||(i.description=e),i},jU=function(t,e,i){t===wU&&jU(BU,e,i),Vj(t);var o=Gj(e);return Vj(i),Qj(RU,o)?(i.enumerable?(Qj(t,vU)&&t[vU][o]&&(t[vU][o]=!1),i=Yj(i,{enumerable:qj(0,!1)})):(Qj(t,vU)||IU(t,vU,qj(1,{})),t[vU][o]=!0),TU(t,o,i)):IU(t,o,i)},UU=function(t,e){Vj(t);var i=Wj(e),o=Zj(i).concat(VU(i));return pU(o,(function(e){jj&&!Tj(LU,i,e)||jU(t,e,i[e])})),t},LU=function(t){var e=Gj(t),i=Tj(OU,this,e);return!(this===wU&&Qj(RU,e)&&!Qj(BU,e))&&(!(i||!Qj(this,e)||!Qj(RU,e)||Qj(this,vU)&&this[vU][e])||i)},QU=function(t,e){var i=Wj(t),o=Gj(e);if(i!==wU||!Qj(RU,o)||Qj(BU,o)){var n=SU(i,o);return!n||!Qj(RU,o)||Qj(i,vU)&&i[vU][o]||(n.enumerable=!0),n}},HU=function(t){var e=MU(Wj(t)),i=[];return pU(e,(function(t){Qj(RU,t)||Qj(sU,t)||DU(i,t)})),i},VU=function(t){var e=t===wU,i=MU(e?BU:Wj(t)),o=[];return pU(i,(function(t){!Qj(RU,t)||e&&!Qj(wU,t)||DU(o,RU[t])})),o};Uj||(AU=function(){if(Hj(EU,this))throw new CU("Symbol is not a constructor");var t=arguments.length&&void 0!==arguments[0]?Kj(arguments[0]):void 0,e=aU(t),i=function(t){this===wU&&Tj(i,BU,t),Qj(this,vU)&&Qj(this[vU],e)&&(this[vU][e]=!1);var o=qj(1,t);try{TU(this,e,o)}catch(t){if(!(t instanceof kU))throw t;FU(this,e,o)}};return jj&&PU&&TU(wU,e,{configurable:!0,set:i}),NU(e,t)},oU(EU=AU[yU],"toString",(function(){return bU(this).tag})),oU(AU,"withoutSetter",(function(t){return NU(aU(t),t)})),iU.f=LU,tU.f=jU,eU.f=UU,$j.f=QU,Jj.f=Xj.f=HU,_j.f=VU,hU.f=function(t){return NU(lU(t),t)},jj&&nU(EU,"description",{configurable:!0,get:function(){return bU(this).description}})),Pj({global:!0,constructor:!0,wrap:!0,forced:!Uj,sham:!Uj},{Symbol:AU}),pU(Zj(zU),(function(t){cU(t)})),Pj({target:gU,stat:!0,forced:!Uj},{useSetter:function(){PU=!0},useSimple:function(){PU=!1}}),Pj({target:"Object",stat:!0,forced:!Uj,sham:!jj},{create:function(t,e){return void 0===e?Yj(t):UU(Yj(t),e)},defineProperty:jU,defineProperties:UU,getOwnPropertyDescriptor:QU}),Pj({target:"Object",stat:!0,forced:!Uj},{getOwnPropertyNames:HU}),dU(),uU(AU,gU),sU[vU]=!0;var WU=AO&&!!Symbol.for&&!!Symbol.keyFor,GU=DR,KU=lO,qU=tD,YU=uz,ZU=YO,JU=WU,XU=ZU("string-to-symbol-registry"),_U=ZU("symbol-to-string-registry");GU({target:"Symbol",stat:!0,forced:!JU},{for:function(t){var e=YU(t);if(qU(XU,e))return XU[e];var i=KU("Symbol")(e);return XU[e]=i,_U[i]=e,i}});var $U=DR,tL=tD,eL=IO,iL=OO,oL=WU,nL=YO("symbol-to-string-registry");$U({target:"Symbol",stat:!0,forced:!oL},{keyFor:function(t){if(!eL(t))throw new TypeError(iL(t)+" is not a symbol");if(tL(nL,t))return nL[t]}});var rL=kN,sL=OM,aL=EM,lL=uz,hL=mM([].push),cL=DR,dL=lO,uL=fM,fL=PM,pL=mM,vL=aM,gL=OM,yL=IO,mL=EB,bL=function(t){if(sL(t))return t;if(rL(t)){for(var e=t.length,i=[],o=0;ot.length)&&(e=t.length);for(var i=0,o=new Array(e);i1?arguments[1]:void 0)}});var CH=TB("Array").map,xH=hO,SH=CH,IH=Array.prototype,MH=function(t){var e=t.map;return t===IH||xH(IH,t)&&e===IH.map?SH:e},OH=nM(MH),DH=XO,RH=rB;DR({target:"Object",stat:!0,forced:aM((function(){RH(1)}))},{keys:function(t){return RH(DH(t))}});var BH=nM(oO.Object.keys),zH=DR,PH=Date,FH=mM(PH.prototype.getTime);zH({target:"Date",stat:!0},{now:function(){return FH(new PH)}});var TH=nM(oO.Date.now),NH=aM,jH=function(t,e){var i=[][t];return!!i&&NH((function(){i.call(null,e||function(){return 1},1)}))},UH=zj.forEach,LH=jH("forEach")?[].forEach:function(t){return UH(this,t,arguments.length>1?arguments[1]:void 0)};DR({target:"Array",proto:!0,forced:[].forEach!==LH},{forEach:LH});var QH=TB("Array").forEach,HH=hz,VH=tD,WH=hO,GH=QH,KH=Array.prototype,qH={DOMTokenList:!0,NodeList:!0},YH=function(t){var e=t.forEach;return t===KH||WH(KH,t)&&e===KH.forEach||VH(qH,HH(t))?GH:e},ZH=nM(YH),JH=DR,XH=kN,_H=mM([].reverse),$H=[1,2];JH({target:"Array",proto:!0,forced:String($H)===String($H.reverse())},{reverse:function(){return XH(this)&&(this.length=this.length),_H(this)}});var tV=TB("Array").reverse,eV=hO,iV=tV,oV=Array.prototype,nV=function(t){var e=t.reverse;return t===oV||eV(oV,t)&&e===oV.reverse?iV:e},rV=nM(nV),sV=OO,aV=TypeError,lV=function(t,e){if(!delete t[e])throw new aV("Cannot delete property "+sV(e)+" of "+sV(t))},hV=DR,cV=XO,dV=UR,uV=FR,fV=VR,pV=xQ,vV=xN,gV=BN,yV=fT,mV=lV,bV=TN("splice"),wV=Math.max,AV=Math.min;hV({target:"Array",proto:!0,forced:!bV},{splice:function(t,e){var i,o,n,r,s,a,l=cV(this),h=fV(l),c=dV(t,h),d=arguments.length;for(0===d?i=o=0:1===d?(i=0,o=h-c):(i=d-2,o=AV(wV(uV(e),0),h-c)),vV(h+i-o),n=gV(l,o),r=0;rh-o+i;r--)mV(l,r-1)}else if(i>o)for(r=h-o;r>c;r--)a=r+i-1,(s=r+o-1)in l?l[a]=l[s]:mV(l,a);for(r=0;r1?arguments[1]:void 0)}});var OV=TB("Array").includes,DV=iO,RV=EM,BV=pD("match"),zV=function(t){var e;return DV(t)&&(void 0!==(e=t[BV])?!!e:"RegExp"===RV(t))},PV=TypeError,FV=pD("match"),TV=DR,NV=function(t){if(zV(t))throw new PV("The method doesn't accept regular expressions");return t},jV=JM,UV=uz,LV=function(t){var e=/./;try{"/./"[t](e)}catch(i){try{return e[FV]=!1,"/./"[t](e)}catch(t){}}return!1},QV=mM("".indexOf);TV({target:"String",proto:!0,forced:!LV("includes")},{includes:function(t){return!!~QV(UV(jV(this)),UV(NV(t)),arguments.length>1?arguments[1]:void 0)}});var HV=TB("String").includes,VV=hO,WV=OV,GV=HV,KV=Array.prototype,qV=String.prototype,YV=function(t){var e=t.includes;return t===KV||VV(KV,t)&&e===KV.includes?WV:"string"==typeof t||t===qV||VV(qV,t)&&e===qV.includes?GV:e},ZV=nM(YV),JV=XO,XV=MP,_V=wP;DR({target:"Object",stat:!0,forced:aM((function(){XV(1)})),sham:!_V},{getPrototypeOf:function(t){return XV(JV(t))}});var $V=oO.Object.getPrototypeOf,tW=nM($V),eW=zj.filter;DR({target:"Array",proto:!0,forced:!TN("filter")},{filter:function(t){return eW(this,t,arguments.length>1?arguments[1]:void 0)}});var iW=TB("Array").filter,oW=hO,nW=iW,rW=Array.prototype,sW=function(t){var e=t.filter;return t===rW||oW(rW,t)&&e===rW.filter?nW:e},aW=nM(sW),lW="\t\n\v\f\r                 \u2028\u2029\ufeff",hW=JM,cW=uz,dW=lW,uW=mM("".replace),fW=RegExp("^["+dW+"]+"),pW=RegExp("(^|[^"+dW+"])["+dW+"]+$"),vW=function(t){return function(e){var i=cW(hW(e));return 1&t&&(i=uW(i,fW,"")),2&t&&(i=uW(i,pW,"$1")),i}},gW={start:vW(1),end:vW(2),trim:vW(3)},yW=sM,mW=aM,bW=mM,wW=uz,AW=gW.trim,EW=lW,kW=yW.parseInt,CW=yW.Symbol,xW=CW&&CW.iterator,SW=/^[+-]?0x/i,IW=bW(SW.exec),MW=8!==kW(EW+"08")||22!==kW(EW+"0x16")||xW&&!mW((function(){kW(Object(xW))}))?function(t,e){var i=AW(wW(t));return kW(i,e>>>0||(IW(SW,i)?16:10))}:kW;DR({global:!0,forced:parseInt!==MW},{parseInt:MW});var OW=nM(oO.parseInt),DW=DR,RW=YR.indexOf,BW=jH,zW=xM([].indexOf),PW=!!zW&&1/zW([1],1,-0)<0;DW({target:"Array",proto:!0,forced:PW||!BW("indexOf")},{indexOf:function(t){var e=arguments.length>1?arguments[1]:void 0;return PW?zW(this,t,e)||0:RW(this,t,e)}});var FW=TB("Array").indexOf,TW=hO,NW=FW,jW=Array.prototype,UW=function(t){var e=t.indexOf;return t===jW||TW(jW,t)&&e===jW.indexOf?NW:e},LW=nM(UW);DR({target:"Object",stat:!0,sham:!RM},{create:bP});var QW=oO.Object,HW=function(t,e){return QW.create(t,e)},VW=HW,WW=nM(VW),GW=oO,KW=fM;GW.JSON||(GW.JSON={stringify:JSON.stringify});var qW=function(t,e,i){return KW(GW.JSON.stringify,null,arguments)},YW=nM(qW),ZW="function"==typeof Bun&&Bun&&"string"==typeof Bun.version,JW=TypeError,XW=sM,_W=fM,$W=OM,tG=ZW,eG=cO,iG=EB,oG=function(t,e){if(ti,s=$W(o)?o:nG(o),a=r?iG(arguments,i):[],l=r?function(){_W(s,this,a)}:s;return e?t(l,n):t(l)}:t},aG=DR,lG=sM,hG=sG(lG.setInterval,!0);aG({global:!0,bind:!0,forced:lG.setInterval!==hG},{setInterval:hG});var cG=DR,dG=sM,uG=sG(dG.setTimeout,!0);cG({global:!0,bind:!0,forced:dG.setTimeout!==uG},{setTimeout:uG});var fG=nM(oO.setTimeout),pG=XO,vG=UR,gG=VR,yG=function(t){for(var e=pG(this),i=gG(e),o=arguments.length,n=vG(o>1?arguments[1]:void 0,i),r=o>2?arguments[2]:void 0,s=void 0===r?i:vG(r,i);s>n;)e[n++]=t;return e};DR({target:"Array",proto:!0},{fill:yG});var mG,bG=TB("Array").fill,wG=hO,AG=bG,EG=Array.prototype,kG=function(t){var e=t.fill;return t===EG||wG(EG,t)&&e===EG.fill?AG:e},CG=nM(kG); /*! Hammer.JS - v2.0.17-rc - 2019-12-16 * http://naver.github.io/egjs * * Forked By Naver egjs * Copyright (c) hammerjs * Licensed under the MIT license */ -function gY(){return gY=Object.assign||function(t){for(var e=1;e-1}var rG=function(){function t(t,e){this.manager=t,this.set(e)}var e=t.prototype;return e.set=function(t){t===AY&&(t=this.compute()),IY&&this.manager.element.style&&NY[t]&&(this.manager.element.style[TY]=t),this.actions=t.toLowerCase().trim()},e.update=function(){this.set(this.manager.options.touchAction)},e.compute=function(){var t=[];return iG(this.manager.recognizers,(function(e){nG(e.options.enable,[e])&&(t=t.concat(e.getTouchAction()))})),function(t){if(oG(t,DY))return DY;var e=oG(t,MY),i=oG(t,FY);return e&&i?DY:e||i?e?MY:FY:oG(t,PY)?PY:RY}(t.join(" "))},e.preventDefaults=function(t){var e=t.srcEvent,i=t.offsetDirection;if(this.manager.session.prevented)e.preventDefault();else{var n=this.actions,o=oG(n,DY)&&!NY[DY],r=oG(n,FY)&&!NY[FY],s=oG(n,MY)&&!NY[MY];if(o){var a=1===t.pointers.length,d=t.distance<2,l=t.deltaTime<250;if(a&&d&&l)return}if(!s||!r)return o||r&&i&ZY||s&&i&QY?this.preventSrc(e):void 0}},e.preventSrc=function(t){this.manager.session.prevented=!0,t.preventDefault()},t}();function sG(t,e){for(;t;){if(t===e)return!0;t=t.parentNode}return!1}function aG(t){var e=t.length;if(1===e)return{x:kY(t[0].clientX),y:kY(t[0].clientY)};for(var i=0,n=0,o=0;o=OY(e)?t<0?XY:YY:e<0?GY:KY}function uG(t,e,i){return{x:e/t||0,y:i/t||0}}function pG(t,e){var i=t.session,n=e.pointers,o=n.length;i.firstInput||(i.firstInput=dG(e)),o>1&&!i.firstMultiple?i.firstMultiple=dG(e):1===o&&(i.firstMultiple=!1);var r=i.firstInput,s=i.firstMultiple,a=s?s.center:r.center,d=e.center=aG(n);e.timeStamp=CY(),e.deltaTime=e.timeStamp-r.timeStamp,e.angle=cG(a,d),e.distance=lG(a,d),function(t,e){var i=e.center,n=t.offsetDelta||{},o=t.prevDelta||{},r=t.prevInput||{};e.eventType!==UY&&r.eventType!==WY||(o=t.prevDelta={x:r.deltaX||0,y:r.deltaY||0},n=t.offsetDelta={x:i.x,y:i.y}),e.deltaX=o.x+(i.x-n.x),e.deltaY=o.y+(i.y-n.y)}(i,e),e.offsetDirection=hG(e.deltaX,e.deltaY);var l,c,h=uG(e.deltaTime,e.deltaX,e.deltaY);e.overallVelocityX=h.x,e.overallVelocityY=h.y,e.overallVelocity=OY(h.x)>OY(h.y)?h.x:h.y,e.scale=s?(l=s.pointers,lG((c=n)[0],c[1],eG)/lG(l[0],l[1],eG)):1,e.rotation=s?function(t,e){return cG(e[1],e[0],eG)+cG(t[1],t[0],eG)}(s.pointers,n):0,e.maxPointers=i.prevInput?e.pointers.length>i.prevInput.maxPointers?e.pointers.length:i.prevInput.maxPointers:e.pointers.length,function(t,e){var i,n,o,r,s=t.lastInterval||e,a=e.timeStamp-s.timeStamp;if(e.eventType!==VY&&(a>$Y||void 0===s.velocity)){var d=e.deltaX-s.deltaX,l=e.deltaY-s.deltaY,c=uG(a,d,l);n=c.x,o=c.y,i=OY(c.x)>OY(c.y)?c.x:c.y,r=hG(d,l),t.lastInterval=e}else i=s.velocity,n=s.velocityX,o=s.velocityY,r=s.direction;e.velocity=i,e.velocityX=n,e.velocityY=o,e.direction=r}(i,e);var u,p=t.element,f=e.srcEvent;sG(u=f.composedPath?f.composedPath()[0]:f.path?f.path[0]:f.target,p)&&(p=u),e.target=p}function fG(t,e,i){var n=i.pointers.length,o=i.changedPointers.length,r=e&UY&&n-o==0,s=e&(WY|VY)&&n-o==0;i.isFirst=!!r,i.isFinal=!!s,r&&(t.session={}),i.eventType=e,pG(t,i),t.emit("hammer.input",i),t.recognize(i),t.session.prevInput=i}function mG(t){return t.trim().split(/\s+/g)}function vG(t,e,i){iG(mG(e),(function(e){t.addEventListener(e,i,!1)}))}function gG(t,e,i){iG(mG(e),(function(e){t.removeEventListener(e,i,!1)}))}function yG(t){var e=t.ownerDocument||t;return e.defaultView||e.parentWindow||window}var bG=function(){function t(t,e){var i=this;this.manager=t,this.callback=e,this.element=t.element,this.target=t.options.inputTarget,this.domHandler=function(e){nG(t.options.enable,[t])&&i.handler(e)},this.init()}var e=t.prototype;return e.handler=function(){},e.init=function(){this.evEl&&vG(this.element,this.evEl,this.domHandler),this.evTarget&&vG(this.target,this.evTarget,this.domHandler),this.evWin&&vG(yG(this.element),this.evWin,this.domHandler)},e.destroy=function(){this.evEl&&gG(this.element,this.evEl,this.domHandler),this.evTarget&&gG(this.target,this.evTarget,this.domHandler),this.evWin&&gG(yG(this.element),this.evWin,this.domHandler)},t}();function xG(t,e,i){if(t.indexOf&&!i)return t.indexOf(e);for(var n=0;ni[e]})):n.sort()),n}var TG={touchstart:UY,touchmove:2,touchend:WY,touchcancel:VY},IG=function(t){function e(){var i;return e.prototype.evTarget="touchstart touchmove touchend touchcancel",(i=t.apply(this,arguments)||this).targetIds={},i}return yY(e,t),e.prototype.handler=function(t){var e=TG[t.type],i=AG.call(this,t,e);i&&this.callback(this.manager,e,{pointers:i[0],changedPointers:i[1],pointerType:jY,srcEvent:t})},e}(bG);function AG(t,e){var i,n,o=CG(t.touches),r=this.targetIds;if(e&(2|UY)&&1===o.length)return r[o[0].identifier]=!0,[o,o];var s=CG(t.changedTouches),a=[],d=this.target;if(n=o.filter((function(t){return sG(t.target,d)})),e===UY)for(i=0;i-1&&n.splice(t,1)}),DG)}}function FG(t,e){t&UY?(this.primaryTouch=e.changedPointers[0].identifier,MG.call(this,e)):t&(WY|VY)&&MG.call(this,e)}function NG(t){for(var e=t.srcEvent.clientX,i=t.srcEvent.clientY,n=0;n-1&&this.requireFail.splice(e,1),this},e.hasRequireFailures=function(){return this.requireFail.length>0},e.canRecognizeWith=function(t){return!!this.simultaneous[t.id]},e.emit=function(t){var e=this,i=this.state;function n(i){e.manager.emit(i,t)}i<8&&n(e.options.event+$G(i)),n(e.options.event),t.additionalEvent&&n(t.additionalEvent),i>=8&&n(e.options.event+$G(i))},e.tryEmit=function(t){if(this.canEmit())return this.emit(t);this.state=zG},e.canEmit=function(){for(var t=0;te.threshold&&o&e.direction},i.attrTest=function(t){return VG.prototype.attrTest.call(this,t)&&(2&this.state||!(2&this.state)&&this.directionTest(t))},i.emit=function(e){this.pX=e.deltaX,this.pY=e.deltaY;var i=qG(e.direction);i&&(e.additionalEvent=this.options.event+i),t.prototype.emit.call(this,e)},e}(VG),YG=function(t){function e(e){return void 0===e&&(e={}),t.call(this,gY({event:"swipe",threshold:10,velocity:.3,direction:ZY|QY,pointers:1},e))||this}yY(e,t);var i=e.prototype;return i.getTouchAction=function(){return XG.prototype.getTouchAction.call(this)},i.attrTest=function(e){var i,n=this.options.direction;return n&(ZY|QY)?i=e.overallVelocity:n&ZY?i=e.overallVelocityX:n&QY&&(i=e.overallVelocityY),t.prototype.attrTest.call(this,e)&&n&e.offsetDirection&&e.distance>this.options.threshold&&e.maxPointers===this.options.pointers&&OY(i)>this.options.velocity&&e.eventType&WY},i.emit=function(t){var e=qG(t.offsetDirection);e&&this.manager.emit(this.options.event+e,t),this.manager.emit(this.options.event,t)},e}(VG),GG=function(t){function e(e){return void 0===e&&(e={}),t.call(this,gY({event:"pinch",threshold:0,pointers:2},e))||this}yY(e,t);var i=e.prototype;return i.getTouchAction=function(){return[DY]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.scale-1)>this.options.threshold||2&this.state)},i.emit=function(e){if(1!==e.scale){var i=e.scale<1?"in":"out";e.additionalEvent=this.options.event+i}t.prototype.emit.call(this,e)},e}(VG),KG=function(t){function e(e){return void 0===e&&(e={}),t.call(this,gY({event:"rotate",threshold:0,pointers:2},e))||this}yY(e,t);var i=e.prototype;return i.getTouchAction=function(){return[DY]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.rotation)>this.options.threshold||2&this.state)},e}(VG),ZG=function(t){function e(e){var i;return void 0===e&&(e={}),(i=t.call(this,gY({event:"press",pointers:1,time:251,threshold:9},e))||this)._timer=null,i._input=null,i}yY(e,t);var i=e.prototype;return i.getTouchAction=function(){return[RY]},i.process=function(t){var e=this,i=this.options,n=t.pointers.length===i.pointers,o=t.distancei.time;if(this._input=t,!o||!n||t.eventType&(WY|VY)&&!r)this.reset();else if(t.eventType&UY)this.reset(),this._timer=setTimeout((function(){e.state=8,e.tryEmit()}),i.time);else if(t.eventType&WY)return 8;return zG},i.reset=function(){clearTimeout(this._timer)},i.emit=function(t){8===this.state&&(t&&t.eventType&WY?this.manager.emit(this.options.event+"up",t):(this._input.timeStamp=CY(),this.manager.emit(this.options.event,this._input)))},e}(UG),QG={domEvents:!1,touchAction:AY,enable:!0,inputTarget:null,inputClass:null,cssProps:{userSelect:"none",touchSelect:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}},JG=[[KG,{enable:!1}],[GG,{enable:!1},["rotate"]],[YG,{direction:ZY}],[XG,{direction:ZY},["swipe"]],[WG],[WG,{event:"doubletap",taps:2},["tap"]],[ZG]];function tK(t,e){var i,n=t.element;n.style&&(iG(t.options.cssProps,(function(o,r){i=SY(n.style,r),e?(t.oldCssProps[i]=n.style[i],n.style[i]=o):n.style[i]=t.oldCssProps[i]||""})),e||(t.oldCssProps={}))}var eK=function(){function t(t,e){var i,n=this;this.options=_Y({},QG,e||{}),this.options.inputTarget=this.options.inputTarget||t,this.handlers={},this.session={},this.recognizers=[],this.oldCssProps={},this.element=t,this.input=new((i=this).options.inputClass||(LY?OG:zY?IG:BY?BG:PG))(i,fG),this.touchAction=new rG(this,this.options.touchAction),tK(this,!0),iG(this.options.recognizers,(function(t){var e=n.add(new t[0](t[1]));t[2]&&e.recognizeWith(t[2]),t[3]&&e.requireFailure(t[3])}),this)}var e=t.prototype;return e.set=function(t){return _Y(this.options,t),t.touchAction&&this.touchAction.update(),t.inputTarget&&(this.input.destroy(),this.input.target=t.inputTarget,this.input.init()),this},e.stop=function(t){this.session.stopped=t?2:1},e.recognize=function(t){var e=this.session;if(!e.stopped){var i;this.touchAction.preventDefaults(t);var n=this.recognizers,o=e.curRecognizer;(!o||o&&8&o.state)&&(e.curRecognizer=null,o=null);for(var r=0;r\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",o=window.console&&(window.console.warn||window.console.log);return o&&o.call(window.console,n,i),t.apply(this,arguments)}}var sK=rK((function(t,e,i){for(var n=Object.keys(e),o=0;o=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function pK(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i>>0,t=(o*=t)>>>0,t+=4294967296*(o-=t)}return 2.3283064365386963e-10*(t>>>0)}}(),e=t(" "),i=t(" "),n=t(" "),o=0;o2&&void 0!==arguments[2]&&arguments[2];for(var n in t)if(void 0!==e[n])if(null===e[n]||"object"!==sW(e[n]))kK(t,e,n,i);else{var o=t[n],r=e[n];EK(o)&&EK(r)&&OK(o,r,i)}}function CK(t,e,i){var n=arguments.length>3&&void 0!==arguments[3]&&arguments[3];if(fV(i))throw new TypeError("Arrays are not supported by deepExtend");for(var o=0;o3&&void 0!==arguments[3]&&arguments[3];if(fV(i))throw new TypeError("Arrays are not supported by deepExtend");for(var o in i)if(Object.prototype.hasOwnProperty.call(i,o)&&!Hq(t).call(t,o))if(i[o]&&i[o].constructor===Object)void 0===e[o]&&(e[o]={}),e[o].constructor===Object?TK(e[o],i[o]):kK(e,i,o,n);else if(fV(i[o])){e[o]=[];for(var r=0;r2&&void 0!==arguments[2]&&arguments[2],n=arguments.length>3&&void 0!==arguments[3]&&arguments[3];for(var o in e)if(Object.prototype.hasOwnProperty.call(e,o)||!0===i)if("object"===sW(e[o])&&null!==e[o]&&qq(e[o])===Object.prototype)void 0===t[o]?t[o]=TK({},e[o],i):"object"===sW(t[o])&&null!==t[o]&&qq(t[o])===Object.prototype?TK(t[o],e[o],i):kK(t,e,o,n);else if(fV(e[o])){var r;t[o]=aV(r=e[o]).call(r)}else kK(t,e,o,n);return t}function IK(t,e){var i;return sV(i=[]).call(i,JW(t),[e])}function AK(t){return t.getBoundingClientRect().top}function RK(t,e){if(fV(t))for(var i=t.length,n=0;n3&&void 0!==arguments[3]?arguments[3]:{},o=function(t){return null!=t},r=function(t){return null!==t&&"object"===sW(t)};if(!r(t))throw new Error("Parameter mergeTarget must be an object");if(!r(e))throw new Error("Parameter options must be an object");if(!o(i))throw new Error("Parameter option must have a value");if(!r(n))throw new Error("Parameter globalOptions must be an object");var s=e[i],a=r(n)&&!function(t){for(var e in t)if(Object.prototype.hasOwnProperty.call(t,e))return!1;return!0}(n),d=a?n[i]:void 0,l=d?d.enabled:void 0;if(void 0!==s){if("boolean"==typeof s)return r(t[i])||(t[i]={}),void(t[i].enabled=s);if(null===s&&!r(t[i])){if(!o(d))return;t[i]=NX(d)}if(r(s)){var c=!0;void 0!==s.enabled?c=s.enabled:void 0!==l&&(c=d.enabled),function(t,e,i){r(t[i])||(t[i]={});var n=e[i],o=t[i];for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(o[s]=n[s])}(t,e,i),t[i].enabled=c}}}var UK={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return t*(2-t)},easeInOutQuad:function(t){return t<.5?2*t*t:(4-2*t)*t-1},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return--t*t*t+1},easeInOutCubic:function(t){return t<.5?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return 1- --t*t*t*t},easeInOutQuart:function(t){return t<.5?8*t*t*t*t:1-8*--t*t*t*t},easeInQuint:function(t){return t*t*t*t*t},easeOutQuint:function(t){return 1+--t*t*t*t*t},easeInOutQuint:function(t){return t<.5?16*t*t*t*t*t:1+16*--t*t*t*t*t}};function WK(t,e){var i;fV(e)||(e=[e]);var n,o=uK(t);try{for(o.s();!(n=o.n()).done;){var r=n.value;if(r){i=r[e[0]];for(var s=1;s0&&void 0!==arguments[0]?arguments[0]:1;rj(this,t),this.pixelRatio=e,this.generated=!1,this.centerCoordinates={x:144.5,y:144.5},this.r=289*.49,this.color={r:255,g:255,b:255,a:1},this.hueCircle=void 0,this.initialColor={r:255,g:255,b:255,a:1},this.previousColor=void 0,this.applied=!1,this.updateCallback=function(){},this.closeCallback=function(){},this._create()}return cW(t,[{key:"insertTo",value:function(t){void 0!==this.hammer&&(this.hammer.destroy(),this.hammer=void 0),this.container=t,this.container.appendChild(this.frame),this._bindHammer(),this._setSize()}},{key:"setUpdateCallback",value:function(t){if("function"!=typeof t)throw new Error("Function attempted to set as colorPicker update callback is not a function.");this.updateCallback=t}},{key:"setCloseCallback",value:function(t){if("function"!=typeof t)throw new Error("Function attempted to set as colorPicker closing callback is not a function.");this.closeCallback=t}},{key:"_isColorString",value:function(t){if("string"==typeof t)return VK[t]}},{key:"setColor",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if("none"!==t){var i,n=this._isColorString(t);if(void 0!==n&&(t=n),!0===wK(t)){if(!0===jK(t)){var o=t.substr(4).substr(0,t.length-5).split(",");i={r:o[0],g:o[1],b:o[2],a:1}}else if(!0===function(t){return xK.test(t)}(t)){var r=t.substr(5).substr(0,t.length-6).split(",");i={r:r[0],g:r[1],b:r[2],a:r[3]}}else if(!0===zK(t)){var s=PK(t);i={r:s.r,g:s.g,b:s.b,a:1}}}else if(t instanceof Object&&void 0!==t.r&&void 0!==t.g&&void 0!==t.b){var a=void 0!==t.a?t.a:"1.0";i={r:t.r,g:t.g,b:t.b,a:a}}if(void 0===i)throw new Error("Unknown color passed to the colorPicker. Supported are strings: rgb, hex, rgba. Object: rgb ({r:r,g:g,b:b,[a:a]}). Supplied: "+jX(t));this._setColor(i,e)}}},{key:"show",value:function(){void 0!==this.closeCallback&&(this.closeCallback(),this.closeCallback=void 0),this.applied=!1,this.frame.style.display="block",this._generateHueCircle()}},{key:"_hide",value:function(){var t=this;!0===(!(arguments.length>0&&void 0!==arguments[0])||arguments[0])&&(this.previousColor=pF({},this.color)),!0===this.applied&&this.updateCallback(this.initialColor),this.frame.style.display="none",rY((function(){void 0!==t.closeCallback&&(t.closeCallback(),t.closeCallback=void 0)}),0)}},{key:"_save",value:function(){this.updateCallback(this.color),this.applied=!1,this._hide()}},{key:"_apply",value:function(){this.applied=!0,this.updateCallback(this.color),this._updatePicker(this.color)}},{key:"_loadLast",value:function(){void 0!==this.previousColor?this.setColor(this.previousColor,!1):alert("There is no last color to load...")}},{key:"_setColor",value:function(t){!0===(!(arguments.length>1&&void 0!==arguments[1])||arguments[1])&&(this.initialColor=pF({},t)),this.color=t;var e=NK(t.r,t.g,t.b),i=2*Math.PI,n=this.r*e.s,o=this.centerCoordinates.x+n*Math.sin(i*e.h),r=this.centerCoordinates.y+n*Math.cos(i*e.h);this.colorPickerSelector.style.left=o-.5*this.colorPickerSelector.clientWidth+"px",this.colorPickerSelector.style.top=r-.5*this.colorPickerSelector.clientHeight+"px",this._updatePicker(t)}},{key:"_setOpacity",value:function(t){this.color.a=t/100,this._updatePicker(this.color)}},{key:"_setBrightness",value:function(t){var e=NK(this.color.r,this.color.g,this.color.b);e.v=t/100;var i=BK(e.h,e.s,e.v);i.a=this.color.a,this.color=i,this._updatePicker()}},{key:"_updatePicker",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.color,e=NK(t.r,t.g,t.b),i=this.colorPickerCanvas.getContext("2d");void 0===this.pixelRation&&(this.pixelRatio=(window.devicePixelRatio||1)/(i.webkitBackingStorePixelRatio||i.mozBackingStorePixelRatio||i.msBackingStorePixelRatio||i.oBackingStorePixelRatio||i.backingStorePixelRatio||1)),i.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var n=this.colorPickerCanvas.clientWidth,o=this.colorPickerCanvas.clientHeight;i.clearRect(0,0,n,o),i.putImageData(this.hueCircle,0,0),i.fillStyle="rgba(0,0,0,"+(1-e.v)+")",i.circle(this.centerCoordinates.x,this.centerCoordinates.y,this.r),vY(i).call(i),this.brightnessRange.value=100*e.v,this.opacityRange.value=100*t.a,this.initialColorDiv.style.backgroundColor="rgba("+this.initialColor.r+","+this.initialColor.g+","+this.initialColor.b+","+this.initialColor.a+")",this.newColorDiv.style.backgroundColor="rgba("+this.color.r+","+this.color.g+","+this.color.b+","+this.color.a+")"}},{key:"_setSize",value:function(){this.colorPickerCanvas.style.width="100%",this.colorPickerCanvas.style.height="100%",this.colorPickerCanvas.width=289*this.pixelRatio,this.colorPickerCanvas.height=289*this.pixelRatio}},{key:"_create",value:function(){var t,e,i,n;if(this.frame=document.createElement("div"),this.frame.className="vis-color-picker",this.colorPickerDiv=document.createElement("div"),this.colorPickerSelector=document.createElement("div"),this.colorPickerSelector.className="vis-selector",this.colorPickerDiv.appendChild(this.colorPickerSelector),this.colorPickerCanvas=document.createElement("canvas"),this.colorPickerDiv.appendChild(this.colorPickerCanvas),this.colorPickerCanvas.getContext){var o=this.colorPickerCanvas.getContext("2d");this.pixelRatio=(window.devicePixelRatio||1)/(o.webkitBackingStorePixelRatio||o.mozBackingStorePixelRatio||o.msBackingStorePixelRatio||o.oBackingStorePixelRatio||o.backingStorePixelRatio||1),this.colorPickerCanvas.getContext("2d").setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0)}else{var r=document.createElement("DIV");r.style.color="red",r.style.fontWeight="bold",r.style.padding="10px",r.innerText="Error: your browser does not support HTML canvas",this.colorPickerCanvas.appendChild(r)}this.colorPickerDiv.className="vis-color",this.opacityDiv=document.createElement("div"),this.opacityDiv.className="vis-opacity",this.brightnessDiv=document.createElement("div"),this.brightnessDiv.className="vis-brightness",this.arrowDiv=document.createElement("div"),this.arrowDiv.className="vis-arrow",this.opacityRange=document.createElement("input");try{this.opacityRange.type="range",this.opacityRange.min="0",this.opacityRange.max="100"}catch(t){}this.opacityRange.value="100",this.opacityRange.className="vis-range",this.brightnessRange=document.createElement("input");try{this.brightnessRange.type="range",this.brightnessRange.min="0",this.brightnessRange.max="100"}catch(t){}this.brightnessRange.value="100",this.brightnessRange.className="vis-range",this.opacityDiv.appendChild(this.opacityRange),this.brightnessDiv.appendChild(this.brightnessRange);var s=this;this.opacityRange.onchange=function(){s._setOpacity(this.value)},this.opacityRange.oninput=function(){s._setOpacity(this.value)},this.brightnessRange.onchange=function(){s._setBrightness(this.value)},this.brightnessRange.oninput=function(){s._setBrightness(this.value)},this.brightnessLabel=document.createElement("div"),this.brightnessLabel.className="vis-label vis-brightness",this.brightnessLabel.innerText="brightness:",this.opacityLabel=document.createElement("div"),this.opacityLabel.className="vis-label vis-opacity",this.opacityLabel.innerText="opacity:",this.newColorDiv=document.createElement("div"),this.newColorDiv.className="vis-new-color",this.newColorDiv.innerText="new",this.initialColorDiv=document.createElement("div"),this.initialColorDiv.className="vis-initial-color",this.initialColorDiv.innerText="initial",this.cancelButton=document.createElement("div"),this.cancelButton.className="vis-button vis-cancel",this.cancelButton.innerText="cancel",this.cancelButton.onclick=FF(t=this._hide).call(t,this,!1),this.applyButton=document.createElement("div"),this.applyButton.className="vis-button vis-apply",this.applyButton.innerText="apply",this.applyButton.onclick=FF(e=this._apply).call(e,this),this.saveButton=document.createElement("div"),this.saveButton.className="vis-button vis-save",this.saveButton.innerText="save",this.saveButton.onclick=FF(i=this._save).call(i,this),this.loadButton=document.createElement("div"),this.loadButton.className="vis-button vis-load",this.loadButton.innerText="load last",this.loadButton.onclick=FF(n=this._loadLast).call(n,this),this.frame.appendChild(this.colorPickerDiv),this.frame.appendChild(this.arrowDiv),this.frame.appendChild(this.brightnessLabel),this.frame.appendChild(this.brightnessDiv),this.frame.appendChild(this.opacityLabel),this.frame.appendChild(this.opacityDiv),this.frame.appendChild(this.newColorDiv),this.frame.appendChild(this.initialColorDiv),this.frame.appendChild(this.cancelButton),this.frame.appendChild(this.applyButton),this.frame.appendChild(this.saveButton),this.frame.appendChild(this.loadButton)}},{key:"_bindHammer",value:function(){var t=this;this.drag={},this.pinch={},this.hammer=new mK(this.colorPickerCanvas),this.hammer.get("pinch").set({enable:!0}),this.hammer.on("hammer.input",(function(e){e.isFirst&&t._moveSelector(e)})),this.hammer.on("tap",(function(e){t._moveSelector(e)})),this.hammer.on("panstart",(function(e){t._moveSelector(e)})),this.hammer.on("panmove",(function(e){t._moveSelector(e)})),this.hammer.on("panend",(function(e){t._moveSelector(e)}))}},{key:"_generateHueCircle",value:function(){if(!1===this.generated){var t=this.colorPickerCanvas.getContext("2d");void 0===this.pixelRation&&(this.pixelRatio=(window.devicePixelRatio||1)/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1)),t.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var e,i,n,o,r=this.colorPickerCanvas.clientWidth,s=this.colorPickerCanvas.clientHeight;t.clearRect(0,0,r,s),this.centerCoordinates={x:.5*r,y:.5*s},this.r=.49*r;var a,d=2*Math.PI/360,l=1/360,c=1/this.r;for(n=0;n<360;n++)for(o=0;o3&&void 0!==arguments[3]?arguments[3]:1,r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:function(){return!1};rj(this,t),this.parent=e,this.changedOptions=[],this.container=i,this.allowCreation=!1,this.hideOption=r,this.options={},this.initialized=!1,this.popupCounter=0,this.defaultOptions={enabled:!1,filter:!0,container:void 0,showButton:!0},pF(this.options,this.defaultOptions),this.configureOptions=n,this.moduleOptions={},this.domElements=[],this.popupDiv={},this.popupLimit=5,this.popupHistory={},this.colorPicker=new qK(o),this.wrapper=void 0}return cW(t,[{key:"setOptions",value:function(t){if(void 0!==t){this.popupHistory={},this._removePopup();var e=!0;if("string"==typeof t)this.options.filter=t;else if(fV(t))this.options.filter=t.join();else if("object"===sW(t)){if(null==t)throw new TypeError("options cannot be null");void 0!==t.container&&(this.options.container=t.container),void 0!==Jq(t)&&(this.options.filter=Jq(t)),void 0!==t.showButton&&(this.options.showButton=t.showButton),void 0!==t.enabled&&(e=t.enabled)}else"boolean"==typeof t?(this.options.filter=!0,e=t):"function"==typeof t&&(this.options.filter=t,e=!0);!1===Jq(this.options)&&(e=!1),this.options.enabled=e}this._clean()}},{key:"setModuleOptions",value:function(t){this.moduleOptions=t,!0===this.options.enabled&&(this._clean(),void 0!==this.options.container&&(this.container=this.options.container),this._create())}},{key:"_create",value:function(){this._clean(),this.changedOptions=[];var t=Jq(this.options),e=0,i=!1;for(var n in this.configureOptions)Object.prototype.hasOwnProperty.call(this.configureOptions,n)&&(this.allowCreation=!1,i=!1,"function"==typeof t?i=(i=t(n,[]))||this._handleObject(this.configureOptions[n],[n],!0):!0!==t&&-1===PX(t).call(t,n)||(i=!0),!1!==i&&(this.allowCreation=!0,e>0&&this._makeItem([]),this._makeHeader(n),this._handleObject(this.configureOptions[n],[n])),e++);this._makeButton(),this._push()}},{key:"_push",value:function(){this.wrapper=document.createElement("div"),this.wrapper.className="vis-configuration-wrapper",this.container.appendChild(this.wrapper);for(var t=0;t1?i-1:0),o=1;o2&&void 0!==arguments[2]&&arguments[2],n=document.createElement("div");if(n.className="vis-configuration vis-config-label vis-config-s"+e.length,!0===i){for(;n.firstChild;)n.removeChild(n.firstChild);n.appendChild(XK("i","b",t))}else n.innerText=t+":";return n}},{key:"_makeDropdown",value:function(t,e,i){var n=document.createElement("select");n.className="vis-configuration vis-config-select";var o=0;void 0!==e&&-1!==PX(t).call(t,e)&&(o=PX(t).call(t,e));for(var r=0;rr&&1!==r&&(a.max=Math.ceil(e*c),l=a.max,d="range increased"),a.value=e}else a.value=n;var h=document.createElement("input");h.className="vis-configuration vis-config-rangeinput",h.value=a.value;var u=this;a.onchange=function(){h.value=this.value,u._update(Number(this.value),i)},a.oninput=function(){h.value=this.value};var p=this._makeLabel(i[i.length-1],i),f=this._makeItem(i,p,a,h);""!==d&&this.popupHistory[f]!==l&&(this.popupHistory[f]=l,this._setupPopup(d,f))}},{key:"_makeButton",value:function(){var t=this;if(!0===this.options.showButton){var e=document.createElement("div");e.className="vis-configuration vis-config-button",e.innerText="generate options",e.onclick=function(){t._printOptions()},e.onmouseover=function(){e.className="vis-configuration vis-config-button hover"},e.onmouseout=function(){e.className="vis-configuration vis-config-button"},this.optionsContainer=document.createElement("div"),this.optionsContainer.className="vis-configuration vis-config-option-container",this.domElements.push(this.optionsContainer),this.domElements.push(e)}}},{key:"_setupPopup",value:function(t,e){var i=this;if(!0===this.initialized&&!0===this.allowCreation&&this.popupCounter1&&void 0!==arguments[1]?arguments[1]:[],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=!1,o=Jq(this.options),r=!1;for(var s in t)if(Object.prototype.hasOwnProperty.call(t,s)){n=!0;var a=t[s],d=IK(e,s);if("function"==typeof o&&!1===(n=o(s,e))&&!fV(a)&&"string"!=typeof a&&"boolean"!=typeof a&&a instanceof Object&&(this.allowCreation=!1,n=this._handleObject(a,d,!0),this.allowCreation=!1===i),!1!==n){r=!0;var l=this._getValue(d);if(fV(a))this._handleArray(a,l,d);else if("string"==typeof a)this._makeTextInput(a,l,d);else if("boolean"==typeof a)this._makeCheckbox(a,l,d);else if(a instanceof Object){if(!this.hideOption(e,s,this.moduleOptions))if(void 0!==a.enabled){var c=IK(d,"enabled"),h=this._getValue(c);if(!0===h){var u=this._makeLabel(s,d,!0);this._makeItem(d,u),r=this._handleObject(a,d)||r}else this._makeCheckbox(a,h,d)}else{var p=this._makeLabel(s,d,!0);this._makeItem(d,p),r=this._handleObject(a,d)||r}}else console.error("dont know how to handle",a,s,d)}}return r}},{key:"_handleArray",value:function(t,e,i){"string"==typeof t[0]&&"color"===t[0]?(this._makeColorField(t,e,i),t[1]!==e&&this.changedOptions.push({path:i,value:e})):"string"==typeof t[0]?(this._makeDropdown(t,e,i),t[0]!==e&&this.changedOptions.push({path:i,value:e})):"number"==typeof t[0]&&(this._makeRange(t,e,i),t[0]!==e&&this.changedOptions.push({path:i,value:Number(e)}))}},{key:"_update",value:function(t,e){var i=this._constructOptions(t,e);this.parent.body&&this.parent.body.emitter&&this.parent.body.emitter.emit&&this.parent.body.emitter.emit("configChange",i),this.initialized=!0,this.parent.setOptions(i)}},{key:"_constructOptions",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},n=i;t="false"!==(t="true"===t||t)&&t;for(var o=0;oo-this.padding&&(a=!0),r=a?this.x-i:this.x,s=d?this.y-e:this.y}else(s=this.y-e)+e+this.padding>n&&(s=n-e-this.padding),so&&(r=o-i-this.padding),rs.distance?" in "+t.printLocation(r.path,e,"")+"Perhaps it was misplaced? Matching option found at: "+t.printLocation(s.path,s.closestMatch,""):r.distance<=8?'. Did you mean "'+r.closestMatch+'"?'+t.printLocation(r.path,e):". Did you mean one of these: "+t.print(kV(i))+t.printLocation(n,e),console.error('%cUnknown option detected: "'+e+'"'+o,QK),ZK=!0}},{key:"findInOptions",value:function(e,i,n){var o,r=arguments.length>3&&void 0!==arguments[3]&&arguments[3],s=1e9,a="",d=[],l=e.toLowerCase(),c=void 0;for(var h in i){var u=void 0;if(void 0!==i[h].__type__&&!0===r){var p=t.findInOptions(e,i[h],IK(n,h));s>p.distance&&(a=p.closestMatch,d=p.path,s=p.distance,c=p.indexMatch)}else{var f;-1!==PX(f=h.toLowerCase()).call(f,l)&&(c=h),s>(u=t.levenshteinDistance(e,h))&&(a=h,d=aV(o=n).call(o),s=u)}}return{closestMatch:a,path:d,distance:s,indexMatch:c}}},{key:"printLocation",value:function(t,e){for(var i="\n\n"+(arguments.length>2&&void 0!==arguments[2]?arguments[2]:"Problem value found at: \n")+"options = {\n",n=0;n":!0,"--":!0},hZ="",uZ=0,pZ="",fZ="",mZ=lZ.NULL;function vZ(){uZ++,pZ=hZ.charAt(uZ)}function gZ(){return hZ.charAt(uZ+1)}function yZ(t){var e=t.charCodeAt(0);return e<47?35===e||46===e:e<59?e>47:e<91?e>64:e<96?95===e:e<123&&e>96}function bZ(t,e){if(t||(t={}),e)for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function xZ(t,e,i){for(var n=e.split("."),o=t;n.length;){var r=n.shift();n.length?(o[r]||(o[r]={}),o=o[r]):o[r]=i}}function _Z(t,e){for(var i,n,o=null,r=[t],s=t;s.parent;)r.push(s.parent),s=s.parent;if(s.nodes)for(i=0,n=s.nodes.length;i=0;i--){var a,d=r[i];d.nodes||(d.nodes=[]),-1===PX(a=d.nodes).call(a,o)&&d.nodes.push(o)}e.attr&&(o.attr=bZ(o.attr,e.attr))}function wZ(t,e){if(t.edges||(t.edges=[]),t.edges.push(e),t.edge){var i=bZ({},t.edge);e.attr=bZ(i,e.attr)}}function EZ(t,e,i,n,o){var r={from:e,to:i,type:n};return t.edge&&(r.attr=bZ({},t.edge)),r.attr=bZ(r.attr||{},o),null!=o&&o.hasOwnProperty("arrows")&&null!=o.arrows&&(r.arrows={to:{enabled:!0,type:o.arrows.type}},o.arrows=null),r}function kZ(){for(mZ=lZ.NULL,fZ="";" "===pZ||"\t"===pZ||"\n"===pZ||"\r"===pZ;)vZ();do{var t=!1;if("#"===pZ){for(var e=uZ-1;" "===hZ.charAt(e)||"\t"===hZ.charAt(e);)e--;if("\n"===hZ.charAt(e)||""===hZ.charAt(e)){for(;""!=pZ&&"\n"!=pZ;)vZ();t=!0}}if("/"===pZ&&"/"===gZ()){for(;""!=pZ&&"\n"!=pZ;)vZ();t=!0}if("/"===pZ&&"*"===gZ()){for(;""!=pZ;){if("*"===pZ&&"/"===gZ()){vZ(),vZ();break}vZ()}t=!0}for(;" "===pZ||"\t"===pZ||"\n"===pZ||"\r"===pZ;)vZ()}while(t);if(""!==pZ){var i=pZ+gZ();if(cZ[i])return mZ=lZ.DELIMITER,fZ=i,vZ(),void vZ();if(cZ[pZ])return mZ=lZ.DELIMITER,fZ=pZ,void vZ();if(yZ(pZ)||"-"===pZ){for(fZ+=pZ,vZ();yZ(pZ);)fZ+=pZ,vZ();return"false"===fZ?fZ=!1:"true"===fZ?fZ=!0:isNaN(Number(fZ))||(fZ=Number(fZ)),void(mZ=lZ.IDENTIFIER)}if('"'===pZ){for(vZ();""!=pZ&&('"'!=pZ||'"'===pZ&&'"'===gZ());)'"'===pZ?(fZ+=pZ,vZ()):"\\"===pZ&&"n"===gZ()?(fZ+="\n",vZ()):fZ+=pZ,vZ();if('"'!=pZ)throw AZ('End of string " expected');return vZ(),void(mZ=lZ.IDENTIFIER)}for(mZ=lZ.UNKNOWN;""!=pZ;)fZ+=pZ,vZ();throw new SyntaxError('Syntax error in part "'+RZ(fZ,30)+'"')}mZ=lZ.DELIMITER}function OZ(t){for(;""!==fZ&&"}"!=fZ;)CZ(t),";"===fZ&&kZ()}function CZ(t){var e=SZ(t);if(e)TZ(t,e);else{var i=function(t){if("node"===fZ)return kZ(),t.node=IZ(),"node";if("edge"===fZ)return kZ(),t.edge=IZ(),"edge";if("graph"===fZ)return kZ(),t.graph=IZ(),"graph";return null}(t);if(!i){if(mZ!=lZ.IDENTIFIER)throw AZ("Identifier expected");var n=fZ;if(kZ(),"="===fZ){if(kZ(),mZ!=lZ.IDENTIFIER)throw AZ("Identifier expected");t[n]=fZ,kZ()}else!function(t,e){var i={id:e},n=IZ();n&&(i.attr=n);_Z(t,i),TZ(t,e)}(t,n)}}}function SZ(t){var e=null;if("subgraph"===fZ&&((e={}).type="subgraph",kZ(),mZ===lZ.IDENTIFIER&&(e.id=fZ,kZ())),"{"===fZ){if(kZ(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,OZ(e),"}"!=fZ)throw AZ("Angle bracket } expected");kZ(),delete e.node,delete e.edge,delete e.graph,delete e.parent,t.subgraphs||(t.subgraphs=[]),t.subgraphs.push(e)}return e}function TZ(t,e){for(;"->"===fZ||"--"===fZ;){var i,n=fZ;kZ();var o=SZ(t);if(o)i=o;else{if(mZ!=lZ.IDENTIFIER)throw AZ("Identifier or subgraph expected");_Z(t,{id:i=fZ}),kZ()}wZ(t,EZ(t,e,i,n,IZ())),e=i}}function IZ(){for(var t,e,i=null,n={dashed:!0,solid:!1,dotted:[1,5]},o={dot:"circle",box:"box",crow:"crow",curve:"curve",icurve:"inv_curve",normal:"triangle",inv:"inv_triangle",diamond:"diamond",tee:"bar",vee:"vee"},r=new Array,s=new Array;"["===fZ;){for(kZ(),i={};""!==fZ&&"]"!=fZ;){if(mZ!=lZ.IDENTIFIER)throw AZ("Attribute name expected");var a=fZ;if(kZ(),"="!=fZ)throw AZ("Equal sign = expected");if(kZ(),mZ!=lZ.IDENTIFIER)throw AZ("Attribute value expected");var d=fZ;"style"===a&&(d=n[d]),"arrowhead"===a&&(a="arrows",d={to:{enabled:!0,type:o[d]}}),"arrowtail"===a&&(a="arrows",d={from:{enabled:!0,type:o[d]}}),r.push({attr:i,name:a,value:d}),s.push(a),kZ(),","==fZ&&kZ()}if("]"!=fZ)throw AZ("Bracket ] expected");kZ()}if(Hq(s).call(s,"dir")){var l={arrows:{}};for(t=0;t"===t.type&&(e.arrows="to"),e};HV(o=i.edges).call(o,(function(t){var e,i,o,s;(e=t.from instanceof Object?t.from.nodes:{id:t.from},i=t.to instanceof Object?t.to.nodes:{id:t.to},t.from instanceof Object&&t.from.edges)&&HV(o=t.from.edges).call(o,(function(t){var e=r(t);n.edges.push(e)}));(function(t,e,i){fV(t)?HV(t).call(t,(function(t){fV(e)?HV(e).call(e,(function(e){i(t,e)})):i(t,e)})):fV(e)?HV(e).call(e,(function(e){i(t,e)})):i(t,e)}(e,i,(function(e,i){var o=EZ(n,e.id,i.id,t.type,t.attr),s=r(o);n.edges.push(s)})),t.to instanceof Object&&t.to.edges)&&HV(s=t.to.edges).call(s,(function(t){var e=r(t);n.edges.push(e)}))}))}return i.attr&&(n.options=i.attr),n}var FZ=Object.freeze({__proto__:null,cn:{addDescription:"单击空白处放置新节点。",addEdge:"添加连接线",addNode:"添加节点",back:"返回",close:"關閉",createEdgeError:"无法将连接线连接到群集。",del:"删除选定",deleteClusterError:"无法删除群集。",edgeDescription:"单击某个节点并将该连接线拖动到另一个节点以连接它们。",edit:"编辑",editClusterError:"无法编辑群集。",editEdge:"编辑连接线",editEdgeDescription:"单击控制节点并将它们拖到节点上连接。",editNode:"编辑节点"},cs:{addDescription:"Kluknutím do prázdného prostoru můžete přidat nový vrchol.",addEdge:"Přidat hranu",addNode:"Přidat vrchol",back:"Zpět",close:"Zavřít",createEdgeError:"Nelze připojit hranu ke shluku.",del:"Smazat výběr",deleteClusterError:"Nelze mazat shluky.",edgeDescription:"Přetažením z jednoho vrcholu do druhého můžete spojit tyto vrcholy novou hranou.",edit:"Upravit",editClusterError:"Nelze upravovat shluky.",editEdge:"Upravit hranu",editEdgeDescription:"Přetažením kontrolního vrcholu hrany ji můžete připojit k jinému vrcholu.",editNode:"Upravit vrchol"},de:{addDescription:"Klicke auf eine freie Stelle, um einen neuen Knoten zu plazieren.",addEdge:"Kante hinzufügen",addNode:"Knoten hinzufügen",back:"Zurück",close:"Schließen",createEdgeError:"Es ist nicht möglich, Kanten mit Clustern zu verbinden.",del:"Lösche Auswahl",deleteClusterError:"Cluster können nicht gelöscht werden.",edgeDescription:"Klicke auf einen Knoten und ziehe die Kante zu einem anderen Knoten, um diese zu verbinden.",edit:"Editieren",editClusterError:"Cluster können nicht editiert werden.",editEdge:"Kante editieren",editEdgeDescription:"Klicke auf die Verbindungspunkte und ziehe diese auf einen Knoten, um sie zu verbinden.",editNode:"Knoten editieren"},en:{addDescription:"Click in an empty space to place a new node.",addEdge:"Add Edge",addNode:"Add Node",back:"Back",close:"Close",createEdgeError:"Cannot link edges to a cluster.",del:"Delete selected",deleteClusterError:"Clusters cannot be deleted.",edgeDescription:"Click on a node and drag the edge to another node to connect them.",edit:"Edit",editClusterError:"Clusters cannot be edited.",editEdge:"Edit Edge",editEdgeDescription:"Click on the control points and drag them to a node to connect to it.",editNode:"Edit Node"},es:{addDescription:"Haga clic en un lugar vacío para colocar un nuevo nodo.",addEdge:"Añadir arista",addNode:"Añadir nodo",back:"Atrás",close:"Cerrar",createEdgeError:"No se puede conectar una arista a un grupo.",del:"Eliminar selección",deleteClusterError:"No es posible eliminar grupos.",edgeDescription:"Haga clic en un nodo y arrastre la arista hacia otro nodo para conectarlos.",edit:"Editar",editClusterError:"No es posible editar grupos.",editEdge:"Editar arista",editEdgeDescription:"Haga clic en un punto de control y arrastrelo a un nodo para conectarlo.",editNode:"Editar nodo"},fr:{addDescription:"Cliquez dans un endroit vide pour placer un nœud.",addEdge:"Ajouter un lien",addNode:"Ajouter un nœud",back:"Retour",close:"Fermer",createEdgeError:"Impossible de créer un lien vers un cluster.",del:"Effacer la sélection",deleteClusterError:"Les clusters ne peuvent pas être effacés.",edgeDescription:"Cliquez sur un nœud et glissez le lien vers un autre nœud pour les connecter.",edit:"Éditer",editClusterError:"Les clusters ne peuvent pas être édités.",editEdge:"Éditer le lien",editEdgeDescription:"Cliquez sur les points de contrôle et glissez-les pour connecter un nœud.",editNode:"Éditer le nœud"},it:{addDescription:"Clicca per aggiungere un nuovo nodo",addEdge:"Aggiungi un vertice",addNode:"Aggiungi un nodo",back:"Indietro",close:"Chiudere",createEdgeError:"Non si possono collegare vertici ad un cluster",del:"Cancella la selezione",deleteClusterError:"I cluster non possono essere cancellati",edgeDescription:"Clicca su un nodo e trascinalo ad un altro nodo per connetterli.",edit:"Modifica",editClusterError:"I clusters non possono essere modificati.",editEdge:"Modifica il vertice",editEdgeDescription:"Clicca sui Punti di controllo e trascinali ad un nodo per connetterli.",editNode:"Modifica il nodo"},nl:{addDescription:"Klik op een leeg gebied om een nieuwe node te maken.",addEdge:"Link toevoegen",addNode:"Node toevoegen",back:"Terug",close:"Sluiten",createEdgeError:"Kan geen link maken naar een cluster.",del:"Selectie verwijderen",deleteClusterError:"Clusters kunnen niet worden verwijderd.",edgeDescription:"Klik op een node en sleep de link naar een andere node om ze te verbinden.",edit:"Wijzigen",editClusterError:"Clusters kunnen niet worden aangepast.",editEdge:"Link wijzigen",editEdgeDescription:"Klik op de verbindingspunten en sleep ze naar een node om daarmee te verbinden.",editNode:"Node wijzigen"},pt:{addDescription:"Clique em um espaço em branco para adicionar um novo nó",addEdge:"Adicionar aresta",addNode:"Adicionar nó",back:"Voltar",close:"Fechar",createEdgeError:"Não foi possível linkar arestas a um cluster.",del:"Remover selecionado",deleteClusterError:"Clusters não puderam ser removidos.",edgeDescription:"Clique em um nó e arraste a aresta até outro nó para conectá-los",edit:"Editar",editClusterError:"Clusters não puderam ser editados.",editEdge:"Editar aresta",editEdgeDescription:"Clique nos pontos de controle e os arraste para um nó para conectá-los",editNode:"Editar nó"},ru:{addDescription:"Кликните в свободное место, чтобы добавить новый узел.",addEdge:"Добавить ребро",addNode:"Добавить узел",back:"Назад",close:"Закрывать",createEdgeError:"Невозможно соединить ребра в кластер.",del:"Удалить выбранное",deleteClusterError:"Кластеры не могут быть удалены",edgeDescription:"Кликните на узел и протяните ребро к другому узлу, чтобы соединить их.",edit:"Редактировать",editClusterError:"Кластеры недоступны для редактирования.",editEdge:"Редактировать ребро",editEdgeDescription:"Кликните на контрольные точки и перетащите их в узел, чтобы подключиться к нему.",editNode:"Редактировать узел"},uk:{addDescription:"Kлікніть на вільне місце, щоб додати новий вузол.",addEdge:"Додати край",addNode:"Додати вузол",back:"Назад",close:"Закрити",createEdgeError:"Не можливо об'єднати краї в групу.",del:"Видалити обране",deleteClusterError:"Групи не можуть бути видалені.",edgeDescription:"Клікніть на вузол і перетягніть край до іншого вузла, щоб їх з'єднати.",edit:"Редагувати",editClusterError:"Групи недоступні для редагування.",editEdge:"Редагувати край",editEdgeDescription:"Клікніть на контрольні точки і перетягніть їх у вузол, щоб підключитися до нього.",editNode:"Редагувати вузол"}});var NZ=function(){function t(){rj(this,t),this.NUM_ITERATIONS=4,this.image=new Image,this.canvas=document.createElement("canvas")}return cW(t,[{key:"init",value:function(){if(!this.initialized()){this.src=this.image.src;var t=this.image.width,e=this.image.height;this.width=t,this.height=e;var i=Math.floor(e/2),n=Math.floor(e/4),o=Math.floor(e/8),r=Math.floor(e/16),s=Math.floor(t/2),a=Math.floor(t/4),d=Math.floor(t/8),l=Math.floor(t/16);this.canvas.width=3*a,this.canvas.height=i,this.coordinates=[[0,0,s,i],[s,0,a,n],[s,n,d,o],[5*d,n,l,r]],this._fillMipMap()}}},{key:"initialized",value:function(){return void 0!==this.coordinates}},{key:"_fillMipMap",value:function(){var t=this.canvas.getContext("2d"),e=this.coordinates[0];t.drawImage(this.image,e[0],e[1],e[2],e[3]);for(var i=1;i2){e*=.5;for(var s=0;e>2&&s=this.NUM_ITERATIONS&&(s=this.NUM_ITERATIONS-1);var a=this.coordinates[s];t.drawImage(this.canvas,a[0],a[1],a[2],a[3],i,n,o,r)}else t.drawImage(this.image,i,n,o,r)}}]),t}(),BZ=function(){function t(e){rj(this,t),this.images={},this.imageBroken={},this.callback=e}return cW(t,[{key:"_tryloadBrokenUrl",value:function(t,e,i){void 0!==t&&void 0!==i&&(void 0!==e?(i.image.onerror=function(){console.error("Could not load brokenImage:",e)},i.image.src=e):console.warn("No broken url image defined"))}},{key:"_redrawWithImage",value:function(t){this.callback&&this.callback(t)}},{key:"load",value:function(t,e){var i=this,n=this.images[t];if(n)return n;var o=new NZ;return this.images[t]=o,o.image.onload=function(){i._fixImageCoordinates(o.image),o.init(),i._redrawWithImage(o)},o.image.onerror=function(){console.error("Could not load image:",t),i._tryloadBrokenUrl(t,e,o)},o.image.src=t,o}},{key:"_fixImageCoordinates",value:function(t){0===t.width&&(document.body.appendChild(t),t.width=t.offsetWidth,t.height=t.offsetHeight,document.body.removeChild(t))}}]),t}(),LZ={exports:{}},zZ=JA((function(){if("function"==typeof ArrayBuffer){var t=new ArrayBuffer(8);Object.isExtensible(t)&&Object.defineProperty(t,"a",{value:8})}})),jZ=JA,HZ=YR,$Z=fR,UZ=zZ,WZ=Object.isExtensible,VZ=jZ((function(){WZ(1)}))||UZ?function(t){return!!HZ(t)&&((!UZ||"ArrayBuffer"!==$Z(t))&&(!WZ||WZ(t)))}:WZ,qZ=!JA((function(){return Object.isExtensible(Object.preventExtensions({}))})),XZ=wM,YZ=cR,GZ=HM,KZ=YR,ZZ=qP,QZ=VD.f,JZ=Uj,tQ=qj,eQ=VZ,iQ=qZ,nQ=!1,oQ=ZP("meta"),rQ=0,sQ=function(t){QZ(t,oQ,{value:{objectID:"O"+rQ++,weakData:{}}})},aQ=LZ.exports={enable:function(){aQ.enable=function(){},nQ=!0;var t=JZ.f,e=YZ([].splice),i={};i[oQ]=1,t(i).length&&(JZ.f=function(i){for(var n=t(i),o=0,r=n.length;or;r++)if((a=g(t[r]))&&mQ(_Q,a))return a;return new xQ(!1)}n=vQ(t,o)}for(d=u?t.next:n.next;!(l=cQ(d,n)).done;){try{a=g(l.value)}catch(t){yQ(n,"throw",t)}if("object"==typeof a&&a&&mQ(_Q,a))return a}return new xQ(!1)},EQ=eP,kQ=TypeError,OQ=function(t,e){if(EQ(e,t))return t;throw new kQ("Incorrect invocation")},CQ=wM,SQ=QA,TQ=dQ,IQ=JA,AQ=cM,RQ=wQ,PQ=OQ,DQ=_R,MQ=YR,FQ=zR,NQ=HB,BQ=VD.f,LQ=OH.forEach,zQ=ER,jQ=DN.set,HQ=DN.getterFor,$Q=function(t,e,i){var n,o=-1!==t.indexOf("Map"),r=-1!==t.indexOf("Weak"),s=o?"set":"add",a=SQ[t],d=a&&a.prototype,l={};if(zQ&&DQ(a)&&(r||d.forEach&&!IQ((function(){(new a).entries().next()})))){var c=(n=e((function(e,i){jQ(PQ(e,c),{type:t,collection:new a}),FQ(i)||RQ(i,e[s],{that:e,AS_ENTRIES:o})}))).prototype,h=HQ(t);LQ(["add","clear","delete","forEach","get","has","set","keys","values","entries"],(function(t){var e="add"===t||"set"===t;!(t in d)||r&&"clear"===t||AQ(c,t,(function(i,n){var o=h(this).collection;if(!e&&r&&!MQ(i))return"get"===t&&void 0;var s=o[t](0===i?0:i,n);return e?this:s}))})),r||BQ(c,"size",{configurable:!0,get:function(){return h(this).collection.size}})}else n=i.getConstructor(e,t,o,s),TQ.enable();return NQ(n,t,!1,!0),l[t]=n,CQ({global:!0,forced:!0},l),r||i.setStrong(n,t,o),n},UQ=wB,WQ=function(t,e,i){for(var n in e)i&&i.unsafe&&t[n]?t[n]=e[n]:UQ(t,n,e[n],i);return t},VQ=tP,qQ=rH,XQ=ER,YQ=sD("species"),GQ=hB,KQ=rH,ZQ=WQ,QQ=WD,JQ=OQ,tJ=zR,eJ=wQ,iJ=yL,nJ=bL,oJ=function(t){var e=VQ(t);XQ&&e&&!e[YQ]&&qQ(e,YQ,{configurable:!0,get:function(){return this}})},rJ=ER,sJ=dQ.fastKey,aJ=DN.set,dJ=DN.getterFor,lJ={getConstructor:function(t,e,i,n){var o=t((function(t,o){JQ(t,r),aJ(t,{type:e,index:GQ(null),first:void 0,last:void 0,size:0}),rJ||(t.size=0),tJ(o)||eJ(o,t[n],{that:t,AS_ENTRIES:i})})),r=o.prototype,s=dJ(e),a=function(t,e,i){var n,o,r=s(t),a=d(t,e);return a?a.value=i:(r.last=a={index:o=sJ(e,!0),key:e,value:i,previous:n=r.last,next:void 0,removed:!1},r.first||(r.first=a),n&&(n.next=a),rJ?r.size++:t.size++,"F"!==o&&(r.index[o]=a)),t},d=function(t,e){var i,n=s(t),o=sJ(e);if("F"!==o)return n.index[o];for(i=n.first;i;i=i.next)if(i.key===e)return i};return ZQ(r,{clear:function(){for(var t=s(this),e=t.index,i=t.first;i;)i.removed=!0,i.previous&&(i.previous=i.previous.next=void 0),delete e[i.index],i=i.next;t.first=t.last=void 0,rJ?t.size=0:this.size=0},delete:function(t){var e=this,i=s(e),n=d(e,t);if(n){var o=n.next,r=n.previous;delete i.index[n.index],n.removed=!0,r&&(r.next=o),o&&(o.previous=r),i.first===n&&(i.first=o),i.last===n&&(i.last=r),rJ?i.size--:e.size--}return!!n},forEach:function(t){for(var e,i=s(this),n=QQ(t,arguments.length>1?arguments[1]:void 0);e=e?e.next:i.first;)for(n(e.value,e.key,this);e&&e.removed;)e=e.previous},has:function(t){return!!d(this,t)}}),ZQ(r,i?{get:function(t){var e=d(this,t);return e&&e.value},set:function(t,e){return a(this,0===t?0:t,e)}}:{add:function(t){return a(this,t=0===t?0:t,t)}}),rJ&&KQ(r,"size",{configurable:!0,get:function(){return s(this).size}}),o},setStrong:function(t,e,i){var n=e+" Iterator",o=dJ(e),r=dJ(n);iJ(t,e,(function(t,e){aJ(this,{type:n,target:t,state:o(t),kind:e,last:void 0})}),(function(){for(var t=r(this),e=t.kind,i=t.last;i&&i.removed;)i=i.previous;return t.target&&(t.last=i=i?i.next:t.state.first)?nJ("keys"===e?i.key:"values"===e?i.value:[i.key,i.value],!1):(t.target=void 0,nJ(void 0,!0))}),i?"entries":"values",!i,!0),oJ(e)}};$Q("Map",(function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}}),lJ);var cJ=KA(GR.Map),hJ=function(){function t(){rj(this,t),this.clear(),this._defaultIndex=0,this._groupIndex=0,this._defaultGroups=[{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"},hover:{border:"#2B7CE9",background:"#D2E5FF"}},{border:"#FFA500",background:"#FFFF00",highlight:{border:"#FFA500",background:"#FFFFA3"},hover:{border:"#FFA500",background:"#FFFFA3"}},{border:"#FA0A10",background:"#FB7E81",highlight:{border:"#FA0A10",background:"#FFAFB1"},hover:{border:"#FA0A10",background:"#FFAFB1"}},{border:"#41A906",background:"#7BE141",highlight:{border:"#41A906",background:"#A1EC76"},hover:{border:"#41A906",background:"#A1EC76"}},{border:"#E129F0",background:"#EB7DF4",highlight:{border:"#E129F0",background:"#F0B3F5"},hover:{border:"#E129F0",background:"#F0B3F5"}},{border:"#7C29F0",background:"#AD85E4",highlight:{border:"#7C29F0",background:"#D3BDF0"},hover:{border:"#7C29F0",background:"#D3BDF0"}},{border:"#C37F00",background:"#FFA807",highlight:{border:"#C37F00",background:"#FFCA66"},hover:{border:"#C37F00",background:"#FFCA66"}},{border:"#4220FB",background:"#6E6EFD",highlight:{border:"#4220FB",background:"#9B9BFD"},hover:{border:"#4220FB",background:"#9B9BFD"}},{border:"#FD5A77",background:"#FFC0CB",highlight:{border:"#FD5A77",background:"#FFD1D9"},hover:{border:"#FD5A77",background:"#FFD1D9"}},{border:"#4AD63A",background:"#C2FABC",highlight:{border:"#4AD63A",background:"#E6FFE3"},hover:{border:"#4AD63A",background:"#E6FFE3"}},{border:"#990000",background:"#EE0000",highlight:{border:"#BB0000",background:"#FF3333"},hover:{border:"#BB0000",background:"#FF3333"}},{border:"#FF6000",background:"#FF6000",highlight:{border:"#FF6000",background:"#FF6000"},hover:{border:"#FF6000",background:"#FF6000"}},{border:"#97C2FC",background:"#2B7CE9",highlight:{border:"#D2E5FF",background:"#2B7CE9"},hover:{border:"#D2E5FF",background:"#2B7CE9"}},{border:"#399605",background:"#255C03",highlight:{border:"#399605",background:"#255C03"},hover:{border:"#399605",background:"#255C03"}},{border:"#B70054",background:"#FF007E",highlight:{border:"#B70054",background:"#FF007E"},hover:{border:"#B70054",background:"#FF007E"}},{border:"#AD85E4",background:"#7C29F0",highlight:{border:"#D3BDF0",background:"#7C29F0"},hover:{border:"#D3BDF0",background:"#7C29F0"}},{border:"#4557FA",background:"#000EA1",highlight:{border:"#6E6EFD",background:"#000EA1"},hover:{border:"#6E6EFD",background:"#000EA1"}},{border:"#FFC0CB",background:"#FD5A77",highlight:{border:"#FFD1D9",background:"#FD5A77"},hover:{border:"#FFD1D9",background:"#FD5A77"}},{border:"#C2FABC",background:"#74D66A",highlight:{border:"#E6FFE3",background:"#74D66A"},hover:{border:"#E6FFE3",background:"#74D66A"}},{border:"#EE0000",background:"#990000",highlight:{border:"#FF3333",background:"#BB0000"},hover:{border:"#FF3333",background:"#BB0000"}}],this.options={},this.defaultOptions={useDefaultGroups:!0},pF(this.options,this.defaultOptions)}return cW(t,[{key:"setOptions",value:function(t){var e=["useDefaultGroups"];if(void 0!==t)for(var i in t)if(Object.prototype.hasOwnProperty.call(t,i)&&-1===PX(e).call(e,i)){var n=t[i];this.add(i,n)}}},{key:"clear",value:function(){this._groups=new cJ,this._groupNames=[]}},{key:"get",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=this._groups.get(t);if(void 0===i&&e)if(!1===this.options.useDefaultGroups&&this._groupNames.length>0){var n=this._groupIndex%this._groupNames.length;++this._groupIndex,(i={}).color=this._groups.get(this._groupNames[n]),this._groups.set(t,i)}else{var o=this._defaultIndex%this._defaultGroups.length;this._defaultIndex++,(i={}).color=this._defaultGroups[o],this._groups.set(t,i)}return i}},{key:"add",value:function(t,e){return this._groups.has(t)||this._groupNames.push(t),this._groups.set(t,e),e}}]),t}();wM({target:"Number",stat:!0},{isNaN:function(t){return t!=t}});var uJ=KA(GR.Number.isNaN),pJ=QA.isFinite,fJ=Number.isFinite||function(t){return"number"==typeof t&&pJ(t)};wM({target:"Number",stat:!0},{isFinite:fJ});var mJ=KA(GR.Number.isFinite),vJ=OH.some;wM({target:"Array",proto:!0,forced:!AV("some")},{some:function(t){return vJ(this,t,arguments.length>1?arguments[1]:void 0)}});var gJ=TF("Array").some,yJ=eP,bJ=gJ,xJ=Array.prototype,_J=function(t){var e=t.some;return t===xJ||yJ(xJ,t)&&e===xJ.some?bJ:e},wJ=KA(_J),EJ=KA(GR.Object.getOwnPropertySymbols),kJ={exports:{}},OJ=wM,CJ=JA,SJ=VR,TJ=wR.f,IJ=ER;OJ({target:"Object",stat:!0,forced:!IJ||CJ((function(){TJ(1)})),sham:!IJ},{getOwnPropertyDescriptor:function(t,e){return TJ(SJ(t),e)}});var AJ=GR.Object,RJ=kJ.exports=function(t,e){return AJ.getOwnPropertyDescriptor(t,e)};AJ.getOwnPropertyDescriptor.sham&&(RJ.sham=!0);var PJ=kJ.exports,DJ=KA(PJ),MJ=pV,FJ=VR,NJ=wR,BJ=rz;wM({target:"Object",stat:!0,sham:!ER},{getOwnPropertyDescriptors:function(t){for(var e,i,n=FJ(t),o=NJ.f,r=MJ(n),s={},a=0;r.length>a;)void 0!==(i=o(n,e=r[a++]))&&BJ(s,e,i);return s}});var LJ=KA(GR.Object.getOwnPropertyDescriptors),zJ={exports:{}},jJ=wM,HJ=ER,$J=jN.f;jJ({target:"Object",stat:!0,forced:Object.defineProperties!==$J,sham:!HJ},{defineProperties:$J});var UJ=GR.Object,WJ=zJ.exports=function(t,e){return UJ.defineProperties(t,e)};UJ.defineProperties.sham&&(WJ.sham=!0);var VJ=KA(zJ.exports),qJ=KA(uj);function XJ(t,e,i){return(e=dW(e))in t?pj(t,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[e]=i,t}var YJ=QA,GJ=JA,KJ=oN,ZJ=dX.trim,QJ=tX,JJ=cR("".charAt),t0=YJ.parseFloat,e0=YJ.Symbol,i0=e0&&e0.iterator,n0=1/t0(QJ+"-0")!=-1/0||i0&&!GJ((function(){t0(Object(i0))}))?function(t){var e=ZJ(KJ(t)),i=t0(e);return 0===i&&"-"===JJ(e,0)?-0:i}:t0;wM({global:!0,forced:parseFloat!==n0},{parseFloat:n0});var o0=KA(GR.parseFloat),r0=wM,s0=JA,a0=qj.f;r0({target:"Object",stat:!0,forced:s0((function(){return!Object.getOwnPropertyNames(1)}))},{getOwnPropertyNames:a0});var d0=GR.Object,l0=function(t){return d0.getOwnPropertyNames(t)},c0=KA(l0);function h0(t,e){var i=["node","edge","label"],n=!0,o=WK(e,"chosen");if("boolean"==typeof o)n=o;else if("object"===sW(o)){if(-1===PX(i).call(i,t))throw new Error("choosify: subOption '"+t+"' should be one of '"+i.join("', '")+"'");var r=WK(e,["chosen",t]);"boolean"!=typeof r&&"function"!=typeof r||(n=r)}return n}function u0(t,e,i){if(t.width<=0||t.height<=0)return!1;if(void 0!==i){var n={x:e.x-i.x,y:e.y-i.y};if(0!==i.angle){var o=-i.angle;e={x:Math.cos(o)*n.x-Math.sin(o)*n.y,y:Math.sin(o)*n.x+Math.cos(o)*n.y}}else e=n}var r=t.x+t.width,s=t.y+t.width;return t.lefte.x&&t.tope.y}function p0(t){return"string"==typeof t&&""!==t}function f0(t,e,i,n){var o=n.x,r=n.y;if("function"==typeof n.distanceToBorder){var s=n.distanceToBorder(t,e),a=Math.sin(e)*s,d=Math.cos(e)*s;d===s?(o+=s,r=n.y):a===s?(o=n.x,r-=s):(o+=d,r-=a)}else n.shape.width>n.shape.height?(o=n.x+.5*n.shape.width,r=n.y-i):(o=n.x+i,r=n.y-.5*n.shape.height);return{x:o,y:r}}var m0=TF("Array").values,v0=eN,g0=qP,y0=eP,b0=m0,x0=Array.prototype,_0={DOMTokenList:!0,NodeList:!0},w0=function(t){var e=t.values;return t===x0||y0(x0,t)&&e===x0.values||g0(_0,v0(t))?b0:e},E0=KA(w0),k0=function(){function t(e){rj(this,t),this.measureText=e,this.current=0,this.width=0,this.height=0,this.lines=[]}return cW(t,[{key:"_add",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"normal";void 0===this.lines[t]&&(this.lines[t]={width:0,height:0,blocks:[]});var n=e;void 0!==e&&""!==e||(n=" ");var o=this.measureText(n,i),r=pF({},E0(o));r.text=e,r.width=o.width,r.mod=i,void 0!==e&&""!==e||(r.width=0),this.lines[t].blocks.push(r),this.lines[t].width+=r.width}},{key:"curWidth",value:function(){var t=this.lines[this.current];return void 0===t?0:t.width}},{key:"append",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"normal";this._add(this.current,t,e)}},{key:"newLine",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"normal";this._add(this.current,t,e),this.current++}},{key:"determineLineHeights",value:function(){for(var t=0;tt&&(t=n.width),e+=n.height}this.width=t,this.height=e}},{key:"removeEmptyBlocks",value:function(){for(var t=[],e=0;e"://,""://,""://,"":/<\/b>/,"":/<\/i>/,"":/<\/code>/,"*":/\*/,_:/_/,"`":/`/,afterBold:/[^*]/,afterItal:/[^_]/,afterMono:/[^`]/},C0=function(){function t(e){rj(this,t),this.text=e,this.bold=!1,this.ital=!1,this.mono=!1,this.spacing=!1,this.position=0,this.buffer="",this.modStack=[],this.blocks=[]}return cW(t,[{key:"mod",value:function(){return 0===this.modStack.length?"normal":this.modStack[0]}},{key:"modName",value:function(){return 0===this.modStack.length?"normal":"mono"===this.modStack[0]?"mono":this.bold&&this.ital?"boldital":this.bold?"bold":this.ital?"ital":void 0}},{key:"emitBlock",value:function(){this.spacing&&(this.add(" "),this.spacing=!1),this.buffer.length>0&&(this.blocks.push({text:this.buffer,mod:this.modName()}),this.buffer="")}},{key:"add",value:function(t){" "===t&&(this.spacing=!0),this.spacing&&(this.buffer+=" ",this.spacing=!1)," "!=t&&(this.buffer+=t)}},{key:"parseWS",value:function(t){return!!/[ \t]/.test(t)&&(this.mono?this.add(t):this.spacing=!0,!0)}},{key:"setTag",value:function(t){this.emitBlock(),this[t]=!0,this.modStack.unshift(t)}},{key:"unsetTag",value:function(t){this.emitBlock(),this[t]=!1,this.modStack.shift()}},{key:"parseStartTag",value:function(t,e){return!(this.mono||this[t]||!this.match(e))&&(this.setTag(t),!0)}},{key:"match",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=QW(this.prepareRegExp(t),2),n=i[0],o=i[1],r=n.test(this.text.substr(this.position,o));return r&&e&&(this.position+=o-1),r}},{key:"parseEndTag",value:function(t,e,i){var n=this.mod()===t;return!(!(n="mono"===t?n&&this.mono:n&&!this.mono)||!this.match(e))&&(void 0!==i?(this.position===this.text.length-1||this.match(i,!1))&&this.unsetTag(t):this.unsetTag(t),!0)}},{key:"replace",value:function(t,e){return!!this.match(t)&&(this.add(e),this.position+=length-1,!0)}},{key:"prepareRegExp",value:function(t){var e,i;if(t instanceof RegExp)i=t,e=1;else{var n=O0[t];i=void 0!==n?n:new RegExp(t),e=t.length}return[i,e]}}]),t}(),S0=function(){function t(e,i,n,o){var r=this;rj(this,t),this.ctx=e,this.parent=i,this.selected=n,this.hover=o;this.lines=new k0((function(t,i){if(void 0===t)return 0;var s=r.parent.getFormattingValues(e,n,o,i),a=0;""!==t&&(a=r.ctx.measureText(t).width);return{width:a,values:s}}))}return cW(t,[{key:"process",value:function(t){if(!p0(t))return this.lines.finalize();var e=this.parent.fontOptions;t=(t=t.replace(/\r\n/g,"\n")).replace(/\r/g,"\n");var i=String(t).split("\n"),n=i.length;if(e.multi)for(var o=0;o0)for(var s=0;s0)for(var u=0;u")||e.parseStartTag("ital","")||e.parseStartTag("mono","")||e.parseEndTag("bold","")||e.parseEndTag("ital","")||e.parseEndTag("mono",""))||i(n)||e.add(n),e.position++}return e.emitBlock(),e.blocks}},{key:"splitMarkdownBlocks",value:function(t){for(var e=this,i=new C0(t),n=!0,o=function(t){return!!/\\/.test(t)&&(i.positionthis.parent.fontOptions.maxWdt}},{key:"getLongestFit",value:function(t){for(var e="",i=0;i1&&void 0!==arguments[1]?arguments[1]:"normal",i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];this.parent.getFormattingValues(this.ctx,this.selected,this.hover,e);for(var n=(t=(t=t.replace(/^( +)/g,"$1\r")).replace(/([^\r][^ ]*)( +)/g,"$1\r$2\r")).split("\r");n.length>0;){var o=this.getLongestFit(n);if(0===o){var r=n[0],s=this.getLongestFitWord(r);this.lines.newLine(aV(r).call(r,0,s),e),n[0]=aV(r).call(r,s)}else{var a=o;" "===n[o-1]?o--:" "===n[a]&&a++;var d=aV(n).call(n,0,o).join("");o==n.length&&i?this.lines.append(d,e):this.lines.newLine(d,e),n=aV(n).call(n,a)}}}}]),t}(),T0=["bold","ital","boldital","mono"],I0=function(){function t(e,i){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];rj(this,t),this.body=e,this.pointToSelf=!1,this.baseSize=void 0,this.fontOptions={},this.setOptions(i),this.size={top:0,left:0,width:0,height:0,yLine:0},this.isEdgeLabel=n}return cW(t,[{key:"setOptions",value:function(t){if(this.elementOptions=t,this.initFontOptions(t.font),p0(t.label)?this.labelDirty=!0:t.label=void 0,void 0!==t.font&&null!==t.font)if("string"==typeof t.font)this.baseSize=this.fontOptions.size;else if("object"===sW(t.font)){var e=t.font.size;void 0!==e&&(this.baseSize=e)}}},{key:"initFontOptions",value:function(e){var i=this;RK(T0,(function(t){i.fontOptions[t]={}})),t.parseFontString(this.fontOptions,e)?this.fontOptions.vadjust=0:RK(e,(function(t,e){null!=t&&"object"!==sW(t)&&(i.fontOptions[e]=t)}))}},{key:"constrain",value:function(t){var e={constrainWidth:!1,maxWdt:-1,minWdt:-1,constrainHeight:!1,minHgt:-1,valign:"middle"},i=WK(t,"widthConstraint");if("number"==typeof i)e.maxWdt=Number(i),e.minWdt=Number(i);else if("object"===sW(i)){var n=WK(t,["widthConstraint","maximum"]);"number"==typeof n&&(e.maxWdt=Number(n));var o=WK(t,["widthConstraint","minimum"]);"number"==typeof o&&(e.minWdt=Number(o))}var r=WK(t,"heightConstraint");if("number"==typeof r)e.minHgt=Number(r);else if("object"===sW(r)){var s=WK(t,["heightConstraint","minimum"]);"number"==typeof s&&(e.minHgt=Number(s));var a=WK(t,["heightConstraint","valign"]);"string"==typeof a&&("top"!==a&&"bottom"!==a||(e.valign=a))}return e}},{key:"update",value:function(t,e){this.setOptions(t,!0),this.propagateFonts(e),TK(this.fontOptions,this.constrain(e)),this.fontOptions.chooser=h0("label",e)}},{key:"adjustSizes",value:function(t){var e=t?t.right+t.left:0;this.fontOptions.constrainWidth&&(this.fontOptions.maxWdt-=e,this.fontOptions.minWdt-=e);var i=t?t.top+t.bottom:0;this.fontOptions.constrainHeight&&(this.fontOptions.minHgt-=i)}},{key:"addFontOptionsToPile",value:function(t,e){for(var i=0;i5&&void 0!==arguments[5]?arguments[5]:"middle";if(void 0!==this.elementOptions.label){var s=this.fontOptions.size*this.body.view.scale;this.elementOptions.label&&s=this.elementOptions.scaling.label.maxVisible&&(s=Number(this.elementOptions.scaling.label.maxVisible)/this.body.view.scale),this.calculateLabelSize(t,n,o,e,i,r),this._drawBackground(t),this._drawText(t,e,this.size.yLine,r,s))}}},{key:"_drawBackground",value:function(t){if(void 0!==this.fontOptions.background&&"none"!==this.fontOptions.background){t.fillStyle=this.fontOptions.background;var e=this.getSize();t.fillRect(e.left,e.top,e.width,e.height)}}},{key:"_drawText",value:function(t,e,i){var n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"middle",o=arguments.length>4?arguments[4]:void 0,r=QW(this._setAlignment(t,e,i,n),2);e=r[0],i=r[1],t.textAlign="left",e-=this.size.width/2,this.fontOptions.valign&&this.size.height>this.size.labelHeight&&("top"===this.fontOptions.valign&&(i-=(this.size.height-this.size.labelHeight)/2),"bottom"===this.fontOptions.valign&&(i+=(this.size.height-this.size.labelHeight)/2));for(var s=0;s0&&(t.lineWidth=c.strokeWidth,t.strokeStyle=p,t.lineJoin="round"),t.fillStyle=u,c.strokeWidth>0&&t.strokeText(c.text,e+d,i+c.vadjust),t.fillText(c.text,e+d,i+c.vadjust),d+=c.width}i+=a.height}}}},{key:"_setAlignment",value:function(t,e,i,n){if(this.isEdgeLabel&&"horizontal"!==this.fontOptions.align&&!1===this.pointToSelf){e=0,i=0;"top"===this.fontOptions.align?(t.textBaseline="alphabetic",i-=4):"bottom"===this.fontOptions.align?(t.textBaseline="hanging",i+=4):t.textBaseline="middle"}else t.textBaseline=n;return[e,i]}},{key:"_getColor",value:function(t,e,i){var n=t||"#000000",o=i||"#ffffff";if(e<=this.elementOptions.scaling.label.drawThreshold){var r=Math.max(0,Math.min(1,1-(this.elementOptions.scaling.label.drawThreshold-e)));n=DK(n,r),o=DK(o,r)}return[n,o]}},{key:"getTextSize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return this._processLabel(t,e,i),{width:this.size.width,height:this.size.height,lineCount:this.lineCount}}},{key:"getSize",value:function(){var t=this.size.left,e=this.size.top-1;if(this.isEdgeLabel){var i=.5*-this.size.width;switch(this.fontOptions.align){case"middle":t=i,e=.5*-this.size.height;break;case"top":t=i,e=-(this.size.height+2);break;case"bottom":t=i,e=2}}return{left:t,top:e,width:this.size.width,height:this.size.height}}},{key:"calculateLabelSize",value:function(t,e,i){var n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,o=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,r=arguments.length>5&&void 0!==arguments[5]?arguments[5]:"middle";this._processLabel(t,e,i),this.size.left=n-.5*this.size.width,this.size.top=o-.5*this.size.height,this.size.yLine=o+.5*(1-this.lineCount)*this.fontOptions.size,"hanging"===r&&(this.size.top+=.5*this.fontOptions.size,this.size.top+=4,this.size.yLine+=4)}},{key:"getFormattingValues",value:function(t,e,i,n){var o=function(t,e,i){return"normal"===e?"mod"===i?"":t[i]:void 0!==t[e][i]?t[e][i]:t[i]},r={color:o(this.fontOptions,n,"color"),size:o(this.fontOptions,n,"size"),face:o(this.fontOptions,n,"face"),mod:o(this.fontOptions,n,"mod"),vadjust:o(this.fontOptions,n,"vadjust"),strokeWidth:this.fontOptions.strokeWidth,strokeColor:this.fontOptions.strokeColor};(e||i)&&("normal"===n&&!0===this.fontOptions.chooser&&this.elementOptions.labelHighlightBold?r.mod="bold":"function"==typeof this.fontOptions.chooser&&this.fontOptions.chooser(r,this.elementOptions.id,e,i));var s="";return void 0!==r.mod&&""!==r.mod&&(s+=r.mod+" "),s+=r.size+"px "+r.face,t.font=s.replace(/"/g,""),r.font=t.font,r.height=r.size,r}},{key:"differentState",value:function(t,e){return t!==this.selectedState||e!==this.hoverState}},{key:"_processLabelText",value:function(t,e,i,n){return new S0(t,this,e,i).process(n)}},{key:"_processLabel",value:function(t,e,i){if(!1!==this.labelDirty||this.differentState(e,i)){var n=this._processLabelText(t,e,i,this.elementOptions.label);this.fontOptions.minWdt>0&&n.width0&&n.height0&&(this.enableBorderDashes(t,e),t.stroke(),this.disableBorderDashes(t,e)),t.restore()}},{key:"performFill",value:function(t,e){t.save(),t.fillStyle=e.color,this.enableShadow(t,e),vY(t).call(t),this.disableShadow(t,e),t.restore(),this.performStroke(t,e)}},{key:"_addBoundingBoxMargin",value:function(t){this.boundingBox.left-=t,this.boundingBox.top-=t,this.boundingBox.bottom+=t,this.boundingBox.right+=t}},{key:"_updateBoundingBox",value:function(t,e,i,n,o){void 0!==i&&this.resize(i,n,o),this.left=t-this.width/2,this.top=e-this.height/2,this.boundingBox.left=this.left,this.boundingBox.top=this.top,this.boundingBox.bottom=this.top+this.height,this.boundingBox.right=this.left+this.width}},{key:"updateBoundingBox",value:function(t,e,i,n,o){this._updateBoundingBox(t,e,i,n,o)}},{key:"getDimensionsFromLabel",value:function(t,e,i){this.textSize=this.labelModule.getTextSize(t,e,i);var n=this.textSize.width,o=this.textSize.height;return 0===n&&(n=14,o=14),{width:n,height:o}}}]),t}();function n1(t){var e=function(){if("undefined"==typeof Reflect||!X0)return!1;if(X0.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(X0(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=e1(t);if(e){var o=e1(this).constructor;i=X0(n,arguments,o)}else i=n.apply(this,arguments);return J0(this,i)}}var o1=function(t){Q0(i,t);var e=n1(i);function i(t,n,o){var r;return rj(this,i),(r=e.call(this,t,n,o))._setMargins(o),r}return cW(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(this.needsRefresh(e,i)){var n=this.getDimensionsFromLabel(t,e,i);this.width=n.width+this.margin.right+this.margin.left,this.height=n.height+this.margin.top+this.margin.bottom,this.radius=this.width/2}}},{key:"draw",value:function(t,e,i,n,o,r){this.resize(t,n,o),this.left=e-this.width/2,this.top=i-this.height/2,this.initContextForDraw(t,r),BF(t,this.left,this.top,this.width,this.height,r.borderRadius),this.performFill(t,r),this.updateBoundingBox(e,i,t,n,o),this.labelModule.draw(t,this.left+this.textSize.width/2+this.margin.left,this.top+this.textSize.height/2+this.margin.top,n,o)}},{key:"updateBoundingBox",value:function(t,e,i,n,o){this._updateBoundingBox(t,e,i,n,o);var r=this.options.shapeProperties.borderRadius;this._addBoundingBoxMargin(r)}},{key:"distanceToBorder",value:function(t,e){t&&this.resize(t);var i=this.options.borderWidth;return Math.min(Math.abs(this.width/2/Math.cos(e)),Math.abs(this.height/2/Math.sin(e)))+i}}]),i}(i1);function r1(t){var e=function(){if("undefined"==typeof Reflect||!X0)return!1;if(X0.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(X0(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=e1(t);if(e){var o=e1(this).constructor;i=X0(n,arguments,o)}else i=n.apply(this,arguments);return J0(this,i)}}var s1=function(t){Q0(i,t);var e=r1(i);function i(t,n,o){var r;return rj(this,i),(r=e.call(this,t,n,o)).labelOffset=0,r.selected=!1,r}return cW(i,[{key:"setOptions",value:function(t,e,i){this.options=t,void 0===e&&void 0===i||this.setImages(e,i)}},{key:"setImages",value:function(t,e){e&&this.selected?(this.imageObj=e,this.imageObjAlt=t):(this.imageObj=t,this.imageObjAlt=e)}},{key:"switchImages",value:function(t){var e=t&&!this.selected||!t&&this.selected;if(this.selected=t,void 0!==this.imageObjAlt&&e){var i=this.imageObj;this.imageObj=this.imageObjAlt,this.imageObjAlt=i}}},{key:"_getImagePadding",value:function(){var t={top:0,right:0,bottom:0,left:0};if(this.options.imagePadding){var e=this.options.imagePadding;"object"==sW(e)?(t.top=e.top,t.right=e.right,t.bottom=e.bottom,t.left=e.left):(t.top=e,t.right=e,t.bottom=e,t.left=e)}return t}},{key:"_resizeImage",value:function(){var t,e;if(!1===this.options.shapeProperties.useImageSize){var i=1,n=1;this.imageObj.width&&this.imageObj.height&&(this.imageObj.width>this.imageObj.height?i=this.imageObj.width/this.imageObj.height:n=this.imageObj.height/this.imageObj.width),t=2*this.options.size*i,e=2*this.options.size*n}else{var o=this._getImagePadding();t=this.imageObj.width+o.left+o.right,e=this.imageObj.height+o.top+o.bottom}this.width=t,this.height=e,this.radius=.5*this.width}},{key:"_drawRawCircle",value:function(t,e,i,n){this.initContextForDraw(t,n),NF(t,e,i,n.size),this.performFill(t,n)}},{key:"_drawImageAtPosition",value:function(t,e){if(0!=this.imageObj.width){t.globalAlpha=void 0!==e.opacity?e.opacity:1,this.enableShadow(t,e);var i=1;!0===this.options.shapeProperties.interpolation&&(i=this.imageObj.width/this.width/this.body.view.scale);var n=this._getImagePadding(),o=this.left+n.left,r=this.top+n.top,s=this.width-n.left-n.right,a=this.height-n.top-n.bottom;this.imageObj.drawImageAtPosition(t,i,o,r,s,a),this.disableShadow(t,e)}}},{key:"_drawImageLabel",value:function(t,e,i,n,o){var r=0;if(void 0!==this.height){r=.5*this.height;var s=this.labelModule.getTextSize(t,n,o);s.lineCount>=1&&(r+=s.height/2)}var a=i+r;this.options.label&&(this.labelOffset=r),this.labelModule.draw(t,e,a,n,o,"hanging")}}]),i}(i1);function a1(t){var e=function(){if("undefined"==typeof Reflect||!X0)return!1;if(X0.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(X0(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=e1(t);if(e){var o=e1(this).constructor;i=X0(n,arguments,o)}else i=n.apply(this,arguments);return J0(this,i)}}var d1=function(t){Q0(i,t);var e=a1(i);function i(t,n,o){var r;return rj(this,i),(r=e.call(this,t,n,o))._setMargins(o),r}return cW(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(this.needsRefresh(e,i)){var n=this.getDimensionsFromLabel(t,e,i),o=Math.max(n.width+this.margin.right+this.margin.left,n.height+this.margin.top+this.margin.bottom);this.options.size=o/2,this.width=o,this.height=o,this.radius=this.width/2}}},{key:"draw",value:function(t,e,i,n,o,r){this.resize(t,n,o),this.left=e-this.width/2,this.top=i-this.height/2,this._drawRawCircle(t,e,i,r),this.updateBoundingBox(e,i),this.labelModule.draw(t,this.left+this.textSize.width/2+this.margin.left,i,n,o)}},{key:"updateBoundingBox",value:function(t,e){this.boundingBox.top=e-this.options.size,this.boundingBox.left=t-this.options.size,this.boundingBox.right=t+this.options.size,this.boundingBox.bottom=e+this.options.size}},{key:"distanceToBorder",value:function(t){return t&&this.resize(t),.5*this.width}}]),i}(s1);function l1(t){var e=function(){if("undefined"==typeof Reflect||!X0)return!1;if(X0.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(X0(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=e1(t);if(e){var o=e1(this).constructor;i=X0(n,arguments,o)}else i=n.apply(this,arguments);return J0(this,i)}}var c1=function(t){Q0(i,t);var e=l1(i);function i(t,n,o,r,s){var a;return rj(this,i),(a=e.call(this,t,n,o)).setImages(r,s),a}return cW(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(void 0===this.imageObj.src||void 0===this.imageObj.width||void 0===this.imageObj.height){var n=2*this.options.size;return this.width=n,this.height=n,void(this.radius=.5*this.width)}this.needsRefresh(e,i)&&this._resizeImage()}},{key:"draw",value:function(t,e,i,n,o,r){this.switchImages(n),this.resize();var s=e,a=i;"top-left"===this.options.shapeProperties.coordinateOrigin?(this.left=e,this.top=i,s+=this.width/2,a+=this.height/2):(this.left=e-this.width/2,this.top=i-this.height/2),this._drawRawCircle(t,s,a,r),t.save(),t.clip(),this._drawImageAtPosition(t,r),t.restore(),this._drawImageLabel(t,s,a,n,o),this.updateBoundingBox(e,i)}},{key:"updateBoundingBox",value:function(t,e){"top-left"===this.options.shapeProperties.coordinateOrigin?(this.boundingBox.top=e,this.boundingBox.left=t,this.boundingBox.right=t+2*this.options.size,this.boundingBox.bottom=e+2*this.options.size):(this.boundingBox.top=e-this.options.size,this.boundingBox.left=t-this.options.size,this.boundingBox.right=t+this.options.size,this.boundingBox.bottom=e+this.options.size),this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelOffset)}},{key:"distanceToBorder",value:function(t){return t&&this.resize(t),.5*this.width}}]),i}(s1);function h1(t){var e=function(){if("undefined"==typeof Reflect||!X0)return!1;if(X0.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(X0(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=e1(t);if(e){var o=e1(this).constructor;i=X0(n,arguments,o)}else i=n.apply(this,arguments);return J0(this,i)}}var u1=function(t){Q0(i,t);var e=h1(i);function i(t,n,o){return rj(this,i),e.call(this,t,n,o)}return cW(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover,n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{size:this.options.size};if(this.needsRefresh(e,i)){var o,r;this.labelModule.getTextSize(t,e,i);var s=2*n.size;this.width=null!==(o=this.customSizeWidth)&&void 0!==o?o:s,this.height=null!==(r=this.customSizeHeight)&&void 0!==r?r:s,this.radius=.5*this.width}}},{key:"_drawShape",value:function(t,e,i,n,o,r,s,a){var d,l=this;return this.resize(t,r,s,a),this.left=n-this.width/2,this.top=o-this.height/2,this.initContextForDraw(t,a),(d=e,Object.prototype.hasOwnProperty.call(HF,d)?HF[d]:function(t){for(var e=arguments.length,i=new Array(e>1?e-1:0),n=1;n0&&(this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelModule.size.height))}}]),i}(i1);function p1(t,e){var i=kV(t);if(EJ){var n=EJ(t);e&&(n=Jq(n).call(n,(function(e){return DJ(t,e).enumerable}))),i.push.apply(i,n)}return i}function f1(t){for(var e=1;e1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(this.needsRefresh(e,i)){var n=this.getDimensionsFromLabel(t,e,i);this.height=2*n.height,this.width=n.width+n.height,this.radius=.5*this.width}}},{key:"draw",value:function(t,e,i,n,o,r){this.resize(t,n,o),this.left=e-.5*this.width,this.top=i-.5*this.height,this.initContextForDraw(t,r),LF(t,this.left,this.top,this.width,this.height),this.performFill(t,r),this.updateBoundingBox(e,i,t,n,o),this.labelModule.draw(t,e,i,n,o)}},{key:"distanceToBorder",value:function(t,e){t&&this.resize(t);var i=.5*this.width,n=.5*this.height,o=Math.sin(e)*i,r=Math.cos(e)*n;return i*n/Math.sqrt(o*o+r*r)}}]),i}(i1);function O1(t){var e=function(){if("undefined"==typeof Reflect||!X0)return!1;if(X0.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(X0(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=e1(t);if(e){var o=e1(this).constructor;i=X0(n,arguments,o)}else i=n.apply(this,arguments);return J0(this,i)}}var C1=function(t){Q0(i,t);var e=O1(i);function i(t,n,o){var r;return rj(this,i),(r=e.call(this,t,n,o))._setMargins(o),r}return cW(i,[{key:"resize",value:function(t,e,i){this.needsRefresh(e,i)&&(this.iconSize={width:Number(this.options.icon.size),height:Number(this.options.icon.size)},this.width=this.iconSize.width+this.margin.right+this.margin.left,this.height=this.iconSize.height+this.margin.top+this.margin.bottom,this.radius=.5*this.width)}},{key:"draw",value:function(t,e,i,n,o,r){var s=this;return this.resize(t,n,o),this.options.icon.size=this.options.icon.size||50,this.left=e-this.width/2,this.top=i-this.height/2,this._icon(t,e,i,n,o,r),{drawExternalLabel:function(){if(void 0!==s.options.label){s.labelModule.draw(t,s.left+s.iconSize.width/2+s.margin.left,i+s.height/2+5,n)}s.updateBoundingBox(e,i)}}}},{key:"updateBoundingBox",value:function(t,e){if(this.boundingBox.top=e-.5*this.options.icon.size,this.boundingBox.left=t-.5*this.options.icon.size,this.boundingBox.right=t+.5*this.options.icon.size,this.boundingBox.bottom=e+.5*this.options.icon.size,void 0!==this.options.label&&this.labelModule.size.width>0){this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelModule.size.height+5)}}},{key:"_icon",value:function(t,e,i,n,o,r){var s=Number(this.options.icon.size);void 0!==this.options.icon.code?(t.font=[null!=this.options.icon.weight?this.options.icon.weight:n?"bold":"",(null!=this.options.icon.weight&&n?5:0)+s+"px",this.options.icon.face].join(" "),t.fillStyle=this.options.icon.color||"black",t.textAlign="center",t.textBaseline="middle",this.enableShadow(t,r),t.fillText(this.options.icon.code,e,i),this.disableShadow(t,r)):console.error("When using the icon shape, you need to define the code in the icon options object. This can be done per node or globally.")}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(i1);function S1(t){var e=function(){if("undefined"==typeof Reflect||!X0)return!1;if(X0.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(X0(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=e1(t);if(e){var o=e1(this).constructor;i=X0(n,arguments,o)}else i=n.apply(this,arguments);return J0(this,i)}}var T1=function(t){Q0(i,t);var e=S1(i);function i(t,n,o,r,s){var a;return rj(this,i),(a=e.call(this,t,n,o)).setImages(r,s),a}return cW(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(void 0===this.imageObj.src||void 0===this.imageObj.width||void 0===this.imageObj.height){var n=2*this.options.size;return this.width=n,void(this.height=n)}this.needsRefresh(e,i)&&this._resizeImage()}},{key:"draw",value:function(t,e,i,n,o,r){t.save(),this.switchImages(n),this.resize();var s=e,a=i;if("top-left"===this.options.shapeProperties.coordinateOrigin?(this.left=e,this.top=i,s+=this.width/2,a+=this.height/2):(this.left=e-this.width/2,this.top=i-this.height/2),!0===this.options.shapeProperties.useBorderWithImage){var d=this.options.borderWidth,l=this.options.borderWidthSelected||2*this.options.borderWidth,c=(n?l:d)/this.body.view.scale;t.lineWidth=Math.min(this.width,c),t.beginPath();var h=n?this.options.color.highlight.border:o?this.options.color.hover.border:this.options.color.border,u=n?this.options.color.highlight.background:o?this.options.color.hover.background:this.options.color.background;void 0!==r.opacity&&(h=DK(h,r.opacity),u=DK(u,r.opacity)),t.strokeStyle=h,t.fillStyle=u,t.rect(this.left-.5*t.lineWidth,this.top-.5*t.lineWidth,this.width+t.lineWidth,this.height+t.lineWidth),vY(t).call(t),this.performStroke(t,r),t.closePath()}this._drawImageAtPosition(t,r),this._drawImageLabel(t,s,a,n,o),this.updateBoundingBox(e,i),t.restore()}},{key:"updateBoundingBox",value:function(t,e){this.resize(),"top-left"===this.options.shapeProperties.coordinateOrigin?(this.left=t,this.top=e):(this.left=t-this.width/2,this.top=e-this.height/2),this.boundingBox.left=this.left,this.boundingBox.top=this.top,this.boundingBox.bottom=this.top+this.height,this.boundingBox.right=this.left+this.width,void 0!==this.options.label&&this.labelModule.size.width>0&&(this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelOffset))}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(s1);function I1(t){var e=function(){if("undefined"==typeof Reflect||!X0)return!1;if(X0.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(X0(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=e1(t);if(e){var o=e1(this).constructor;i=X0(n,arguments,o)}else i=n.apply(this,arguments);return J0(this,i)}}var A1=function(t){Q0(i,t);var e=I1(i);function i(t,n,o){return rj(this,i),e.call(this,t,n,o)}return cW(i,[{key:"draw",value:function(t,e,i,n,o,r){return this._drawShape(t,"square",2,e,i,n,o,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(u1);function R1(t){var e=function(){if("undefined"==typeof Reflect||!X0)return!1;if(X0.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(X0(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=e1(t);if(e){var o=e1(this).constructor;i=X0(n,arguments,o)}else i=n.apply(this,arguments);return J0(this,i)}}var P1=function(t){Q0(i,t);var e=R1(i);function i(t,n,o){return rj(this,i),e.call(this,t,n,o)}return cW(i,[{key:"draw",value:function(t,e,i,n,o,r){return this._drawShape(t,"hexagon",4,e,i,n,o,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(u1);function D1(t){var e=function(){if("undefined"==typeof Reflect||!X0)return!1;if(X0.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(X0(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=e1(t);if(e){var o=e1(this).constructor;i=X0(n,arguments,o)}else i=n.apply(this,arguments);return J0(this,i)}}var M1=function(t){Q0(i,t);var e=D1(i);function i(t,n,o){return rj(this,i),e.call(this,t,n,o)}return cW(i,[{key:"draw",value:function(t,e,i,n,o,r){return this._drawShape(t,"star",4,e,i,n,o,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(u1);function F1(t){var e=function(){if("undefined"==typeof Reflect||!X0)return!1;if(X0.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(X0(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=e1(t);if(e){var o=e1(this).constructor;i=X0(n,arguments,o)}else i=n.apply(this,arguments);return J0(this,i)}}var N1=function(t){Q0(i,t);var e=F1(i);function i(t,n,o){var r;return rj(this,i),(r=e.call(this,t,n,o))._setMargins(o),r}return cW(i,[{key:"resize",value:function(t,e,i){this.needsRefresh(e,i)&&(this.textSize=this.labelModule.getTextSize(t,e,i),this.width=this.textSize.width+this.margin.right+this.margin.left,this.height=this.textSize.height+this.margin.top+this.margin.bottom,this.radius=.5*this.width)}},{key:"draw",value:function(t,e,i,n,o,r){this.resize(t,n,o),this.left=e-this.width/2,this.top=i-this.height/2,this.enableShadow(t,r),this.labelModule.draw(t,this.left+this.textSize.width/2+this.margin.left,this.top+this.textSize.height/2+this.margin.top,n,o),this.disableShadow(t,r),this.updateBoundingBox(e,i,t,n,o)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(i1);function B1(t){var e=function(){if("undefined"==typeof Reflect||!X0)return!1;if(X0.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(X0(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=e1(t);if(e){var o=e1(this).constructor;i=X0(n,arguments,o)}else i=n.apply(this,arguments);return J0(this,i)}}var L1=function(t){Q0(i,t);var e=B1(i);function i(t,n,o){return rj(this,i),e.call(this,t,n,o)}return cW(i,[{key:"draw",value:function(t,e,i,n,o,r){return this._drawShape(t,"triangle",3,e,i,n,o,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(u1);function z1(t){var e=function(){if("undefined"==typeof Reflect||!X0)return!1;if(X0.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(X0(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=e1(t);if(e){var o=e1(this).constructor;i=X0(n,arguments,o)}else i=n.apply(this,arguments);return J0(this,i)}}var j1=function(t){Q0(i,t);var e=z1(i);function i(t,n,o){return rj(this,i),e.call(this,t,n,o)}return cW(i,[{key:"draw",value:function(t,e,i,n,o,r){return this._drawShape(t,"triangleDown",3,e,i,n,o,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(u1);function H1(t,e){var i=kV(t);if(EJ){var n=EJ(t);e&&(n=Jq(n).call(n,(function(e){return DJ(t,e).enumerable}))),i.push.apply(i,n)}return i}function $1(t){for(var e=1;et.left&&this.shape.topt.top}},{key:"isBoundingBoxOverlappingWith",value:function(t){return this.shape.boundingBox.leftt.left&&this.shape.boundingBox.topt.top}}],[{key:"checkOpacity",value:function(t){return 0<=t&&t<=1}},{key:"checkCoordinateOrigin",value:function(t){return void 0===t||"center"===t||"top-left"===t}},{key:"updateGroupOptions",value:function(e,i,n){var o;if(void 0!==n){var r=e.group;if(void 0!==i&&void 0!==i.group&&r!==i.group)throw new Error("updateGroupOptions: group values in options don't match.");if("number"==typeof r||"string"==typeof r&&""!=r){var s=n.get(r);void 0!==s.opacity&&void 0===i.opacity&&(t.checkOpacity(s.opacity)||(console.error("Invalid option for node opacity. Value must be between 0 and 1, found: "+s.opacity),s.opacity=void 0));var a=Jq(o=c0(i)).call(o,(function(t){return null!=i[t]}));a.push("font"),SK(a,e,s),e.color=FK(e.color)}}}},{key:"parseOptions",value:function(e,i){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},r=arguments.length>4?arguments[4]:void 0;if(SK(["color","fixed","shadow"],e,i,n),t.checkMass(i),void 0!==e.opacity&&(t.checkOpacity(e.opacity)||(console.error("Invalid option for node opacity. Value must be between 0 and 1, found: "+e.opacity),e.opacity=void 0)),void 0!==i.opacity&&(t.checkOpacity(i.opacity)||(console.error("Invalid option for node opacity. Value must be between 0 and 1, found: "+i.opacity),i.opacity=void 0)),i.shapeProperties&&!t.checkCoordinateOrigin(i.shapeProperties.coordinateOrigin)&&console.error("Invalid option for node coordinateOrigin, found: "+i.shapeProperties.coordinateOrigin),$K(e,i,"shadow",o),void 0!==i.color&&null!==i.color){var s=FK(i.color);OK(e.color,s)}else!0===n&&null===i.color&&(e.color=HK(o.color));void 0!==i.fixed&&null!==i.fixed&&("boolean"==typeof i.fixed?(e.fixed.x=i.fixed,e.fixed.y=i.fixed):(void 0!==i.fixed.x&&"boolean"==typeof i.fixed.x&&(e.fixed.x=i.fixed.x),void 0!==i.fixed.y&&"boolean"==typeof i.fixed.y&&(e.fixed.y=i.fixed.y))),!0===n&&null===i.font&&(e.font=HK(o.font)),t.updateGroupOptions(e,i,r),void 0!==i.scaling&&$K(e.scaling,i.scaling,"label",o.scaling)}},{key:"checkMass",value:function(t,e){if(void 0!==t.mass&&t.mass<=0){var i="";void 0!==e&&(i=" in node id: "+e),console.error("%cNegative or zero mass disallowed"+i+", setting mass to 1.",oZ),t.mass=1}}}]),t}();function W1(t,e){var i=void 0!==tV&&oj(t)||t["@@iterator"];if(!i){if(fV(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return V1(t,e);var n=aV(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return Bz(t);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return V1(t,e)}(t))||e){i&&(t=i);var n=0,o=function(){};return{s:o,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function V1(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i1?console.error("Invalid option for node opacity. Value must be between 0 and 1, found: "+t.opacity):this.options.opacity=t.opacity),void 0!==t.shape)for(var e in this.body.nodes)Object.prototype.hasOwnProperty.call(this.body.nodes,e)&&this.body.nodes[e].updateShape();if(void 0!==t.font||void 0!==t.widthConstraint||void 0!==t.heightConstraint)for(var i=0,n=kV(this.body.nodes);i1&&void 0!==arguments[1]&&arguments[1],i=this.body.data.nodes;if(YA("id",t))this.body.data.nodes=t;else if(fV(t))this.body.data.nodes=new XA,this.body.data.nodes.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.body.data.nodes=new XA}if(i&&RK(this.nodesListeners,(function(t,e){i.off(e,t)})),this.body.nodes={},this.body.data.nodes){var n=this;RK(this.nodesListeners,(function(t,e){n.body.data.nodes.on(e,t)}));var o=this.body.data.nodes.getIds();this.add(o,!0)}!1===e&&this.body.emitter.emit("_dataChanged")}},{key:"add",value:function(t){for(var e,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=[],o=0;o1&&void 0!==arguments[1]?arguments[1]:U1)(t,this.body,this.images,this.groups,this.options,this.defaultOptions)}},{key:"refresh",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];RK(this.body.nodes,(function(i,n){var o=t.body.data.nodes.get(n);void 0!==o&&(!0===e&&i.setOptions({x:null,y:null}),i.setOptions({fixed:!1}),i.setOptions(o))}))}},{key:"getPositions",value:function(t){var e={};if(void 0!==t){if(!0===fV(t)){for(var i=0;i0?(n=i/a)*n:i;return a===1/0?1/0:a*s2(o)}});var a2=KA(GR.Math.hypot);function d2(t){var e=function(){if("undefined"==typeof Reflect||!X0)return!1;if(X0.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(X0(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=e1(t);if(e){var o=e1(this).constructor;i=X0(n,arguments,o)}else i=n.apply(this,arguments);return J0(this,i)}}var l2=function(){function t(){rj(this,t)}return cW(t,null,[{key:"transform",value:function(t,e){fV(t)||(t=[t]);for(var i=e.point.x,n=e.point.y,o=e.angle,r=e.length,s=0;s4&&void 0!==arguments[4]?arguments[4]:this.getViaNode();t.strokeStyle=this.getColor(t,e),t.lineWidth=e.width,!1!==e.dashes?this._drawDashedLine(t,e,o):this._drawLine(t,e,o)}},{key:"_drawLine",value:function(t,e,i,n,o){if(this.from!=this.to)this._line(t,e,i,n,o);else{var r=QW(this._getCircleData(t),3),s=r[0],a=r[1],d=r[2];this._circle(t,e,s,a,d)}}},{key:"_drawDashedLine",value:function(t,e,i,n,o){t.lineCap="round";var r=fV(e.dashes)?e.dashes:[5,5];if(void 0!==t.setLineDash){if(t.save(),t.setLineDash(r),t.lineDashOffset=0,this.from!=this.to)this._line(t,e,i);else{var s=QW(this._getCircleData(t),3),a=s[0],d=s[1],l=s[2];this._circle(t,e,a,d,l)}t.setLineDash([0]),t.lineDashOffset=0,t.restore()}else{if(this.from!=this.to)jF(t,this.from.x,this.from.y,this.to.x,this.to.y,r);else{var c=QW(this._getCircleData(t),3),h=c[0],u=c[1],p=c[2];this._circle(t,e,h,u,p)}this.enableShadow(t,e),t.stroke(),this.disableShadow(t,e)}}},{key:"findBorderPosition",value:function(t,e,i){return this.from!=this.to?this._findBorderPosition(t,e,i):this._findBorderPositionCircle(t,e,i)}},{key:"findBorderPositions",value:function(t){if(this.from!=this.to)return{from:this._findBorderPosition(this.from,t),to:this._findBorderPosition(this.to,t)};var e,i=QW(aV(e=this._getCircleData(t)).call(e,0,2),2),n=i[0],o=i[1];return{from:this._findBorderPositionCircle(this.from,t,{x:n,y:o,low:.25,high:.6,direction:-1}),to:this._findBorderPositionCircle(this.from,t,{x:n,y:o,low:.6,high:.8,direction:1})}}},{key:"_getCircleData",value:function(t){var e=this.options.selfReference.size;void 0!==t&&void 0===this.from.shape.width&&this.from.shape.resize(t);var i=f0(t,this.options.selfReference.angle,e,this.from);return[i.x,i.y,e]}},{key:"_pointOnCircle",value:function(t,e,i,n){var o=2*n*Math.PI;return{x:t+i*Math.cos(o),y:e-i*Math.sin(o)}}},{key:"_findBorderPositionCircle",value:function(t,e,i){var n,o=i.x,r=i.y,s=i.low,a=i.high,d=i.direction,l=this.options.selfReference.size,c=.5*(s+a),h=0;!0===this.options.arrowStrikethrough&&(-1===d?h=this.options.endPointOffset.from:1===d&&(h=this.options.endPointOffset.to));var u=0;do{c=.5*(s+a),n=this._pointOnCircle(o,r,l,c);var p=Math.atan2(t.y-n.y,t.x-n.x),f=t.distanceToBorder(e,p)+h-Math.sqrt(Math.pow(n.x-t.x,2)+Math.pow(n.y-t.y,2));if(Math.abs(f)<.05)break;f>0?d>0?s=c:a=c:d>0?a=c:s=c,++u}while(s<=a&&u<10);return k2(k2({},n),{},{t:c})}},{key:"getLineWidth",value:function(t,e){return!0===t?Math.max(this.selectionWidth,.3/this._body.view.scale):!0===e?Math.max(this.hoverWidth,.3/this._body.view.scale):Math.max(this.options.width,.3/this._body.view.scale)}},{key:"getColor",value:function(t,e){if(!1!==e.inheritsColor){if("both"===e.inheritsColor&&this.from.id!==this.to.id){var i=t.createLinearGradient(this.from.x,this.from.y,this.to.x,this.to.y),n=this.from.options.color.highlight.border,o=this.to.options.color.highlight.border;return!1===this.from.selected&&!1===this.to.selected?(n=DK(this.from.options.color.border,e.opacity),o=DK(this.to.options.color.border,e.opacity)):!0===this.from.selected&&!1===this.to.selected?o=this.to.options.color.border:!1===this.from.selected&&!0===this.to.selected&&(n=this.from.options.color.border),i.addColorStop(0,n),i.addColorStop(1,o),i}return"to"===e.inheritsColor?DK(this.to.options.color.border,e.opacity):DK(this.from.options.color.border,e.opacity)}return DK(e.color,e.opacity)}},{key:"_circle",value:function(t,e,i,n,o){this.enableShadow(t,e);var r=0,s=2*Math.PI;if(!this.options.selfReference.renderBehindTheNode){var a=this.options.selfReference.angle,d=this.options.selfReference.angle+Math.PI,l=this._findBorderPositionCircle(this.from,t,{x:i,y:n,low:a,high:d,direction:-1}),c=this._findBorderPositionCircle(this.from,t,{x:i,y:n,low:a,high:d,direction:1});r=Math.atan2(l.y-n,l.x-i),s=Math.atan2(c.y-n,c.x-i)}t.beginPath(),t.arc(i,n,o,r,s,!1),t.stroke(),this.disableShadow(t,e)}},{key:"getDistanceToEdge",value:function(t,e,i,n,o,r){if(this.from!=this.to)return this._getDistanceToEdge(t,e,i,n,o,r);var s=QW(this._getCircleData(void 0),3),a=s[0],d=s[1],l=s[2],c=a-o,h=d-r;return Math.abs(Math.sqrt(c*c+h*h)-l)}},{key:"_getDistanceToLine",value:function(t,e,i,n,o,r){var s=i-t,a=n-e,d=((o-t)*s+(r-e)*a)/(s*s+a*a);d>1?d=1:d<0&&(d=0);var l=t+d*s-o,c=e+d*a-r;return Math.sqrt(l*l+c*c)}},{key:"getArrowData",value:function(t,e,i,n,o,r){var s,a,d,l,c,h,u,p=r.width;"from"===e?(d=this.from,l=this.to,c=r.fromArrowScale<0,h=Math.abs(r.fromArrowScale),u=r.fromArrowType):"to"===e?(d=this.to,l=this.from,c=r.toArrowScale<0,h=Math.abs(r.toArrowScale),u=r.toArrowType):(d=this.to,l=this.from,c=r.middleArrowScale<0,h=Math.abs(r.middleArrowScale),u=r.middleArrowType);var f=15*h+3*p;if(d!=l){var m=f/a2(d.x-l.x,d.y-l.y);if("middle"!==e)if(!0===this.options.smooth.enabled){var v=this._findBorderPosition(d,t,{via:i}),g=this.getPoint(v.t+m*("from"===e?1:-1),i);s=Math.atan2(v.y-g.y,v.x-g.x),a=v}else s=Math.atan2(d.y-l.y,d.x-l.x),a=this._findBorderPosition(d,t);else{var y=(c?-m:m)/2,b=this.getPoint(.5+y,i),x=this.getPoint(.5-y,i);s=Math.atan2(b.y-x.y,b.x-x.x),a=this.getPoint(.5,i)}}else{var _=QW(this._getCircleData(t),3),w=_[0],E=_[1],k=_[2];if("from"===e){var O=this.options.selfReference.angle,C=this.options.selfReference.angle+Math.PI,S=this._findBorderPositionCircle(this.from,t,{x:w,y:E,low:O,high:C,direction:-1});s=-2*S.t*Math.PI+1.5*Math.PI+.1*Math.PI,a=S}else if("to"===e){var T=this.options.selfReference.angle,I=this.options.selfReference.angle+Math.PI,A=this._findBorderPositionCircle(this.from,t,{x:w,y:E,low:T,high:I,direction:1});s=-2*A.t*Math.PI+1.5*Math.PI-1.1*Math.PI,a=A}else{var R=this.options.selfReference.angle/(2*Math.PI);a=this._pointOnCircle(w,E,k,R),s=-2*R*Math.PI+1.5*Math.PI+.1*Math.PI}}return{point:a,core:{x:a.x-.9*f*Math.cos(s),y:a.y-.9*f*Math.sin(s)},angle:s,length:f,type:u}}},{key:"drawArrowHead",value:function(t,e,i,n,o){t.strokeStyle=this.getColor(t,e),t.fillStyle=t.strokeStyle,t.lineWidth=e.width,w2.draw(t,o)&&(this.enableShadow(t,e),vY(t).call(t),this.disableShadow(t,e))}},{key:"enableShadow",value:function(t,e){!0===e.shadow&&(t.shadowColor=e.shadowColor,t.shadowBlur=e.shadowSize,t.shadowOffsetX=e.shadowX,t.shadowOffsetY=e.shadowY)}},{key:"disableShadow",value:function(t,e){!0===e.shadow&&(t.shadowColor="rgba(0,0,0,0)",t.shadowBlur=0,t.shadowOffsetX=0,t.shadowOffsetY=0)}},{key:"drawBackground",value:function(t,e){if(!1!==e.background){var i={strokeStyle:t.strokeStyle,lineWidth:t.lineWidth,dashes:t.dashes};t.strokeStyle=e.backgroundColor,t.lineWidth=e.backgroundSize,this.setStrokeDashed(t,e.backgroundDashes),t.stroke(),t.strokeStyle=i.strokeStyle,t.lineWidth=i.lineWidth,t.dashes=i.dashes,this.setStrokeDashed(t,e.dashes)}}},{key:"setStrokeDashed",value:function(t,e){if(!1!==e)if(void 0!==t.setLineDash){var i=fV(e)?e:[5,5];t.setLineDash(i)}else console.warn("setLineDash is not supported in this browser. The dashed stroke cannot be used.");else void 0!==t.setLineDash?t.setLineDash([]):console.warn("setLineDash is not supported in this browser. The dashed stroke cannot be used.")}}]),t}();function C2(t,e){var i=kV(t);if(EJ){var n=EJ(t);e&&(n=Jq(n).call(n,(function(e){return DJ(t,e).enumerable}))),i.push.apply(i,n)}return i}function S2(t){for(var e=1;e2&&void 0!==arguments[2]?arguments[2]:this._getViaCoordinates(),r=!1,s=1,a=0,d=this.to,l=this.options.endPointOffset?this.options.endPointOffset.to:0;t.id===this.from.id&&(d=this.from,r=!0,l=this.options.endPointOffset?this.options.endPointOffset.from:0),!1===this.options.arrowStrikethrough&&(l=0);var c=0;do{n=.5*(a+s),i=this.getPoint(n,o);var h=Math.atan2(d.y-i.y,d.x-i.x),u=d.distanceToBorder(e,h)+l-Math.sqrt(Math.pow(i.x-d.x,2)+Math.pow(i.y-d.y,2));if(Math.abs(u)<.2)break;u<0?!1===r?a=n:s=n:!1===r?s=n:a=n,++c}while(a<=s&&c<10);return S2(S2({},i),{},{t:n})}},{key:"_getDistanceToBezierEdge",value:function(t,e,i,n,o,r,s){var a,d,l,c,h,u=1e9,p=t,f=e;for(d=1;d<10;d++)l=.1*d,c=Math.pow(1-l,2)*t+2*l*(1-l)*s.x+Math.pow(l,2)*i,h=Math.pow(1-l,2)*e+2*l*(1-l)*s.y+Math.pow(l,2)*n,d>0&&(u=(a=this._getDistanceToLine(p,f,c,h,o,r))1&&void 0!==arguments[1]?arguments[1]:this.via;if(this.from===this.to){var i=QW(this._getCircleData(),3),n=i[0],o=i[1],r=i[2],s=2*Math.PI*(1-t);return{x:n+r*Math.sin(s),y:o+r-r*(1-Math.cos(s))}}return{x:Math.pow(1-t,2)*this.fromPoint.x+2*t*(1-t)*e.x+Math.pow(t,2)*this.toPoint.x,y:Math.pow(1-t,2)*this.fromPoint.y+2*t*(1-t)*e.y+Math.pow(t,2)*this.toPoint.y}}},{key:"_findBorderPosition",value:function(t,e){return this._findBorderPositionBezier(t,e,this.via)}},{key:"_getDistanceToEdge",value:function(t,e,i,n,o,r){return this._getDistanceToBezierEdge(t,e,i,n,o,r,this.via)}}]),i}(I2);function P2(t){var e=function(){if("undefined"==typeof Reflect||!X0)return!1;if(X0.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(X0(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=e1(t);if(e){var o=e1(this).constructor;i=X0(n,arguments,o)}else i=n.apply(this,arguments);return J0(this,i)}}var D2=function(t){Q0(i,t);var e=P2(i);function i(t,n,o){return rj(this,i),e.call(this,t,n,o)}return cW(i,[{key:"_line",value:function(t,e,i){this._bezierCurve(t,e,i)}},{key:"getViaNode",value:function(){return this._getViaCoordinates()}},{key:"_getViaCoordinates",value:function(){var t,e,i=this.options.smooth.roundness,n=this.options.smooth.type,o=Math.abs(this.from.x-this.to.x),r=Math.abs(this.from.y-this.to.y);if("discrete"===n||"diagonalCross"===n){var s,a;s=a=o<=r?i*r:i*o,this.from.x>this.to.x&&(s=-s),this.from.y>=this.to.y&&(a=-a);var d=this.from.x+s,l=this.from.y+a;return"discrete"===n&&(o<=r?d=othis.to.x&&(t=-t),this.from.y>=this.to.y&&(e=-e);var x=this.from.x+t,_=this.from.y+e;return o<=r?x=this.from.x<=this.to.x?this.to.xx?this.to.x:x:_=this.from.y>=this.to.y?this.to.y>_?this.to.y:_:this.to.y<_?this.to.y:_,{x:x,y:_}}},{key:"_findBorderPosition",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return this._findBorderPositionBezier(t,e,i.via)}},{key:"_getDistanceToEdge",value:function(t,e,i,n,o,r){var s=arguments.length>6&&void 0!==arguments[6]?arguments[6]:this._getViaCoordinates();return this._getDistanceToBezierEdge(t,e,i,n,o,r,s)}},{key:"getPoint",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this._getViaCoordinates(),i=t;return{x:Math.pow(1-i,2)*this.fromPoint.x+2*i*(1-i)*e.x+Math.pow(i,2)*this.toPoint.x,y:Math.pow(1-i,2)*this.fromPoint.y+2*i*(1-i)*e.y+Math.pow(i,2)*this.toPoint.y}}}]),i}(I2);function M2(t){var e=function(){if("undefined"==typeof Reflect||!X0)return!1;if(X0.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(X0(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=e1(t);if(e){var o=e1(this).constructor;i=X0(n,arguments,o)}else i=n.apply(this,arguments);return J0(this,i)}}var F2=function(t){Q0(i,t);var e=M2(i);function i(t,n,o){return rj(this,i),e.call(this,t,n,o)}return cW(i,[{key:"_getDistanceToBezierEdge2",value:function(t,e,i,n,o,r,s,a){for(var d=1e9,l=t,c=e,h=[0,0,0,0],u=1;u<10;u++){var p=.1*u;h[0]=Math.pow(1-p,3),h[1]=3*p*Math.pow(1-p,2),h[2]=3*Math.pow(p,2)*(1-p),h[3]=Math.pow(p,3);var f=h[0]*t+h[1]*s.x+h[2]*a.x+h[3]*i,m=h[0]*e+h[1]*s.y+h[2]*a.y+h[3]*n;if(u>0){var v=this._getDistanceToLine(l,c,f,m,o,r);d=vMath.abs(r)||!0===this.options.smooth.forceDirection||"horizontal"===this.options.smooth.forceDirection)&&"vertical"!==this.options.smooth.forceDirection?(e=this.from.y,n=this.to.y,t=this.from.x-s*o,i=this.to.x+s*o):(e=this.from.y-s*r,n=this.to.y+s*r,t=this.from.x,i=this.to.x),[{x:t,y:e},{x:i,y:n}]}},{key:"getViaNode",value:function(){return this._getViaCoordinates()}},{key:"_findBorderPosition",value:function(t,e){return this._findBorderPositionBezier(t,e)}},{key:"_getDistanceToEdge",value:function(t,e,i,n,o,r){var s=QW(arguments.length>6&&void 0!==arguments[6]?arguments[6]:this._getViaCoordinates(),2),a=s[0],d=s[1];return this._getDistanceToBezierEdge2(t,e,i,n,o,r,a,d)}},{key:"getPoint",value:function(t){var e=QW(arguments.length>1&&void 0!==arguments[1]?arguments[1]:this._getViaCoordinates(),2),i=e[0],n=e[1],o=t,r=[Math.pow(1-o,3),3*o*Math.pow(1-o,2),3*Math.pow(o,2)*(1-o),Math.pow(o,3)];return{x:r[0]*this.fromPoint.x+r[1]*i.x+r[2]*n.x+r[3]*this.toPoint.x,y:r[0]*this.fromPoint.y+r[1]*i.y+r[2]*n.y+r[3]*this.toPoint.y}}}]),i}(F2);function L2(t){var e=function(){if("undefined"==typeof Reflect||!X0)return!1;if(X0.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(X0(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=e1(t);if(e){var o=e1(this).constructor;i=X0(n,arguments,o)}else i=n.apply(this,arguments);return J0(this,i)}}var z2=function(t){Q0(i,t);var e=L2(i);function i(t,n,o){return rj(this,i),e.call(this,t,n,o)}return cW(i,[{key:"_line",value:function(t,e){t.beginPath(),t.moveTo(this.fromPoint.x,this.fromPoint.y),t.lineTo(this.toPoint.x,this.toPoint.y),this.enableShadow(t,e),t.stroke(),this.disableShadow(t,e)}},{key:"getViaNode",value:function(){}},{key:"getPoint",value:function(t){return{x:(1-t)*this.fromPoint.x+t*this.toPoint.x,y:(1-t)*this.fromPoint.y+t*this.toPoint.y}}},{key:"_findBorderPosition",value:function(t,e){var i=this.to,n=this.from;t.id===this.from.id&&(i=this.from,n=this.to);var o=Math.atan2(i.y-n.y,i.x-n.x),r=i.x-n.x,s=i.y-n.y,a=Math.sqrt(r*r+s*s),d=(a-t.distanceToBorder(e,o))/a;return{x:(1-d)*n.x+d*i.x,y:(1-d)*n.y+d*i.y,t:0}}},{key:"_getDistanceToEdge",value:function(t,e,i,n,o,r){return this._getDistanceToLine(t,e,i,n,o,r)}}]),i}(O2),j2=function(){function t(e,i,n,o,r){if(rj(this,t),void 0===i)throw new Error("No body provided");this.options=HK(o),this.globalOptions=o,this.defaultOptions=r,this.body=i,this.imagelist=n,this.id=void 0,this.fromId=void 0,this.toId=void 0,this.selected=!1,this.hover=!1,this.labelDirty=!0,this.baseWidth=this.options.width,this.baseFontSize=this.options.font.size,this.from=void 0,this.to=void 0,this.edgeType=void 0,this.connected=!1,this.labelModule=new I0(this.body,this.options,!0),this.setOptions(e)}return cW(t,[{key:"setOptions",value:function(e){if(e){var i=void 0!==e.physics&&this.options.physics!==e.physics||void 0!==e.hidden&&(this.options.hidden||!1)!==(e.hidden||!1)||void 0!==e.from&&this.options.from!==e.from||void 0!==e.to&&this.options.to!==e.to;t.parseOptions(this.options,e,!0,this.globalOptions),void 0!==e.id&&(this.id=e.id),void 0!==e.from&&(this.fromId=e.from),void 0!==e.to&&(this.toId=e.to),void 0!==e.title&&(this.title=e.title),void 0!==e.value&&(e.value=o0(e.value));var n=[e,this.options,this.defaultOptions];return this.chooser=h0("edge",n),this.updateLabelModule(e),i=this.updateEdgeType()||i,this._setInteractionWidths(),this.connect(),i}}},{key:"getFormattingValues",value:function(){var t=!0===this.options.arrows.to||!0===this.options.arrows.to.enabled,e=!0===this.options.arrows.from||!0===this.options.arrows.from.enabled,i=!0===this.options.arrows.middle||!0===this.options.arrows.middle.enabled,n=this.options.color.inherit,o={toArrow:t,toArrowScale:this.options.arrows.to.scaleFactor,toArrowType:this.options.arrows.to.type,toArrowSrc:this.options.arrows.to.src,toArrowImageWidth:this.options.arrows.to.imageWidth,toArrowImageHeight:this.options.arrows.to.imageHeight,middleArrow:i,middleArrowScale:this.options.arrows.middle.scaleFactor,middleArrowType:this.options.arrows.middle.type,middleArrowSrc:this.options.arrows.middle.src,middleArrowImageWidth:this.options.arrows.middle.imageWidth,middleArrowImageHeight:this.options.arrows.middle.imageHeight,fromArrow:e,fromArrowScale:this.options.arrows.from.scaleFactor,fromArrowType:this.options.arrows.from.type,fromArrowSrc:this.options.arrows.from.src,fromArrowImageWidth:this.options.arrows.from.imageWidth,fromArrowImageHeight:this.options.arrows.from.imageHeight,arrowStrikethrough:this.options.arrowStrikethrough,color:n?void 0:this.options.color.color,inheritsColor:n,opacity:this.options.color.opacity,hidden:this.options.hidden,length:this.options.length,shadow:this.options.shadow.enabled,shadowColor:this.options.shadow.color,shadowSize:this.options.shadow.size,shadowX:this.options.shadow.x,shadowY:this.options.shadow.y,dashes:this.options.dashes,width:this.options.width,background:this.options.background.enabled,backgroundColor:this.options.background.color,backgroundSize:this.options.background.size,backgroundDashes:this.options.background.dashes};if(this.selected||this.hover)if(!0===this.chooser){if(this.selected){var r=this.options.selectionWidth;"function"==typeof r?o.width=r(o.width):"number"==typeof r&&(o.width+=r),o.width=Math.max(o.width,.3/this.body.view.scale),o.color=this.options.color.highlight,o.shadow=this.options.shadow.enabled}else if(this.hover){var s=this.options.hoverWidth;"function"==typeof s?o.width=s(o.width):"number"==typeof s&&(o.width+=s),o.width=Math.max(o.width,.3/this.body.view.scale),o.color=this.options.color.hover,o.shadow=this.options.shadow.enabled}}else"function"==typeof this.chooser&&(this.chooser(o,this.options.id,this.selected,this.hover),void 0!==o.color&&(o.inheritsColor=!1),!1===o.shadow&&(o.shadowColor===this.options.shadow.color&&o.shadowSize===this.options.shadow.size&&o.shadowX===this.options.shadow.x&&o.shadowY===this.options.shadow.y||(o.shadow=!0)));else o.shadow=this.options.shadow.enabled,o.width=Math.max(o.width,.3/this.body.view.scale);return o}},{key:"updateLabelModule",value:function(t){var e=[t,this.options,this.globalOptions,this.defaultOptions];this.labelModule.update(this.options,e),void 0!==this.labelModule.baseSize&&(this.baseFontSize=this.labelModule.baseSize)}},{key:"updateEdgeType",value:function(){var t=this.options.smooth,e=!1,i=!0;return void 0!==this.edgeType&&((this.edgeType instanceof R2&&!0===t.enabled&&"dynamic"===t.type||this.edgeType instanceof B2&&!0===t.enabled&&"cubicBezier"===t.type||this.edgeType instanceof D2&&!0===t.enabled&&"dynamic"!==t.type&&"cubicBezier"!==t.type||this.edgeType instanceof z2&&!1===t.type.enabled)&&(i=!1),!0===i&&(e=this.cleanup())),!0===i?!0===t.enabled?"dynamic"===t.type?(e=!0,this.edgeType=new R2(this.options,this.body,this.labelModule)):"cubicBezier"===t.type?this.edgeType=new B2(this.options,this.body,this.labelModule):this.edgeType=new D2(this.options,this.body,this.labelModule):this.edgeType=new z2(this.options,this.body,this.labelModule):this.edgeType.setOptions(this.options),e}},{key:"connect",value:function(){this.disconnect(),this.from=this.body.nodes[this.fromId]||void 0,this.to=this.body.nodes[this.toId]||void 0,this.connected=void 0!==this.from&&void 0!==this.to,!0===this.connected?(this.from.attachEdge(this),this.to.attachEdge(this)):(this.from&&this.from.detachEdge(this),this.to&&this.to.detachEdge(this)),this.edgeType.connect()}},{key:"disconnect",value:function(){this.from&&(this.from.detachEdge(this),this.from=void 0),this.to&&(this.to.detachEdge(this),this.to=void 0),this.connected=!1}},{key:"getTitle",value:function(){return this.title}},{key:"isSelected",value:function(){return this.selected}},{key:"getValue",value:function(){return this.options.value}},{key:"setValueRange",value:function(t,e,i){if(void 0!==this.options.value){var n=this.options.scaling.customScalingFunction(t,e,i,this.options.value),o=this.options.scaling.max-this.options.scaling.min;if(!0===this.options.scaling.label.enabled){var r=this.options.scaling.label.max-this.options.scaling.label.min;this.options.font.size=this.options.scaling.label.min+n*r}this.options.width=this.options.scaling.min+n*o}else this.options.width=this.baseWidth,this.options.font.size=this.baseFontSize;this._setInteractionWidths(),this.updateLabelModule()}},{key:"_setInteractionWidths",value:function(){"function"==typeof this.options.hoverWidth?this.edgeType.hoverWidth=this.options.hoverWidth(this.options.width):this.edgeType.hoverWidth=this.options.hoverWidth+this.options.width,"function"==typeof this.options.selectionWidth?this.edgeType.selectionWidth=this.options.selectionWidth(this.options.width):this.edgeType.selectionWidth=this.options.selectionWidth+this.options.width}},{key:"draw",value:function(t){var e=this.getFormattingValues();if(!e.hidden){var i=this.edgeType.getViaNode();this.edgeType.drawLine(t,e,this.selected,this.hover,i),this.drawLabel(t,i)}}},{key:"drawArrows",value:function(t){var e=this.getFormattingValues();if(!e.hidden){var i=this.edgeType.getViaNode(),n={};this.edgeType.fromPoint=this.edgeType.from,this.edgeType.toPoint=this.edgeType.to,e.fromArrow&&(n.from=this.edgeType.getArrowData(t,"from",i,this.selected,this.hover,e),!1===e.arrowStrikethrough&&(this.edgeType.fromPoint=n.from.core),e.fromArrowSrc&&(n.from.image=this.imagelist.load(e.fromArrowSrc)),e.fromArrowImageWidth&&(n.from.imageWidth=e.fromArrowImageWidth),e.fromArrowImageHeight&&(n.from.imageHeight=e.fromArrowImageHeight)),e.toArrow&&(n.to=this.edgeType.getArrowData(t,"to",i,this.selected,this.hover,e),!1===e.arrowStrikethrough&&(this.edgeType.toPoint=n.to.core),e.toArrowSrc&&(n.to.image=this.imagelist.load(e.toArrowSrc)),e.toArrowImageWidth&&(n.to.imageWidth=e.toArrowImageWidth),e.toArrowImageHeight&&(n.to.imageHeight=e.toArrowImageHeight)),e.middleArrow&&(n.middle=this.edgeType.getArrowData(t,"middle",i,this.selected,this.hover,e),e.middleArrowSrc&&(n.middle.image=this.imagelist.load(e.middleArrowSrc)),e.middleArrowImageWidth&&(n.middle.imageWidth=e.middleArrowImageWidth),e.middleArrowImageHeight&&(n.middle.imageHeight=e.middleArrowImageHeight)),e.fromArrow&&this.edgeType.drawArrowHead(t,e,this.selected,this.hover,n.from),e.middleArrow&&this.edgeType.drawArrowHead(t,e,this.selected,this.hover,n.middle),e.toArrow&&this.edgeType.drawArrowHead(t,e,this.selected,this.hover,n.to)}}},{key:"drawLabel",value:function(t,e){if(void 0!==this.options.label){var i,n=this.from,o=this.to;if(this.labelModule.differentState(this.selected,this.hover)&&this.labelModule.getTextSize(t,this.selected,this.hover),n.id!=o.id){this.labelModule.pointToSelf=!1,i=this.edgeType.getPoint(.5,e),t.save();var r=this._getRotation(t);0!=r.angle&&(t.translate(r.x,r.y),t.rotate(r.angle)),this.labelModule.draw(t,i.x,i.y,this.selected,this.hover),t.restore()}else{this.labelModule.pointToSelf=!0;var s=f0(t,this.options.selfReference.angle,this.options.selfReference.size,n);i=this._pointOnCircle(s.x,s.y,this.options.selfReference.size,this.options.selfReference.angle),this.labelModule.draw(t,i.x,i.y,this.selected,this.hover)}}}},{key:"getItemsOnPoint",value:function(t){var e=[];if(this.labelModule.visible()){var i=this._getRotation();u0(this.labelModule.getSize(),t,i)&&e.push({edgeId:this.id,labelId:0})}var n={left:t.x,top:t.y};return this.isOverlappingWith(n)&&e.push({edgeId:this.id}),e}},{key:"isOverlappingWith",value:function(t){if(this.connected){var e=this.from.x,i=this.from.y,n=this.to.x,o=this.to.y,r=t.left,s=t.top;return this.edgeType.getDistanceToEdge(e,i,n,o,r,s)<10}return!1}},{key:"_getRotation",value:function(t){var e=this.edgeType.getViaNode(),i=this.edgeType.getPoint(.5,e);void 0!==t&&this.labelModule.calculateLabelSize(t,this.selected,this.hover,i.x,i.y);var n={x:i.x,y:this.labelModule.size.yLine,angle:0};if(!this.labelModule.visible())return n;if("horizontal"===this.options.font.align)return n;var o=this.from.y-this.to.y,r=this.from.x-this.to.x,s=Math.atan2(o,r);return(s<-1&&r<0||s>0&&r<0)&&(s+=Math.PI),n.angle=s,n}},{key:"_pointOnCircle",value:function(t,e,i,n){return{x:t+i*Math.cos(n),y:e-i*Math.sin(n)}}},{key:"select",value:function(){this.selected=!0}},{key:"unselect",value:function(){this.selected=!1}},{key:"cleanup",value:function(){return this.edgeType.cleanup()}},{key:"remove",value:function(){this.cleanup(),this.disconnect(),delete this.body.edges[this.id]}},{key:"endPointsValid",value:function(){return void 0!==this.body.nodes[this.fromId]&&void 0!==this.body.nodes[this.toId]}}],[{key:"parseOptions",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},o=arguments.length>4&&void 0!==arguments[4]&&arguments[4];if(CK(["endPointOffset","arrowStrikethrough","id","from","hidden","hoverWidth","labelHighlightBold","length","line","opacity","physics","scaling","selectionWidth","selfReferenceSize","selfReference","to","title","value","width","font","chosen","widthConstraint"],t,e,i),void 0!==e.endPointOffset&&void 0!==e.endPointOffset.from&&(mJ(e.endPointOffset.from)?t.endPointOffset.from=e.endPointOffset.from:(t.endPointOffset.from=void 0!==n.endPointOffset.from?n.endPointOffset.from:0,console.error("endPointOffset.from is not a valid number"))),void 0!==e.endPointOffset&&void 0!==e.endPointOffset.to&&(mJ(e.endPointOffset.to)?t.endPointOffset.to=e.endPointOffset.to:(t.endPointOffset.to=void 0!==n.endPointOffset.to?n.endPointOffset.to:0,console.error("endPointOffset.to is not a valid number"))),p0(e.label)?t.label=e.label:p0(t.label)||(t.label=void 0),$K(t,e,"smooth",n),$K(t,e,"shadow",n),$K(t,e,"background",n),void 0!==e.dashes&&null!==e.dashes?t.dashes=e.dashes:!0===i&&null===e.dashes&&(t.dashes=NX(n.dashes)),void 0!==e.scaling&&null!==e.scaling?(void 0!==e.scaling.min&&(t.scaling.min=e.scaling.min),void 0!==e.scaling.max&&(t.scaling.max=e.scaling.max),$K(t.scaling,e.scaling,"label",n.scaling)):!0===i&&null===e.scaling&&(t.scaling=NX(n.scaling)),void 0!==e.arrows&&null!==e.arrows)if("string"==typeof e.arrows){var r=e.arrows.toLowerCase();t.arrows.to.enabled=-1!=PX(r).call(r,"to"),t.arrows.middle.enabled=-1!=PX(r).call(r,"middle"),t.arrows.from.enabled=-1!=PX(r).call(r,"from")}else{if("object"!==sW(e.arrows))throw new Error("The arrow newOptions can only be an object or a string. Refer to the documentation. You used:"+jX(e.arrows));$K(t.arrows,e.arrows,"to",n.arrows),$K(t.arrows,e.arrows,"middle",n.arrows),$K(t.arrows,e.arrows,"from",n.arrows)}else!0===i&&null===e.arrows&&(t.arrows=NX(n.arrows));if(void 0!==e.color&&null!==e.color){var s=wK(e.color)?{color:e.color,highlight:e.color,hover:e.color,inherit:!1,opacity:1}:e.color,a=t.color;if(o)TK(a,n.color,!1,i);else for(var d in a)Object.prototype.hasOwnProperty.call(a,d)&&delete a[d];if(wK(a))a.color=a,a.highlight=a,a.hover=a,a.inherit=!1,void 0===s.opacity&&(a.opacity=1);else{var l=!1;void 0!==s.color&&(a.color=s.color,l=!0),void 0!==s.highlight&&(a.highlight=s.highlight,l=!0),void 0!==s.hover&&(a.hover=s.hover,l=!0),void 0!==s.inherit&&(a.inherit=s.inherit),void 0!==s.opacity&&(a.opacity=Math.min(1,Math.max(0,s.opacity))),!0===l?a.inherit=!1:void 0===a.inherit&&(a.inherit="from")}}else!0===i&&null===e.color&&(t.color=HK(n.color));!0===i&&null===e.font&&(t.font=HK(n.font)),Object.prototype.hasOwnProperty.call(e,"selfReferenceSize")&&(console.warn("The selfReferenceSize property has been deprecated. Please use selfReference property instead. The selfReference can be set like thise selfReference:{size:30, angle:Math.PI / 4}"),t.selfReference.size=e.selfReferenceSize)}}]),t}(),H2=function(){function t(e,i,n){var o,r=this;rj(this,t),this.body=e,this.images=i,this.groups=n,this.body.functions.createEdge=FF(o=this.create).call(o,this),this.edgesListeners={add:function(t,e){r.add(e.items)},update:function(t,e){r.update(e.items)},remove:function(t,e){r.remove(e.items)}},this.options={},this.defaultOptions={arrows:{to:{enabled:!1,scaleFactor:1,type:"arrow"},middle:{enabled:!1,scaleFactor:1,type:"arrow"},from:{enabled:!1,scaleFactor:1,type:"arrow"}},endPointOffset:{from:0,to:0},arrowStrikethrough:!0,color:{color:"#848484",highlight:"#848484",hover:"#848484",inherit:"from",opacity:1},dashes:!1,font:{color:"#343434",size:14,face:"arial",background:"none",strokeWidth:2,strokeColor:"#ffffff",align:"horizontal",multi:!1,vadjust:0,bold:{mod:"bold"},boldital:{mod:"bold italic"},ital:{mod:"italic"},mono:{mod:"",size:15,face:"courier new",vadjust:2}},hidden:!1,hoverWidth:1.5,label:void 0,labelHighlightBold:!0,length:void 0,physics:!0,scaling:{min:1,max:15,label:{enabled:!0,min:14,max:30,maxVisible:30,drawThreshold:5},customScalingFunction:function(t,e,i,n){if(e===t)return.5;var o=1/(e-t);return Math.max(0,(n-t)*o)}},selectionWidth:1.5,selfReference:{size:20,angle:Math.PI/4,renderBehindTheNode:!0},shadow:{enabled:!1,color:"rgba(0,0,0,0.5)",size:10,x:5,y:5},background:{enabled:!1,color:"rgba(111,111,111,1)",size:10,dashes:!1},smooth:{enabled:!0,type:"dynamic",forceDirection:"none",roundness:.5},title:void 0,width:1,value:void 0},TK(this.options,this.defaultOptions),this.bindEventListeners()}return cW(t,[{key:"bindEventListeners",value:function(){var t,e,i=this;this.body.emitter.on("_forceDisableDynamicCurves",(function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];"dynamic"===t&&(t="continuous");var n=!1;for(var o in i.body.edges)if(Object.prototype.hasOwnProperty.call(i.body.edges,o)){var r=i.body.edges[o],s=i.body.data.edges.get(o);if(null!=s){var a=s.smooth;void 0!==a&&!0===a.enabled&&"dynamic"===a.type&&(void 0===t?r.setOptions({smooth:!1}):r.setOptions({smooth:{type:t}}),n=!0)}}!0===e&&!0===n&&i.body.emitter.emit("_dataChanged")})),this.body.emitter.on("_dataUpdated",(function(){i.reconnectEdges()})),this.body.emitter.on("refreshEdges",FF(t=this.refresh).call(t,this)),this.body.emitter.on("refresh",FF(e=this.refresh).call(e,this)),this.body.emitter.on("destroy",(function(){RK(i.edgesListeners,(function(t,e){i.body.data.edges&&i.body.data.edges.off(e,t)})),delete i.body.functions.createEdge,delete i.edgesListeners.add,delete i.edgesListeners.update,delete i.edgesListeners.remove,delete i.edgesListeners}))}},{key:"setOptions",value:function(t){if(void 0!==t){j2.parseOptions(this.options,t,!0,this.defaultOptions,!0);var e=!1;if(void 0!==t.smooth)for(var i in this.body.edges)Object.prototype.hasOwnProperty.call(this.body.edges,i)&&(e=this.body.edges[i].updateEdgeType()||e);if(void 0!==t.font)for(var n in this.body.edges)Object.prototype.hasOwnProperty.call(this.body.edges,n)&&this.body.edges[n].updateLabelModule();void 0===t.hidden&&void 0===t.physics&&!0!==e||this.body.emitter.emit("_dataChanged")}}},{key:"setData",value:function(t){var e=this,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=this.body.data.edges;if(YA("id",t))this.body.data.edges=t;else if(fV(t))this.body.data.edges=new XA,this.body.data.edges.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.body.data.edges=new XA}if(n&&RK(this.edgesListeners,(function(t,e){n.off(e,t)})),this.body.edges={},this.body.data.edges){RK(this.edgesListeners,(function(t,i){e.body.data.edges.on(i,t)}));var o=this.body.data.edges.getIds();this.add(o,!0)}this.body.emitter.emit("_adjustEdgesForHierarchicalLayout"),!1===i&&this.body.emitter.emit("_dataChanged")}},{key:"add",value:function(t){for(var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=this.body.edges,n=this.body.data.edges,o=0;o1&&void 0!==arguments[1])||arguments[1];if(0!==t.length){var i=this.body.edges;RK(t,(function(t){var e=i[t];void 0!==e&&e.remove()})),e&&this.body.emitter.emit("_dataChanged")}}},{key:"refresh",value:function(){var t=this;RK(this.body.edges,(function(e,i){var n=t.body.data.edges.get(i);void 0!==n&&e.setOptions(n)}))}},{key:"create",value:function(t){return new j2(t,this.body,this.images,this.options,this.defaultOptions)}},{key:"reconnectEdges",value:function(){var t,e=this.body.nodes,i=this.body.edges;for(t in e)Object.prototype.hasOwnProperty.call(e,t)&&(e[t].edges=[]);for(t in i)if(Object.prototype.hasOwnProperty.call(i,t)){var n=i[t];n.from=null,n.to=null,n.connect()}}},{key:"getConnectedNodes",value:function(t){var e=[];if(void 0!==this.body.edges[t]){var i=this.body.edges[t];void 0!==i.fromId&&e.push(i.fromId),void 0!==i.toId&&e.push(i.toId)}return e}},{key:"_updateState",value:function(){this._addMissingEdges(),this._removeInvalidEdges()}},{key:"_removeInvalidEdges",value:function(){var t=this,e=[];RK(this.body.edges,(function(i,n){var o=t.body.nodes[i.toId],r=t.body.nodes[i.fromId];void 0!==o&&!0===o.isCluster||void 0!==r&&!0===r.isCluster||void 0!==o&&void 0!==r||e.push(n)})),this.remove(e,!1)}},{key:"_addMissingEdges",value:function(){var t=this.body.data.edges;if(null!=t){var e=this.body.edges,i=[];HV(t).call(t,(function(t,n){void 0===e[n]&&i.push(n)})),this.add(i,!0)}}}]),t}(),$2=function(){function t(e,i,n){rj(this,t),this.body=e,this.physicsBody=i,this.barnesHutTree,this.setOptions(n),this._rng=fK("BARNES HUT SOLVER")}return cW(t,[{key:"setOptions",value:function(t){this.options=t,this.thetaInversed=1/this.options.theta,this.overlapAvoidanceFactor=1-Math.max(0,Math.min(1,this.options.avoidOverlap))}},{key:"solve",value:function(){if(0!==this.options.gravitationalConstant&&this.physicsBody.physicsNodeIndices.length>0){var t,e=this.body.nodes,i=this.physicsBody.physicsNodeIndices,n=i.length,o=this._formBarnesHutTree(e,i);this.barnesHutTree=o;for(var r=0;r0&&this._getForceContributions(o.root,t)}}},{key:"_getForceContributions",value:function(t,e){this._getForceContribution(t.children.NW,e),this._getForceContribution(t.children.NE,e),this._getForceContribution(t.children.SW,e),this._getForceContribution(t.children.SE,e)}},{key:"_getForceContribution",value:function(t,e){if(t.childrenCount>0){var i=t.centerOfMass.x-e.x,n=t.centerOfMass.y-e.y,o=Math.sqrt(i*i+n*n);o*t.calcSize>this.thetaInversed?this._calculateForces(o,i,n,e,t):4===t.childrenCount?this._getForceContributions(t,e):t.children.data.id!=e.id&&this._calculateForces(o,i,n,e,t)}}},{key:"_calculateForces",value:function(t,e,i,n,o){0===t&&(e=t=.1),this.overlapAvoidanceFactor<1&&n.shape.radius&&(t=Math.max(.1+this.overlapAvoidanceFactor*n.shape.radius,t-n.shape.radius));var r=this.options.gravitationalConstant*o.mass*n.options.mass/Math.pow(t,3),s=e*r,a=i*r;this.physicsBody.forces[n.id].x+=s,this.physicsBody.forces[n.id].y+=a}},{key:"_formBarnesHutTree",value:function(t,e){for(var i,n=e.length,o=t[e[0]].x,r=t[e[0]].y,s=t[e[0]].x,a=t[e[0]].y,d=1;d0&&(cs&&(s=c),ha&&(a=h))}var u=Math.abs(s-o)-Math.abs(a-r);u>0?(r-=.5*u,a+=.5*u):(o+=.5*u,s-=.5*u);var p=Math.max(1e-5,Math.abs(s-o)),f=.5*p,m=.5*(o+s),v=.5*(r+a),g={root:{centerOfMass:{x:0,y:0},mass:0,range:{minX:m-f,maxX:m+f,minY:v-f,maxY:v+f},size:p,calcSize:1/p,children:{data:null},maxWidth:0,level:0,childrenCount:4}};this._splitBranch(g.root);for(var y=0;y0&&this._placeInTree(g.root,i);return g}},{key:"_updateBranchMass",value:function(t,e){var i=t.centerOfMass,n=t.mass+e.options.mass,o=1/n;i.x=i.x*t.mass+e.x*e.options.mass,i.x*=o,i.y=i.y*t.mass+e.y*e.options.mass,i.y*=o,t.mass=n;var r=Math.max(Math.max(e.height,e.radius),e.width);t.maxWidth=t.maxWidthe.x?o.maxY>e.y?"NW":"SW":o.maxY>e.y?"NE":"SE",this._placeInRegion(t,e,n)}},{key:"_placeInRegion",value:function(t,e,i){var n=t.children[i];switch(n.childrenCount){case 0:n.children.data=e,n.childrenCount=1,this._updateBranchMass(n,e);break;case 1:n.children.data.x===e.x&&n.children.data.y===e.y?(e.x+=this._rng(),e.y+=this._rng()):(this._splitBranch(n),this._placeInTree(n,e));break;case 4:this._placeInTree(n,e)}}},{key:"_splitBranch",value:function(t){var e=null;1===t.childrenCount&&(e=t.children.data,t.mass=0,t.centerOfMass.x=0,t.centerOfMass.y=0),t.childrenCount=4,t.children.data=null,this._insertRegion(t,"NW"),this._insertRegion(t,"NE"),this._insertRegion(t,"SW"),this._insertRegion(t,"SE"),null!=e&&this._placeInTree(t,e)}},{key:"_insertRegion",value:function(t,e){var i,n,o,r,s=.5*t.size;switch(e){case"NW":i=t.range.minX,n=t.range.minX+s,o=t.range.minY,r=t.range.minY+s;break;case"NE":i=t.range.minX+s,n=t.range.maxX,o=t.range.minY,r=t.range.minY+s;break;case"SW":i=t.range.minX,n=t.range.minX+s,o=t.range.minY+s,r=t.range.maxY;break;case"SE":i=t.range.minX+s,n=t.range.maxX,o=t.range.minY+s,r=t.range.maxY}t.children[e]={centerOfMass:{x:0,y:0},mass:0,range:{minX:i,maxX:n,minY:o,maxY:r},size:.5*t.size,calcSize:2*t.calcSize,children:{data:null},maxWidth:0,level:t.level+1,childrenCount:0}}},{key:"_debug",value:function(t,e){void 0!==this.barnesHutTree&&(t.lineWidth=1,this._drawBranch(this.barnesHutTree.root,t,e))}},{key:"_drawBranch",value:function(t,e,i){void 0===i&&(i="#FF0000"),4===t.childrenCount&&(this._drawBranch(t.children.NW,e),this._drawBranch(t.children.NE,e),this._drawBranch(t.children.SE,e),this._drawBranch(t.children.SW,e)),e.strokeStyle=i,e.beginPath(),e.moveTo(t.range.minX,t.range.minY),e.lineTo(t.range.maxX,t.range.minY),e.stroke(),e.beginPath(),e.moveTo(t.range.maxX,t.range.minY),e.lineTo(t.range.maxX,t.range.maxY),e.stroke(),e.beginPath(),e.moveTo(t.range.maxX,t.range.maxY),e.lineTo(t.range.minX,t.range.maxY),e.stroke(),e.beginPath(),e.moveTo(t.range.minX,t.range.maxY),e.lineTo(t.range.minX,t.range.minY),e.stroke()}}]),t}(),U2=function(){function t(e,i,n){rj(this,t),this._rng=fK("REPULSION SOLVER"),this.body=e,this.physicsBody=i,this.setOptions(n)}return cW(t,[{key:"setOptions",value:function(t){this.options=t}},{key:"solve",value:function(){for(var t,e,i,n,o,r,s,a,d=this.body.nodes,l=this.physicsBody.physicsNodeIndices,c=this.physicsBody.forces,h=this.options.nodeDistance,u=-2/3/h,p=4/3,f=0;f0){var r=o.edges.length+1,s=this.options.centralGravity*r*o.options.mass;n[o.id].x=e*s,n[o.id].y=i*s}}}]),i}(X2),Q2=function(){function t(e){rj(this,t),this.body=e,this.physicsBody={physicsNodeIndices:[],physicsEdgeIndices:[],forces:{},velocities:{}},this.physicsEnabled=!0,this.simulationInterval=1e3/60,this.requiresTimeout=!0,this.previousStates={},this.referenceState={},this.freezeCache={},this.renderTimer=void 0,this.adaptiveTimestep=!1,this.adaptiveTimestepEnabled=!1,this.adaptiveCounter=0,this.adaptiveInterval=3,this.stabilized=!1,this.startedStabilization=!1,this.stabilizationIterations=0,this.ready=!1,this.options={},this.defaultOptions={enabled:!0,barnesHut:{theta:.5,gravitationalConstant:-2e3,centralGravity:.3,springLength:95,springConstant:.04,damping:.09,avoidOverlap:0},forceAtlas2Based:{theta:.5,gravitationalConstant:-50,centralGravity:.01,springConstant:.08,springLength:100,damping:.4,avoidOverlap:0},repulsion:{centralGravity:.2,springLength:200,springConstant:.05,nodeDistance:100,damping:.09,avoidOverlap:0},hierarchicalRepulsion:{centralGravity:0,springLength:100,springConstant:.01,nodeDistance:120,damping:.09},maxVelocity:50,minVelocity:.75,solver:"barnesHut",stabilization:{enabled:!0,iterations:1e3,updateInterval:50,onlyDynamicEdges:!1,fit:!0},timestep:.5,adaptiveTimestep:!0,wind:{x:0,y:0}},pF(this.options,this.defaultOptions),this.timestep=.5,this.layoutFailed=!1,this.bindEventListeners()}return cW(t,[{key:"bindEventListeners",value:function(){var t=this;this.body.emitter.on("initPhysics",(function(){t.initPhysics()})),this.body.emitter.on("_layoutFailed",(function(){t.layoutFailed=!0})),this.body.emitter.on("resetPhysics",(function(){t.stopSimulation(),t.ready=!1})),this.body.emitter.on("disablePhysics",(function(){t.physicsEnabled=!1,t.stopSimulation()})),this.body.emitter.on("restorePhysics",(function(){t.setOptions(t.options),!0===t.ready&&t.startSimulation()})),this.body.emitter.on("startSimulation",(function(){!0===t.ready&&t.startSimulation()})),this.body.emitter.on("stopSimulation",(function(){t.stopSimulation()})),this.body.emitter.on("destroy",(function(){t.stopSimulation(!1),t.body.emitter.off()})),this.body.emitter.on("_dataChanged",(function(){t.updatePhysicsData()}))}},{key:"setOptions",value:function(t){if(void 0!==t)if(!1===t)this.options.enabled=!1,this.physicsEnabled=!1,this.stopSimulation();else if(!0===t)this.options.enabled=!0,this.physicsEnabled=!0,this.startSimulation();else{this.physicsEnabled=!0,SK(["stabilization"],this.options,t),$K(this.options,t,"stabilization"),void 0===t.enabled&&(this.options.enabled=!0),!1===this.options.enabled&&(this.physicsEnabled=!1,this.stopSimulation());var e=this.options.wind;e&&(("number"!=typeof e.x||uJ(e.x))&&(e.x=0),("number"!=typeof e.y||uJ(e.y))&&(e.y=0)),this.timestep=this.options.timestep}this.init()}},{key:"init",value:function(){var t;"forceAtlas2Based"===this.options.solver?(t=this.options.forceAtlas2Based,this.nodesSolver=new G2(this.body,this.physicsBody,t),this.edgesSolver=new V2(this.body,this.physicsBody,t),this.gravitySolver=new Z2(this.body,this.physicsBody,t)):"repulsion"===this.options.solver?(t=this.options.repulsion,this.nodesSolver=new U2(this.body,this.physicsBody,t),this.edgesSolver=new V2(this.body,this.physicsBody,t),this.gravitySolver=new X2(this.body,this.physicsBody,t)):"hierarchicalRepulsion"===this.options.solver?(t=this.options.hierarchicalRepulsion,this.nodesSolver=new W2(this.body,this.physicsBody,t),this.edgesSolver=new q2(this.body,this.physicsBody,t),this.gravitySolver=new X2(this.body,this.physicsBody,t)):(t=this.options.barnesHut,this.nodesSolver=new $2(this.body,this.physicsBody,t),this.edgesSolver=new V2(this.body,this.physicsBody,t),this.gravitySolver=new X2(this.body,this.physicsBody,t)),this.modelOptions=t}},{key:"initPhysics",value:function(){!0===this.physicsEnabled&&!0===this.options.enabled?!0===this.options.stabilization.enabled?this.stabilize():(this.stabilized=!1,this.ready=!0,this.body.emitter.emit("fit",{},this.layoutFailed),this.startSimulation()):(this.ready=!0,this.body.emitter.emit("fit"))}},{key:"startSimulation",value:function(){var t;!0===this.physicsEnabled&&!0===this.options.enabled?(this.stabilized=!1,this.adaptiveTimestep=!1,this.body.emitter.emit("_resizeNodes"),void 0===this.viewFunction&&(this.viewFunction=FF(t=this.simulationStep).call(t,this),this.body.emitter.on("initRedraw",this.viewFunction),this.body.emitter.emit("_startRendering"))):this.body.emitter.emit("_redraw")}},{key:"stopSimulation",value:function(){var t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];this.stabilized=!0,!0===t&&this._emitStabilized(),void 0!==this.viewFunction&&(this.body.emitter.off("initRedraw",this.viewFunction),this.viewFunction=void 0,!0===t&&this.body.emitter.emit("_stopRendering"))}},{key:"simulationStep",value:function(){var t=TV();this.physicsTick(),(TV()-t<.4*this.simulationInterval||!0===this.runDoubleSpeed)&&!1===this.stabilized&&(this.physicsTick(),this.runDoubleSpeed=!0),!0===this.stabilized&&this.stopSimulation()}},{key:"_emitStabilized",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.stabilizationIterations;(this.stabilizationIterations>1||!0===this.startedStabilization)&&rY((function(){t.body.emitter.emit("stabilized",{iterations:e}),t.startedStabilization=!1,t.stabilizationIterations=0}),0)}},{key:"physicsStep",value:function(){this.gravitySolver.solve(),this.nodesSolver.solve(),this.edgesSolver.solve(),this.moveNodes()}},{key:"adjustTimeStep",value:function(){!0===this._evaluateStepQuality()?this.timestep=1.2*this.timestep:this.timestep/1.2.3))return!1;return!0}},{key:"moveNodes",value:function(){for(var t=this.physicsBody.physicsNodeIndices,e=0,i=0,n=0;nn&&(t=t>0?n:-n),t}},{key:"_performStep",value:function(t){var e=this.body.nodes[t],i=this.physicsBody.forces[t];this.options.wind&&(i.x+=this.options.wind.x,i.y+=this.options.wind.y);var n=this.physicsBody.velocities[t];return this.previousStates[t]={x:e.x,y:e.y,vx:n.x,vy:n.y},!1===e.options.fixed.x?(n.x=this.calculateComponentVelocity(n.x,i.x,e.options.mass),e.x+=n.x*this.timestep):(i.x=0,n.x=0),!1===e.options.fixed.y?(n.y=this.calculateComponentVelocity(n.y,i.y,e.options.mass),e.y+=n.y*this.timestep):(i.y=0,n.y=0),Math.sqrt(Math.pow(n.x,2)+Math.pow(n.y,2))}},{key:"_freezeNodes",value:function(){var t=this.body.nodes;for(var e in t)if(Object.prototype.hasOwnProperty.call(t,e)&&t[e].x&&t[e].y){var i=t[e].options.fixed;this.freezeCache[e]={x:i.x,y:i.y},i.x=!0,i.y=!0}}},{key:"_restoreFrozenNodes",value:function(){var t=this.body.nodes;for(var e in t)Object.prototype.hasOwnProperty.call(t,e)&&void 0!==this.freezeCache[e]&&(t[e].options.fixed.x=this.freezeCache[e].x,t[e].options.fixed.y=this.freezeCache[e].y);this.freezeCache={}}},{key:"stabilize",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.options.stabilization.iterations;"number"!=typeof e&&(e=this.options.stabilization.iterations,console.error("The stabilize method needs a numeric amount of iterations. Switching to default: ",e)),0!==this.physicsBody.physicsNodeIndices.length?(this.adaptiveTimestep=this.options.adaptiveTimestep,this.body.emitter.emit("_resizeNodes"),this.stopSimulation(),this.stabilized=!1,this.body.emitter.emit("_blockRedraw"),this.targetIterations=e,!0===this.options.stabilization.onlyDynamicEdges&&this._freezeNodes(),this.stabilizationIterations=0,rY((function(){return t._stabilizationBatch()}),0)):this.ready=!0}},{key:"_startStabilizing",value:function(){return!0!==this.startedStabilization&&(this.body.emitter.emit("startStabilizing"),this.startedStabilization=!0,!0)}},{key:"_stabilizationBatch",value:function(){var t=this,e=function(){return!1===t.stabilized&&t.stabilizationIterations1&&void 0!==arguments[1]?arguments[1]:[],n=1e9,o=-1e9,r=1e9,s=-1e9;if(i.length>0)for(var a=0;a(e=t[i[a]]).shape.boundingBox.left&&(r=e.shape.boundingBox.left),se.shape.boundingBox.top&&(n=e.shape.boundingBox.top),o1&&void 0!==arguments[1]?arguments[1]:[],n=1e9,o=-1e9,r=1e9,s=-1e9;if(i.length>0)for(var a=0;a(e=t[i[a]]).x&&(r=e.x),se.y&&(n=e.y),o=t&&i.push(o.id)}for(var r=0;r0&&void 0!==arguments[0]?arguments[0]:{},i=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(void 0===e.joinCondition)throw new Error("Cannot call clusterByNodeData without a joinCondition function in the options.");e=this._checkOptions(e);var n={},o={};RK(this.body.nodes,(function(i,r){i.options&&!0===e.joinCondition(i.options)&&(n[r]=i,RK(i.edges,(function(e){void 0===t.clusteredEdges[e.id]&&(o[e.id]=e)})))})),this._cluster(n,o,e,i)}},{key:"clusterByEdgeCount",value:function(t,e){var i=this,n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];e=this._checkOptions(e);for(var o,r,s,a=[],d={},l=function(){var n={},l={},h=i.body.nodeIndices[c],u=i.body.nodes[h];if(void 0===d[h]){s=0,r=[];for(var p=0;p0&&kV(l).length>0&&!0===m){var y=function(){for(var t=0;t1&&void 0!==arguments[1])||arguments[1];this.clusterByEdgeCount(1,t,e)}},{key:"clusterBridges",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];this.clusterByEdgeCount(2,t,e)}},{key:"clusterByConnection",value:function(t,e){var i,n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];if(void 0===t)throw new Error("No nodeId supplied to clusterByConnection!");if(void 0===this.body.nodes[t])throw new Error("The nodeId given to clusterByConnection does not exist!");var o=this.body.nodes[t];void 0===(e=this._checkOptions(e,o)).clusterNodeProperties.x&&(e.clusterNodeProperties.x=o.x),void 0===e.clusterNodeProperties.y&&(e.clusterNodeProperties.y=o.y),void 0===e.clusterNodeProperties.fixed&&(e.clusterNodeProperties.fixed={},e.clusterNodeProperties.fixed.x=o.options.fixed.x,e.clusterNodeProperties.fixed.y=o.options.fixed.y);var r={},s={},a=o.id,d=r5.cloneOptions(o);r[a]=o;for(var l=0;l-1&&(s[g.id]=g)}this._cluster(r,s,e,n)}},{key:"_createClusterEdges",value:function(t,e,i,n){for(var o,r,s,a,d,l,c=kV(t),h=[],u=0;u0&&void 0!==arguments[0]?arguments[0]:{};return void 0===t.clusterEdgeProperties&&(t.clusterEdgeProperties={}),void 0===t.clusterNodeProperties&&(t.clusterNodeProperties={}),t}},{key:"_cluster",value:function(t,e,i){var n=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],o=[];for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&void 0!==this.clusteredNodes[r]&&o.push(r);for(var s=0;so?e.x:o,r=e.ys?e.y:s;return{x:.5*(n+o),y:.5*(r+s)}}},{key:"openCluster",value:function(t,e){var i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];if(void 0===t)throw new Error("No clusterNodeId supplied to openCluster.");var n=this.body.nodes[t];if(void 0===n)throw new Error("The clusterNodeId supplied to openCluster does not exist.");if(!0!==n.isCluster||void 0===n.containedNodes||void 0===n.containedEdges)throw new Error("The node:"+t+" is not a valid cluster.");var o=this.findNode(t),r=PX(o).call(o,t)-1;if(r>=0){var s=o[r];return this.body.nodes[s]._openChildCluster(t),delete this.body.nodes[t],void(!0===i&&this.body.emitter.emit("_dataChanged"))}var a=n.containedNodes,d=n.containedEdges;if(void 0!==e&&void 0!==e.releaseFunction&&"function"==typeof e.releaseFunction){var l={},c={x:n.x,y:n.y};for(var h in a)if(Object.prototype.hasOwnProperty.call(a,h)){var u=this.body.nodes[h];l[h]={x:u.x,y:u.y}}var p=e.releaseFunction(c,l);for(var f in a)if(Object.prototype.hasOwnProperty.call(a,f)){var m=this.body.nodes[f];void 0!==p[f]&&(m.x=void 0===p[f].x?n.x:p[f].x,m.y=void 0===p[f].y?n.y:p[f].y)}}else RK(a,(function(t){!1===t.options.fixed.x&&(t.x=n.x),!1===t.options.fixed.y&&(t.y=n.y)}));for(var v in a)if(Object.prototype.hasOwnProperty.call(a,v)){var g=this.body.nodes[v];g.vx=n.vx,g.vy=n.vy,g.setOptions({physics:!0}),delete this.clusteredNodes[v]}for(var y=[],b=0;b0&&o<100;){var r=e.pop();if(void 0!==r){var s=this.body.edges[r];if(void 0!==s){o++;var a=s.clusteringEdgeReplacingIds;if(void 0===a)n.push(r);else for(var d=0;dn&&(n=r.edges.length),t+=r.edges.length,e+=Math.pow(r.edges.length,2),i+=1}t/=i;var s=(e/=i)-Math.pow(t,2),a=Math.sqrt(s),d=Math.floor(t+2*a);return d>n&&(d=n),d}},{key:"_createClusteredEdge",value:function(t,e,i,n,o){var r=r5.cloneOptions(i,"edge");TK(r,n),r.from=t,r.to=e,r.id="clusterEdge:"+o5(),void 0!==o&&TK(r,o);var s=this.body.functions.createEdge(r);return s.clusteringEdgeReplacingIds=[i.id],s.connect(),this.body.edges[s.id]=s,s}},{key:"_clusterEdges",value:function(t,e,i,n){if(e instanceof j2){var o=e,r={};r[o.id]=o,e=r}if(t instanceof U1){var s=t,a={};a[s.id]=s,t=a}if(null==i)throw new Error("_clusterEdges: parameter clusterNode required");for(var d in void 0===n&&(n=i.clusterEdgeProperties),this._createClusterEdges(t,e,i,n),e)if(Object.prototype.hasOwnProperty.call(e,d)&&void 0!==this.body.edges[d]){var l=this.body.edges[d];this._backupEdgeOptions(l),l.setOptions({physics:!1})}for(var c in t)Object.prototype.hasOwnProperty.call(t,c)&&(this.clusteredNodes[c]={clusterId:i.id,node:this.body.nodes[c]},this.body.nodes[c].setOptions({physics:!1}))}},{key:"_getClusterNodeForNode",value:function(t){if(void 0!==t){var e=this.clusteredNodes[t];if(void 0!==e){var i=e.clusterId;if(void 0!==i)return this.body.nodes[i]}}}},{key:"_filter",value:function(t,e){var i=[];return RK(t,(function(t){e(t)&&i.push(t)})),i}},{key:"_updateState",value:function(){var t,e=this,i=[],n={},o=function(t){RK(e.body.nodes,(function(e){!0===e.isCluster&&t(e)}))};for(t in this.clusteredNodes){if(Object.prototype.hasOwnProperty.call(this.clusteredNodes,t))void 0===this.body.nodes[t]&&i.push(t)}o((function(t){for(var e=0;e0}t.endPointsValid()&&o||(n[i]=i)})),o((function(t){RK(n,(function(i){delete t.containedEdges[i],RK(t.edges,(function(o,r){o.id!==i?o.clusteringEdgeReplacingIds=e._filter(o.clusteringEdgeReplacingIds,(function(t){return!n[t]})):t.edges[r]=null})),t.edges=e._filter(t.edges,(function(t){return null!==t}))}))})),RK(n,(function(t){delete e.clusteredEdges[t]})),RK(n,(function(t){delete e.body.edges[t]})),RK(kV(this.body.edges),(function(t){var i=e.body.edges[t],n=e._isClusteredNode(i.fromId)||e._isClusteredNode(i.toId);if(n!==e._isClusteredEdge(i.id))if(n){var o=e._getClusterNodeForNode(i.fromId);void 0!==o&&e._clusterEdges(e.body.nodes[i.fromId],i,o);var r=e._getClusterNodeForNode(i.toId);void 0!==r&&e._clusterEdges(e.body.nodes[i.toId],i,r)}else delete e._clusterEdges[t],e._restoreEdge(i)}));for(var s=!1,a=!0,d=function(){var t=[];o((function(e){var i=kV(e.containedNodes).length,n=!0===e.options.allowSingleNodeCluster;(n&&i<1||!n&&i<2)&&t.push(e.id)}));for(var i=0;i0,s=s||a};a;)d();s&&this._updateState()}},{key:"_isClusteredNode",value:function(t){return void 0!==this.clusteredNodes[t]}},{key:"_isClusteredEdge",value:function(t){return void 0!==this.clusteredEdges[t]}}]),t}();var l5=function(){function t(e,i){var n;rj(this,t),void 0!==window&&(n=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame),window.requestAnimationFrame=void 0===n?function(t){t()}:n,this.body=e,this.canvas=i,this.redrawRequested=!1,this.renderTimer=void 0,this.requiresTimeout=!0,this.renderingActive=!1,this.renderRequests=0,this.allowRedraw=!0,this.dragging=!1,this.zooming=!1,this.options={},this.defaultOptions={hideEdgesOnDrag:!1,hideEdgesOnZoom:!1,hideNodesOnDrag:!1},pF(this.options,this.defaultOptions),this._determineBrowserMethod(),this.bindEventListeners()}return cW(t,[{key:"bindEventListeners",value:function(){var t,e=this;this.body.emitter.on("dragStart",(function(){e.dragging=!0})),this.body.emitter.on("dragEnd",(function(){e.dragging=!1})),this.body.emitter.on("zoom",(function(){e.zooming=!0,window.clearTimeout(e.zoomTimeoutId),e.zoomTimeoutId=rY((function(){var t;e.zooming=!1,FF(t=e._requestRedraw).call(t,e)()}),250)})),this.body.emitter.on("_resizeNodes",(function(){e._resizeNodes()})),this.body.emitter.on("_redraw",(function(){!1===e.renderingActive&&e._redraw()})),this.body.emitter.on("_blockRedraw",(function(){e.allowRedraw=!1})),this.body.emitter.on("_allowRedraw",(function(){e.allowRedraw=!0,e.redrawRequested=!1})),this.body.emitter.on("_requestRedraw",FF(t=this._requestRedraw).call(t,this)),this.body.emitter.on("_startRendering",(function(){e.renderRequests+=1,e.renderingActive=!0,e._startRendering()})),this.body.emitter.on("_stopRendering",(function(){e.renderRequests-=1,e.renderingActive=e.renderRequests>0,e.renderTimer=void 0})),this.body.emitter.on("destroy",(function(){e.renderRequests=0,e.allowRedraw=!1,e.renderingActive=!1,!0===e.requiresTimeout?clearTimeout(e.renderTimer):window.cancelAnimationFrame(e.renderTimer),e.body.emitter.off()}))}},{key:"setOptions",value:function(t){if(void 0!==t){CK(["hideEdgesOnDrag","hideEdgesOnZoom","hideNodesOnDrag"],this.options,t)}}},{key:"_requestNextFrame",value:function(t,e){if("undefined"!=typeof window){var i,n=window;return!0===this.requiresTimeout?i=rY(t,e):n.requestAnimationFrame&&(i=n.requestAnimationFrame(t)),i}}},{key:"_startRendering",value:function(){var t;!0===this.renderingActive&&(void 0===this.renderTimer&&(this.renderTimer=this._requestNextFrame(FF(t=this._renderStep).call(t,this),this.simulationInterval)))}},{key:"_renderStep",value:function(){!0===this.renderingActive&&(this.renderTimer=void 0,!0===this.requiresTimeout&&this._startRendering(),this._redraw(),!1===this.requiresTimeout&&this._startRendering())}},{key:"redraw",value:function(){this.body.emitter.emit("setSize"),this._redraw()}},{key:"_requestRedraw",value:function(){var t=this;!0!==this.redrawRequested&&!1===this.renderingActive&&!0===this.allowRedraw&&(this.redrawRequested=!0,this._requestNextFrame((function(){t._redraw(!1)}),0))}},{key:"_redraw",value:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(!0===this.allowRedraw){this.body.emitter.emit("initRedraw"),this.redrawRequested=!1;var e={drawExternalLabels:null};0!==this.canvas.frame.canvas.width&&0!==this.canvas.frame.canvas.height||this.canvas.setSize(),this.canvas.setTransform();var i=this.canvas.getContext(),n=this.canvas.frame.canvas.clientWidth,o=this.canvas.frame.canvas.clientHeight;if(i.clearRect(0,0,n,o),0===this.canvas.frame.clientWidth)return;if(i.save(),i.translate(this.body.view.translation.x,this.body.view.translation.y),i.scale(this.body.view.scale,this.body.view.scale),i.beginPath(),this.body.emitter.emit("beforeDrawing",i),i.closePath(),!1===t&&(!1===this.dragging||!0===this.dragging&&!1===this.options.hideEdgesOnDrag)&&(!1===this.zooming||!0===this.zooming&&!1===this.options.hideEdgesOnZoom)&&this._drawEdges(i),!1===this.dragging||!0===this.dragging&&!1===this.options.hideNodesOnDrag){var r=this._drawNodes(i,t).drawExternalLabels;e.drawExternalLabels=r}!1===t&&(!1===this.dragging||!0===this.dragging&&!1===this.options.hideEdgesOnDrag)&&(!1===this.zooming||!0===this.zooming&&!1===this.options.hideEdgesOnZoom)&&this._drawArrows(i),null!=e.drawExternalLabels&&e.drawExternalLabels(),!1===t&&this._drawSelectionBox(i),i.beginPath(),this.body.emitter.emit("afterDrawing",i),i.closePath(),i.restore(),!0===t&&i.clearRect(0,0,n,o)}}},{key:"_resizeNodes",value:function(){this.canvas.setTransform();var t=this.canvas.getContext();t.save(),t.translate(this.body.view.translation.x,this.body.view.translation.y),t.scale(this.body.view.scale,this.body.view.scale);var e,i=this.body.nodes;for(var n in i)Object.prototype.hasOwnProperty.call(i,n)&&((e=i[n]).resize(t),e.updateBoundingBox(t,e.selected));t.restore()}},{key:"_drawNodes",value:function(t){for(var e,i,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],o=this.body.nodes,r=this.body.nodeIndices,s=[],a=[],d=this.canvas.DOMtoCanvas({x:-20,y:-20}),l=this.canvas.DOMtoCanvas({x:this.canvas.frame.canvas.clientWidth+20,y:this.canvas.frame.canvas.clientHeight+20}),c={top:d.y,left:d.x,bottom:l.y,right:l.x},h=[],u=0;u0&&void 0!==arguments[0]?arguments[0]:this.pixelRatio;!0===this.initialized&&(this.cameraState.previousWidth=this.frame.canvas.width/t,this.cameraState.previousHeight=this.frame.canvas.height/t,this.cameraState.scale=this.body.view.scale,this.cameraState.position=this.DOMtoCanvas({x:.5*this.frame.canvas.width/t,y:.5*this.frame.canvas.height/t}))}},{key:"_setCameraState",value:function(){if(void 0!==this.cameraState.scale&&0!==this.frame.canvas.clientWidth&&0!==this.frame.canvas.clientHeight&&0!==this.pixelRatio&&this.cameraState.previousWidth>0&&this.cameraState.previousHeight>0){var t=this.frame.canvas.width/this.pixelRatio/this.cameraState.previousWidth,e=this.frame.canvas.height/this.pixelRatio/this.cameraState.previousHeight,i=this.cameraState.scale;1!=t&&1!=e?i=.5*this.cameraState.scale*(t+e):1!=t?i=this.cameraState.scale*t:1!=e&&(i=this.cameraState.scale*e),this.body.view.scale=i;var n=this.DOMtoCanvas({x:.5*this.frame.canvas.clientWidth,y:.5*this.frame.canvas.clientHeight}),o={x:n.x-this.cameraState.position.x,y:n.y-this.cameraState.position.y};this.body.view.translation.x+=o.x*this.body.view.scale,this.body.view.translation.y+=o.y*this.body.view.scale}}},{key:"_prepareValue",value:function(t){if("number"==typeof t)return t+"px";if("string"==typeof t){if(-1!==PX(t).call(t,"%")||-1!==PX(t).call(t,"px"))return t;if(-1===PX(t).call(t,"%"))return t+"px"}throw new Error("Could not use the value supplied for width or height:"+t)}},{key:"_create",value:function(){for(;this.body.container.hasChildNodes();)this.body.container.removeChild(this.body.container.firstChild);if(this.frame=document.createElement("div"),this.frame.className="vis-network",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.tabIndex=0,this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),this.frame.canvas.getContext)this._setPixelRatio(),this.setTransform();else{var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerText="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t)}this.body.container.appendChild(this.frame),this.body.view.scale=1,this.body.view.translation={x:.5*this.frame.canvas.clientWidth,y:.5*this.frame.canvas.clientHeight},this._bindHammer()}},{key:"_bindHammer",value:function(){var t=this;void 0!==this.hammer&&this.hammer.destroy(),this.drag={},this.pinch={},this.hammer=new iZ(this.frame.canvas),this.hammer.get("pinch").set({enable:!0}),this.hammer.get("pan").set({threshold:5,direction:iZ.DIRECTION_ALL}),h5(this.hammer,(function(e){t.body.eventListeners.onTouch(e)})),this.hammer.on("tap",(function(e){t.body.eventListeners.onTap(e)})),this.hammer.on("doubletap",(function(e){t.body.eventListeners.onDoubleTap(e)})),this.hammer.on("press",(function(e){t.body.eventListeners.onHold(e)})),this.hammer.on("panstart",(function(e){t.body.eventListeners.onDragStart(e)})),this.hammer.on("panmove",(function(e){t.body.eventListeners.onDrag(e)})),this.hammer.on("panend",(function(e){t.body.eventListeners.onDragEnd(e)})),this.hammer.on("pinch",(function(e){t.body.eventListeners.onPinch(e)})),this.frame.canvas.addEventListener("wheel",(function(e){t.body.eventListeners.onMouseWheel(e)})),this.frame.canvas.addEventListener("mousemove",(function(e){t.body.eventListeners.onMouseMove(e)})),this.frame.canvas.addEventListener("contextmenu",(function(e){t.body.eventListeners.onContext(e)})),this.hammerFrame=new iZ(this.frame),u5(this.hammerFrame,(function(e){t.body.eventListeners.onRelease(e)}))}},{key:"setSize",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.options.width,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.options.height;t=this._prepareValue(t),e=this._prepareValue(e);var i=!1,n=this.frame.canvas.width,o=this.frame.canvas.height,r=this.pixelRatio;if(this._setPixelRatio(),t!=this.options.width||e!=this.options.height||this.frame.style.width!=t||this.frame.style.height!=e)this._getCameraState(r),this.frame.style.width=t,this.frame.style.height=e,this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=Math.round(this.frame.canvas.clientWidth*this.pixelRatio),this.frame.canvas.height=Math.round(this.frame.canvas.clientHeight*this.pixelRatio),this.options.width=t,this.options.height=e,this.canvasViewCenter={x:.5*this.frame.clientWidth,y:.5*this.frame.clientHeight},i=!0;else{var s=Math.round(this.frame.canvas.clientWidth*this.pixelRatio),a=Math.round(this.frame.canvas.clientHeight*this.pixelRatio);this.frame.canvas.width===s&&this.frame.canvas.height===a||this._getCameraState(r),this.frame.canvas.width!==s&&(this.frame.canvas.width=s,i=!0),this.frame.canvas.height!==a&&(this.frame.canvas.height=a,i=!0)}return!0===i&&(this.body.emitter.emit("resize",{width:Math.round(this.frame.canvas.width/this.pixelRatio),height:Math.round(this.frame.canvas.height/this.pixelRatio),oldWidth:Math.round(n/this.pixelRatio),oldHeight:Math.round(o/this.pixelRatio)}),this._setCameraState()),this.initialized=!0,i}},{key:"getContext",value:function(){return this.frame.canvas.getContext("2d")}},{key:"_determinePixelRatio",value:function(){var t=this.getContext();if(void 0===t)throw new Error("Could not get canvax context");var e=1;return"undefined"!=typeof window&&(e=window.devicePixelRatio||1),e/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1)}},{key:"_setPixelRatio",value:function(){this.pixelRatio=this._determinePixelRatio()}},{key:"setTransform",value:function(){var t=this.getContext();if(void 0===t)throw new Error("Could not get canvax context");t.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0)}},{key:"_XconvertDOMtoCanvas",value:function(t){return(t-this.body.view.translation.x)/this.body.view.scale}},{key:"_XconvertCanvasToDOM",value:function(t){return t*this.body.view.scale+this.body.view.translation.x}},{key:"_YconvertDOMtoCanvas",value:function(t){return(t-this.body.view.translation.y)/this.body.view.scale}},{key:"_YconvertCanvasToDOM",value:function(t){return t*this.body.view.scale+this.body.view.translation.y}},{key:"canvasToDOM",value:function(t){return{x:this._XconvertCanvasToDOM(t.x),y:this._YconvertCanvasToDOM(t.y)}}},{key:"DOMtoCanvas",value:function(t){return{x:this._XconvertDOMtoCanvas(t.x),y:this._YconvertDOMtoCanvas(t.y)}}}]),t}();var f5=function(){function t(e,i){var n,o,r=this;rj(this,t),this.body=e,this.canvas=i,this.animationSpeed=1/this.renderRefreshRate,this.animationEasingFunction="easeInOutQuint",this.easingTime=0,this.sourceScale=0,this.targetScale=0,this.sourceTranslation=0,this.targetTranslation=0,this.lockedOnNodeId=void 0,this.lockedOnNodeOffset=void 0,this.touchTime=0,this.viewFunction=void 0,this.body.emitter.on("fit",FF(n=this.fit).call(n,this)),this.body.emitter.on("animationFinished",(function(){r.body.emitter.emit("_stopRendering")})),this.body.emitter.on("unlockNode",FF(o=this.releaseNode).call(o,this))}return cW(t,[{key:"setOptions",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.options=t}},{key:"fit",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];t=function(t,e){var i=pF({nodes:e,minZoomLevel:Number.MIN_VALUE,maxZoomLevel:1},null!=t?t:{});if(!fV(i.nodes))throw new TypeError("Nodes has to be an array of ids.");if(0===i.nodes.length&&(i.nodes=e),!("number"==typeof i.minZoomLevel&&i.minZoomLevel>0))throw new TypeError("Min zoom level has to be a number higher than zero.");if(!("number"==typeof i.maxZoomLevel&&i.minZoomLevel<=i.maxZoomLevel))throw new TypeError("Max zoom level has to be a number higher than min zoom level.");return i}(t,this.body.nodeIndices);var i,n,o=this.canvas.frame.canvas.clientWidth,r=this.canvas.frame.canvas.clientHeight;if(0===o||0===r)n=1,i=r5.getRange(this.body.nodes,t.nodes);else if(!0===e){var s=0;for(var a in this.body.nodes){if(Object.prototype.hasOwnProperty.call(this.body.nodes,a))!0===this.body.nodes[a].predefinedPosition&&(s+=1)}if(s>.5*this.body.nodeIndices.length)return void this.fit(t,!1);i=r5.getRange(this.body.nodes,t.nodes),n=12.662/(this.body.nodeIndices.length+7.4147)+.0964822,n*=Math.min(o/600,r/600)}else{this.body.emitter.emit("_resizeNodes"),i=r5.getRange(this.body.nodes,t.nodes);var d=o/(1.1*Math.abs(i.maxX-i.minX)),l=r/(1.1*Math.abs(i.maxY-i.minY));n=d<=l?d:l}n>t.maxZoomLevel?n=t.maxZoomLevel:n1&&void 0!==arguments[1]?arguments[1]:{};if(void 0!==this.body.nodes[t]){var i={x:this.body.nodes[t].x,y:this.body.nodes[t].y};e.position=i,e.lockedOnNode=t,this.moveTo(e)}else console.error("Node: "+t+" cannot be found.")}},{key:"moveTo",value:function(t){if(void 0!==t){if(null!=t.offset){if(null!=t.offset.x){if(t.offset.x=+t.offset.x,!mJ(t.offset.x))throw new TypeError('The option "offset.x" has to be a finite number.')}else t.offset.x=0;if(null!=t.offset.y){if(t.offset.y=+t.offset.y,!mJ(t.offset.y))throw new TypeError('The option "offset.y" has to be a finite number.')}else t.offset.x=0}else t.offset={x:0,y:0};if(null!=t.position){if(null!=t.position.x){if(t.position.x=+t.position.x,!mJ(t.position.x))throw new TypeError('The option "position.x" has to be a finite number.')}else t.position.x=0;if(null!=t.position.y){if(t.position.y=+t.position.y,!mJ(t.position.y))throw new TypeError('The option "position.y" has to be a finite number.')}else t.position.x=0}else t.position=this.getViewPosition();if(null!=t.scale){if(t.scale=+t.scale,!(t.scale>0))throw new TypeError('The option "scale" has to be a number greater than zero.')}else t.scale=this.body.view.scale;void 0===t.animation&&(t.animation={duration:0}),!1===t.animation&&(t.animation={duration:0}),!0===t.animation&&(t.animation={}),void 0===t.animation.duration&&(t.animation.duration=1e3),void 0===t.animation.easingFunction&&(t.animation.easingFunction="easeInOutQuad"),this.animateView(t)}else t={}}},{key:"animateView",value:function(t){if(void 0!==t){this.animationEasingFunction=t.animation.easingFunction,this.releaseNode(),!0===t.locked&&(this.lockedOnNodeId=t.lockedOnNode,this.lockedOnNodeOffset=t.offset),0!=this.easingTime&&this._transitionRedraw(!0),this.sourceScale=this.body.view.scale,this.sourceTranslation=this.body.view.translation,this.targetScale=t.scale,this.body.view.scale=this.targetScale;var e,i,n=this.canvas.DOMtoCanvas({x:.5*this.canvas.frame.canvas.clientWidth,y:.5*this.canvas.frame.canvas.clientHeight}),o=n.x-t.position.x,r=n.y-t.position.y;if(this.targetTranslation={x:this.sourceTranslation.x+o*this.targetScale+t.offset.x,y:this.sourceTranslation.y+r*this.targetScale+t.offset.y},0===t.animation.duration)if(null!=this.lockedOnNodeId)this.viewFunction=FF(e=this._lockedRedraw).call(e,this),this.body.emitter.on("initRedraw",this.viewFunction);else this.body.view.scale=this.targetScale,this.body.view.translation=this.targetTranslation,this.body.emitter.emit("_requestRedraw");else this.animationSpeed=1/(60*t.animation.duration*.001)||1/60,this.animationEasingFunction=t.animation.easingFunction,this.viewFunction=FF(i=this._transitionRedraw).call(i,this),this.body.emitter.on("initRedraw",this.viewFunction),this.body.emitter.emit("_startRendering")}}},{key:"_lockedRedraw",value:function(){var t=this.body.nodes[this.lockedOnNodeId].x,e=this.body.nodes[this.lockedOnNodeId].y,i=this.canvas.DOMtoCanvas({x:.5*this.canvas.frame.canvas.clientWidth,y:.5*this.canvas.frame.canvas.clientHeight}),n=i.x-t,o=i.y-e,r=this.body.view.translation,s={x:r.x+n*this.body.view.scale+this.lockedOnNodeOffset.x,y:r.y+o*this.body.view.scale+this.lockedOnNodeOffset.y};this.body.view.translation=s}},{key:"releaseNode",value:function(){void 0!==this.lockedOnNodeId&&void 0!==this.viewFunction&&(this.body.emitter.off("initRedraw",this.viewFunction),this.lockedOnNodeId=void 0,this.lockedOnNodeOffset=void 0)}},{key:"_transitionRedraw",value:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];this.easingTime+=this.animationSpeed,this.easingTime=!0===t?1:this.easingTime;var e=UK[this.animationEasingFunction](this.easingTime);if(this.body.view.scale=this.sourceScale+(this.targetScale-this.sourceScale)*e,this.body.view.translation={x:this.sourceTranslation.x+(this.targetTranslation.x-this.sourceTranslation.x)*e,y:this.sourceTranslation.y+(this.targetTranslation.y-this.sourceTranslation.y)*e},this.easingTime>=1){var i;if(this.body.emitter.off("initRedraw",this.viewFunction),this.easingTime=0,null!=this.lockedOnNodeId)this.viewFunction=FF(i=this._lockedRedraw).call(i,this),this.body.emitter.on("initRedraw",this.viewFunction);this.body.emitter.emit("animationFinished")}}},{key:"getScale",value:function(){return this.body.view.scale}},{key:"getViewPosition",value:function(){return this.canvas.DOMtoCanvas({x:.5*this.canvas.frame.canvas.clientWidth,y:.5*this.canvas.frame.canvas.clientHeight})}}]),t}();function m5(t){var e,i=t&&t.preventDefault||!1,n=t&&t.container||window,o={},r={keydown:{},keyup:{}},s={};for(e=97;e<=122;e++)s[String.fromCharCode(e)]={code:e-97+65,shift:!1};for(e=65;e<=90;e++)s[String.fromCharCode(e)]={code:e,shift:!0};for(e=0;e<=9;e++)s[""+e]={code:48+e,shift:!1};for(e=1;e<=12;e++)s["F"+e]={code:111+e,shift:!1};for(e=0;e<=9;e++)s["num"+e]={code:96+e,shift:!1};s["num*"]={code:106,shift:!1},s["num+"]={code:107,shift:!1},s["num-"]={code:109,shift:!1},s["num/"]={code:111,shift:!1},s["num."]={code:110,shift:!1},s.left={code:37,shift:!1},s.up={code:38,shift:!1},s.right={code:39,shift:!1},s.down={code:40,shift:!1},s.space={code:32,shift:!1},s.enter={code:13,shift:!1},s.shift={code:16,shift:void 0},s.esc={code:27,shift:!1},s.backspace={code:8,shift:!1},s.tab={code:9,shift:!1},s.ctrl={code:17,shift:!1},s.alt={code:18,shift:!1},s.delete={code:46,shift:!1},s.pageup={code:33,shift:!1},s.pagedown={code:34,shift:!1},s["="]={code:187,shift:!1},s["-"]={code:189,shift:!1},s["]"]={code:221,shift:!1},s["["]={code:219,shift:!1};var a=function(t){l(t,"keydown")},d=function(t){l(t,"keyup")},l=function(t,e){if(void 0!==r[e][t.keyCode]){for(var n=r[e][t.keyCode],o=0;o700&&(this.body.emitter.emit("fit",{duration:700}),this.touchTime=(new Date).valueOf())}},{key:"_stopMovement",value:function(){for(var t in this.boundFunctions)Object.prototype.hasOwnProperty.call(this.boundFunctions,t)&&(this.body.emitter.off("initRedraw",this.boundFunctions[t]),this.body.emitter.emit("_stopRendering"));this.boundFunctions={}}},{key:"_moveUp",value:function(){this.body.view.translation.y+=this.options.keyboard.speed.y}},{key:"_moveDown",value:function(){this.body.view.translation.y-=this.options.keyboard.speed.y}},{key:"_moveLeft",value:function(){this.body.view.translation.x+=this.options.keyboard.speed.x}},{key:"_moveRight",value:function(){this.body.view.translation.x-=this.options.keyboard.speed.x}},{key:"_zoomIn",value:function(){var t=this.body.view.scale,e=this.body.view.scale*(1+this.options.keyboard.speed.zoom),i=this.body.view.translation,n=e/t,o=(1-n)*this.canvas.canvasViewCenter.x+i.x*n,r=(1-n)*this.canvas.canvasViewCenter.y+i.y*n;this.body.view.scale=e,this.body.view.translation={x:o,y:r},this.body.emitter.emit("zoom",{direction:"+",scale:this.body.view.scale,pointer:null})}},{key:"_zoomOut",value:function(){var t=this.body.view.scale,e=this.body.view.scale/(1+this.options.keyboard.speed.zoom),i=this.body.view.translation,n=e/t,o=(1-n)*this.canvas.canvasViewCenter.x+i.x*n,r=(1-n)*this.canvas.canvasViewCenter.y+i.y*n;this.body.view.scale=e,this.body.view.translation={x:o,y:r},this.body.emitter.emit("zoom",{direction:"-",scale:this.body.view.scale,pointer:null})}},{key:"configureKeyboardBindings",value:function(){var t,e,i,n,o,r,s,a,d,l,c,h,u,p,f,m,v,g,y,b,x,_,w,E,k=this;(void 0!==this.keycharm&&this.keycharm.destroy(),!0===this.options.keyboard.enabled)&&(!0===this.options.keyboard.bindToWindow?this.keycharm=m5({container:window,preventDefault:!0}):this.keycharm=m5({container:this.canvas.frame,preventDefault:!0}),this.keycharm.reset(),!0===this.activated&&(FF(t=this.keycharm).call(t,"up",(function(){k.bindToRedraw("_moveUp")}),"keydown"),FF(e=this.keycharm).call(e,"down",(function(){k.bindToRedraw("_moveDown")}),"keydown"),FF(i=this.keycharm).call(i,"left",(function(){k.bindToRedraw("_moveLeft")}),"keydown"),FF(n=this.keycharm).call(n,"right",(function(){k.bindToRedraw("_moveRight")}),"keydown"),FF(o=this.keycharm).call(o,"=",(function(){k.bindToRedraw("_zoomIn")}),"keydown"),FF(r=this.keycharm).call(r,"num+",(function(){k.bindToRedraw("_zoomIn")}),"keydown"),FF(s=this.keycharm).call(s,"num-",(function(){k.bindToRedraw("_zoomOut")}),"keydown"),FF(a=this.keycharm).call(a,"-",(function(){k.bindToRedraw("_zoomOut")}),"keydown"),FF(d=this.keycharm).call(d,"[",(function(){k.bindToRedraw("_zoomOut")}),"keydown"),FF(l=this.keycharm).call(l,"]",(function(){k.bindToRedraw("_zoomIn")}),"keydown"),FF(c=this.keycharm).call(c,"pageup",(function(){k.bindToRedraw("_zoomIn")}),"keydown"),FF(h=this.keycharm).call(h,"pagedown",(function(){k.bindToRedraw("_zoomOut")}),"keydown"),FF(u=this.keycharm).call(u,"up",(function(){k.unbindFromRedraw("_moveUp")}),"keyup"),FF(p=this.keycharm).call(p,"down",(function(){k.unbindFromRedraw("_moveDown")}),"keyup"),FF(f=this.keycharm).call(f,"left",(function(){k.unbindFromRedraw("_moveLeft")}),"keyup"),FF(m=this.keycharm).call(m,"right",(function(){k.unbindFromRedraw("_moveRight")}),"keyup"),FF(v=this.keycharm).call(v,"=",(function(){k.unbindFromRedraw("_zoomIn")}),"keyup"),FF(g=this.keycharm).call(g,"num+",(function(){k.unbindFromRedraw("_zoomIn")}),"keyup"),FF(y=this.keycharm).call(y,"num-",(function(){k.unbindFromRedraw("_zoomOut")}),"keyup"),FF(b=this.keycharm).call(b,"-",(function(){k.unbindFromRedraw("_zoomOut")}),"keyup"),FF(x=this.keycharm).call(x,"[",(function(){k.unbindFromRedraw("_zoomOut")}),"keyup"),FF(_=this.keycharm).call(_,"]",(function(){k.unbindFromRedraw("_zoomIn")}),"keyup"),FF(w=this.keycharm).call(w,"pageup",(function(){k.unbindFromRedraw("_zoomIn")}),"keyup"),FF(E=this.keycharm).call(E,"pagedown",(function(){k.unbindFromRedraw("_zoomOut")}),"keyup")))}}]),t}();function g5(t,e){var i=void 0!==tV&&oj(t)||t["@@iterator"];if(!i){if(fV(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return y5(t,e);var n=aV(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return Bz(t);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return y5(t,e)}(t))||e){i&&(t=i);var n=0,o=function(){};return{s:o,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function y5(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i50&&(this.drag.pointer=this.getPointer(t.center),this.drag.pinched=!1,this.pinch.scale=this.body.view.scale,this.touchTime=(new Date).valueOf())}},{key:"onTap",value:function(t){var e=this.getPointer(t.center),i=this.selectionHandler.options.multiselect&&(t.changedPointers[0].ctrlKey||t.changedPointers[0].metaKey);this.checkSelectionChanges(e,i),this.selectionHandler.commitAndEmit(e,t),this.selectionHandler.generateClickEvent("click",t,e)}},{key:"onDoubleTap",value:function(t){var e=this.getPointer(t.center);this.selectionHandler.generateClickEvent("doubleClick",t,e)}},{key:"onHold",value:function(t){var e=this.getPointer(t.center),i=this.selectionHandler.options.multiselect;this.checkSelectionChanges(e,i),this.selectionHandler.commitAndEmit(e,t),this.selectionHandler.generateClickEvent("click",t,e),this.selectionHandler.generateClickEvent("hold",t,e)}},{key:"onRelease",value:function(t){if((new Date).valueOf()-this.touchTime>10){var e=this.getPointer(t.center);this.selectionHandler.generateClickEvent("release",t,e),this.touchTime=(new Date).valueOf()}}},{key:"onContext",value:function(t){var e=this.getPointer({x:t.clientX,y:t.clientY});this.selectionHandler.generateClickEvent("oncontext",t,e)}},{key:"checkSelectionChanges",value:function(t){!0===(arguments.length>1&&void 0!==arguments[1]&&arguments[1])?this.selectionHandler.selectAdditionalOnPoint(t):this.selectionHandler.selectOnPoint(t)}},{key:"_determineDifference",value:function(t,e){var i=function(t,e){for(var i=[],n=0;n=o.minX&&i.x<=o.maxX&&i.y>=o.minY&&i.y<=o.maxY}));HV(r).call(r,(function(t){return e.selectionHandler.selectObject(e.body.nodes[t])}));var s=this.getPointer(t.center);this.selectionHandler.commitAndEmit(s,t),this.selectionHandler.generateClickEvent("dragEnd",t,this.getPointer(t.center),void 0,!0),this.body.emitter.emit("_requestRedraw")}else{var a=this.drag.selection;a&&a.length?(HV(a).call(a,(function(t){t.node.options.fixed.x=t.xFixed,t.node.options.fixed.y=t.yFixed})),this.selectionHandler.generateClickEvent("dragEnd",t,this.getPointer(t.center)),this.body.emitter.emit("startSimulation")):(this.selectionHandler.generateClickEvent("dragEnd",t,this.getPointer(t.center),void 0,!0),this.body.emitter.emit("_requestRedraw"))}}},{key:"onPinch",value:function(t){var e=this.getPointer(t.center);this.drag.pinched=!0,void 0===this.pinch.scale&&(this.pinch.scale=1);var i=this.pinch.scale*t.scale;this.zoom(i,e)}},{key:"zoom",value:function(t,e){if(!0===this.options.zoomView){var i=this.body.view.scale;t<1e-5&&(t=1e-5),t>10&&(t=10);var n=void 0;void 0!==this.drag&&!0===this.drag.dragging&&(n=this.canvas.DOMtoCanvas(this.drag.pointer));var o=this.body.view.translation,r=t/i,s=(1-r)*e.x+o.x*r,a=(1-r)*e.y+o.y*r;if(this.body.view.scale=t,this.body.view.translation={x:s,y:a},null!=n){var d=this.canvas.canvasToDOM(n);this.drag.pointer.x=d.x,this.drag.pointer.y=d.y}this.body.emitter.emit("_requestRedraw"),i0&&(this.popupObj=l[c[c.length-1]],r=!0)}if(void 0===this.popupObj&&!1===r){for(var u,p=this.body.edgeIndices,f=this.body.edges,m=[],v=0;v0&&(this.popupObj=f[m[m.length-1]],s="edge")}void 0!==this.popupObj?this.popupObj.id!==o&&(void 0===this.popup&&(this.popup=new nZ(this.canvas.frame)),this.popup.popupTargetType=s,this.popup.popupTargetId=this.popupObj.id,this.popup.setPosition(t.x+3,t.y-5),this.popup.setText(this.popupObj.getTitle()),this.popup.show(),this.body.emitter.emit("showPopup",this.popupObj.id)):void 0!==this.popup&&(this.popup.hide(),this.body.emitter.emit("hidePopup"))}},{key:"_checkHidePopup",value:function(t){var e=this.selectionHandler._pointerToPositionObject(t),i=!1;if("node"===this.popup.popupTargetType){if(void 0!==this.body.nodes[this.popup.popupTargetId]&&!0===(i=this.body.nodes[this.popup.popupTargetId].isOverlappingWith(e))){var n=this.selectionHandler.getNodeAt(t);i=void 0!==n&&n.id===this.popup.popupTargetId}}else void 0===this.selectionHandler.getNodeAt(t)&&void 0!==this.body.edges[this.popup.popupTargetId]&&(i=this.body.edges[this.popup.popupTargetId].isOverlappingWith(e));!1===i&&(this.popupObj=void 0,this.popup.hide(),this.body.emitter.emit("hidePopup"))}}]),t}();$Q("Set",(function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}}),lJ);var x5=KA(GR.Set),_5=cR,w5=WQ,E5=dQ.getWeakData,k5=OQ,O5=KD,C5=zR,S5=YR,T5=wQ,I5=qP,A5=DN.set,R5=DN.getterFor,P5=OH.find,D5=OH.findIndex,M5=_5([].splice),F5=0,N5=function(t){return t.frozen||(t.frozen=new B5)},B5=function(){this.entries=[]},L5=function(t,e){return P5(t.entries,(function(t){return t[0]===e}))};B5.prototype={get:function(t){var e=L5(this,t);if(e)return e[1]},has:function(t){return!!L5(this,t)},set:function(t,e){var i=L5(this,t);i?i[1]=e:this.entries.push([t,e])},delete:function(t){var e=D5(this.entries,(function(e){return e[0]===t}));return~e&&M5(this.entries,e,1),!!~e}};var z5,j5={getConstructor:function(t,e,i,n){var o=t((function(t,o){k5(t,r),A5(t,{type:e,id:F5++,frozen:void 0}),C5(o)||T5(o,t[n],{that:t,AS_ENTRIES:i})})),r=o.prototype,s=R5(e),a=function(t,e,i){var n=s(t),o=E5(O5(e),!0);return!0===o?N5(n).set(e,i):o[n.id]=i,t};return w5(r,{delete:function(t){var e=s(this);if(!S5(t))return!1;var i=E5(t);return!0===i?N5(e).delete(t):i&&I5(i,e.id)&&delete i[e.id]},has:function(t){var e=s(this);if(!S5(t))return!1;var i=E5(t);return!0===i?N5(e).has(t):i&&I5(i,e.id)}}),w5(r,i?{get:function(t){var e=s(this);if(S5(t)){var i=E5(t);return!0===i?N5(e).get(t):i?i[e.id]:void 0}},set:function(t,e){return a(this,t,e)}}:{add:function(t){return a(this,t,!0)}}),o}},H5=qZ,$5=QA,U5=cR,W5=WQ,V5=dQ,q5=$Q,X5=j5,Y5=YR,G5=DN.enforce,K5=JA,Z5=vN,Q5=Object,J5=Array.isArray,t3=Q5.isExtensible,e3=Q5.isFrozen,i3=Q5.isSealed,n3=Q5.freeze,o3=Q5.seal,r3={},s3={},a3=!$5.ActiveXObject&&"ActiveXObject"in $5,d3=function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}},l3=q5("WeakMap",d3,X5),c3=l3.prototype,h3=U5(c3.set);if(Z5)if(a3){z5=X5.getConstructor(d3,"WeakMap",!0),V5.enable();var u3=U5(c3.delete),p3=U5(c3.has),f3=U5(c3.get);W5(c3,{delete:function(t){if(Y5(t)&&!t3(t)){var e=G5(this);return e.frozen||(e.frozen=new z5),u3(this,t)||e.frozen.delete(t)}return u3(this,t)},has:function(t){if(Y5(t)&&!t3(t)){var e=G5(this);return e.frozen||(e.frozen=new z5),p3(this,t)||e.frozen.has(t)}return p3(this,t)},get:function(t){if(Y5(t)&&!t3(t)){var e=G5(this);return e.frozen||(e.frozen=new z5),p3(this,t)?f3(this,t):e.frozen.get(t)}return f3(this,t)},set:function(t,e){if(Y5(t)&&!t3(t)){var i=G5(this);i.frozen||(i.frozen=new z5),p3(this,t)?h3(this,t,e):i.frozen.set(t,e)}else h3(this,t,e);return this}})}else H5&&K5((function(){var t=n3([]);return h3(new l3,t,1),!e3(t)}))&&W5(c3,{set:function(t,e){var i;return J5(t)&&(e3(t)?i=r3:i3(t)&&(i=s3)),h3(this,t,e),i===r3&&n3(t),i===s3&&o3(t),this}});var m3,v3,g3,y3,b3,x3=KA(GR.WeakMap);function _3(t,e,i,n){if("a"===i&&!n)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!n:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===i?n:"a"===i?n.call(t):n?n.value:e.get(t)}function w3(t,e,i,n,o){if("function"==typeof e?t!==e||!o:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return e.set(t,i),i}function E3(t,e){var i=void 0!==tV&&oj(t)||t["@@iterator"];if(!i){if(fV(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return k3(t,e);var n=aV(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return Bz(t);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return k3(t,e)}(t))||e){i&&(t=i);var n=0,o=function(){};return{s:o,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function k3(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i0&&void 0!==arguments[0]?arguments[0]:function(){};rj(this,t),g3.set(this,new C3),y3.set(this,new C3),b3.set(this,void 0),w3(this,b3,e)}return cW(t,[{key:"sizeNodes",get:function(){return _3(this,g3,"f").size}},{key:"sizeEdges",get:function(){return _3(this,y3,"f").size}},{key:"getNodes",value:function(){return _3(this,g3,"f").getSelection()}},{key:"getEdges",value:function(){return _3(this,y3,"f").getSelection()}},{key:"addNodes",value:function(){var t;(t=_3(this,g3,"f")).add.apply(t,arguments)}},{key:"addEdges",value:function(){var t;(t=_3(this,y3,"f")).add.apply(t,arguments)}},{key:"deleteNodes",value:function(t){_3(this,g3,"f").delete(t)}},{key:"deleteEdges",value:function(t){_3(this,y3,"f").delete(t)}},{key:"clear",value:function(){_3(this,g3,"f").clear(),_3(this,y3,"f").clear()}},{key:"commit",value:function(){for(var t,e,i={nodes:_3(this,g3,"f").commit(),edges:_3(this,y3,"f").commit()},n=arguments.length,o=new Array(n),r=0;r=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function I3(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i4&&void 0!==arguments[4]&&arguments[4],r=this._initBaseEvent(e,i);if(!0===o)r.nodes=[],r.edges=[];else{var s=this.getSelection();r.nodes=s.nodes,r.edges=s.edges}void 0!==n&&(r.previousSelection=n),"click"==t&&(r.items=this.getClickedItems(i)),void 0!==e.controlEdge&&(r.controlEdge=e.controlEdge),this.body.emitter.emit(t,r)}},{key:"selectObject",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.options.selectConnectedEdges;if(void 0!==t){if(t instanceof U1){var i;if(!0===e)(i=this._selectionAccumulator).addEdges.apply(i,JW(t.edges));this._selectionAccumulator.addNodes(t)}else this._selectionAccumulator.addEdges(t);return!0}return!1}},{key:"deselectObject",value:function(t){!0===t.isSelected()&&(t.selected=!1,this._removeFromSelection(t))}},{key:"_getAllNodesOverlappingWith",value:function(t){for(var e=[],i=this.body.nodes,n=0;n1&&void 0!==arguments[1])||arguments[1],i=this._pointerToPositionObject(t),n=this._getAllNodesOverlappingWith(i);return n.length>0?!0===e?this.body.nodes[n[n.length-1]]:n[n.length-1]:void 0}},{key:"_getEdgesOverlappingWith",value:function(t,e){for(var i=this.body.edges,n=0;n1&&void 0!==arguments[1])||arguments[1],i=this.canvas.DOMtoCanvas(t),n=10,o=null,r=this.body.edges,s=0;s0&&(this.generateClickEvent("deselectEdge",e,t,o),i=!0),n.nodes.deleted.length>0&&(this.generateClickEvent("deselectNode",e,t,o),i=!0),n.nodes.added.length>0&&(this.generateClickEvent("selectNode",e,t),i=!0),n.edges.added.length>0&&(this.generateClickEvent("selectEdge",e,t),i=!0),!0===i&&this.generateClickEvent("select",e,t)}},{key:"getSelection",value:function(){return{nodes:this.getSelectedNodeIds(),edges:this.getSelectedEdgeIds()}}},{key:"getSelectedNodes",value:function(){return this._selectionAccumulator.getNodes()}},{key:"getSelectedEdges",value:function(){return this._selectionAccumulator.getEdges()}},{key:"getSelectedNodeIds",value:function(){var t;return _V(t=this._selectionAccumulator.getNodes()).call(t,(function(t){return t.id}))}},{key:"getSelectedEdgeIds",value:function(){var t;return _V(t=this._selectionAccumulator.getEdges()).call(t,(function(t){return t.id}))}},{key:"setSelection",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!t||!t.nodes&&!t.edges)throw new TypeError("Selection must be an object with nodes and/or edges properties");if((e.unselectAll||void 0===e.unselectAll)&&this.unselectAll(),t.nodes){var i,n=T3(t.nodes);try{for(n.s();!(i=n.n()).done;){var o=i.value,r=this.body.nodes[o];if(!r)throw new RangeError('Node with id "'+o+'" not found');this.selectObject(r,e.highlightEdges)}}catch(t){n.e(t)}finally{n.f()}}if(t.edges){var s,a=T3(t.edges);try{for(a.s();!(s=a.n()).done;){var d=s.value,l=this.body.edges[d];if(!l)throw new RangeError('Edge with id "'+d+'" not found');this.selectObject(l)}}catch(t){a.e(t)}finally{a.f()}}this.body.emitter.emit("_requestRedraw"),this._selectionAccumulator.commit()}},{key:"selectNodes",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(!t||void 0===t.length)throw"Selection must be an array with ids";this.setSelection({nodes:t},{highlightEdges:e})}},{key:"selectEdges",value:function(t){if(!t||void 0===t.length)throw"Selection must be an array with ids";this.setSelection({edges:t})}},{key:"updateSelection",value:function(){for(var t in this._selectionAccumulator.getNodes())Object.prototype.hasOwnProperty.call(this.body.nodes,t.id)||this._selectionAccumulator.deleteNodes(t);for(var e in this._selectionAccumulator.getEdges())Object.prototype.hasOwnProperty.call(this.body.edges,e.id)||this._selectionAccumulator.deleteEdges(e)}},{key:"getClickedItems",value:function(t){for(var e=this.canvas.DOMtoCanvas(t),i=[],n=this.body.nodeIndices,o=this.body.nodes,r=n.length-1;r>=0;r--){var s=o[n[r]].getItemsOnPoint(e);i.push.apply(i,s)}for(var a=this.body.edgeIndices,d=this.body.edges,l=a.length-1;l>=0;l--){var c=d[a[l]].getItemsOnPoint(e);i.push.apply(i,c)}return i}}]),t}(),R3=Qj,P3=Math.floor,D3=function(t,e){var i=t.length,n=P3(i/2);return i<8?M3(t,e):F3(t,D3(R3(t,0,n),e),D3(R3(t,n),e),e)},M3=function(t,e){for(var i,n,o=t.length,r=1;r0;)t[n]=t[--n];n!==r++&&(t[n]=i)}return t},F3=function(t,e,i,n){for(var o=e.length,r=i.length,s=0,a=0;s3)){if(J3)return!0;if(e4)return e4<603;var t,e,i,n,o="";for(t=65;t<76;t++){switch(e=String.fromCharCode(t),t){case 66:case 69:case 70:case 72:i=3;break;case 68:case 71:i=4;break;default:i=2}for(n=0;n<47;n++)i4.push({k:e+n,v:i})}for(i4.sort((function(t,e){return e.v-t.v})),n=0;nY3(i)?1:-1}}(t)),i=q3(o),n=0;n=0:a>d;d+=l)d in s&&(o=i(o,s[d],d,r));return o}},_4={left:x4(!1),right:x4(!0)},w4="process"===fR(QA.process),E4=_4.left;wM({target:"Array",proto:!0,forced:!w4&&lP>79&&lP<83||!AV("reduce")},{reduce:function(t){var e=arguments.length;return E4(this,t,e,e>1?arguments[1]:void 0)}});var k4=TF("Array").reduce,O4=eP,C4=k4,S4=Array.prototype,T4=function(t){var e=t.reduce;return t===S4||O4(S4,t)&&e===S4.reduce?C4:e},I4=KA(T4);function A4(t){var e=function(){if("undefined"==typeof Reflect||!X0)return!1;if(X0.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(X0(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=e1(t);if(e){var o=e1(this).constructor;i=X0(n,arguments,o)}else i=n.apply(this,arguments);return J0(this,i)}}var R4=function(){function t(){rj(this,t)}return cW(t,[{key:"abstract",value:function(){throw new Error("Can't instantiate abstract class!")}},{key:"fake_use",value:function(){}},{key:"curveType",value:function(){return this.abstract()}},{key:"getPosition",value:function(t){return this.fake_use(t),this.abstract()}},{key:"setPosition",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0;this.fake_use(t,e,i),this.abstract()}},{key:"getTreeSize",value:function(t){return this.fake_use(t),this.abstract()}},{key:"sort",value:function(t){this.fake_use(t),this.abstract()}},{key:"fix",value:function(t,e){this.fake_use(t,e),this.abstract()}},{key:"shift",value:function(t,e){this.fake_use(t,e),this.abstract()}}]),t}(),P4=function(t){Q0(i,t);var e=A4(i);function i(t){var n;return rj(this,i),(n=e.call(this)).layout=t,n}return cW(i,[{key:"curveType",value:function(){return"horizontal"}},{key:"getPosition",value:function(t){return t.x}},{key:"setPosition",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0;void 0!==i&&this.layout.hierarchical.addToOrdering(t,i),t.x=e}},{key:"getTreeSize",value:function(t){var e=this.layout.hierarchical.getTreeSize(this.layout.body.nodes,t);return{min:e.min_x,max:e.max_x}}},{key:"sort",value:function(t){f4(t).call(t,(function(t,e){return t.x-e.x}))}},{key:"fix",value:function(t,e){t.y=this.layout.options.hierarchical.levelSeparation*e,t.options.fixed.y=!0}},{key:"shift",value:function(t,e){this.layout.body.nodes[t].x+=e}}]),i}(R4),D4=function(t){Q0(i,t);var e=A4(i);function i(t){var n;return rj(this,i),(n=e.call(this)).layout=t,n}return cW(i,[{key:"curveType",value:function(){return"vertical"}},{key:"getPosition",value:function(t){return t.y}},{key:"setPosition",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0;void 0!==i&&this.layout.hierarchical.addToOrdering(t,i),t.y=e}},{key:"getTreeSize",value:function(t){var e=this.layout.hierarchical.getTreeSize(this.layout.body.nodes,t);return{min:e.min_y,max:e.max_y}}},{key:"sort",value:function(t){f4(t).call(t,(function(t,e){return t.y-e.y}))}},{key:"fix",value:function(t,e){t.x=this.layout.options.hierarchical.levelSeparation*e,t.options.fixed.x=!0}},{key:"shift",value:function(t,e){this.layout.body.nodes[t].y+=e}}]),i}(R4),M4=OH.every;wM({target:"Array",proto:!0,forced:!AV("every")},{every:function(t){return M4(this,t,arguments.length>1?arguments[1]:void 0)}});var F4=TF("Array").every,N4=eP,B4=F4,L4=Array.prototype,z4=function(t){var e=t.every;return t===L4||N4(L4,t)&&e===L4.every?B4:e},j4=KA(z4);function H4(t,e){var i=void 0!==tV&&oj(t)||t["@@iterator"];if(!i){if(fV(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return $4(t,e);var n=aV(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return Bz(t);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return $4(t,e)}(t))||e){i&&(t=i);var n=0,o=function(){};return{s:o,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function $4(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i=e[n])&&(e[n]=e[i]+1)})),e}function W4(t,e,i,n){var o,r,s=NX(null),a=I4(o=JW(E0(n).call(n))).call(o,(function(t,e){return t+1+e.edges.length}),0),d=i+"Id",l="to"===i?1:-1,c=H4(n);try{var h,u=function(){var o=QW(r.value,2),c=o[0],h=o[1];if(!n.has(c)||!t(h))return 0;s[c]=0;for(var u,p,f=[h],m=0,v=function(){var t,o;if(!n.has(c))return 0;var r=s[u.id]+l;if(HV(t=Jq(o=u.edges).call(o,(function(t){return t.connected&&t.to!==t.from&&t[i]!==u&&n.has(t.toId)&&n.has(t.fromId)}))).call(t,(function(t){var n=t[d],o=s[n];(null==o||e(r,o))&&(s[n]=r,f.push(t[i]))})),m>a)return{v:{v:U4(n,s)}};++m};u=f.pop();)if(0!==(p=v())&&p)return p.v};for(c.s();!(r=c.n()).done;)if(0!==(h=u())&&h)return h.v}catch(t){c.e(t)}finally{c.f()}return s}var V4=function(){function t(){rj(this,t),this.childrenReference={},this.parentReference={},this.trees={},this.distributionOrdering={},this.levels={},this.distributionIndex={},this.isTree=!1,this.treeIndex=-1}return cW(t,[{key:"addRelation",value:function(t,e){void 0===this.childrenReference[t]&&(this.childrenReference[t]=[]),this.childrenReference[t].push(e),void 0===this.parentReference[e]&&(this.parentReference[e]=[]),this.parentReference[e].push(t)}},{key:"checkIfTree",value:function(){for(var t in this.parentReference)if(this.parentReference[t].length>1)return void(this.isTree=!1);this.isTree=!0}},{key:"numTrees",value:function(){return this.treeIndex+1}},{key:"setTreeIndex",value:function(t,e){void 0!==e&&void 0===this.trees[t.id]&&(this.trees[t.id]=e,this.treeIndex=Math.max(e,this.treeIndex))}},{key:"ensureLevel",value:function(t){void 0===this.levels[t]&&(this.levels[t]=0)}},{key:"getMaxLevel",value:function(t){var e=this,i={};return function t(n){if(void 0!==i[n])return i[n];var o=e.levels[n];if(e.childrenReference[n]){var r=e.childrenReference[n];if(r.length>0)for(var s=0;s0&&(i.levelSeparation*=-1):i.levelSeparation<0&&(i.levelSeparation*=-1),this.setDirectionStrategy(),this.body.emitter.emit("_resetHierarchicalLayout"),this.adaptAllOptionsForHierarchicalLayout(e);if(!0===n)return this.body.emitter.emit("refresh"),TK(e,this.optionsBackup)}return e}},{key:"_resetRNG",value:function(t){this.initialRandomSeed=t,this._rng=fK(this.initialRandomSeed)}},{key:"adaptAllOptionsForHierarchicalLayout",value:function(t){if(!0===this.options.hierarchical.enabled){var e=this.optionsBackup.physics;void 0===t.physics||!0===t.physics?(t.physics={enabled:void 0===e.enabled||e.enabled,solver:"hierarchicalRepulsion"},e.enabled=void 0===e.enabled||e.enabled,e.solver=e.solver||"barnesHut"):"object"===sW(t.physics)?(e.enabled=void 0===t.physics.enabled||t.physics.enabled,e.solver=t.physics.solver||"barnesHut",t.physics.solver="hierarchicalRepulsion"):!1!==t.physics&&(e.solver="barnesHut",t.physics={solver:"hierarchicalRepulsion"});var i=this.direction.curveType();if(void 0===t.edges)this.optionsBackup.edges={smooth:{enabled:!0,type:"dynamic"}},t.edges={smooth:!1};else if(void 0===t.edges.smooth)this.optionsBackup.edges={smooth:{enabled:!0,type:"dynamic"}},t.edges.smooth=!1;else if("boolean"==typeof t.edges.smooth)this.optionsBackup.edges={smooth:t.edges.smooth},t.edges.smooth={enabled:t.edges.smooth,type:i};else{var n=t.edges.smooth;void 0!==n.type&&"dynamic"!==n.type&&(i=n.type),this.optionsBackup.edges={smooth:{enabled:void 0===n.enabled||n.enabled,type:void 0===n.type?"dynamic":n.type,roundness:void 0===n.roundness?.5:n.roundness,forceDirection:void 0!==n.forceDirection&&n.forceDirection}},t.edges.smooth={enabled:void 0===n.enabled||n.enabled,type:i,roundness:void 0===n.roundness?.5:n.roundness,forceDirection:void 0!==n.forceDirection&&n.forceDirection}}this.body.emitter.emit("_forceDisableDynamicCurves",i)}return t}},{key:"positionInitially",value:function(t){if(!0!==this.options.hierarchical.enabled){this._resetRNG(this.initialRandomSeed);for(var e=t.length+50,i=0;io){for(var s=t.length;t.length>o&&n<=10;){n+=1;var a=t.length;if(n%3==0?this.body.modules.clustering.clusterBridges(r):this.body.modules.clustering.clusterOutliers(r),a==t.length&&n%3!=0)return this._declusterAll(),this.body.emitter.emit("_layoutFailed"),void console.info("This network could not be positioned by this version of the improved layout algorithm. Please disable improvedLayout for better performance.")}this.body.modules.kamadaKawai.setOptions({springLength:Math.max(150,2*s)})}n>10&&console.info("The clustering didn't succeed within the amount of interations allowed, progressing with partial result."),this.body.modules.kamadaKawai.solve(t,this.body.edgeIndices,!0),this._shiftToCenter();for(var d=0;d0){var t,e,i=!1,n=!1;for(e in this.lastNodeOnLevel={},this.hierarchical=new V4,this.body.nodes)Object.prototype.hasOwnProperty.call(this.body.nodes,e)&&(void 0!==(t=this.body.nodes[e]).options.level?(i=!0,this.hierarchical.levels[e]=t.options.level):n=!0);if(!0===n&&!0===i)throw new Error("To use the hierarchical layout, nodes require either no predefined levels or levels have to be defined for all nodes.");if(!0===n){var o=this.options.hierarchical.sortMethod;"hubsize"===o?this._determineLevelsByHubsize():"directed"===o?this._determineLevelsDirected():"custom"===o&&this._determineLevelsCustomCallback()}for(var r in this.body.nodes)Object.prototype.hasOwnProperty.call(this.body.nodes,r)&&this.hierarchical.ensureLevel(r);var s=this._getDistribution();this._generateMap(),this._placeNodesByHierarchy(s),this._condenseHierarchy(),this._shiftToCenter()}}},{key:"_condenseHierarchy",value:function(){var t=this,e=!1,i={},n=function(e,i){var n=t.hierarchical.trees;for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&n[o]===e&&t.direction.shift(o,i)},o=function(){for(var e=[],i=0;i0)for(var r=0;r1&&void 0!==arguments[1]?arguments[1]:1e9,n=1e9,o=1e9,r=1e9,s=-1e9;for(var a in e)if(Object.prototype.hasOwnProperty.call(e,a)){var d=t.body.nodes[a],l=t.hierarchical.levels[d.id],c=t.direction.getPosition(d),h=QW(t._getSpaceAroundNode(d,e),2),u=h[0],p=h[1];n=Math.min(u,n),o=Math.min(p,o),l<=i&&(r=Math.min(c,r),s=Math.max(c,s))}return[r,s,n,o]},a=function(e,i,n){for(var o=t.hierarchical,r=0;r1)for(var d=0;d2&&void 0!==arguments[2]&&arguments[2],a=t.direction.getPosition(i),d=t.direction.getPosition(n),l=Math.abs(d-a),c=t.options.hierarchical.nodeSpacing;if(l>c){var h={},u={};r(i,h),r(n,u);var p=function(e,i){var n=t.hierarchical.getMaxLevel(e.id),o=t.hierarchical.getMaxLevel(i.id);return Math.min(n,o)}(i,n),f=s(h,p),m=s(u,p),v=f[1],g=m[0],y=m[2];if(Math.abs(v-g)>c){var b=v-g+c;b<-y+c&&(b=-y+c),b<0&&(t._shiftBlock(n.id,b),e=!0,!0===o&&t._centerParent(n))}}},l=function(n,o){for(var a=o.id,d=o.edges,l=t.hierarchical.levels[o.id],c=t.options.hierarchical.levelSeparation*t.options.hierarchical.levelSeparation,h={},u=[],p=0;p0?p=Math.min(u,h-t.options.hierarchical.nodeSpacing):u<0&&(p=-Math.min(-u,c-t.options.hierarchical.nodeSpacing)),0!=p&&(t._shiftBlock(o.id,p),e=!0)}(b),function(i){var n=t.direction.getPosition(o),r=QW(t._getSpaceAroundNode(o),2),s=r[0],a=r[1],d=i-n,l=n;d>0?l=Math.min(n+(a-t.options.hierarchical.nodeSpacing),i):d<0&&(l=Math.max(n-(s-t.options.hierarchical.nodeSpacing),i)),l!==n&&(t.direction.setPosition(o,l),e=!0)}(b=y(n,d))};!0===this.options.hierarchical.blockShifting&&(function(i){var n=t.hierarchical.getLevels();n=ZV(n).call(n);for(var o=0;o0&&Math.abs(h)0&&(d=this.direction.getPosition(n[r-1])+a),this.direction.setPosition(s,d,e),this._validatePositionAndContinue(s,e,d),o++}}}}},{key:"_placeBranchNodes",value:function(t,e){var i,n=this.hierarchical.childrenReference[t];if(void 0!==n){for(var o=[],r=0;re&&void 0===this.positionedNodes[a.id]))return;var l=this.options.hierarchical.nodeSpacing,c=void 0;c=0===s?this.direction.getPosition(this.body.nodes[t]):this.direction.getPosition(o[s-1])+l,this.direction.setPosition(a,c,d),this._validatePositionAndContinue(a,d,c)}var h=this._getCenterPosition(o);this.direction.setPosition(this.body.nodes[t],h,e)}}},{key:"_validatePositionAndContinue",value:function(t,e,i){if(this.hierarchical.isTree){if(void 0!==this.lastNodeOnLevel[e]){var n=this.direction.getPosition(this.body.nodes[this.lastNodeOnLevel[e]]);if(i-nt}),"from",t)}(i),this.hierarchical.setMinLevelToZero(this.body.nodes)}},{key:"_generateMap",value:function(){var t=this;this._crawlNetwork((function(e,i){t.hierarchical.levels[i.id]>t.hierarchical.levels[e.id]&&t.hierarchical.addRelation(e.id,i.id)})),this.hierarchical.checkIfTree()}},{key:"_crawlNetwork",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:function(){},i=arguments.length>1?arguments[1]:void 0,n={},o=function i(o,r){if(void 0===n[o.id]){var s;t.hierarchical.setTreeIndex(o,r),n[o.id]=!0;for(var a=t._getActiveEdges(o),d=0;d=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function Y4(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i0&&!1!==this.options.deleteNode||0===i&&!1!==this.options.deleteEdge)&&(!0===s&&this._createSeperator(4),this._createDeleteButton(r)),this._bindElementEvents(this.closeDiv,FF(t=this.toggleEditMode).call(t,this)),this._temporaryBindEvent("select",FF(e=this.showManipulatorToolbar).call(e,this))}this.body.emitter.emit("_redraw")}},{key:"addNodeMode",value:function(){var t;if(!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="addNode",!0===this.guiEnabled){var e,i=this.options.locales[this.options.locale];this.manipulationDOM={},this._createBackButton(i),this._createSeperator(),this._createDescription(i.addDescription||this.options.locales.en.addDescription),this._bindElementEvents(this.closeDiv,FF(e=this.toggleEditMode).call(e,this))}this._temporaryBindEvent("click",FF(t=this._performAddNode).call(t,this))}},{key:"editNode",value:function(){var t=this;!0!==this.editMode&&this.enableEditMode(),this._clean();var e=this.selectionHandler.getSelectedNodes()[0];if(void 0!==e){if(this.inMode="editNode","function"!=typeof this.options.editNode)throw new Error("No function has been configured to handle the editing of nodes.");if(!0!==e.isCluster){var i=TK({},e.options,!1);if(i.x=e.x,i.y=e.y,2!==this.options.editNode.length)throw new Error("The function for edit does not support two arguments (data, callback)");this.options.editNode(i,(function(e){null!=e&&"editNode"===t.inMode&&t.body.data.nodes.getDataSet().update(e),t.showManipulatorToolbar()}))}else alert(this.options.locales[this.options.locale].editClusterError||this.options.locales.en.editClusterError)}else this.showManipulatorToolbar()}},{key:"addEdgeMode",value:function(){var t,e,i,n,o;if(!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="addEdge",!0===this.guiEnabled){var r,s=this.options.locales[this.options.locale];this.manipulationDOM={},this._createBackButton(s),this._createSeperator(),this._createDescription(s.edgeDescription||this.options.locales.en.edgeDescription),this._bindElementEvents(this.closeDiv,FF(r=this.toggleEditMode).call(r,this))}this._temporaryBindUI("onTouch",FF(t=this._handleConnect).call(t,this)),this._temporaryBindUI("onDragEnd",FF(e=this._finishConnect).call(e,this)),this._temporaryBindUI("onDrag",FF(i=this._dragControlNode).call(i,this)),this._temporaryBindUI("onRelease",FF(n=this._finishConnect).call(n,this)),this._temporaryBindUI("onDragStart",FF(o=this._dragStartEdge).call(o,this)),this._temporaryBindUI("onHold",(function(){}))}},{key:"editEdgeMode",value:function(){if(!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="editEdge","object"!==sW(this.options.editEdge)||"function"!=typeof this.options.editEdge.editWithoutDrag||(this.edgeBeingEditedId=this.selectionHandler.getSelectedEdgeIds()[0],void 0===this.edgeBeingEditedId)){if(!0===this.guiEnabled){var t,e=this.options.locales[this.options.locale];this.manipulationDOM={},this._createBackButton(e),this._createSeperator(),this._createDescription(e.editEdgeDescription||this.options.locales.en.editEdgeDescription),this._bindElementEvents(this.closeDiv,FF(t=this.toggleEditMode).call(t,this))}if(this.edgeBeingEditedId=this.selectionHandler.getSelectedEdgeIds()[0],void 0!==this.edgeBeingEditedId){var i,n,o,r,s=this.body.edges[this.edgeBeingEditedId],a=this._getNewTargetNode(s.from.x,s.from.y),d=this._getNewTargetNode(s.to.x,s.to.y);this.temporaryIds.nodes.push(a.id),this.temporaryIds.nodes.push(d.id),this.body.nodes[a.id]=a,this.body.nodeIndices.push(a.id),this.body.nodes[d.id]=d,this.body.nodeIndices.push(d.id),this._temporaryBindUI("onTouch",FF(i=this._controlNodeTouch).call(i,this)),this._temporaryBindUI("onTap",(function(){})),this._temporaryBindUI("onHold",(function(){})),this._temporaryBindUI("onDragStart",FF(n=this._controlNodeDragStart).call(n,this)),this._temporaryBindUI("onDrag",FF(o=this._controlNodeDrag).call(o,this)),this._temporaryBindUI("onDragEnd",FF(r=this._controlNodeDragEnd).call(r,this)),this._temporaryBindUI("onMouseMove",(function(){})),this._temporaryBindEvent("beforeDrawing",(function(t){var e=s.edgeType.findBorderPositions(t);!1===a.selected&&(a.x=e.from.x,a.y=e.from.y),!1===d.selected&&(d.x=e.to.x,d.y=e.to.y)})),this.body.emitter.emit("_redraw")}else this.showManipulatorToolbar()}else{var l=this.body.edges[this.edgeBeingEditedId];this._performEditEdge(l.from.id,l.to.id)}}},{key:"deleteSelected",value:function(){var t=this;!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="delete";var e=this.selectionHandler.getSelectedNodeIds(),i=this.selectionHandler.getSelectedEdgeIds(),n=void 0;if(e.length>0){for(var o=0;o0&&"function"==typeof this.options.deleteEdge&&(n=this.options.deleteEdge);if("function"==typeof n){var r={nodes:e,edges:i};if(2!==n.length)throw new Error("The function for delete does not support two arguments (data, callback)");n(r,(function(e){null!=e&&"delete"===t.inMode?(t.body.data.edges.getDataSet().remove(e.edges),t.body.data.nodes.getDataSet().remove(e.nodes),t.body.emitter.emit("startSimulation"),t.showManipulatorToolbar()):(t.body.emitter.emit("startSimulation"),t.showManipulatorToolbar())}))}else this.body.data.edges.getDataSet().remove(i),this.body.data.nodes.getDataSet().remove(e),this.body.emitter.emit("startSimulation"),this.showManipulatorToolbar()}},{key:"_setup",value:function(){!0===this.options.enabled?(this.guiEnabled=!0,this._createWrappers(),!1===this.editMode?this._createEditButton():this.showManipulatorToolbar()):(this._removeManipulationDOM(),this.guiEnabled=!1)}},{key:"_createWrappers",value:function(){var t,e;(void 0===this.manipulationDiv&&(this.manipulationDiv=document.createElement("div"),this.manipulationDiv.className="vis-manipulation",!0===this.editMode?this.manipulationDiv.style.display="block":this.manipulationDiv.style.display="none",this.canvas.frame.appendChild(this.manipulationDiv)),void 0===this.editModeDiv&&(this.editModeDiv=document.createElement("div"),this.editModeDiv.className="vis-edit-mode",!0===this.editMode?this.editModeDiv.style.display="none":this.editModeDiv.style.display="block",this.canvas.frame.appendChild(this.editModeDiv)),void 0===this.closeDiv)&&(this.closeDiv=document.createElement("button"),this.closeDiv.className="vis-close",this.closeDiv.setAttribute("aria-label",null!==(t=null===(e=this.options.locales[this.options.locale])||void 0===e?void 0:e.close)&&void 0!==t?t:this.options.locales.en.close),this.closeDiv.style.display=this.manipulationDiv.style.display,this.canvas.frame.appendChild(this.closeDiv))}},{key:"_getNewTargetNode",value:function(t,e){var i=TK({},this.options.controlNodeStyle);i.id="targetNode"+o5(),i.hidden=!1,i.physics=!1,i.x=t,i.y=e;var n=this.body.functions.createNode(i);return n.shape.boundingBox={left:t,right:t,top:e,bottom:e},n}},{key:"_createEditButton",value:function(){var t;this._clean(),this.manipulationDOM={},_K(this.editModeDiv);var e=this.options.locales[this.options.locale],i=this._createButton("editMode","vis-edit vis-edit-mode",e.edit||this.options.locales.en.edit);this.editModeDiv.appendChild(i),this._bindElementEvents(i,FF(t=this.toggleEditMode).call(t,this))}},{key:"_clean",value:function(){this.inMode=!1,!0===this.guiEnabled&&(_K(this.editModeDiv),_K(this.manipulationDiv),this._cleanupDOMEventListeners()),this._cleanupTemporaryNodesAndEdges(),this._unbindTemporaryUIs(),this._unbindTemporaryEvents(),this.body.emitter.emit("restorePhysics")}},{key:"_cleanupDOMEventListeners",value:function(){var t,e,i=X4(bq(t=this._domEventListenerCleanupQueue).call(t,0));try{for(i.s();!(e=i.n()).done;){(0,e.value)()}}catch(t){i.e(t)}finally{i.f()}}},{key:"_removeManipulationDOM",value:function(){this._clean(),_K(this.manipulationDiv),_K(this.editModeDiv),_K(this.closeDiv),this.manipulationDiv&&this.canvas.frame.removeChild(this.manipulationDiv),this.editModeDiv&&this.canvas.frame.removeChild(this.editModeDiv),this.closeDiv&&this.canvas.frame.removeChild(this.closeDiv),this.manipulationDiv=void 0,this.editModeDiv=void 0,this.closeDiv=void 0}},{key:"_createSeperator",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1;this.manipulationDOM["seperatorLineDiv"+t]=document.createElement("div"),this.manipulationDOM["seperatorLineDiv"+t].className="vis-separator-line",this.manipulationDiv.appendChild(this.manipulationDOM["seperatorLineDiv"+t])}},{key:"_createAddNodeButton",value:function(t){var e,i=this._createButton("addNode","vis-add",t.addNode||this.options.locales.en.addNode);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,FF(e=this.addNodeMode).call(e,this))}},{key:"_createAddEdgeButton",value:function(t){var e,i=this._createButton("addEdge","vis-connect",t.addEdge||this.options.locales.en.addEdge);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,FF(e=this.addEdgeMode).call(e,this))}},{key:"_createEditNodeButton",value:function(t){var e,i=this._createButton("editNode","vis-edit",t.editNode||this.options.locales.en.editNode);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,FF(e=this.editNode).call(e,this))}},{key:"_createEditEdgeButton",value:function(t){var e,i=this._createButton("editEdge","vis-edit",t.editEdge||this.options.locales.en.editEdge);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,FF(e=this.editEdgeMode).call(e,this))}},{key:"_createDeleteButton",value:function(t){var e,i;i=this.options.rtl?"vis-delete-rtl":"vis-delete";var n=this._createButton("delete",i,t.del||this.options.locales.en.del);this.manipulationDiv.appendChild(n),this._bindElementEvents(n,FF(e=this.deleteSelected).call(e,this))}},{key:"_createBackButton",value:function(t){var e,i=this._createButton("back","vis-back",t.back||this.options.locales.en.back);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,FF(e=this.showManipulatorToolbar).call(e,this))}},{key:"_createButton",value:function(t,e,i){var n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"vis-label";return this.manipulationDOM[t+"Div"]=document.createElement("button"),this.manipulationDOM[t+"Div"].className="vis-button "+e,this.manipulationDOM[t+"Label"]=document.createElement("div"),this.manipulationDOM[t+"Label"].className=n,this.manipulationDOM[t+"Label"].innerText=i,this.manipulationDOM[t+"Div"].appendChild(this.manipulationDOM[t+"Label"]),this.manipulationDOM[t+"Div"]}},{key:"_createDescription",value:function(t){this.manipulationDOM.descriptionLabel=document.createElement("div"),this.manipulationDOM.descriptionLabel.className="vis-none",this.manipulationDOM.descriptionLabel.innerText=t,this.manipulationDiv.appendChild(this.manipulationDOM.descriptionLabel)}},{key:"_temporaryBindEvent",value:function(t,e){this.temporaryEventFunctions.push({event:t,boundFunction:e}),this.body.emitter.on(t,e)}},{key:"_temporaryBindUI",value:function(t,e){if(void 0===this.body.eventListeners[t])throw new Error("This UI function does not exist. Typo? You tried: "+t+" possible are: "+jX(kV(this.body.eventListeners)));this.temporaryUIFunctions[t]=this.body.eventListeners[t],this.body.eventListeners[t]=e}},{key:"_unbindTemporaryUIs",value:function(){for(var t in this.temporaryUIFunctions)Object.prototype.hasOwnProperty.call(this.temporaryUIFunctions,t)&&(this.body.eventListeners[t]=this.temporaryUIFunctions[t],delete this.temporaryUIFunctions[t]);this.temporaryUIFunctions={}}},{key:"_unbindTemporaryEvents",value:function(){for(var t=0;t=0;s--)if(o[s]!==this.selectedControlNode.id){r=this.body.nodes[o[s]];break}if(void 0!==r&&void 0!==this.selectedControlNode)if(!0===r.isCluster)alert(this.options.locales[this.options.locale].createEdgeError||this.options.locales.en.createEdgeError);else{var a=this.body.nodes[this.temporaryIds.nodes[0]];this.selectedControlNode.id===a.id?this._performEditEdge(r.id,n.to.id):this._performEditEdge(n.from.id,r.id)}else n.updateEdgeType(),this.body.emitter.emit("restorePhysics");this.body.emitter.emit("_redraw")}}},{key:"_handleConnect",value:function(t){if((new Date).valueOf()-this.touchTime>100){this.lastTouch=this.body.functions.getPointer(t.center),this.lastTouch.translation=pF({},this.body.view.translation),this.interactionHandler.drag.pointer=this.lastTouch,this.interactionHandler.drag.translation=this.lastTouch.translation;var e=this.lastTouch,i=this.selectionHandler.getNodeAt(e);if(void 0!==i)if(!0===i.isCluster)alert(this.options.locales[this.options.locale].createEdgeError||this.options.locales.en.createEdgeError);else{var n=this._getNewTargetNode(i.x,i.y);this.body.nodes[n.id]=n,this.body.nodeIndices.push(n.id);var o=this.body.functions.createEdge({id:"connectionEdge"+o5(),from:i.id,to:n.id,physics:!1,smooth:{enabled:!0,type:"continuous",roundness:.5}});this.body.edges[o.id]=o,this.body.edgeIndices.push(o.id),this.temporaryIds.nodes.push(n.id),this.temporaryIds.edges.push(o.id)}this.touchTime=(new Date).valueOf()}}},{key:"_dragControlNode",value:function(t){var e=this.body.functions.getPointer(t.center),i=this.selectionHandler._pointerToPositionObject(e),n=void 0;void 0!==this.temporaryIds.edges[0]&&(n=this.body.edges[this.temporaryIds.edges[0]].fromId);for(var o=this.selectionHandler._getAllNodesOverlappingWith(i),r=void 0,s=o.length-1;s>=0;s--){var a;if(-1===PX(a=this.temporaryIds.nodes).call(a,o[s])){r=this.body.nodes[o[s]];break}}if(t.controlEdge={from:n,to:r?r.id:void 0},this.selectionHandler.generateClickEvent("controlNodeDragging",t,e),void 0!==this.temporaryIds.nodes[0]){var d=this.body.nodes[this.temporaryIds.nodes[0]];d.x=this.canvas._XconvertDOMtoCanvas(e.x),d.y=this.canvas._YconvertDOMtoCanvas(e.y),this.body.emitter.emit("_redraw")}else this.interactionHandler.onDrag(t)}},{key:"_finishConnect",value:function(t){var e=this.body.functions.getPointer(t.center),i=this.selectionHandler._pointerToPositionObject(e),n=void 0;void 0!==this.temporaryIds.edges[0]&&(n=this.body.edges[this.temporaryIds.edges[0]].fromId);for(var o=this.selectionHandler._getAllNodesOverlappingWith(i),r=void 0,s=o.length-1;s>=0;s--){var a;if(-1===PX(a=this.temporaryIds.nodes).call(a,o[s])){r=this.body.nodes[o[s]];break}}this._cleanupTemporaryNodesAndEdges(),void 0!==r&&(!0===r.isCluster?alert(this.options.locales[this.options.locale].createEdgeError||this.options.locales.en.createEdgeError):void 0!==this.body.nodes[n]&&void 0!==this.body.nodes[r.id]&&this._performAddEdge(n,r.id)),t.controlEdge={from:n,to:r?r.id:void 0},this.selectionHandler.generateClickEvent("controlNodeDragEnd",t,e),this.body.emitter.emit("_redraw")}},{key:"_dragStartEdge",value:function(t){var e=this.lastTouch;this.selectionHandler.generateClickEvent("dragStart",t,e,void 0,!0)}},{key:"_performAddNode",value:function(t){var e=this,i={id:o5(),x:t.pointer.canvas.x,y:t.pointer.canvas.y,label:"new"};if("function"==typeof this.options.addNode){if(2!==this.options.addNode.length)throw this.showManipulatorToolbar(),new Error("The function for add does not support two arguments (data,callback)");this.options.addNode(i,(function(t){null!=t&&"addNode"===e.inMode&&e.body.data.nodes.getDataSet().add(t),e.showManipulatorToolbar()}))}else this.body.data.nodes.getDataSet().add(i),this.showManipulatorToolbar()}},{key:"_performAddEdge",value:function(t,e){var i=this,n={from:t,to:e};if("function"==typeof this.options.addEdge){if(2!==this.options.addEdge.length)throw new Error("The function for connect does not support two arguments (data,callback)");this.options.addEdge(n,(function(t){null!=t&&"addEdge"===i.inMode&&(i.body.data.edges.getDataSet().add(t),i.selectionHandler.unselectAll(),i.showManipulatorToolbar())}))}else this.body.data.edges.getDataSet().add(n),this.selectionHandler.unselectAll(),this.showManipulatorToolbar()}},{key:"_performEditEdge",value:function(t,e){var i=this,n={id:this.edgeBeingEditedId,from:t,to:e,label:this.body.data.edges.get(this.edgeBeingEditedId).label},o=this.options.editEdge;if("object"===sW(o)&&(o=o.editWithoutDrag),"function"==typeof o){if(2!==o.length)throw new Error("The function for edit does not support two arguments (data, callback)");o(n,(function(t){null==t||"editEdge"!==i.inMode?(i.body.edges[n.id].updateEdgeType(),i.body.emitter.emit("_redraw"),i.showManipulatorToolbar()):(i.body.data.edges.getDataSet().update(t),i.selectionHandler.unselectAll(),i.showManipulatorToolbar())}))}else this.body.data.edges.getDataSet().update(n),this.selectionHandler.unselectAll(),this.showManipulatorToolbar()}}]),t}(),K4="string",Z4="boolean",Q4="number",J4="array",t6="object",e6=["arrow","bar","box","circle","crow","curve","diamond","image","inv_curve","inv_triangle","triangle","vee"],i6={borderWidth:{number:Q4},borderWidthSelected:{number:Q4,undefined:"undefined"},brokenImage:{string:K4,undefined:"undefined"},chosen:{label:{boolean:Z4,function:"function"},node:{boolean:Z4,function:"function"},__type__:{object:t6,boolean:Z4}},color:{border:{string:K4},background:{string:K4},highlight:{border:{string:K4},background:{string:K4},__type__:{object:t6,string:K4}},hover:{border:{string:K4},background:{string:K4},__type__:{object:t6,string:K4}},__type__:{object:t6,string:K4}},opacity:{number:Q4,undefined:"undefined"},fixed:{x:{boolean:Z4},y:{boolean:Z4},__type__:{object:t6,boolean:Z4}},font:{align:{string:K4},color:{string:K4},size:{number:Q4},face:{string:K4},background:{string:K4},strokeWidth:{number:Q4},strokeColor:{string:K4},vadjust:{number:Q4},multi:{boolean:Z4,string:K4},bold:{color:{string:K4},size:{number:Q4},face:{string:K4},mod:{string:K4},vadjust:{number:Q4},__type__:{object:t6,string:K4}},boldital:{color:{string:K4},size:{number:Q4},face:{string:K4},mod:{string:K4},vadjust:{number:Q4},__type__:{object:t6,string:K4}},ital:{color:{string:K4},size:{number:Q4},face:{string:K4},mod:{string:K4},vadjust:{number:Q4},__type__:{object:t6,string:K4}},mono:{color:{string:K4},size:{number:Q4},face:{string:K4},mod:{string:K4},vadjust:{number:Q4},__type__:{object:t6,string:K4}},__type__:{object:t6,string:K4}},group:{string:K4,number:Q4,undefined:"undefined"},heightConstraint:{minimum:{number:Q4},valign:{string:K4},__type__:{object:t6,boolean:Z4,number:Q4}},hidden:{boolean:Z4},icon:{face:{string:K4},code:{string:K4},size:{number:Q4},color:{string:K4},weight:{string:K4,number:Q4},__type__:{object:t6}},id:{string:K4,number:Q4},image:{selected:{string:K4,undefined:"undefined"},unselected:{string:K4,undefined:"undefined"},__type__:{object:t6,string:K4}},imagePadding:{top:{number:Q4},right:{number:Q4},bottom:{number:Q4},left:{number:Q4},__type__:{object:t6,number:Q4}},label:{string:K4,undefined:"undefined"},labelHighlightBold:{boolean:Z4},level:{number:Q4,undefined:"undefined"},margin:{top:{number:Q4},right:{number:Q4},bottom:{number:Q4},left:{number:Q4},__type__:{object:t6,number:Q4}},mass:{number:Q4},physics:{boolean:Z4},scaling:{min:{number:Q4},max:{number:Q4},label:{enabled:{boolean:Z4},min:{number:Q4},max:{number:Q4},maxVisible:{number:Q4},drawThreshold:{number:Q4},__type__:{object:t6,boolean:Z4}},customScalingFunction:{function:"function"},__type__:{object:t6}},shadow:{enabled:{boolean:Z4},color:{string:K4},size:{number:Q4},x:{number:Q4},y:{number:Q4},__type__:{object:t6,boolean:Z4}},shape:{string:["custom","ellipse","circle","database","box","text","image","circularImage","diamond","dot","star","triangle","triangleDown","square","icon","hexagon"]},ctxRenderer:{function:"function"},shapeProperties:{borderDashes:{boolean:Z4,array:J4},borderRadius:{number:Q4},interpolation:{boolean:Z4},useImageSize:{boolean:Z4},useBorderWithImage:{boolean:Z4},coordinateOrigin:{string:["center","top-left"]},__type__:{object:t6}},size:{number:Q4},title:{string:K4,dom:"dom",undefined:"undefined"},value:{number:Q4,undefined:"undefined"},widthConstraint:{minimum:{number:Q4},maximum:{number:Q4},__type__:{object:t6,boolean:Z4,number:Q4}},x:{number:Q4},y:{number:Q4},__type__:{object:t6}},n6={configure:{enabled:{boolean:Z4},filter:{boolean:Z4,string:K4,array:J4,function:"function"},container:{dom:"dom"},showButton:{boolean:Z4},__type__:{object:t6,boolean:Z4,string:K4,array:J4,function:"function"}},edges:{arrows:{to:{enabled:{boolean:Z4},scaleFactor:{number:Q4},type:{string:e6},imageHeight:{number:Q4},imageWidth:{number:Q4},src:{string:K4},__type__:{object:t6,boolean:Z4}},middle:{enabled:{boolean:Z4},scaleFactor:{number:Q4},type:{string:e6},imageWidth:{number:Q4},imageHeight:{number:Q4},src:{string:K4},__type__:{object:t6,boolean:Z4}},from:{enabled:{boolean:Z4},scaleFactor:{number:Q4},type:{string:e6},imageWidth:{number:Q4},imageHeight:{number:Q4},src:{string:K4},__type__:{object:t6,boolean:Z4}},__type__:{string:["from","to","middle"],object:t6}},endPointOffset:{from:{number:Q4},to:{number:Q4},__type__:{object:t6,number:Q4}},arrowStrikethrough:{boolean:Z4},background:{enabled:{boolean:Z4},color:{string:K4},size:{number:Q4},dashes:{boolean:Z4,array:J4},__type__:{object:t6,boolean:Z4}},chosen:{label:{boolean:Z4,function:"function"},edge:{boolean:Z4,function:"function"},__type__:{object:t6,boolean:Z4}},color:{color:{string:K4},highlight:{string:K4},hover:{string:K4},inherit:{string:["from","to","both"],boolean:Z4},opacity:{number:Q4},__type__:{object:t6,string:K4}},dashes:{boolean:Z4,array:J4},font:{color:{string:K4},size:{number:Q4},face:{string:K4},background:{string:K4},strokeWidth:{number:Q4},strokeColor:{string:K4},align:{string:["horizontal","top","middle","bottom"]},vadjust:{number:Q4},multi:{boolean:Z4,string:K4},bold:{color:{string:K4},size:{number:Q4},face:{string:K4},mod:{string:K4},vadjust:{number:Q4},__type__:{object:t6,string:K4}},boldital:{color:{string:K4},size:{number:Q4},face:{string:K4},mod:{string:K4},vadjust:{number:Q4},__type__:{object:t6,string:K4}},ital:{color:{string:K4},size:{number:Q4},face:{string:K4},mod:{string:K4},vadjust:{number:Q4},__type__:{object:t6,string:K4}},mono:{color:{string:K4},size:{number:Q4},face:{string:K4},mod:{string:K4},vadjust:{number:Q4},__type__:{object:t6,string:K4}},__type__:{object:t6,string:K4}},hidden:{boolean:Z4},hoverWidth:{function:"function",number:Q4},label:{string:K4,undefined:"undefined"},labelHighlightBold:{boolean:Z4},length:{number:Q4,undefined:"undefined"},physics:{boolean:Z4},scaling:{min:{number:Q4},max:{number:Q4},label:{enabled:{boolean:Z4},min:{number:Q4},max:{number:Q4},maxVisible:{number:Q4},drawThreshold:{number:Q4},__type__:{object:t6,boolean:Z4}},customScalingFunction:{function:"function"},__type__:{object:t6}},selectionWidth:{function:"function",number:Q4},selfReferenceSize:{number:Q4},selfReference:{size:{number:Q4},angle:{number:Q4},renderBehindTheNode:{boolean:Z4},__type__:{object:t6}},shadow:{enabled:{boolean:Z4},color:{string:K4},size:{number:Q4},x:{number:Q4},y:{number:Q4},__type__:{object:t6,boolean:Z4}},smooth:{enabled:{boolean:Z4},type:{string:["dynamic","continuous","discrete","diagonalCross","straightCross","horizontal","vertical","curvedCW","curvedCCW","cubicBezier"]},roundness:{number:Q4},forceDirection:{string:["horizontal","vertical","none"],boolean:Z4},__type__:{object:t6,boolean:Z4}},title:{string:K4,undefined:"undefined"},width:{number:Q4},widthConstraint:{maximum:{number:Q4},__type__:{object:t6,boolean:Z4,number:Q4}},value:{number:Q4,undefined:"undefined"},__type__:{object:t6}},groups:{useDefaultGroups:{boolean:Z4},__any__:i6,__type__:{object:t6}},interaction:{dragNodes:{boolean:Z4},dragView:{boolean:Z4},hideEdgesOnDrag:{boolean:Z4},hideEdgesOnZoom:{boolean:Z4},hideNodesOnDrag:{boolean:Z4},hover:{boolean:Z4},keyboard:{enabled:{boolean:Z4},speed:{x:{number:Q4},y:{number:Q4},zoom:{number:Q4},__type__:{object:t6}},bindToWindow:{boolean:Z4},autoFocus:{boolean:Z4},__type__:{object:t6,boolean:Z4}},multiselect:{boolean:Z4},navigationButtons:{boolean:Z4},selectable:{boolean:Z4},selectConnectedEdges:{boolean:Z4},hoverConnectedEdges:{boolean:Z4},tooltipDelay:{number:Q4},zoomView:{boolean:Z4},zoomSpeed:{number:Q4},__type__:{object:t6}},layout:{randomSeed:{undefined:"undefined",number:Q4,string:K4},improvedLayout:{boolean:Z4},clusterThreshold:{number:Q4},hierarchical:{enabled:{boolean:Z4},levelSeparation:{number:Q4},nodeSpacing:{number:Q4},treeSpacing:{number:Q4},blockShifting:{boolean:Z4},edgeMinimization:{boolean:Z4},parentCentralization:{boolean:Z4},direction:{string:["UD","DU","LR","RL"]},sortMethod:{string:["hubsize","directed"]},shakeTowards:{string:["leaves","roots"]},__type__:{object:t6,boolean:Z4}},__type__:{object:t6}},manipulation:{enabled:{boolean:Z4},initiallyActive:{boolean:Z4},addNode:{boolean:Z4,function:"function"},addEdge:{boolean:Z4,function:"function"},editNode:{function:"function"},editEdge:{editWithoutDrag:{function:"function"},__type__:{object:t6,boolean:Z4,function:"function"}},deleteNode:{boolean:Z4,function:"function"},deleteEdge:{boolean:Z4,function:"function"},controlNodeStyle:i6,__type__:{object:t6,boolean:Z4}},nodes:i6,physics:{enabled:{boolean:Z4},barnesHut:{theta:{number:Q4},gravitationalConstant:{number:Q4},centralGravity:{number:Q4},springLength:{number:Q4},springConstant:{number:Q4},damping:{number:Q4},avoidOverlap:{number:Q4},__type__:{object:t6}},forceAtlas2Based:{theta:{number:Q4},gravitationalConstant:{number:Q4},centralGravity:{number:Q4},springLength:{number:Q4},springConstant:{number:Q4},damping:{number:Q4},avoidOverlap:{number:Q4},__type__:{object:t6}},repulsion:{centralGravity:{number:Q4},springLength:{number:Q4},springConstant:{number:Q4},nodeDistance:{number:Q4},damping:{number:Q4},__type__:{object:t6}},hierarchicalRepulsion:{centralGravity:{number:Q4},springLength:{number:Q4},springConstant:{number:Q4},nodeDistance:{number:Q4},damping:{number:Q4},avoidOverlap:{number:Q4},__type__:{object:t6}},maxVelocity:{number:Q4},minVelocity:{number:Q4},solver:{string:["barnesHut","repulsion","hierarchicalRepulsion","forceAtlas2Based"]},stabilization:{enabled:{boolean:Z4},iterations:{number:Q4},updateInterval:{number:Q4},onlyDynamicEdges:{boolean:Z4},fit:{boolean:Z4},__type__:{object:t6,boolean:Z4}},timestep:{number:Q4},adaptiveTimestep:{boolean:Z4},wind:{x:{number:Q4},y:{number:Q4},__type__:{object:t6}},__type__:{object:t6,boolean:Z4}},autoResize:{boolean:Z4},clickToUse:{boolean:Z4},locale:{string:K4},locales:{__any__:{any:"any"},__type__:{object:t6}},height:{string:K4},width:{string:K4},__type__:{object:t6}},o6={nodes:{borderWidth:[1,0,10,1],borderWidthSelected:[2,0,10,1],color:{border:["color","#2B7CE9"],background:["color","#97C2FC"],highlight:{border:["color","#2B7CE9"],background:["color","#D2E5FF"]},hover:{border:["color","#2B7CE9"],background:["color","#D2E5FF"]}},opacity:[0,0,1,.1],fixed:{x:!1,y:!1},font:{color:["color","#343434"],size:[14,0,100,1],face:["arial","verdana","tahoma"],background:["color","none"],strokeWidth:[0,0,50,1],strokeColor:["color","#ffffff"]},hidden:!1,labelHighlightBold:!0,physics:!0,scaling:{min:[10,0,200,1],max:[30,0,200,1],label:{enabled:!1,min:[14,0,200,1],max:[30,0,200,1],maxVisible:[30,0,200,1],drawThreshold:[5,0,20,1]}},shadow:{enabled:!1,color:"rgba(0,0,0,0.5)",size:[10,0,20,1],x:[5,-30,30,1],y:[5,-30,30,1]},shape:["ellipse","box","circle","database","diamond","dot","square","star","text","triangle","triangleDown","hexagon"],shapeProperties:{borderDashes:!1,borderRadius:[6,0,20,1],interpolation:!0,useImageSize:!1},size:[25,0,200,1]},edges:{arrows:{to:{enabled:!1,scaleFactor:[1,0,3,.05],type:"arrow"},middle:{enabled:!1,scaleFactor:[1,0,3,.05],type:"arrow"},from:{enabled:!1,scaleFactor:[1,0,3,.05],type:"arrow"}},endPointOffset:{from:[0,-10,10,1],to:[0,-10,10,1]},arrowStrikethrough:!0,color:{color:["color","#848484"],highlight:["color","#848484"],hover:["color","#848484"],inherit:["from","to","both",!0,!1],opacity:[1,0,1,.05]},dashes:!1,font:{color:["color","#343434"],size:[14,0,100,1],face:["arial","verdana","tahoma"],background:["color","none"],strokeWidth:[2,0,50,1],strokeColor:["color","#ffffff"],align:["horizontal","top","middle","bottom"]},hidden:!1,hoverWidth:[1.5,0,5,.1],labelHighlightBold:!0,physics:!0,scaling:{min:[1,0,100,1],max:[15,0,100,1],label:{enabled:!0,min:[14,0,200,1],max:[30,0,200,1],maxVisible:[30,0,200,1],drawThreshold:[5,0,20,1]}},selectionWidth:[1.5,0,5,.1],selfReferenceSize:[20,0,200,1],selfReference:{size:[20,0,200,1],angle:[Math.PI/2,-6*Math.PI,6*Math.PI,Math.PI/8],renderBehindTheNode:!0},shadow:{enabled:!1,color:"rgba(0,0,0,0.5)",size:[10,0,20,1],x:[5,-30,30,1],y:[5,-30,30,1]},smooth:{enabled:!0,type:["dynamic","continuous","discrete","diagonalCross","straightCross","horizontal","vertical","curvedCW","curvedCCW","cubicBezier"],forceDirection:["horizontal","vertical","none"],roundness:[.5,0,1,.05]},width:[1,0,30,1]},layout:{hierarchical:{enabled:!1,levelSeparation:[150,20,500,5],nodeSpacing:[100,20,500,5],treeSpacing:[200,20,500,5],blockShifting:!0,edgeMinimization:!0,parentCentralization:!0,direction:["UD","DU","LR","RL"],sortMethod:["hubsize","directed"],shakeTowards:["leaves","roots"]}},interaction:{dragNodes:!0,dragView:!0,hideEdgesOnDrag:!1,hideEdgesOnZoom:!1,hideNodesOnDrag:!1,hover:!1,keyboard:{enabled:!1,speed:{x:[10,0,40,1],y:[10,0,40,1],zoom:[.02,0,.1,.005]},bindToWindow:!0,autoFocus:!0},multiselect:!1,navigationButtons:!1,selectable:!0,selectConnectedEdges:!0,hoverConnectedEdges:!0,tooltipDelay:[300,0,1e3,25],zoomView:!0,zoomSpeed:[1,.1,2,.1]},manipulation:{enabled:!1,initiallyActive:!1},physics:{enabled:!0,barnesHut:{theta:[.5,.1,1,.05],gravitationalConstant:[-2e3,-3e4,0,50],centralGravity:[.3,0,10,.05],springLength:[95,0,500,5],springConstant:[.04,0,1.2,.005],damping:[.09,0,1,.01],avoidOverlap:[0,0,1,.01]},forceAtlas2Based:{theta:[.5,.1,1,.05],gravitationalConstant:[-50,-500,0,1],centralGravity:[.01,0,1,.005],springLength:[95,0,500,5],springConstant:[.08,0,1.2,.005],damping:[.4,0,1,.01],avoidOverlap:[0,0,1,.01]},repulsion:{centralGravity:[.2,0,10,.05],springLength:[200,0,500,5],springConstant:[.05,0,1.2,.005],nodeDistance:[100,0,500,5],damping:[.09,0,1,.01]},hierarchicalRepulsion:{centralGravity:[.2,0,10,.05],springLength:[100,0,500,5],springConstant:[.01,0,1.2,.005],nodeDistance:[120,0,500,5],damping:[.09,0,1,.01],avoidOverlap:[0,0,1,.01]},maxVelocity:[50,0,150,1],minVelocity:[.1,.01,.5,.01],solver:["barnesHut","forceAtlas2Based","repulsion","hierarchicalRepulsion"],timestep:[.5,.01,1,.01],wind:{x:[0,-10,10,.1],y:[0,-10,10,.1]}}},r6=function(t,e,i){var n;return!(!Hq(t).call(t,"physics")||!Hq(n=o6.physics.solver).call(n,e)||i.physics.solver===e||"wind"===e)},s6=function(){function t(){rj(this,t)}return cW(t,[{key:"getDistances",value:function(t,e,i){for(var n={},o=t.edges,r=0;r2&&void 0!==arguments[2]&&arguments[2],n=this.distanceSolver.getDistances(this.body,t,e);this._createL_matrix(n),this._createK_matrix(n),this._createE_matrix();for(var o=0,r=Math.max(1e3,Math.min(10*this.body.nodeIndices.length,6e3)),s=1e9,a=0,d=0,l=0,c=0,h=0;s>.01&&o1&&h<5;){h+=1,this._moveNode(a,d,l);var p=QW(this._getEnergy(a),3);c=p[0],d=p[1],l=p[2]}}}},{key:"_getHighestEnergyNode",value:function(t){for(var e=this.body.nodeIndices,i=this.body.nodes,n=0,o=e[0],r=0,s=0,a=0;a{class e extends t{connectedCallback(){super.connectedCallback(),this.__checkSubscribed()}disconnectedCallback(){if(super.disconnectedCallback(),this.__unsubs){for(;this.__unsubs.length;){const t=this.__unsubs.pop();t instanceof Promise?t.then((t=>t())):null!=t&&t()}this.__unsubs=void 0}}updated(t){super.updated(t),t.has("hass")&&this.__checkSubscribed()}hassSubscribe(){return[]}__checkSubscribed(){void 0===this.__unsubs&&this.isConnected&&void 0!==this.hass&&(this.__unsubs=this.hassSubscribe())}}return o([At({attribute:!1})],e.prototype,"hass",void 0),e};return console.info(`%c WISER-ZIGBEE-NETWORK-CARD \n%c ${Zt("common.version")} ${$t} `,"color: orange; font-weight: bold; background: black","color: white; font-weight: bold; background: dimgray"),window.customCards=window.customCards||[],window.customCards.push({type:"wiser-zigbee-card",name:"Wiser Zigbee Card",description:"A card to display Wiser Zigbee network between devices"}),t.WiserZigbeeCard=class extends(l6(Ot)){constructor(){super(...arguments),this.options=Ut,this.current_theme="",this.need_render=!1,this.is_initialised=!1,this.is_preview=!0}static async getConfigElement(){return document.createElement("wiser-zigbee-card-editor")}static getStubConfig(){return{}}setConfig(t){if(!t)throw new Error(Zt("common.invalid_configuration"));this.config=Object.assign({name:"Wiser Zigbee Network"},t),this.loadCardHelpers(),this.initialise()}async loadCardHelpers(){this._helpers=await window.loadCardHelpers()}async isComponentLoaded(){for(;!this.hass||!this.hass.config.components.includes("wiser");)await new Promise((t=>setTimeout(t,100)));return!0}async initialise(){var t;await this.isComponentLoaded()&&(null===(t=this.config)||void 0===t?void 0:t.layout_data)&&(this.layoutData=this.config.layout_data);const e=this._dialog_close.bind(this);return window.addEventListener("dialog-closed",e),this.loadData(),!0}hassSubscribe(){return[this.hass.connection.subscribeMessage((t=>this.handleUpdate(t)),{type:"wiser_updated"})]}_dialog_close(t){this.is_preview&&"hui-dialog-edit-card"==t.detail.dialog&&(this.is_preview=!1,this.need_render=!0)}async handleUpdate(t){"wiser_updated"==t.event&&this.config.auto_update&&!this.is_preview&&this.is_initialised&&await this.loadData()}async loadData(){const t=await(e=this.hass,i=this.config.hub,e.callWS({type:"wiser/zigbee",hub:i}));var e,i;this.layoutData?this.zigbeeData=await this.addLayout(t):this.zigbeeData=t,this.need_render=!0}async addLayout(t){for(let e=0;e{let t=document.querySelector("home-assistant");return t=t&&t.shadowRoot,t=t&&t.querySelector("hui-dialog-edit-card"),t=t&&t.shadowRoot,t=t&&t.querySelector("ha-dialog"),!!t})(),!this.hass||!this.config)return!1;if(1==this.need_render)return!0;if(this.is_preview&&this.is_initialised)return!1;if((null===(e=this.hass)||void 0===e?void 0:e.selectedTheme)&&this.current_theme!=(null===(i=this.hass)||void 0===i?void 0:i.selectedTheme)){this.current_theme=this.hass.selectedTheme;const t=getComputedStyle(document.documentElement).getPropertyValue("--primary-text-color");return this.options.edges.font.color=t,null===(n=this.network)||void 0===n||n.setOptions(this.options),!0}return function(t,e,i){if(e.has("config")||i)return!0;if(t.config.entity){var n=e.get("hass");return!n||n.states[t.config.entity]!==t.hass.states[t.config.entity]}return!1}(this,t,!1)}async _initialise_network(){var t;await this.loadData(),this.container=null===(t=this.shadowRoot)||void 0===t?void 0:t.getElementById("zigbee-network"),this.network=new d6(this.container,this.zigbeeData,this.options)}firstUpdated(){this._initialise_network(),this.is_initialised=!0}render(){var t;return this.need_render=!1,this.zigbeeData&&this.network&&(null===(t=this.network)||void 0===t||t.setData(this.zigbeeData)),$` - -
-
${this.config.name}
+function xG(){return xG=Object.assign||function(t){for(var e=1;e-1}var fK=function(){function t(t,e){this.manager=t,this.set(e)}var e=t.prototype;return e.set=function(t){t===jG&&(t=this.compute()),NG&&this.manager.element.style&&WG[t]&&(this.manager.element.style[TG]=t),this.actions=t.toLowerCase().trim()},e.update=function(){this.set(this.manager.options.touchAction)},e.compute=function(){var t=[];return cK(this.manager.recognizers,(function(e){dK(e.options.enable,[e])&&(t=t.concat(e.getTouchAction()))})),function(t){if(uK(t,QG))return QG;var e=uK(t,HG),i=uK(t,VG);return e&&i?QG:e||i?e?HG:VG:uK(t,LG)?LG:UG}(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=uK(o,QG)&&!WG[QG],r=uK(o,VG)&&!WG[VG],s=uK(o,HG)&&!WG[HG];if(n){var a=1===t.pointers.length,l=t.distance<2,h=t.deltaTime<250;if(a&&l&&h)return}if(!s||!r)return n||r&&i&rK||s&&i&sK?this.preventSrc(e):void 0}},e.preventSrc=function(t){this.manager.session.prevented=!0,t.preventDefault()},t}();function pK(t,e){for(;t;){if(t===e)return!0;t=t.parentNode}return!1}function vK(t){var e=t.length;if(1===e)return{x:BG(t[0].clientX),y:BG(t[0].clientY)};for(var i=0,o=0,n=0;n=zG(e)?t<0?eK:iK:e<0?oK:nK}function wK(t,e,i){return{x:e/t||0,y:i/t||0}}function AK(t,e){var i=t.session,o=e.pointers,n=o.length;i.firstInput||(i.firstInput=gK(e)),n>1&&!i.firstMultiple?i.firstMultiple=gK(e):1===n&&(i.firstMultiple=!1);var r=i.firstInput,s=i.firstMultiple,a=s?s.center:r.center,l=e.center=vK(o);e.timeStamp=PG(),e.deltaTime=e.timeStamp-r.timeStamp,e.angle=mK(a,l),e.distance=yK(a,l),function(t,e){var i=e.center,o=t.offsetDelta||{},n=t.prevDelta||{},r=t.prevInput||{};e.eventType!==XG&&r.eventType!==_G||(n=t.prevDelta={x:r.deltaX||0,y:r.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=bK(e.deltaX,e.deltaY);var h,c,d=wK(e.deltaTime,e.deltaX,e.deltaY);e.overallVelocityX=d.x,e.overallVelocityY=d.y,e.overallVelocity=zG(d.x)>zG(d.y)?d.x:d.y,e.scale=s?(h=s.pointers,yK((c=o)[0],c[1],hK)/yK(h[0],h[1],hK)):1,e.rotation=s?function(t,e){return mK(e[1],e[0],hK)+mK(t[1],t[0],hK)}(s.pointers,o):0,e.maxPointers=i.prevInput?e.pointers.length>i.prevInput.maxPointers?e.pointers.length:i.prevInput.maxPointers:e.pointers.length,function(t,e){var i,o,n,r,s=t.lastInterval||e,a=e.timeStamp-s.timeStamp;if(e.eventType!==$G&&(a>JG||void 0===s.velocity)){var l=e.deltaX-s.deltaX,h=e.deltaY-s.deltaY,c=wK(a,l,h);o=c.x,n=c.y,i=zG(c.x)>zG(c.y)?c.x:c.y,r=bK(l,h),t.lastInterval=e}else i=s.velocity,o=s.velocityX,n=s.velocityY,r=s.direction;e.velocity=i,e.velocityX=o,e.velocityY=n,e.direction=r}(i,e);var u,f=t.element,p=e.srcEvent;pK(u=p.composedPath?p.composedPath()[0]:p.path?p.path[0]:p.target,f)&&(f=u),e.target=f}function EK(t,e,i){var o=i.pointers.length,n=i.changedPointers.length,r=e&XG&&o-n==0,s=e&(_G|$G)&&o-n==0;i.isFirst=!!r,i.isFinal=!!s,r&&(t.session={}),i.eventType=e,AK(t,i),t.emit("hammer.input",i),t.recognize(i),t.session.prevInput=i}function kK(t){return t.trim().split(/\s+/g)}function CK(t,e,i){cK(kK(e),(function(e){t.addEventListener(e,i,!1)}))}function xK(t,e,i){cK(kK(e),(function(e){t.removeEventListener(e,i,!1)}))}function SK(t){var e=t.ownerDocument||t;return e.defaultView||e.parentWindow||window}var IK=function(){function t(t,e){var i=this;this.manager=t,this.callback=e,this.element=t.element,this.target=t.options.inputTarget,this.domHandler=function(e){dK(t.options.enable,[t])&&i.handler(e)},this.init()}var e=t.prototype;return e.handler=function(){},e.init=function(){this.evEl&&CK(this.element,this.evEl,this.domHandler),this.evTarget&&CK(this.target,this.evTarget,this.domHandler),this.evWin&&CK(SK(this.element),this.evWin,this.domHandler)},e.destroy=function(){this.evEl&&xK(this.element,this.evEl,this.domHandler),this.evTarget&&xK(this.target,this.evTarget,this.domHandler),this.evWin&&xK(SK(this.element),this.evWin,this.domHandler)},t}();function MK(t,e,i){if(t.indexOf&&!i)return t.indexOf(e);for(var o=0;oi[e]})):o.sort()),o}var TK={touchstart:XG,touchmove:2,touchend:_G,touchcancel:$G},NK=function(t){function e(){var i;return e.prototype.evTarget="touchstart touchmove touchend touchcancel",(i=t.apply(this,arguments)||this).targetIds={},i}return SG(e,t),e.prototype.handler=function(t){var e=TK[t.type],i=jK.call(this,t,e);i&&this.callback(this.manager,e,{pointers:i[0],changedPointers:i[1],pointerType:YG,srcEvent:t})},e}(IK);function jK(t,e){var i,o,n=PK(t.touches),r=this.targetIds;if(e&(2|XG)&&1===n.length)return r[n[0].identifier]=!0,[n,n];var s=PK(t.changedTouches),a=[],l=this.target;if(o=n.filter((function(t){return pK(t.target,l)})),e===XG)for(i=0;i-1&&o.splice(t,1)}),QK)}}function VK(t,e){t&XG?(this.primaryTouch=e.changedPointers[0].identifier,HK.call(this,e)):t&(_G|$G)&&HK.call(this,e)}function WK(t){for(var e=t.srcEvent.clientX,i=t.srcEvent.clientY,o=0;o-1&&this.requireFail.splice(e,1),this},e.hasRequireFailures=function(){return this.requireFail.length>0},e.canRecognizeWith=function(t){return!!this.simultaneous[t.id]},e.emit=function(t){var e=this,i=this.state;function o(i){e.manager.emit(i,t)}i<8&&o(e.options.event+JK(i)),o(e.options.event),t.additionalEvent&&o(t.additionalEvent),i>=8&&o(e.options.event+JK(i))},e.tryEmit=function(t){if(this.canEmit())return this.emit(t);this.state=qK},e.canEmit=function(){for(var t=0;te.threshold&&n&e.direction},i.attrTest=function(t){return $K.prototype.attrTest.call(this,t)&&(2&this.state||!(2&this.state)&&this.directionTest(t))},i.emit=function(e){this.pX=e.deltaX,this.pY=e.deltaY;var i=tq(e.direction);i&&(e.additionalEvent=this.options.event+i),t.prototype.emit.call(this,e)},e}($K),iq=function(t){function e(e){return void 0===e&&(e={}),t.call(this,xG({event:"swipe",threshold:10,velocity:.3,direction:rK|sK,pointers:1},e))||this}SG(e,t);var i=e.prototype;return i.getTouchAction=function(){return eq.prototype.getTouchAction.call(this)},i.attrTest=function(e){var i,o=this.options.direction;return o&(rK|sK)?i=e.overallVelocity:o&rK?i=e.overallVelocityX:o&sK&&(i=e.overallVelocityY),t.prototype.attrTest.call(this,e)&&o&e.offsetDirection&&e.distance>this.options.threshold&&e.maxPointers===this.options.pointers&&zG(i)>this.options.velocity&&e.eventType&_G},i.emit=function(t){var e=tq(t.offsetDirection);e&&this.manager.emit(this.options.event+e,t),this.manager.emit(this.options.event,t)},e}($K),oq=function(t){function e(e){return void 0===e&&(e={}),t.call(this,xG({event:"pinch",threshold:0,pointers:2},e))||this}SG(e,t);var i=e.prototype;return i.getTouchAction=function(){return[QG]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.scale-1)>this.options.threshold||2&this.state)},i.emit=function(e){if(1!==e.scale){var i=e.scale<1?"in":"out";e.additionalEvent=this.options.event+i}t.prototype.emit.call(this,e)},e}($K),nq=function(t){function e(e){return void 0===e&&(e={}),t.call(this,xG({event:"rotate",threshold:0,pointers:2},e))||this}SG(e,t);var i=e.prototype;return i.getTouchAction=function(){return[QG]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.rotation)>this.options.threshold||2&this.state)},e}($K),rq=function(t){function e(e){var i;return void 0===e&&(e={}),(i=t.call(this,xG({event:"press",pointers:1,time:251,threshold:9},e))||this)._timer=null,i._input=null,i}SG(e,t);var i=e.prototype;return i.getTouchAction=function(){return[UG]},i.process=function(t){var e=this,i=this.options,o=t.pointers.length===i.pointers,n=t.distancei.time;if(this._input=t,!n||!o||t.eventType&(_G|$G)&&!r)this.reset();else if(t.eventType&XG)this.reset(),this._timer=setTimeout((function(){e.state=8,e.tryEmit()}),i.time);else if(t.eventType&_G)return 8;return qK},i.reset=function(){clearTimeout(this._timer)},i.emit=function(t){8===this.state&&(t&&t.eventType&_G?this.manager.emit(this.options.event+"up",t):(this._input.timeStamp=PG(),this.manager.emit(this.options.event,this._input)))},e}(XK),sq={domEvents:!1,touchAction:jG,enable:!0,inputTarget:null,inputClass:null,cssProps:{userSelect:"none",touchSelect:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}},aq=[[nq,{enable:!1}],[oq,{enable:!1},["rotate"]],[iq,{direction:rK}],[eq,{direction:rK},["swipe"]],[_K],[_K,{event:"doubletap",taps:2},["tap"]],[rq]];function lq(t,e){var i,o=t.element;o.style&&(cK(t.options.cssProps,(function(n,r){i=FG(o.style,r),e?(t.oldCssProps[i]=o.style[i],o.style[i]=n):o.style[i]=t.oldCssProps[i]||""})),e||(t.oldCssProps={}))}var hq=function(){function t(t,e){var i,o=this;this.options=OG({},sq,e||{}),this.options.inputTarget=this.options.inputTarget||t,this.handlers={},this.session={},this.recognizers=[],this.oldCssProps={},this.element=t,this.input=new((i=this).options.inputClass||(KG?zK:qG?NK:GG?GK:LK))(i,EK),this.touchAction=new fK(this,this.options.touchAction),lq(this,!0),cK(this.options.recognizers,(function(t){var e=o.add(new t[0](t[1]));t[2]&&e.recognizeWith(t[2]),t[3]&&e.requireFailure(t[3])}),this)}var e=t.prototype;return e.set=function(t){return OG(this.options,t),t.touchAction&&this.touchAction.update(),t.inputTarget&&(this.input.destroy(),this.input.target=t.inputTarget,this.input.init()),this},e.stop=function(t){this.session.stopped=t?2:1},e.recognize=function(t){var e=this.session;if(!e.stopped){var i;this.touchAction.preventDefaults(t);var o=this.recognizers,n=e.curRecognizer;(!n||n&&8&n.state)&&(e.curRecognizer=null,n=null);for(var r=0;r\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",n=window.console&&(window.console.warn||window.console.log);return n&&n.call(window.console,o,i),t.apply(this,arguments)}}var pq=fq((function(t,e,i){for(var o=Object.keys(e),n=0;n=t.length?{done:!0}:{done:!1,value:t[o++]}},e:function(t){throw t},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function Aq(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,o=new Array(e);i>>0,t=(n*=t)>>>0,t+=4294967296*(n-=t)}return 2.3283064365386963e-10*(t>>>0)}}(),e=t(" "),i=t(" "),o=t(" "),n=0;n2&&void 0!==arguments[2]&&arguments[2];for(var o in t)if(void 0!==e[o])if(null===e[o]||"object"!==pQ(e[o]))Bq(t,e,o,i);else{var n=t[o],r=e[o];Rq(n)&&Rq(r)&&zq(n,r,i)}}function Pq(t,e,i){var o=arguments.length>3&&void 0!==arguments[3]&&arguments[3];if(EH(i))throw new TypeError("Arrays are not supported by deepExtend");for(var n=0;n3&&void 0!==arguments[3]&&arguments[3];if(EH(i))throw new TypeError("Arrays are not supported by deepExtend");for(var n in i)if(Object.prototype.hasOwnProperty.call(i,n)&&!ZV(t).call(t,n))if(i[n]&&i[n].constructor===Object)void 0===e[n]&&(e[n]={}),e[n].constructor===Object?Tq(e[n],i[n]):Bq(e,i,n,o);else if(EH(i[n])){e[n]=[];for(var r=0;r2&&void 0!==arguments[2]&&arguments[2],o=arguments.length>3&&void 0!==arguments[3]&&arguments[3];for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)||!0===i)if("object"===pQ(e[n])&&null!==e[n]&&tW(e[n])===Object.prototype)void 0===t[n]?t[n]=Tq({},e[n],i):"object"===pQ(t[n])&&null!==t[n]&&tW(t[n])===Object.prototype?Tq(t[n],e[n],i):Bq(t,e,n,o);else if(EH(e[n])){var r;t[n]=vH(r=e[n]).call(r)}else Bq(t,e,n,o);return t}function Nq(t,e){var i;return pH(i=[]).call(i,aH(t),[e])}function jq(t){return t.getBoundingClientRect().top}function Uq(t,e){if(EH(t))for(var i=t.length,o=0;o3&&void 0!==arguments[3]?arguments[3]:{},n=function(t){return null!=t},r=function(t){return null!==t&&"object"===pQ(t)};if(!r(t))throw new Error("Parameter mergeTarget must be an object");if(!r(e))throw new Error("Parameter options must be an object");if(!n(i))throw new Error("Parameter option must have a value");if(!r(o))throw new Error("Parameter globalOptions must be an object");var s=e[i],a=r(o)&&!function(t){for(var e in t)if(Object.prototype.hasOwnProperty.call(t,e))return!1;return!0}(o),l=a?o[i]:void 0,h=l?l.enabled:void 0;if(void 0!==s){if("boolean"==typeof s)return r(t[i])||(t[i]={}),void(t[i].enabled=s);if(null===s&&!r(t[i])){if(!n(l))return;t[i]=WW(l)}if(r(s)){var c=!0;void 0!==s.enabled?c=s.enabled:void 0!==h&&(c=l.enabled),function(t,e,i){r(t[i])||(t[i]={});var o=e[i],n=t[i];for(var s in o)Object.prototype.hasOwnProperty.call(o,s)&&(n[s]=o[s])}(t,e,i),t[i].enabled=c}}}var Xq={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return t*(2-t)},easeInOutQuad:function(t){return t<.5?2*t*t:(4-2*t)*t-1},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return--t*t*t+1},easeInOutCubic:function(t){return t<.5?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return 1- --t*t*t*t},easeInOutQuart:function(t){return t<.5?8*t*t*t*t:1-8*--t*t*t*t},easeInQuint:function(t){return t*t*t*t*t},easeOutQuint:function(t){return 1+--t*t*t*t*t},easeInOutQuint:function(t){return t<.5?16*t*t*t*t*t:1+16*--t*t*t*t*t}};function _q(t,e){var i;EH(e)||(e=[e]);var o,n=wq(t);try{for(n.s();!(o=n.n()).done;){var r=o.value;if(r){i=r[e[0]];for(var s=1;s0&&void 0!==arguments[0]?arguments[0]:1;fN(this,t),this.pixelRatio=e,this.generated=!1,this.centerCoordinates={x:144.5,y:144.5},this.r=289*.49,this.color={r:255,g:255,b:255,a:1},this.hueCircle=void 0,this.initialColor={r:255,g:255,b:255,a:1},this.previousColor=void 0,this.applied=!1,this.updateCallback=function(){},this.closeCallback=function(){},this._create()}return mQ(t,[{key:"insertTo",value:function(t){void 0!==this.hammer&&(this.hammer.destroy(),this.hammer=void 0),this.container=t,this.container.appendChild(this.frame),this._bindHammer(),this._setSize()}},{key:"setUpdateCallback",value:function(t){if("function"!=typeof t)throw new Error("Function attempted to set as colorPicker update callback is not a function.");this.updateCallback=t}},{key:"setCloseCallback",value:function(t){if("function"!=typeof t)throw new Error("Function attempted to set as colorPicker closing callback is not a function.");this.closeCallback=t}},{key:"_isColorString",value:function(t){if("string"==typeof t)return $q[t]}},{key:"setColor",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if("none"!==t){var i,o=this._isColorString(t);if(void 0!==o&&(t=o),!0===Dq(t)){if(!0===Yq(t)){var n=t.substr(4).substr(0,t.length-5).split(",");i={r:n[0],g:n[1],b:n[2],a:1}}else if(!0===function(t){return Mq.test(t)}(t)){var r=t.substr(5).substr(0,t.length-6).split(",");i={r:r[0],g:r[1],b:r[2],a:r[3]}}else if(!0===qq(t)){var s=Lq(t);i={r:s.r,g:s.g,b:s.b,a:1}}}else if(t instanceof Object&&void 0!==t.r&&void 0!==t.g&&void 0!==t.b){var a=void 0!==t.a?t.a:"1.0";i={r:t.r,g:t.g,b:t.b,a:a}}if(void 0===i)throw new Error("Unknown color passed to the colorPicker. Supported are strings: rgb, hex, rgba. Object: rgb ({r:r,g:g,b:b,[a:a]}). Supplied: "+YW(t));this._setColor(i,e)}}},{key:"show",value:function(){void 0!==this.closeCallback&&(this.closeCallback(),this.closeCallback=void 0),this.applied=!1,this.frame.style.display="block",this._generateHueCircle()}},{key:"_hide",value:function(){var t=this;!0===(!(arguments.length>0&&void 0!==arguments[0])||arguments[0])&&(this.previousColor=AB({},this.color)),!0===this.applied&&this.updateCallback(this.initialColor),this.frame.style.display="none",fG((function(){void 0!==t.closeCallback&&(t.closeCallback(),t.closeCallback=void 0)}),0)}},{key:"_save",value:function(){this.updateCallback(this.color),this.applied=!1,this._hide()}},{key:"_apply",value:function(){this.applied=!0,this.updateCallback(this.color),this._updatePicker(this.color)}},{key:"_loadLast",value:function(){void 0!==this.previousColor?this.setColor(this.previousColor,!1):alert("There is no last color to load...")}},{key:"_setColor",value:function(t){!0===(!(arguments.length>1&&void 0!==arguments[1])||arguments[1])&&(this.initialColor=AB({},t)),this.color=t;var e=Wq(t.r,t.g,t.b),i=2*Math.PI,o=this.r*e.s,n=this.centerCoordinates.x+o*Math.sin(i*e.h),r=this.centerCoordinates.y+o*Math.cos(i*e.h);this.colorPickerSelector.style.left=n-.5*this.colorPickerSelector.clientWidth+"px",this.colorPickerSelector.style.top=r-.5*this.colorPickerSelector.clientHeight+"px",this._updatePicker(t)}},{key:"_setOpacity",value:function(t){this.color.a=t/100,this._updatePicker(this.color)}},{key:"_setBrightness",value:function(t){var e=Wq(this.color.r,this.color.g,this.color.b);e.v=t/100;var i=Gq(e.h,e.s,e.v);i.a=this.color.a,this.color=i,this._updatePicker()}},{key:"_updatePicker",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.color,e=Wq(t.r,t.g,t.b),i=this.colorPickerCanvas.getContext("2d");void 0===this.pixelRation&&(this.pixelRatio=(window.devicePixelRatio||1)/(i.webkitBackingStorePixelRatio||i.mozBackingStorePixelRatio||i.msBackingStorePixelRatio||i.oBackingStorePixelRatio||i.backingStorePixelRatio||1)),i.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var o=this.colorPickerCanvas.clientWidth,n=this.colorPickerCanvas.clientHeight;i.clearRect(0,0,o,n),i.putImageData(this.hueCircle,0,0),i.fillStyle="rgba(0,0,0,"+(1-e.v)+")",i.circle(this.centerCoordinates.x,this.centerCoordinates.y,this.r),CG(i).call(i),this.brightnessRange.value=100*e.v,this.opacityRange.value=100*t.a,this.initialColorDiv.style.backgroundColor="rgba("+this.initialColor.r+","+this.initialColor.g+","+this.initialColor.b+","+this.initialColor.a+")",this.newColorDiv.style.backgroundColor="rgba("+this.color.r+","+this.color.g+","+this.color.b+","+this.color.a+")"}},{key:"_setSize",value:function(){this.colorPickerCanvas.style.width="100%",this.colorPickerCanvas.style.height="100%",this.colorPickerCanvas.width=289*this.pixelRatio,this.colorPickerCanvas.height=289*this.pixelRatio}},{key:"_create",value:function(){var t,e,i,o;if(this.frame=document.createElement("div"),this.frame.className="vis-color-picker",this.colorPickerDiv=document.createElement("div"),this.colorPickerSelector=document.createElement("div"),this.colorPickerSelector.className="vis-selector",this.colorPickerDiv.appendChild(this.colorPickerSelector),this.colorPickerCanvas=document.createElement("canvas"),this.colorPickerDiv.appendChild(this.colorPickerCanvas),this.colorPickerCanvas.getContext){var n=this.colorPickerCanvas.getContext("2d");this.pixelRatio=(window.devicePixelRatio||1)/(n.webkitBackingStorePixelRatio||n.mozBackingStorePixelRatio||n.msBackingStorePixelRatio||n.oBackingStorePixelRatio||n.backingStorePixelRatio||1),this.colorPickerCanvas.getContext("2d").setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0)}else{var r=document.createElement("DIV");r.style.color="red",r.style.fontWeight="bold",r.style.padding="10px",r.innerText="Error: your browser does not support HTML canvas",this.colorPickerCanvas.appendChild(r)}this.colorPickerDiv.className="vis-color",this.opacityDiv=document.createElement("div"),this.opacityDiv.className="vis-opacity",this.brightnessDiv=document.createElement("div"),this.brightnessDiv.className="vis-brightness",this.arrowDiv=document.createElement("div"),this.arrowDiv.className="vis-arrow",this.opacityRange=document.createElement("input");try{this.opacityRange.type="range",this.opacityRange.min="0",this.opacityRange.max="100"}catch(t){}this.opacityRange.value="100",this.opacityRange.className="vis-range",this.brightnessRange=document.createElement("input");try{this.brightnessRange.type="range",this.brightnessRange.min="0",this.brightnessRange.max="100"}catch(t){}this.brightnessRange.value="100",this.brightnessRange.className="vis-range",this.opacityDiv.appendChild(this.opacityRange),this.brightnessDiv.appendChild(this.brightnessRange);var s=this;this.opacityRange.onchange=function(){s._setOpacity(this.value)},this.opacityRange.oninput=function(){s._setOpacity(this.value)},this.brightnessRange.onchange=function(){s._setBrightness(this.value)},this.brightnessRange.oninput=function(){s._setBrightness(this.value)},this.brightnessLabel=document.createElement("div"),this.brightnessLabel.className="vis-label vis-brightness",this.brightnessLabel.innerText="brightness:",this.opacityLabel=document.createElement("div"),this.opacityLabel.className="vis-label vis-opacity",this.opacityLabel.innerText="opacity:",this.newColorDiv=document.createElement("div"),this.newColorDiv.className="vis-new-color",this.newColorDiv.innerText="new",this.initialColorDiv=document.createElement("div"),this.initialColorDiv.className="vis-initial-color",this.initialColorDiv.innerText="initial",this.cancelButton=document.createElement("div"),this.cancelButton.className="vis-button vis-cancel",this.cancelButton.innerText="cancel",this.cancelButton.onclick=VB(t=this._hide).call(t,this,!1),this.applyButton=document.createElement("div"),this.applyButton.className="vis-button vis-apply",this.applyButton.innerText="apply",this.applyButton.onclick=VB(e=this._apply).call(e,this),this.saveButton=document.createElement("div"),this.saveButton.className="vis-button vis-save",this.saveButton.innerText="save",this.saveButton.onclick=VB(i=this._save).call(i,this),this.loadButton=document.createElement("div"),this.loadButton.className="vis-button vis-load",this.loadButton.innerText="load last",this.loadButton.onclick=VB(o=this._loadLast).call(o,this),this.frame.appendChild(this.colorPickerDiv),this.frame.appendChild(this.arrowDiv),this.frame.appendChild(this.brightnessLabel),this.frame.appendChild(this.brightnessDiv),this.frame.appendChild(this.opacityLabel),this.frame.appendChild(this.opacityDiv),this.frame.appendChild(this.newColorDiv),this.frame.appendChild(this.initialColorDiv),this.frame.appendChild(this.cancelButton),this.frame.appendChild(this.applyButton),this.frame.appendChild(this.saveButton),this.frame.appendChild(this.loadButton)}},{key:"_bindHammer",value:function(){var t=this;this.drag={},this.pinch={},this.hammer=new kq(this.colorPickerCanvas),this.hammer.get("pinch").set({enable:!0}),this.hammer.on("hammer.input",(function(e){e.isFirst&&t._moveSelector(e)})),this.hammer.on("tap",(function(e){t._moveSelector(e)})),this.hammer.on("panstart",(function(e){t._moveSelector(e)})),this.hammer.on("panmove",(function(e){t._moveSelector(e)})),this.hammer.on("panend",(function(e){t._moveSelector(e)}))}},{key:"_generateHueCircle",value:function(){if(!1===this.generated){var t=this.colorPickerCanvas.getContext("2d");void 0===this.pixelRation&&(this.pixelRatio=(window.devicePixelRatio||1)/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1)),t.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var e,i,o,n,r=this.colorPickerCanvas.clientWidth,s=this.colorPickerCanvas.clientHeight;t.clearRect(0,0,r,s),this.centerCoordinates={x:.5*r,y:.5*s},this.r=.49*r;var a,l=2*Math.PI/360,h=1/360,c=1/this.r;for(o=0;o<360;o++)for(n=0;n3&&void 0!==arguments[3]?arguments[3]:1,r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:function(){return!1};fN(this,t),this.parent=e,this.changedOptions=[],this.container=i,this.allowCreation=!1,this.hideOption=r,this.options={},this.initialized=!1,this.popupCounter=0,this.defaultOptions={enabled:!1,filter:!0,container:void 0,showButton:!0},AB(this.options,this.defaultOptions),this.configureOptions=o,this.moduleOptions={},this.domElements=[],this.popupDiv={},this.popupLimit=5,this.popupHistory={},this.colorPicker=new tY(n),this.wrapper=void 0}return mQ(t,[{key:"setOptions",value:function(t){if(void 0!==t){this.popupHistory={},this._removePopup();var e=!0;if("string"==typeof t)this.options.filter=t;else if(EH(t))this.options.filter=t.join();else if("object"===pQ(t)){if(null==t)throw new TypeError("options cannot be null");void 0!==t.container&&(this.options.container=t.container),void 0!==aW(t)&&(this.options.filter=aW(t)),void 0!==t.showButton&&(this.options.showButton=t.showButton),void 0!==t.enabled&&(e=t.enabled)}else"boolean"==typeof t?(this.options.filter=!0,e=t):"function"==typeof t&&(this.options.filter=t,e=!0);!1===aW(this.options)&&(e=!1),this.options.enabled=e}this._clean()}},{key:"setModuleOptions",value:function(t){this.moduleOptions=t,!0===this.options.enabled&&(this._clean(),void 0!==this.options.container&&(this.container=this.options.container),this._create())}},{key:"_create",value:function(){this._clean(),this.changedOptions=[];var t=aW(this.options),e=0,i=!1;for(var o in this.configureOptions)Object.prototype.hasOwnProperty.call(this.configureOptions,o)&&(this.allowCreation=!1,i=!1,"function"==typeof t?i=(i=t(o,[]))||this._handleObject(this.configureOptions[o],[o],!0):!0!==t&&-1===LW(t).call(t,o)||(i=!0),!1!==i&&(this.allowCreation=!0,e>0&&this._makeItem([]),this._makeHeader(o),this._handleObject(this.configureOptions[o],[o])),e++);this._makeButton(),this._push()}},{key:"_push",value:function(){this.wrapper=document.createElement("div"),this.wrapper.className="vis-configuration-wrapper",this.container.appendChild(this.wrapper);for(var t=0;t1?i-1:0),n=1;n2&&void 0!==arguments[2]&&arguments[2],o=document.createElement("div");if(o.className="vis-configuration vis-config-label vis-config-s"+e.length,!0===i){for(;o.firstChild;)o.removeChild(o.firstChild);o.appendChild(eY("i","b",t))}else o.innerText=t+":";return o}},{key:"_makeDropdown",value:function(t,e,i){var o=document.createElement("select");o.className="vis-configuration vis-config-select";var n=0;void 0!==e&&-1!==LW(t).call(t,e)&&(n=LW(t).call(t,e));for(var r=0;rr&&1!==r&&(a.max=Math.ceil(e*c),h=a.max,l="range increased"),a.value=e}else a.value=o;var d=document.createElement("input");d.className="vis-configuration vis-config-rangeinput",d.value=a.value;var u=this;a.onchange=function(){d.value=this.value,u._update(Number(this.value),i)},a.oninput=function(){d.value=this.value};var f=this._makeLabel(i[i.length-1],i),p=this._makeItem(i,f,a,d);""!==l&&this.popupHistory[p]!==h&&(this.popupHistory[p]=h,this._setupPopup(l,p))}},{key:"_makeButton",value:function(){var t=this;if(!0===this.options.showButton){var e=document.createElement("div");e.className="vis-configuration vis-config-button",e.innerText="generate options",e.onclick=function(){t._printOptions()},e.onmouseover=function(){e.className="vis-configuration vis-config-button hover"},e.onmouseout=function(){e.className="vis-configuration vis-config-button"},this.optionsContainer=document.createElement("div"),this.optionsContainer.className="vis-configuration vis-config-option-container",this.domElements.push(this.optionsContainer),this.domElements.push(e)}}},{key:"_setupPopup",value:function(t,e){var i=this;if(!0===this.initialized&&!0===this.allowCreation&&this.popupCounter1&&void 0!==arguments[1]?arguments[1]:[],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],o=!1,n=aW(this.options),r=!1;for(var s in t)if(Object.prototype.hasOwnProperty.call(t,s)){o=!0;var a=t[s],l=Nq(e,s);if("function"==typeof n&&!1===(o=n(s,e))&&!EH(a)&&"string"!=typeof a&&"boolean"!=typeof a&&a instanceof Object&&(this.allowCreation=!1,o=this._handleObject(a,l,!0),this.allowCreation=!1===i),!1!==o){r=!0;var h=this._getValue(l);if(EH(a))this._handleArray(a,h,l);else if("string"==typeof a)this._makeTextInput(a,h,l);else if("boolean"==typeof a)this._makeCheckbox(a,h,l);else if(a instanceof Object){if(!this.hideOption(e,s,this.moduleOptions))if(void 0!==a.enabled){var c=Nq(l,"enabled"),d=this._getValue(c);if(!0===d){var u=this._makeLabel(s,l,!0);this._makeItem(l,u),r=this._handleObject(a,l)||r}else this._makeCheckbox(a,d,l)}else{var f=this._makeLabel(s,l,!0);this._makeItem(l,f),r=this._handleObject(a,l)||r}}else console.error("dont know how to handle",a,s,l)}}return r}},{key:"_handleArray",value:function(t,e,i){"string"==typeof t[0]&&"color"===t[0]?(this._makeColorField(t,e,i),t[1]!==e&&this.changedOptions.push({path:i,value:e})):"string"==typeof t[0]?(this._makeDropdown(t,e,i),t[0]!==e&&this.changedOptions.push({path:i,value:e})):"number"==typeof t[0]&&(this._makeRange(t,e,i),t[0]!==e&&this.changedOptions.push({path:i,value:Number(e)}))}},{key:"_update",value:function(t,e){var i=this._constructOptions(t,e);this.parent.body&&this.parent.body.emitter&&this.parent.body.emitter.emit&&this.parent.body.emitter.emit("configChange",i),this.initialized=!0,this.parent.setOptions(i)}},{key:"_constructOptions",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},o=i;t="false"!==(t="true"===t||t)&&t;for(var n=0;nn-this.padding&&(a=!0),r=a?this.x-i:this.x,s=l?this.y-e:this.y}else(s=this.y-e)+e+this.padding>o&&(s=o-e-this.padding),sn&&(r=n-i-this.padding),rs.distance?" in "+t.printLocation(r.path,e,"")+"Perhaps it was misplaced? Matching option found at: "+t.printLocation(s.path,s.closestMatch,""):r.distance<=8?'. Did you mean "'+r.closestMatch+'"?'+t.printLocation(r.path,e):". Did you mean one of these: "+t.print(BH(i))+t.printLocation(o,e),console.error('%cUnknown option detected: "'+e+'"'+n,sY),rY=!0}},{key:"findInOptions",value:function(e,i,o){var n,r=arguments.length>3&&void 0!==arguments[3]&&arguments[3],s=1e9,a="",l=[],h=e.toLowerCase(),c=void 0;for(var d in i){var u=void 0;if(void 0!==i[d].__type__&&!0===r){var f=t.findInOptions(e,i[d],Nq(o,d));s>f.distance&&(a=f.closestMatch,l=f.path,s=f.distance,c=f.indexMatch)}else{var p;-1!==LW(p=d.toLowerCase()).call(p,h)&&(c=d),s>(u=t.levenshteinDistance(e,d))&&(a=d,l=vH(n=o).call(n),s=u)}}return{closestMatch:a,path:l,distance:s,indexMatch:c}}},{key:"printLocation",value:function(t,e){for(var i="\n\n"+(arguments.length>2&&void 0!==arguments[2]?arguments[2]:"Problem value found at: \n")+"options = {\n",o=0;o":!0,"--":!0},bY="",wY=0,AY="",EY="",kY=yY.NULL;function CY(){wY++,AY=bY.charAt(wY)}function xY(){return bY.charAt(wY+1)}function SY(t){var e=t.charCodeAt(0);return e<47?35===e||46===e:e<59?e>47:e<91?e>64:e<96?95===e:e<123&&e>96}function IY(t,e){if(t||(t={}),e)for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function MY(t,e,i){for(var o=e.split("."),n=t;o.length;){var r=o.shift();o.length?(n[r]||(n[r]={}),n=n[r]):n[r]=i}}function OY(t,e){for(var i,o,n=null,r=[t],s=t;s.parent;)r.push(s.parent),s=s.parent;if(s.nodes)for(i=0,o=s.nodes.length;i=0;i--){var a,l=r[i];l.nodes||(l.nodes=[]),-1===LW(a=l.nodes).call(a,n)&&l.nodes.push(n)}e.attr&&(n.attr=IY(n.attr,e.attr))}function DY(t,e){if(t.edges||(t.edges=[]),t.edges.push(e),t.edge){var i=IY({},t.edge);e.attr=IY(i,e.attr)}}function RY(t,e,i,o,n){var r={from:e,to:i,type:o};return t.edge&&(r.attr=IY({},t.edge)),r.attr=IY(r.attr||{},n),null!=n&&n.hasOwnProperty("arrows")&&null!=n.arrows&&(r.arrows={to:{enabled:!0,type:n.arrows.type}},n.arrows=null),r}function BY(){for(kY=yY.NULL,EY="";" "===AY||"\t"===AY||"\n"===AY||"\r"===AY;)CY();do{var t=!1;if("#"===AY){for(var e=wY-1;" "===bY.charAt(e)||"\t"===bY.charAt(e);)e--;if("\n"===bY.charAt(e)||""===bY.charAt(e)){for(;""!=AY&&"\n"!=AY;)CY();t=!0}}if("/"===AY&&"/"===xY()){for(;""!=AY&&"\n"!=AY;)CY();t=!0}if("/"===AY&&"*"===xY()){for(;""!=AY;){if("*"===AY&&"/"===xY()){CY(),CY();break}CY()}t=!0}for(;" "===AY||"\t"===AY||"\n"===AY||"\r"===AY;)CY()}while(t);if(""!==AY){var i=AY+xY();if(mY[i])return kY=yY.DELIMITER,EY=i,CY(),void CY();if(mY[AY])return kY=yY.DELIMITER,EY=AY,void CY();if(SY(AY)||"-"===AY){for(EY+=AY,CY();SY(AY);)EY+=AY,CY();return"false"===EY?EY=!1:"true"===EY?EY=!0:isNaN(Number(EY))||(EY=Number(EY)),void(kY=yY.IDENTIFIER)}if('"'===AY){for(CY();""!=AY&&('"'!=AY||'"'===AY&&'"'===xY());)'"'===AY?(EY+=AY,CY()):"\\"===AY&&"n"===xY()?(EY+="\n",CY()):EY+=AY,CY();if('"'!=AY)throw jY('End of string " expected');return CY(),void(kY=yY.IDENTIFIER)}for(kY=yY.UNKNOWN;""!=AY;)EY+=AY,CY();throw new SyntaxError('Syntax error in part "'+UY(EY,30)+'"')}kY=yY.DELIMITER}function zY(t){for(;""!==EY&&"}"!=EY;)PY(t),";"===EY&&BY()}function PY(t){var e=FY(t);if(e)TY(t,e);else{var i=function(t){if("node"===EY)return BY(),t.node=NY(),"node";if("edge"===EY)return BY(),t.edge=NY(),"edge";if("graph"===EY)return BY(),t.graph=NY(),"graph";return null}(t);if(!i){if(kY!=yY.IDENTIFIER)throw jY("Identifier expected");var o=EY;if(BY(),"="===EY){if(BY(),kY!=yY.IDENTIFIER)throw jY("Identifier expected");t[o]=EY,BY()}else!function(t,e){var i={id:e},o=NY();o&&(i.attr=o);OY(t,i),TY(t,e)}(t,o)}}}function FY(t){var e=null;if("subgraph"===EY&&((e={}).type="subgraph",BY(),kY===yY.IDENTIFIER&&(e.id=EY,BY())),"{"===EY){if(BY(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,zY(e),"}"!=EY)throw jY("Angle bracket } expected");BY(),delete e.node,delete e.edge,delete e.graph,delete e.parent,t.subgraphs||(t.subgraphs=[]),t.subgraphs.push(e)}return e}function TY(t,e){for(;"->"===EY||"--"===EY;){var i,o=EY;BY();var n=FY(t);if(n)i=n;else{if(kY!=yY.IDENTIFIER)throw jY("Identifier or subgraph expected");OY(t,{id:i=EY}),BY()}DY(t,RY(t,e,i,o,NY())),e=i}}function NY(){for(var t,e,i=null,o={dashed:!0,solid:!1,dotted:[1,5]},n={dot:"circle",box:"box",crow:"crow",curve:"curve",icurve:"inv_curve",normal:"triangle",inv:"inv_triangle",diamond:"diamond",tee:"bar",vee:"vee"},r=new Array,s=new Array;"["===EY;){for(BY(),i={};""!==EY&&"]"!=EY;){if(kY!=yY.IDENTIFIER)throw jY("Attribute name expected");var a=EY;if(BY(),"="!=EY)throw jY("Equal sign = expected");if(BY(),kY!=yY.IDENTIFIER)throw jY("Attribute value expected");var l=EY;"style"===a&&(l=o[l]),"arrowhead"===a&&(a="arrows",l={to:{enabled:!0,type:n[l]}}),"arrowtail"===a&&(a="arrows",l={from:{enabled:!0,type:n[l]}}),r.push({attr:i,name:a,value:l}),s.push(a),BY(),","==EY&&BY()}if("]"!=EY)throw jY("Bracket ] expected");BY()}if(ZV(s).call(s,"dir")){var h={arrows:{}};for(t=0;t"===t.type&&(e.arrows="to"),e};ZH(n=i.edges).call(n,(function(t){var e,i,n,s,a,l,h;(e=t.from instanceof Object?t.from.nodes:{id:t.from},i=t.to instanceof Object?t.to.nodes:{id:t.to},t.from instanceof Object&&t.from.edges)&&ZH(n=t.from.edges).call(n,(function(t){var e=r(t);o.edges.push(e)}));(a=i,l=function(e,i){var n=RY(o,e.id,i.id,t.type,t.attr),s=r(n);o.edges.push(s)},EH(s=e)?ZH(s).call(s,(function(t){EH(a)?ZH(a).call(a,(function(e){l(t,e)})):l(t,a)})):EH(a)?ZH(a).call(a,(function(t){l(s,t)})):l(s,a),t.to instanceof Object&&t.to.edges)&&ZH(h=t.to.edges).call(h,(function(t){var e=r(t);o.edges.push(e)}))}))}return i.attr&&(o.options=i.attr),o}var VY=Object.freeze({__proto__:null,cn:{addDescription:"单击空白处放置新节点。",addEdge:"添加连接线",addNode:"添加节点",back:"返回",close:"關閉",createEdgeError:"无法将连接线连接到群集。",del:"删除选定",deleteClusterError:"无法删除群集。",edgeDescription:"单击某个节点并将该连接线拖动到另一个节点以连接它们。",edit:"编辑",editClusterError:"无法编辑群集。",editEdge:"编辑连接线",editEdgeDescription:"单击控制节点并将它们拖到节点上连接。",editNode:"编辑节点"},cs:{addDescription:"Kluknutím do prázdného prostoru můžete přidat nový vrchol.",addEdge:"Přidat hranu",addNode:"Přidat vrchol",back:"Zpět",close:"Zavřít",createEdgeError:"Nelze připojit hranu ke shluku.",del:"Smazat výběr",deleteClusterError:"Nelze mazat shluky.",edgeDescription:"Přetažením z jednoho vrcholu do druhého můžete spojit tyto vrcholy novou hranou.",edit:"Upravit",editClusterError:"Nelze upravovat shluky.",editEdge:"Upravit hranu",editEdgeDescription:"Přetažením kontrolního vrcholu hrany ji můžete připojit k jinému vrcholu.",editNode:"Upravit vrchol"},de:{addDescription:"Klicke auf eine freie Stelle, um einen neuen Knoten zu plazieren.",addEdge:"Kante hinzufügen",addNode:"Knoten hinzufügen",back:"Zurück",close:"Schließen",createEdgeError:"Es ist nicht möglich, Kanten mit Clustern zu verbinden.",del:"Lösche Auswahl",deleteClusterError:"Cluster können nicht gelöscht werden.",edgeDescription:"Klicke auf einen Knoten und ziehe die Kante zu einem anderen Knoten, um diese zu verbinden.",edit:"Editieren",editClusterError:"Cluster können nicht editiert werden.",editEdge:"Kante editieren",editEdgeDescription:"Klicke auf die Verbindungspunkte und ziehe diese auf einen Knoten, um sie zu verbinden.",editNode:"Knoten editieren"},en:{addDescription:"Click in an empty space to place a new node.",addEdge:"Add Edge",addNode:"Add Node",back:"Back",close:"Close",createEdgeError:"Cannot link edges to a cluster.",del:"Delete selected",deleteClusterError:"Clusters cannot be deleted.",edgeDescription:"Click on a node and drag the edge to another node to connect them.",edit:"Edit",editClusterError:"Clusters cannot be edited.",editEdge:"Edit Edge",editEdgeDescription:"Click on the control points and drag them to a node to connect to it.",editNode:"Edit Node"},es:{addDescription:"Haga clic en un lugar vacío para colocar un nuevo nodo.",addEdge:"Añadir arista",addNode:"Añadir nodo",back:"Atrás",close:"Cerrar",createEdgeError:"No se puede conectar una arista a un grupo.",del:"Eliminar selección",deleteClusterError:"No es posible eliminar grupos.",edgeDescription:"Haga clic en un nodo y arrastre la arista hacia otro nodo para conectarlos.",edit:"Editar",editClusterError:"No es posible editar grupos.",editEdge:"Editar arista",editEdgeDescription:"Haga clic en un punto de control y arrastrelo a un nodo para conectarlo.",editNode:"Editar nodo"},fr:{addDescription:"Cliquez dans un endroit vide pour placer un nœud.",addEdge:"Ajouter un lien",addNode:"Ajouter un nœud",back:"Retour",close:"Fermer",createEdgeError:"Impossible de créer un lien vers un cluster.",del:"Effacer la sélection",deleteClusterError:"Les clusters ne peuvent pas être effacés.",edgeDescription:"Cliquez sur un nœud et glissez le lien vers un autre nœud pour les connecter.",edit:"Éditer",editClusterError:"Les clusters ne peuvent pas être édités.",editEdge:"Éditer le lien",editEdgeDescription:"Cliquez sur les points de contrôle et glissez-les pour connecter un nœud.",editNode:"Éditer le nœud"},it:{addDescription:"Clicca per aggiungere un nuovo nodo",addEdge:"Aggiungi un vertice",addNode:"Aggiungi un nodo",back:"Indietro",close:"Chiudere",createEdgeError:"Non si possono collegare vertici ad un cluster",del:"Cancella la selezione",deleteClusterError:"I cluster non possono essere cancellati",edgeDescription:"Clicca su un nodo e trascinalo ad un altro nodo per connetterli.",edit:"Modifica",editClusterError:"I clusters non possono essere modificati.",editEdge:"Modifica il vertice",editEdgeDescription:"Clicca sui Punti di controllo e trascinali ad un nodo per connetterli.",editNode:"Modifica il nodo"},nl:{addDescription:"Klik op een leeg gebied om een nieuwe node te maken.",addEdge:"Link toevoegen",addNode:"Node toevoegen",back:"Terug",close:"Sluiten",createEdgeError:"Kan geen link maken naar een cluster.",del:"Selectie verwijderen",deleteClusterError:"Clusters kunnen niet worden verwijderd.",edgeDescription:"Klik op een node en sleep de link naar een andere node om ze te verbinden.",edit:"Wijzigen",editClusterError:"Clusters kunnen niet worden aangepast.",editEdge:"Link wijzigen",editEdgeDescription:"Klik op de verbindingspunten en sleep ze naar een node om daarmee te verbinden.",editNode:"Node wijzigen"},pt:{addDescription:"Clique em um espaço em branco para adicionar um novo nó",addEdge:"Adicionar aresta",addNode:"Adicionar nó",back:"Voltar",close:"Fechar",createEdgeError:"Não foi possível linkar arestas a um cluster.",del:"Remover selecionado",deleteClusterError:"Clusters não puderam ser removidos.",edgeDescription:"Clique em um nó e arraste a aresta até outro nó para conectá-los",edit:"Editar",editClusterError:"Clusters não puderam ser editados.",editEdge:"Editar aresta",editEdgeDescription:"Clique nos pontos de controle e os arraste para um nó para conectá-los",editNode:"Editar nó"},ru:{addDescription:"Кликните в свободное место, чтобы добавить новый узел.",addEdge:"Добавить ребро",addNode:"Добавить узел",back:"Назад",close:"Закрывать",createEdgeError:"Невозможно соединить ребра в кластер.",del:"Удалить выбранное",deleteClusterError:"Кластеры не могут быть удалены",edgeDescription:"Кликните на узел и протяните ребро к другому узлу, чтобы соединить их.",edit:"Редактировать",editClusterError:"Кластеры недоступны для редактирования.",editEdge:"Редактировать ребро",editEdgeDescription:"Кликните на контрольные точки и перетащите их в узел, чтобы подключиться к нему.",editNode:"Редактировать узел"},uk:{addDescription:"Kлікніть на вільне місце, щоб додати новий вузол.",addEdge:"Додати край",addNode:"Додати вузол",back:"Назад",close:"Закрити",createEdgeError:"Не можливо об'єднати краї в групу.",del:"Видалити обране",deleteClusterError:"Групи не можуть бути видалені.",edgeDescription:"Клікніть на вузол і перетягніть край до іншого вузла, щоб їх з'єднати.",edit:"Редагувати",editClusterError:"Групи недоступні для редагування.",editEdge:"Редагувати край",editEdgeDescription:"Клікніть на контрольні точки і перетягніть їх у вузол, щоб підключитися до нього.",editNode:"Редагувати вузол"}});var WY=function(){function t(){fN(this,t),this.NUM_ITERATIONS=4,this.image=new Image,this.canvas=document.createElement("canvas")}return mQ(t,[{key:"init",value:function(){if(!this.initialized()){this.src=this.image.src;var t=this.image.width,e=this.image.height;this.width=t,this.height=e;var i=Math.floor(e/2),o=Math.floor(e/4),n=Math.floor(e/8),r=Math.floor(e/16),s=Math.floor(t/2),a=Math.floor(t/4),l=Math.floor(t/8),h=Math.floor(t/16);this.canvas.width=3*a,this.canvas.height=i,this.coordinates=[[0,0,s,i],[s,0,a,o],[s,o,l,n],[5*l,o,h,r]],this._fillMipMap()}}},{key:"initialized",value:function(){return void 0!==this.coordinates}},{key:"_fillMipMap",value:function(){var t=this.canvas.getContext("2d"),e=this.coordinates[0];t.drawImage(this.image,e[0],e[1],e[2],e[3]);for(var i=1;i2){e*=.5;for(var s=0;e>2&&s=this.NUM_ITERATIONS&&(s=this.NUM_ITERATIONS-1);var a=this.coordinates[s];t.drawImage(this.canvas,a[0],a[1],a[2],a[3],i,o,n,r)}else t.drawImage(this.image,i,o,n,r)}}]),t}(),GY=function(){function t(e){fN(this,t),this.images={},this.imageBroken={},this.callback=e}return mQ(t,[{key:"_tryloadBrokenUrl",value:function(t,e,i){void 0!==t&&void 0!==i&&(void 0!==e?(i.image.onerror=function(){console.error("Could not load brokenImage:",e)},i.image.src=e):console.warn("No broken url image defined"))}},{key:"_redrawWithImage",value:function(t){this.callback&&this.callback(t)}},{key:"load",value:function(t,e){var i=this,o=this.images[t];if(o)return o;var n=new WY;return this.images[t]=n,n.image.onload=function(){i._fixImageCoordinates(n.image),n.init(),i._redrawWithImage(n)},n.image.onerror=function(){console.error("Could not load image:",t),i._tryloadBrokenUrl(t,e,n)},n.image.src=t,n}},{key:"_fixImageCoordinates",value:function(t){0===t.width&&(document.body.appendChild(t),t.width=t.offsetWidth,t.height=t.offsetHeight,document.body.removeChild(t))}}]),t}(),KY={exports:{}},qY=aM((function(){if("function"==typeof ArrayBuffer){var t=new ArrayBuffer(8);Object.isExtensible(t)&&Object.defineProperty(t,"a",{value:8})}})),YY=aM,ZY=iO,JY=EM,XY=qY,_Y=Object.isExtensible,$Y=YY((function(){_Y(1)}))||XY?function(t){return!!ZY(t)&&((!XY||"ArrayBuffer"!==JY(t))&&(!_Y||_Y(t)))}:_Y,tZ=!aM((function(){return Object.isExtensible(Object.preventExtensions({}))})),eZ=DR,iZ=mM,oZ=ZR,nZ=iO,rZ=tD,sZ=$D.f,aZ=XN,lZ=tj,hZ=$Y,cZ=tZ,dZ=!1,uZ=rD("meta"),fZ=0,pZ=function(t){sZ(t,uZ,{value:{objectID:"O"+fZ++,weakData:{}}})},vZ=KY.exports={enable:function(){vZ.enable=function(){},dZ=!0;var t=aZ.f,e=iZ([].splice),i={};i[uZ]=1,t(i).length&&(aZ.f=function(i){for(var o=t(i),n=0,r=o.length;nr;r++)if((a=y(t[r]))&&kZ(OZ,a))return a;return new MZ(!1)}o=CZ(t,n)}for(l=u?t.next:o.next;!(h=mZ(l,o)).done;){try{a=y(h.value)}catch(t){SZ(o,"throw",t)}if("object"==typeof a&&a&&kZ(OZ,a))return a}return new MZ(!1)},RZ=hO,BZ=TypeError,zZ=function(t,e){if(RZ(e,t))return t;throw new BZ("Incorrect invocation")},PZ=DR,FZ=sM,TZ=gZ,NZ=aM,jZ=mR,UZ=DZ,LZ=zZ,QZ=OM,HZ=iO,VZ=qM,WZ=ZP,GZ=$D.f,KZ=zj.forEach,qZ=RM,YZ=Qz.set,ZZ=Qz.getterFor,JZ=function(t,e,i){var o,n=-1!==t.indexOf("Map"),r=-1!==t.indexOf("Weak"),s=n?"set":"add",a=FZ[t],l=a&&a.prototype,h={};if(qZ&&QZ(a)&&(r||l.forEach&&!NZ((function(){(new a).entries().next()})))){var c=(o=e((function(e,i){YZ(LZ(e,c),{type:t,collection:new a}),VZ(i)||UZ(i,e[s],{that:e,AS_ENTRIES:n})}))).prototype,d=ZZ(t);KZ(["add","clear","delete","forEach","get","has","set","keys","values","entries"],(function(t){var e="add"===t||"set"===t;!(t in l)||r&&"clear"===t||jZ(c,t,(function(i,o){var n=d(this).collection;if(!e&&r&&!HZ(i))return"get"===t&&void 0;var s=n[t](0===i?0:i,o);return e?this:s}))})),r||GZ(c,"size",{configurable:!0,get:function(){return d(this).collection.size}})}else o=i.getConstructor(e,t,n,s),TZ.enable();return WZ(o,t,!1,!0),h[t]=o,PZ({global:!0,forced:!0},h),r||i.setStrong(o,t,n),o},XZ=DP,_Z=function(t,e,i){for(var o in e)i&&i.unsafe&&t[o]?t[o]=e[o]:XZ(t,o,e[o],i);return t},$Z=lO,tJ=fj,eJ=RM,iJ=pD("species"),oJ=bP,nJ=fj,rJ=_Z,sJ=_D,aJ=zZ,lJ=qM,hJ=DZ,cJ=SF,dJ=IF,uJ=function(t){var e=$Z(t);eJ&&e&&!e[iJ]&&tJ(e,iJ,{configurable:!0,get:function(){return this}})},fJ=RM,pJ=gZ.fastKey,vJ=Qz.set,gJ=Qz.getterFor,yJ={getConstructor:function(t,e,i,o){var n=t((function(t,n){aJ(t,r),vJ(t,{type:e,index:oJ(null),first:void 0,last:void 0,size:0}),fJ||(t.size=0),lJ(n)||hJ(n,t[o],{that:t,AS_ENTRIES:i})})),r=n.prototype,s=gJ(e),a=function(t,e,i){var o,n,r=s(t),a=l(t,e);return a?a.value=i:(r.last=a={index:n=pJ(e,!0),key:e,value:i,previous:o=r.last,next:void 0,removed:!1},r.first||(r.first=a),o&&(o.next=a),fJ?r.size++:t.size++,"F"!==n&&(r.index[n]=a)),t},l=function(t,e){var i,o=s(t),n=pJ(e);if("F"!==n)return o.index[n];for(i=o.first;i;i=i.next)if(i.key===e)return i};return rJ(r,{clear:function(){for(var t=s(this),e=t.index,i=t.first;i;)i.removed=!0,i.previous&&(i.previous=i.previous.next=void 0),delete e[i.index],i=i.next;t.first=t.last=void 0,fJ?t.size=0:this.size=0},delete:function(t){var e=this,i=s(e),o=l(e,t);if(o){var n=o.next,r=o.previous;delete i.index[o.index],o.removed=!0,r&&(r.next=n),n&&(n.previous=r),i.first===o&&(i.first=n),i.last===o&&(i.last=r),fJ?i.size--:e.size--}return!!o},forEach:function(t){for(var e,i=s(this),o=sJ(t,arguments.length>1?arguments[1]:void 0);e=e?e.next:i.first;)for(o(e.value,e.key,this);e&&e.removed;)e=e.previous},has:function(t){return!!l(this,t)}}),rJ(r,i?{get:function(t){var e=l(this,t);return e&&e.value},set:function(t,e){return a(this,0===t?0:t,e)}}:{add:function(t){return a(this,t=0===t?0:t,t)}}),fJ&&nJ(r,"size",{configurable:!0,get:function(){return s(this).size}}),n},setStrong:function(t,e,i){var o=e+" Iterator",n=gJ(e),r=gJ(o);cJ(t,e,(function(t,e){vJ(this,{type:o,target:t,state:n(t),kind:e,last:void 0})}),(function(){for(var t=r(this),e=t.kind,i=t.last;i&&i.removed;)i=i.previous;return t.target&&(t.last=i=i?i.next:t.state.first)?dJ("keys"===e?i.key:"values"===e?i.value:[i.key,i.value],!1):(t.target=void 0,dJ(void 0,!0))}),i?"entries":"values",!i,!0),uJ(e)}};JZ("Map",(function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}}),yJ);var mJ=nM(oO.Map),bJ=function(){function t(){fN(this,t),this.clear(),this._defaultIndex=0,this._groupIndex=0,this._defaultGroups=[{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"},hover:{border:"#2B7CE9",background:"#D2E5FF"}},{border:"#FFA500",background:"#FFFF00",highlight:{border:"#FFA500",background:"#FFFFA3"},hover:{border:"#FFA500",background:"#FFFFA3"}},{border:"#FA0A10",background:"#FB7E81",highlight:{border:"#FA0A10",background:"#FFAFB1"},hover:{border:"#FA0A10",background:"#FFAFB1"}},{border:"#41A906",background:"#7BE141",highlight:{border:"#41A906",background:"#A1EC76"},hover:{border:"#41A906",background:"#A1EC76"}},{border:"#E129F0",background:"#EB7DF4",highlight:{border:"#E129F0",background:"#F0B3F5"},hover:{border:"#E129F0",background:"#F0B3F5"}},{border:"#7C29F0",background:"#AD85E4",highlight:{border:"#7C29F0",background:"#D3BDF0"},hover:{border:"#7C29F0",background:"#D3BDF0"}},{border:"#C37F00",background:"#FFA807",highlight:{border:"#C37F00",background:"#FFCA66"},hover:{border:"#C37F00",background:"#FFCA66"}},{border:"#4220FB",background:"#6E6EFD",highlight:{border:"#4220FB",background:"#9B9BFD"},hover:{border:"#4220FB",background:"#9B9BFD"}},{border:"#FD5A77",background:"#FFC0CB",highlight:{border:"#FD5A77",background:"#FFD1D9"},hover:{border:"#FD5A77",background:"#FFD1D9"}},{border:"#4AD63A",background:"#C2FABC",highlight:{border:"#4AD63A",background:"#E6FFE3"},hover:{border:"#4AD63A",background:"#E6FFE3"}},{border:"#990000",background:"#EE0000",highlight:{border:"#BB0000",background:"#FF3333"},hover:{border:"#BB0000",background:"#FF3333"}},{border:"#FF6000",background:"#FF6000",highlight:{border:"#FF6000",background:"#FF6000"},hover:{border:"#FF6000",background:"#FF6000"}},{border:"#97C2FC",background:"#2B7CE9",highlight:{border:"#D2E5FF",background:"#2B7CE9"},hover:{border:"#D2E5FF",background:"#2B7CE9"}},{border:"#399605",background:"#255C03",highlight:{border:"#399605",background:"#255C03"},hover:{border:"#399605",background:"#255C03"}},{border:"#B70054",background:"#FF007E",highlight:{border:"#B70054",background:"#FF007E"},hover:{border:"#B70054",background:"#FF007E"}},{border:"#AD85E4",background:"#7C29F0",highlight:{border:"#D3BDF0",background:"#7C29F0"},hover:{border:"#D3BDF0",background:"#7C29F0"}},{border:"#4557FA",background:"#000EA1",highlight:{border:"#6E6EFD",background:"#000EA1"},hover:{border:"#6E6EFD",background:"#000EA1"}},{border:"#FFC0CB",background:"#FD5A77",highlight:{border:"#FFD1D9",background:"#FD5A77"},hover:{border:"#FFD1D9",background:"#FD5A77"}},{border:"#C2FABC",background:"#74D66A",highlight:{border:"#E6FFE3",background:"#74D66A"},hover:{border:"#E6FFE3",background:"#74D66A"}},{border:"#EE0000",background:"#990000",highlight:{border:"#FF3333",background:"#BB0000"},hover:{border:"#FF3333",background:"#BB0000"}}],this.options={},this.defaultOptions={useDefaultGroups:!0},AB(this.options,this.defaultOptions)}return mQ(t,[{key:"setOptions",value:function(t){var e=["useDefaultGroups"];if(void 0!==t)for(var i in t)if(Object.prototype.hasOwnProperty.call(t,i)&&-1===LW(e).call(e,i)){var o=t[i];this.add(i,o)}}},{key:"clear",value:function(){this._groups=new mJ,this._groupNames=[]}},{key:"get",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=this._groups.get(t);if(void 0===i&&e)if(!1===this.options.useDefaultGroups&&this._groupNames.length>0){var o=this._groupIndex%this._groupNames.length;++this._groupIndex,(i={}).color=this._groups.get(this._groupNames[o]),this._groups.set(t,i)}else{var n=this._defaultIndex%this._defaultGroups.length;this._defaultIndex++,(i={}).color=this._defaultGroups[n],this._groups.set(t,i)}return i}},{key:"add",value:function(t,e){return this._groups.has(t)||this._groupNames.push(t),this._groups.set(t,e),e}}]),t}();DR({target:"Number",stat:!0},{isNaN:function(t){return t!=t}});var wJ=nM(oO.Number.isNaN),AJ=sM.isFinite,EJ=Number.isFinite||function(t){return"number"==typeof t&&AJ(t)};DR({target:"Number",stat:!0},{isFinite:EJ});var kJ=nM(oO.Number.isFinite),CJ=zj.some;DR({target:"Array",proto:!0,forced:!jH("some")},{some:function(t){return CJ(this,t,arguments.length>1?arguments[1]:void 0)}});var xJ=TB("Array").some,SJ=hO,IJ=xJ,MJ=Array.prototype,OJ=function(t){var e=t.some;return t===MJ||SJ(MJ,t)&&e===MJ.some?IJ:e},DJ=nM(OJ),RJ=nM(oO.Object.getOwnPropertySymbols),BJ={exports:{}},zJ=DR,PJ=aM,FJ=$M,TJ=DM.f,NJ=RM;zJ({target:"Object",stat:!0,forced:!NJ||PJ((function(){TJ(1)})),sham:!NJ},{getOwnPropertyDescriptor:function(t,e){return TJ(FJ(t),e)}});var jJ=oO.Object,UJ=BJ.exports=function(t,e){return jJ.getOwnPropertyDescriptor(t,e)};jJ.getOwnPropertyDescriptor.sham&&(UJ.sham=!0);var LJ=BJ.exports,QJ=nM(LJ),HJ=AH,VJ=$M,WJ=DM,GJ=fT;DR({target:"Object",stat:!0,sham:!RM},{getOwnPropertyDescriptors:function(t){for(var e,i,o=VJ(t),n=WJ.f,r=HJ(o),s={},a=0;r.length>a;)void 0!==(i=n(o,e=r[a++]))&&GJ(s,e,i);return s}});var KJ=nM(oO.Object.getOwnPropertyDescriptors),qJ={exports:{}},YJ=DR,ZJ=RM,JJ=Yz.f;YJ({target:"Object",stat:!0,forced:Object.defineProperties!==JJ,sham:!ZJ},{defineProperties:JJ});var XJ=oO.Object,_J=qJ.exports=function(t,e){return XJ.defineProperties(t,e)};XJ.defineProperties.sham&&(_J.sham=!0);var $J=nM(qJ.exports),tX=nM(wN);function eX(t,e,i){return(e=gQ(e))in t?AN(t,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[e]=i,t}var iX=sM,oX=aM,nX=uz,rX=gW.trim,sX=lW,aX=mM("".charAt),lX=iX.parseFloat,hX=iX.Symbol,cX=hX&&hX.iterator,dX=1/lX(sX+"-0")!=-1/0||cX&&!oX((function(){lX(Object(cX))}))?function(t){var e=rX(nX(t)),i=lX(e);return 0===i&&"-"===aX(e,0)?-0:i}:lX;DR({global:!0,forced:parseFloat!==dX},{parseFloat:dX});var uX=nM(oO.parseFloat),fX=DR,pX=aM,vX=tj.f;fX({target:"Object",stat:!0,forced:pX((function(){return!Object.getOwnPropertyNames(1)}))},{getOwnPropertyNames:vX});var gX=oO.Object,yX=function(t){return gX.getOwnPropertyNames(t)},mX=nM(yX);function bX(t,e){var i=["node","edge","label"],o=!0,n=_q(e,"chosen");if("boolean"==typeof n)o=n;else if("object"===pQ(n)){if(-1===LW(i).call(i,t))throw new Error("choosify: subOption '"+t+"' should be one of '"+i.join("', '")+"'");var r=_q(e,["chosen",t]);"boolean"!=typeof r&&"function"!=typeof r||(o=r)}return o}function wX(t,e,i){if(t.width<=0||t.height<=0)return!1;if(void 0!==i){var o={x:e.x-i.x,y:e.y-i.y};if(0!==i.angle){var n=-i.angle;e={x:Math.cos(n)*o.x-Math.sin(n)*o.y,y:Math.sin(n)*o.x+Math.cos(n)*o.y}}else e=o}var r=t.x+t.width,s=t.y+t.width;return t.lefte.x&&t.tope.y}function AX(t){return"string"==typeof t&&""!==t}function EX(t,e,i,o){var n=o.x,r=o.y;if("function"==typeof o.distanceToBorder){var s=o.distanceToBorder(t,e),a=Math.sin(e)*s,l=Math.cos(e)*s;l===s?(n+=s,r=o.y):a===s?(n=o.x,r-=s):(n+=l,r-=a)}else o.shape.width>o.shape.height?(n=o.x+.5*o.shape.width,r=o.y-i):(n=o.x+i,r=o.y-.5*o.shape.height);return{x:n,y:r}}var kX=TB("Array").values,CX=hz,xX=tD,SX=hO,IX=kX,MX=Array.prototype,OX={DOMTokenList:!0,NodeList:!0},DX=function(t){var e=t.values;return t===MX||SX(MX,t)&&e===MX.values||xX(OX,CX(t))?IX:e},RX=nM(DX),BX=function(){function t(e){fN(this,t),this.measureText=e,this.current=0,this.width=0,this.height=0,this.lines=[]}return mQ(t,[{key:"_add",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"normal";void 0===this.lines[t]&&(this.lines[t]={width:0,height:0,blocks:[]});var o=e;void 0!==e&&""!==e||(o=" ");var n=this.measureText(o,i),r=AB({},RX(n));r.text=e,r.width=n.width,r.mod=i,void 0!==e&&""!==e||(r.width=0),this.lines[t].blocks.push(r),this.lines[t].width+=r.width}},{key:"curWidth",value:function(){var t=this.lines[this.current];return void 0===t?0:t.width}},{key:"append",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"normal";this._add(this.current,t,e)}},{key:"newLine",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"normal";this._add(this.current,t,e),this.current++}},{key:"determineLineHeights",value:function(){for(var t=0;tt&&(t=o.width),e+=o.height}this.width=t,this.height=e}},{key:"removeEmptyBlocks",value:function(){for(var t=[],e=0;e"://,""://,""://,"":/<\/b>/,"":/<\/i>/,"":/<\/code>/,"*":/\*/,_:/_/,"`":/`/,afterBold:/[^*]/,afterItal:/[^_]/,afterMono:/[^`]/},PX=function(){function t(e){fN(this,t),this.text=e,this.bold=!1,this.ital=!1,this.mono=!1,this.spacing=!1,this.position=0,this.buffer="",this.modStack=[],this.blocks=[]}return mQ(t,[{key:"mod",value:function(){return 0===this.modStack.length?"normal":this.modStack[0]}},{key:"modName",value:function(){return 0===this.modStack.length?"normal":"mono"===this.modStack[0]?"mono":this.bold&&this.ital?"boldital":this.bold?"bold":this.ital?"ital":void 0}},{key:"emitBlock",value:function(){this.spacing&&(this.add(" "),this.spacing=!1),this.buffer.length>0&&(this.blocks.push({text:this.buffer,mod:this.modName()}),this.buffer="")}},{key:"add",value:function(t){" "===t&&(this.spacing=!0),this.spacing&&(this.buffer+=" ",this.spacing=!1)," "!=t&&(this.buffer+=t)}},{key:"parseWS",value:function(t){return!!/[ \t]/.test(t)&&(this.mono?this.add(t):this.spacing=!0,!0)}},{key:"setTag",value:function(t){this.emitBlock(),this[t]=!0,this.modStack.unshift(t)}},{key:"unsetTag",value:function(t){this.emitBlock(),this[t]=!1,this.modStack.shift()}},{key:"parseStartTag",value:function(t,e){return!(this.mono||this[t]||!this.match(e))&&(this.setTag(t),!0)}},{key:"match",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=sH(this.prepareRegExp(t),2),o=i[0],n=i[1],r=o.test(this.text.substr(this.position,n));return r&&e&&(this.position+=n-1),r}},{key:"parseEndTag",value:function(t,e,i){var o=this.mod()===t;return!(!(o="mono"===t?o&&this.mono:o&&!this.mono)||!this.match(e))&&(void 0!==i?(this.position===this.text.length-1||this.match(i,!1))&&this.unsetTag(t):this.unsetTag(t),!0)}},{key:"replace",value:function(t,e){return!!this.match(t)&&(this.add(e),this.position+=length-1,!0)}},{key:"prepareRegExp",value:function(t){var e,i;if(t instanceof RegExp)i=t,e=1;else{var o=zX[t];i=void 0!==o?o:new RegExp(t),e=t.length}return[i,e]}}]),t}(),FX=function(){function t(e,i,o,n){var r=this;fN(this,t),this.ctx=e,this.parent=i,this.selected=o,this.hover=n;this.lines=new BX((function(t,i){if(void 0===t)return 0;var s=r.parent.getFormattingValues(e,o,n,i),a=0;""!==t&&(a=r.ctx.measureText(t).width);return{width:a,values:s}}))}return mQ(t,[{key:"process",value:function(t){if(!AX(t))return this.lines.finalize();var e=this.parent.fontOptions;t=(t=t.replace(/\r\n/g,"\n")).replace(/\r/g,"\n");var i=String(t).split("\n"),o=i.length;if(e.multi)for(var n=0;n0)for(var s=0;s0)for(var u=0;u")||e.parseStartTag("ital","")||e.parseStartTag("mono","")||e.parseEndTag("bold","")||e.parseEndTag("ital","")||e.parseEndTag("mono",""))||i(o)||e.add(o),e.position++}return e.emitBlock(),e.blocks}},{key:"splitMarkdownBlocks",value:function(t){for(var e=this,i=new PX(t),o=!0,n=function(t){return!!/\\/.test(t)&&(i.positionthis.parent.fontOptions.maxWdt}},{key:"getLongestFit",value:function(t){for(var e="",i=0;i1&&void 0!==arguments[1]?arguments[1]:"normal",i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];this.parent.getFormattingValues(this.ctx,this.selected,this.hover,e);for(var o=(t=(t=t.replace(/^( +)/g,"$1\r")).replace(/([^\r][^ ]*)( +)/g,"$1\r$2\r")).split("\r");o.length>0;){var n=this.getLongestFit(o);if(0===n){var r=o[0],s=this.getLongestFitWord(r);this.lines.newLine(vH(r).call(r,0,s),e),o[0]=vH(r).call(r,s)}else{var a=n;" "===o[n-1]?n--:" "===o[a]&&a++;var l=vH(o).call(o,0,n).join("");n==o.length&&i?this.lines.append(l,e):this.lines.newLine(l,e),o=vH(o).call(o,a)}}}}]),t}(),TX=["bold","ital","boldital","mono"],NX=function(){function t(e,i){var o=arguments.length>2&&void 0!==arguments[2]&&arguments[2];fN(this,t),this.body=e,this.pointToSelf=!1,this.baseSize=void 0,this.fontOptions={},this.setOptions(i),this.size={top:0,left:0,width:0,height:0,yLine:0},this.isEdgeLabel=o}return mQ(t,[{key:"setOptions",value:function(t){if(this.elementOptions=t,this.initFontOptions(t.font),AX(t.label)?this.labelDirty=!0:t.label=void 0,void 0!==t.font&&null!==t.font)if("string"==typeof t.font)this.baseSize=this.fontOptions.size;else if("object"===pQ(t.font)){var e=t.font.size;void 0!==e&&(this.baseSize=e)}}},{key:"initFontOptions",value:function(e){var i=this;Uq(TX,(function(t){i.fontOptions[t]={}})),t.parseFontString(this.fontOptions,e)?this.fontOptions.vadjust=0:Uq(e,(function(t,e){null!=t&&"object"!==pQ(t)&&(i.fontOptions[e]=t)}))}},{key:"constrain",value:function(t){var e={constrainWidth:!1,maxWdt:-1,minWdt:-1,constrainHeight:!1,minHgt:-1,valign:"middle"},i=_q(t,"widthConstraint");if("number"==typeof i)e.maxWdt=Number(i),e.minWdt=Number(i);else if("object"===pQ(i)){var o=_q(t,["widthConstraint","maximum"]);"number"==typeof o&&(e.maxWdt=Number(o));var n=_q(t,["widthConstraint","minimum"]);"number"==typeof n&&(e.minWdt=Number(n))}var r=_q(t,"heightConstraint");if("number"==typeof r)e.minHgt=Number(r);else if("object"===pQ(r)){var s=_q(t,["heightConstraint","minimum"]);"number"==typeof s&&(e.minHgt=Number(s));var a=_q(t,["heightConstraint","valign"]);"string"==typeof a&&("top"!==a&&"bottom"!==a||(e.valign=a))}return e}},{key:"update",value:function(t,e){this.setOptions(t,!0),this.propagateFonts(e),Tq(this.fontOptions,this.constrain(e)),this.fontOptions.chooser=bX("label",e)}},{key:"adjustSizes",value:function(t){var e=t?t.right+t.left:0;this.fontOptions.constrainWidth&&(this.fontOptions.maxWdt-=e,this.fontOptions.minWdt-=e);var i=t?t.top+t.bottom:0;this.fontOptions.constrainHeight&&(this.fontOptions.minHgt-=i)}},{key:"addFontOptionsToPile",value:function(t,e){for(var i=0;i5&&void 0!==arguments[5]?arguments[5]:"middle";if(void 0!==this.elementOptions.label){var s=this.fontOptions.size*this.body.view.scale;this.elementOptions.label&&s=this.elementOptions.scaling.label.maxVisible&&(s=Number(this.elementOptions.scaling.label.maxVisible)/this.body.view.scale),this.calculateLabelSize(t,o,n,e,i,r),this._drawBackground(t),this._drawText(t,e,this.size.yLine,r,s))}}},{key:"_drawBackground",value:function(t){if(void 0!==this.fontOptions.background&&"none"!==this.fontOptions.background){t.fillStyle=this.fontOptions.background;var e=this.getSize();t.fillRect(e.left,e.top,e.width,e.height)}}},{key:"_drawText",value:function(t,e,i){var o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"middle",n=arguments.length>4?arguments[4]:void 0,r=sH(this._setAlignment(t,e,i,o),2);e=r[0],i=r[1],t.textAlign="left",e-=this.size.width/2,this.fontOptions.valign&&this.size.height>this.size.labelHeight&&("top"===this.fontOptions.valign&&(i-=(this.size.height-this.size.labelHeight)/2),"bottom"===this.fontOptions.valign&&(i+=(this.size.height-this.size.labelHeight)/2));for(var s=0;s0&&(t.lineWidth=c.strokeWidth,t.strokeStyle=f,t.lineJoin="round"),t.fillStyle=u,c.strokeWidth>0&&t.strokeText(c.text,e+l,i+c.vadjust),t.fillText(c.text,e+l,i+c.vadjust),l+=c.width}i+=a.height}}}},{key:"_setAlignment",value:function(t,e,i,o){if(this.isEdgeLabel&&"horizontal"!==this.fontOptions.align&&!1===this.pointToSelf){e=0,i=0;"top"===this.fontOptions.align?(t.textBaseline="alphabetic",i-=4):"bottom"===this.fontOptions.align?(t.textBaseline="hanging",i+=4):t.textBaseline="middle"}else t.textBaseline=o;return[e,i]}},{key:"_getColor",value:function(t,e,i){var o=t||"#000000",n=i||"#ffffff";if(e<=this.elementOptions.scaling.label.drawThreshold){var r=Math.max(0,Math.min(1,1-(this.elementOptions.scaling.label.drawThreshold-e)));o=Qq(o,r),n=Qq(n,r)}return[o,n]}},{key:"getTextSize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return this._processLabel(t,e,i),{width:this.size.width,height:this.size.height,lineCount:this.lineCount}}},{key:"getSize",value:function(){var t=this.size.left,e=this.size.top-1;if(this.isEdgeLabel){var i=.5*-this.size.width;switch(this.fontOptions.align){case"middle":t=i,e=.5*-this.size.height;break;case"top":t=i,e=-(this.size.height+2);break;case"bottom":t=i,e=2}}return{left:t,top:e,width:this.size.width,height:this.size.height}}},{key:"calculateLabelSize",value:function(t,e,i){var o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,n=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,r=arguments.length>5&&void 0!==arguments[5]?arguments[5]:"middle";this._processLabel(t,e,i),this.size.left=o-.5*this.size.width,this.size.top=n-.5*this.size.height,this.size.yLine=n+.5*(1-this.lineCount)*this.fontOptions.size,"hanging"===r&&(this.size.top+=.5*this.fontOptions.size,this.size.top+=4,this.size.yLine+=4)}},{key:"getFormattingValues",value:function(t,e,i,o){var n=function(t,e,i){return"normal"===e?"mod"===i?"":t[i]:void 0!==t[e][i]?t[e][i]:t[i]},r={color:n(this.fontOptions,o,"color"),size:n(this.fontOptions,o,"size"),face:n(this.fontOptions,o,"face"),mod:n(this.fontOptions,o,"mod"),vadjust:n(this.fontOptions,o,"vadjust"),strokeWidth:this.fontOptions.strokeWidth,strokeColor:this.fontOptions.strokeColor};(e||i)&&("normal"===o&&!0===this.fontOptions.chooser&&this.elementOptions.labelHighlightBold?r.mod="bold":"function"==typeof this.fontOptions.chooser&&this.fontOptions.chooser(r,this.elementOptions.id,e,i));var s="";return void 0!==r.mod&&""!==r.mod&&(s+=r.mod+" "),s+=r.size+"px "+r.face,t.font=s.replace(/"/g,""),r.font=t.font,r.height=r.size,r}},{key:"differentState",value:function(t,e){return t!==this.selectedState||e!==this.hoverState}},{key:"_processLabelText",value:function(t,e,i,o){return new FX(t,this,e,i).process(o)}},{key:"_processLabel",value:function(t,e,i){if(!1!==this.labelDirty||this.differentState(e,i)){var o=this._processLabelText(t,e,i,this.elementOptions.label);this.fontOptions.minWdt>0&&o.width0&&o.height0&&(this.enableBorderDashes(t,e),t.stroke(),this.disableBorderDashes(t,e)),t.restore()}},{key:"performFill",value:function(t,e){t.save(),t.fillStyle=e.color,this.enableShadow(t,e),CG(t).call(t),this.disableShadow(t,e),t.restore(),this.performStroke(t,e)}},{key:"_addBoundingBoxMargin",value:function(t){this.boundingBox.left-=t,this.boundingBox.top-=t,this.boundingBox.bottom+=t,this.boundingBox.right+=t}},{key:"_updateBoundingBox",value:function(t,e,i,o,n){void 0!==i&&this.resize(i,o,n),this.left=t-this.width/2,this.top=e-this.height/2,this.boundingBox.left=this.left,this.boundingBox.top=this.top,this.boundingBox.bottom=this.top+this.height,this.boundingBox.right=this.left+this.width}},{key:"updateBoundingBox",value:function(t,e,i,o,n){this._updateBoundingBox(t,e,i,o,n)}},{key:"getDimensionsFromLabel",value:function(t,e,i){this.textSize=this.labelModule.getTextSize(t,e,i);var o=this.textSize.width,n=this.textSize.height;return 0===o&&(o=14,n=14),{width:o,height:n}}}]),t}();function d_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var u_=function(t){s_(i,t);var e=d_(i);function i(t,o,n){var r;return fN(this,i),(r=e.call(this,t,o,n))._setMargins(n),r}return mQ(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(this.needsRefresh(e,i)){var o=this.getDimensionsFromLabel(t,e,i);this.width=o.width+this.margin.right+this.margin.left,this.height=o.height+this.margin.top+this.margin.bottom,this.radius=this.width/2}}},{key:"draw",value:function(t,e,i,o,n,r){this.resize(t,o,n),this.left=e-this.width/2,this.top=i-this.height/2,this.initContextForDraw(t,r),GB(t,this.left,this.top,this.width,this.height,r.borderRadius),this.performFill(t,r),this.updateBoundingBox(e,i,t,o,n),this.labelModule.draw(t,this.left+this.textSize.width/2+this.margin.left,this.top+this.textSize.height/2+this.margin.top,o,n)}},{key:"updateBoundingBox",value:function(t,e,i,o,n){this._updateBoundingBox(t,e,i,o,n);var r=this.options.shapeProperties.borderRadius;this._addBoundingBoxMargin(r)}},{key:"distanceToBorder",value:function(t,e){t&&this.resize(t);var i=this.options.borderWidth;return Math.min(Math.abs(this.width/2/Math.cos(e)),Math.abs(this.height/2/Math.sin(e)))+i}}]),i}(c_);function f_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var p_=function(t){s_(i,t);var e=f_(i);function i(t,o,n){var r;return fN(this,i),(r=e.call(this,t,o,n)).labelOffset=0,r.selected=!1,r}return mQ(i,[{key:"setOptions",value:function(t,e,i){this.options=t,void 0===e&&void 0===i||this.setImages(e,i)}},{key:"setImages",value:function(t,e){e&&this.selected?(this.imageObj=e,this.imageObjAlt=t):(this.imageObj=t,this.imageObjAlt=e)}},{key:"switchImages",value:function(t){var e=t&&!this.selected||!t&&this.selected;if(this.selected=t,void 0!==this.imageObjAlt&&e){var i=this.imageObj;this.imageObj=this.imageObjAlt,this.imageObjAlt=i}}},{key:"_getImagePadding",value:function(){var t={top:0,right:0,bottom:0,left:0};if(this.options.imagePadding){var e=this.options.imagePadding;"object"==pQ(e)?(t.top=e.top,t.right=e.right,t.bottom=e.bottom,t.left=e.left):(t.top=e,t.right=e,t.bottom=e,t.left=e)}return t}},{key:"_resizeImage",value:function(){var t,e;if(!1===this.options.shapeProperties.useImageSize){var i=1,o=1;this.imageObj.width&&this.imageObj.height&&(this.imageObj.width>this.imageObj.height?i=this.imageObj.width/this.imageObj.height:o=this.imageObj.height/this.imageObj.width),t=2*this.options.size*i,e=2*this.options.size*o}else{var n=this._getImagePadding();t=this.imageObj.width+n.left+n.right,e=this.imageObj.height+n.top+n.bottom}this.width=t,this.height=e,this.radius=.5*this.width}},{key:"_drawRawCircle",value:function(t,e,i,o){this.initContextForDraw(t,o),WB(t,e,i,o.size),this.performFill(t,o)}},{key:"_drawImageAtPosition",value:function(t,e){if(0!=this.imageObj.width){t.globalAlpha=void 0!==e.opacity?e.opacity:1,this.enableShadow(t,e);var i=1;!0===this.options.shapeProperties.interpolation&&(i=this.imageObj.width/this.width/this.body.view.scale);var o=this._getImagePadding(),n=this.left+o.left,r=this.top+o.top,s=this.width-o.left-o.right,a=this.height-o.top-o.bottom;this.imageObj.drawImageAtPosition(t,i,n,r,s,a),this.disableShadow(t,e)}}},{key:"_drawImageLabel",value:function(t,e,i,o,n){var r=0;if(void 0!==this.height){r=.5*this.height;var s=this.labelModule.getTextSize(t,o,n);s.lineCount>=1&&(r+=s.height/2)}var a=i+r;this.options.label&&(this.labelOffset=r),this.labelModule.draw(t,e,a,o,n,"hanging")}}]),i}(c_);function v_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var g_=function(t){s_(i,t);var e=v_(i);function i(t,o,n){var r;return fN(this,i),(r=e.call(this,t,o,n))._setMargins(n),r}return mQ(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(this.needsRefresh(e,i)){var o=this.getDimensionsFromLabel(t,e,i),n=Math.max(o.width+this.margin.right+this.margin.left,o.height+this.margin.top+this.margin.bottom);this.options.size=n/2,this.width=n,this.height=n,this.radius=this.width/2}}},{key:"draw",value:function(t,e,i,o,n,r){this.resize(t,o,n),this.left=e-this.width/2,this.top=i-this.height/2,this._drawRawCircle(t,e,i,r),this.updateBoundingBox(e,i),this.labelModule.draw(t,this.left+this.textSize.width/2+this.margin.left,i,o,n)}},{key:"updateBoundingBox",value:function(t,e){this.boundingBox.top=e-this.options.size,this.boundingBox.left=t-this.options.size,this.boundingBox.right=t+this.options.size,this.boundingBox.bottom=e+this.options.size}},{key:"distanceToBorder",value:function(t){return t&&this.resize(t),.5*this.width}}]),i}(p_);function y_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var m_=function(t){s_(i,t);var e=y_(i);function i(t,o,n,r,s){var a;return fN(this,i),(a=e.call(this,t,o,n)).setImages(r,s),a}return mQ(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(void 0===this.imageObj.src||void 0===this.imageObj.width||void 0===this.imageObj.height){var o=2*this.options.size;return this.width=o,this.height=o,void(this.radius=.5*this.width)}this.needsRefresh(e,i)&&this._resizeImage()}},{key:"draw",value:function(t,e,i,o,n,r){this.switchImages(o),this.resize();var s=e,a=i;"top-left"===this.options.shapeProperties.coordinateOrigin?(this.left=e,this.top=i,s+=this.width/2,a+=this.height/2):(this.left=e-this.width/2,this.top=i-this.height/2),this._drawRawCircle(t,s,a,r),t.save(),t.clip(),this._drawImageAtPosition(t,r),t.restore(),this._drawImageLabel(t,s,a,o,n),this.updateBoundingBox(e,i)}},{key:"updateBoundingBox",value:function(t,e){"top-left"===this.options.shapeProperties.coordinateOrigin?(this.boundingBox.top=e,this.boundingBox.left=t,this.boundingBox.right=t+2*this.options.size,this.boundingBox.bottom=e+2*this.options.size):(this.boundingBox.top=e-this.options.size,this.boundingBox.left=t-this.options.size,this.boundingBox.right=t+this.options.size,this.boundingBox.bottom=e+this.options.size),this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelOffset)}},{key:"distanceToBorder",value:function(t){return t&&this.resize(t),.5*this.width}}]),i}(p_);function b_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var w_=function(t){s_(i,t);var e=b_(i);function i(t,o,n){return fN(this,i),e.call(this,t,o,n)}return mQ(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{size:this.options.size};if(this.needsRefresh(e,i)){var n,r;this.labelModule.getTextSize(t,e,i);var s=2*o.size;this.width=null!==(n=this.customSizeWidth)&&void 0!==n?n:s,this.height=null!==(r=this.customSizeHeight)&&void 0!==r?r:s,this.radius=.5*this.width}}},{key:"_drawShape",value:function(t,e,i,o,n,r,s,a){var l,h=this;return this.resize(t,r,s,a),this.left=o-this.width/2,this.top=n-this.height/2,this.initContextForDraw(t,a),(l=e,Object.prototype.hasOwnProperty.call(ZB,l)?ZB[l]:function(t){for(var e=arguments.length,i=new Array(e>1?e-1:0),o=1;o0&&(this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelModule.size.height))}}]),i}(c_);function A_(t,e){var i=BH(t);if(RJ){var o=RJ(t);e&&(o=aW(o).call(o,(function(e){return QJ(t,e).enumerable}))),i.push.apply(i,o)}return i}function E_(t){for(var e=1;e1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(this.needsRefresh(e,i)){var o=this.getDimensionsFromLabel(t,e,i);this.height=2*o.height,this.width=o.width+o.height,this.radius=.5*this.width}}},{key:"draw",value:function(t,e,i,o,n,r){this.resize(t,o,n),this.left=e-.5*this.width,this.top=i-.5*this.height,this.initContextForDraw(t,r),KB(t,this.left,this.top,this.width,this.height),this.performFill(t,r),this.updateBoundingBox(e,i,t,o,n),this.labelModule.draw(t,e,i,o,n)}},{key:"distanceToBorder",value:function(t,e){t&&this.resize(t);var i=.5*this.width,o=.5*this.height,n=Math.sin(e)*i,r=Math.cos(e)*o;return i*o/Math.sqrt(n*n+r*r)}}]),i}(c_);function z_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var P_=function(t){s_(i,t);var e=z_(i);function i(t,o,n){var r;return fN(this,i),(r=e.call(this,t,o,n))._setMargins(n),r}return mQ(i,[{key:"resize",value:function(t,e,i){this.needsRefresh(e,i)&&(this.iconSize={width:Number(this.options.icon.size),height:Number(this.options.icon.size)},this.width=this.iconSize.width+this.margin.right+this.margin.left,this.height=this.iconSize.height+this.margin.top+this.margin.bottom,this.radius=.5*this.width)}},{key:"draw",value:function(t,e,i,o,n,r){var s=this;return this.resize(t,o,n),this.options.icon.size=this.options.icon.size||50,this.left=e-this.width/2,this.top=i-this.height/2,this._icon(t,e,i,o,n,r),{drawExternalLabel:function(){if(void 0!==s.options.label){s.labelModule.draw(t,s.left+s.iconSize.width/2+s.margin.left,i+s.height/2+5,o)}s.updateBoundingBox(e,i)}}}},{key:"updateBoundingBox",value:function(t,e){if(this.boundingBox.top=e-.5*this.options.icon.size,this.boundingBox.left=t-.5*this.options.icon.size,this.boundingBox.right=t+.5*this.options.icon.size,this.boundingBox.bottom=e+.5*this.options.icon.size,void 0!==this.options.label&&this.labelModule.size.width>0){this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelModule.size.height+5)}}},{key:"_icon",value:function(t,e,i,o,n,r){var s=Number(this.options.icon.size);void 0!==this.options.icon.code?(t.font=[null!=this.options.icon.weight?this.options.icon.weight:o?"bold":"",(null!=this.options.icon.weight&&o?5:0)+s+"px",this.options.icon.face].join(" "),t.fillStyle=this.options.icon.color||"black",t.textAlign="center",t.textBaseline="middle",this.enableShadow(t,r),t.fillText(this.options.icon.code,e,i),this.disableShadow(t,r)):console.error("When using the icon shape, you need to define the code in the icon options object. This can be done per node or globally.")}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(c_);function F_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var T_=function(t){s_(i,t);var e=F_(i);function i(t,o,n,r,s){var a;return fN(this,i),(a=e.call(this,t,o,n)).setImages(r,s),a}return mQ(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(void 0===this.imageObj.src||void 0===this.imageObj.width||void 0===this.imageObj.height){var o=2*this.options.size;return this.width=o,void(this.height=o)}this.needsRefresh(e,i)&&this._resizeImage()}},{key:"draw",value:function(t,e,i,o,n,r){t.save(),this.switchImages(o),this.resize();var s=e,a=i;if("top-left"===this.options.shapeProperties.coordinateOrigin?(this.left=e,this.top=i,s+=this.width/2,a+=this.height/2):(this.left=e-this.width/2,this.top=i-this.height/2),!0===this.options.shapeProperties.useBorderWithImage){var l=this.options.borderWidth,h=this.options.borderWidthSelected||2*this.options.borderWidth,c=(o?h:l)/this.body.view.scale;t.lineWidth=Math.min(this.width,c),t.beginPath();var d=o?this.options.color.highlight.border:n?this.options.color.hover.border:this.options.color.border,u=o?this.options.color.highlight.background:n?this.options.color.hover.background:this.options.color.background;void 0!==r.opacity&&(d=Qq(d,r.opacity),u=Qq(u,r.opacity)),t.strokeStyle=d,t.fillStyle=u,t.rect(this.left-.5*t.lineWidth,this.top-.5*t.lineWidth,this.width+t.lineWidth,this.height+t.lineWidth),CG(t).call(t),this.performStroke(t,r),t.closePath()}this._drawImageAtPosition(t,r),this._drawImageLabel(t,s,a,o,n),this.updateBoundingBox(e,i),t.restore()}},{key:"updateBoundingBox",value:function(t,e){this.resize(),"top-left"===this.options.shapeProperties.coordinateOrigin?(this.left=t,this.top=e):(this.left=t-this.width/2,this.top=e-this.height/2),this.boundingBox.left=this.left,this.boundingBox.top=this.top,this.boundingBox.bottom=this.top+this.height,this.boundingBox.right=this.left+this.width,void 0!==this.options.label&&this.labelModule.size.width>0&&(this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelOffset))}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(p_);function N_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var j_=function(t){s_(i,t);var e=N_(i);function i(t,o,n){return fN(this,i),e.call(this,t,o,n)}return mQ(i,[{key:"draw",value:function(t,e,i,o,n,r){return this._drawShape(t,"square",2,e,i,o,n,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(w_);function U_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var L_=function(t){s_(i,t);var e=U_(i);function i(t,o,n){return fN(this,i),e.call(this,t,o,n)}return mQ(i,[{key:"draw",value:function(t,e,i,o,n,r){return this._drawShape(t,"hexagon",4,e,i,o,n,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(w_);function Q_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var H_=function(t){s_(i,t);var e=Q_(i);function i(t,o,n){return fN(this,i),e.call(this,t,o,n)}return mQ(i,[{key:"draw",value:function(t,e,i,o,n,r){return this._drawShape(t,"star",4,e,i,o,n,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(w_);function V_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var W_=function(t){s_(i,t);var e=V_(i);function i(t,o,n){var r;return fN(this,i),(r=e.call(this,t,o,n))._setMargins(n),r}return mQ(i,[{key:"resize",value:function(t,e,i){this.needsRefresh(e,i)&&(this.textSize=this.labelModule.getTextSize(t,e,i),this.width=this.textSize.width+this.margin.right+this.margin.left,this.height=this.textSize.height+this.margin.top+this.margin.bottom,this.radius=.5*this.width)}},{key:"draw",value:function(t,e,i,o,n,r){this.resize(t,o,n),this.left=e-this.width/2,this.top=i-this.height/2,this.enableShadow(t,r),this.labelModule.draw(t,this.left+this.textSize.width/2+this.margin.left,this.top+this.textSize.height/2+this.margin.top,o,n),this.disableShadow(t,r),this.updateBoundingBox(e,i,t,o,n)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(c_);function G_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var K_=function(t){s_(i,t);var e=G_(i);function i(t,o,n){return fN(this,i),e.call(this,t,o,n)}return mQ(i,[{key:"draw",value:function(t,e,i,o,n,r){return this._drawShape(t,"triangle",3,e,i,o,n,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(w_);function q_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var Y_=function(t){s_(i,t);var e=q_(i);function i(t,o,n){return fN(this,i),e.call(this,t,o,n)}return mQ(i,[{key:"draw",value:function(t,e,i,o,n,r){return this._drawShape(t,"triangleDown",3,e,i,o,n,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(w_);function Z_(t,e){var i=BH(t);if(RJ){var o=RJ(t);e&&(o=aW(o).call(o,(function(e){return QJ(t,e).enumerable}))),i.push.apply(i,o)}return i}function J_(t){for(var e=1;et.left&&this.shape.topt.top}},{key:"isBoundingBoxOverlappingWith",value:function(t){return this.shape.boundingBox.leftt.left&&this.shape.boundingBox.topt.top}}],[{key:"checkOpacity",value:function(t){return 0<=t&&t<=1}},{key:"checkCoordinateOrigin",value:function(t){return void 0===t||"center"===t||"top-left"===t}},{key:"updateGroupOptions",value:function(e,i,o){var n;if(void 0!==o){var r=e.group;if(void 0!==i&&void 0!==i.group&&r!==i.group)throw new Error("updateGroupOptions: group values in options don't match.");if("number"==typeof r||"string"==typeof r&&""!=r){var s=o.get(r);void 0!==s.opacity&&void 0===i.opacity&&(t.checkOpacity(s.opacity)||(console.error("Invalid option for node opacity. Value must be between 0 and 1, found: "+s.opacity),s.opacity=void 0));var a=aW(n=mX(i)).call(n,(function(t){return null!=i[t]}));a.push("font"),Fq(a,e,s),e.color=Vq(e.color)}}}},{key:"parseOptions",value:function(e,i){var o=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},r=arguments.length>4?arguments[4]:void 0;if(Fq(["color","fixed","shadow"],e,i,o),t.checkMass(i),void 0!==e.opacity&&(t.checkOpacity(e.opacity)||(console.error("Invalid option for node opacity. Value must be between 0 and 1, found: "+e.opacity),e.opacity=void 0)),void 0!==i.opacity&&(t.checkOpacity(i.opacity)||(console.error("Invalid option for node opacity. Value must be between 0 and 1, found: "+i.opacity),i.opacity=void 0)),i.shapeProperties&&!t.checkCoordinateOrigin(i.shapeProperties.coordinateOrigin)&&console.error("Invalid option for node coordinateOrigin, found: "+i.shapeProperties.coordinateOrigin),Jq(e,i,"shadow",n),void 0!==i.color&&null!==i.color){var s=Vq(i.color);zq(e.color,s)}else!0===o&&null===i.color&&(e.color=Zq(n.color));void 0!==i.fixed&&null!==i.fixed&&("boolean"==typeof i.fixed?(e.fixed.x=i.fixed,e.fixed.y=i.fixed):(void 0!==i.fixed.x&&"boolean"==typeof i.fixed.x&&(e.fixed.x=i.fixed.x),void 0!==i.fixed.y&&"boolean"==typeof i.fixed.y&&(e.fixed.y=i.fixed.y))),!0===o&&null===i.font&&(e.font=Zq(n.font)),t.updateGroupOptions(e,i,r),void 0!==i.scaling&&Jq(e.scaling,i.scaling,"label",n.scaling)}},{key:"checkMass",value:function(t,e){if(void 0!==t.mass&&t.mass<=0){var i="";void 0!==e&&(i=" in node id: "+e),console.error("%cNegative or zero mass disallowed"+i+", setting mass to 1.",uY),t.mass=1}}}]),t}();function __(t,e){var i=void 0!==lH&&uN(t)||t["@@iterator"];if(!i){if(EH(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return $_(t,e);var o=vH(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===o&&t.constructor&&(o=t.constructor.name);if("Map"===o||"Set"===o)return GT(t);if("Arguments"===o||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(o))return $_(t,e)}(t))||e){i&&(t=i);var o=0,n=function(){};return{s:n,n:function(){return o>=t.length?{done:!0}:{done:!1,value:t[o++]}},e:function(t){throw t},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function $_(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,o=new Array(e);i1?console.error("Invalid option for node opacity. Value must be between 0 and 1, found: "+t.opacity):this.options.opacity=t.opacity),void 0!==t.shape)for(var e in this.body.nodes)Object.prototype.hasOwnProperty.call(this.body.nodes,e)&&this.body.nodes[e].updateShape();if(void 0!==t.font||void 0!==t.widthConstraint||void 0!==t.heightConstraint)for(var i=0,o=BH(this.body.nodes);i1&&void 0!==arguments[1]&&arguments[1],i=this.body.data.nodes;if(iM("id",t))this.body.data.nodes=t;else if(EH(t))this.body.data.nodes=new eM,this.body.data.nodes.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.body.data.nodes=new eM}if(i&&Uq(this.nodesListeners,(function(t,e){i.off(e,t)})),this.body.nodes={},this.body.data.nodes){var o=this;Uq(this.nodesListeners,(function(t,e){o.body.data.nodes.on(e,t)}));var n=this.body.data.nodes.getIds();this.add(n,!0)}!1===e&&this.body.emitter.emit("_dataChanged")}},{key:"add",value:function(t){for(var e,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],o=[],n=0;n1&&void 0!==arguments[1]?arguments[1]:X_)(t,this.body,this.images,this.groups,this.options,this.defaultOptions)}},{key:"refresh",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];Uq(this.body.nodes,(function(i,o){var n=t.body.data.nodes.get(o);void 0!==n&&(!0===e&&i.setOptions({x:null,y:null}),i.setOptions({fixed:!1}),i.setOptions(n))}))}},{key:"getPositions",value:function(t){var e={};if(void 0!==t){if(!0===EH(t)){for(var i=0;i0?(o=i/a)*o:i;return a===1/0?1/0:a*p$(n)}});var v$=nM(oO.Math.hypot);function g$(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var y$=function(){function t(){fN(this,t)}return mQ(t,null,[{key:"transform",value:function(t,e){EH(t)||(t=[t]);for(var i=e.point.x,o=e.point.y,n=e.angle,r=e.length,s=0;s4&&void 0!==arguments[4]?arguments[4]:this.getViaNode();t.strokeStyle=this.getColor(t,e),t.lineWidth=e.width,!1!==e.dashes?this._drawDashedLine(t,e,n):this._drawLine(t,e,n)}},{key:"_drawLine",value:function(t,e,i,o,n){if(this.from!=this.to)this._line(t,e,i,o,n);else{var r=sH(this._getCircleData(t),3),s=r[0],a=r[1],l=r[2];this._circle(t,e,s,a,l)}}},{key:"_drawDashedLine",value:function(t,e,i,o,n){t.lineCap="round";var r=EH(e.dashes)?e.dashes:[5,5];if(void 0!==t.setLineDash){if(t.save(),t.setLineDash(r),t.lineDashOffset=0,this.from!=this.to)this._line(t,e,i);else{var s=sH(this._getCircleData(t),3),a=s[0],l=s[1],h=s[2];this._circle(t,e,a,l,h)}t.setLineDash([0]),t.lineDashOffset=0,t.restore()}else{if(this.from!=this.to)YB(t,this.from.x,this.from.y,this.to.x,this.to.y,r);else{var c=sH(this._getCircleData(t),3),d=c[0],u=c[1],f=c[2];this._circle(t,e,d,u,f)}this.enableShadow(t,e),t.stroke(),this.disableShadow(t,e)}}},{key:"findBorderPosition",value:function(t,e,i){return this.from!=this.to?this._findBorderPosition(t,e,i):this._findBorderPositionCircle(t,e,i)}},{key:"findBorderPositions",value:function(t){if(this.from!=this.to)return{from:this._findBorderPosition(this.from,t),to:this._findBorderPosition(this.to,t)};var e,i=sH(vH(e=this._getCircleData(t)).call(e,0,2),2),o=i[0],n=i[1];return{from:this._findBorderPositionCircle(this.from,t,{x:o,y:n,low:.25,high:.6,direction:-1}),to:this._findBorderPositionCircle(this.from,t,{x:o,y:n,low:.6,high:.8,direction:1})}}},{key:"_getCircleData",value:function(t){var e=this.options.selfReference.size;void 0!==t&&void 0===this.from.shape.width&&this.from.shape.resize(t);var i=EX(t,this.options.selfReference.angle,e,this.from);return[i.x,i.y,e]}},{key:"_pointOnCircle",value:function(t,e,i,o){var n=2*o*Math.PI;return{x:t+i*Math.cos(n),y:e-i*Math.sin(n)}}},{key:"_findBorderPositionCircle",value:function(t,e,i){var o,n=i.x,r=i.y,s=i.low,a=i.high,l=i.direction,h=this.options.selfReference.size,c=.5*(s+a),d=0;!0===this.options.arrowStrikethrough&&(-1===l?d=this.options.endPointOffset.from:1===l&&(d=this.options.endPointOffset.to));var u=0;do{c=.5*(s+a),o=this._pointOnCircle(n,r,h,c);var f=Math.atan2(t.y-o.y,t.x-o.x),p=t.distanceToBorder(e,f)+d-Math.sqrt(Math.pow(o.x-t.x,2)+Math.pow(o.y-t.y,2));if(Math.abs(p)<.05)break;p>0?l>0?s=c:a=c:l>0?a=c:s=c,++u}while(s<=a&&u<10);return B$(B$({},o),{},{t:c})}},{key:"getLineWidth",value:function(t,e){return!0===t?Math.max(this.selectionWidth,.3/this._body.view.scale):!0===e?Math.max(this.hoverWidth,.3/this._body.view.scale):Math.max(this.options.width,.3/this._body.view.scale)}},{key:"getColor",value:function(t,e){if(!1!==e.inheritsColor){if("both"===e.inheritsColor&&this.from.id!==this.to.id){var i=t.createLinearGradient(this.from.x,this.from.y,this.to.x,this.to.y),o=this.from.options.color.highlight.border,n=this.to.options.color.highlight.border;return!1===this.from.selected&&!1===this.to.selected?(o=Qq(this.from.options.color.border,e.opacity),n=Qq(this.to.options.color.border,e.opacity)):!0===this.from.selected&&!1===this.to.selected?n=this.to.options.color.border:!1===this.from.selected&&!0===this.to.selected&&(o=this.from.options.color.border),i.addColorStop(0,o),i.addColorStop(1,n),i}return"to"===e.inheritsColor?Qq(this.to.options.color.border,e.opacity):Qq(this.from.options.color.border,e.opacity)}return Qq(e.color,e.opacity)}},{key:"_circle",value:function(t,e,i,o,n){this.enableShadow(t,e);var r=0,s=2*Math.PI;if(!this.options.selfReference.renderBehindTheNode){var a=this.options.selfReference.angle,l=this.options.selfReference.angle+Math.PI,h=this._findBorderPositionCircle(this.from,t,{x:i,y:o,low:a,high:l,direction:-1}),c=this._findBorderPositionCircle(this.from,t,{x:i,y:o,low:a,high:l,direction:1});r=Math.atan2(h.y-o,h.x-i),s=Math.atan2(c.y-o,c.x-i)}t.beginPath(),t.arc(i,o,n,r,s,!1),t.stroke(),this.disableShadow(t,e)}},{key:"getDistanceToEdge",value:function(t,e,i,o,n,r){if(this.from!=this.to)return this._getDistanceToEdge(t,e,i,o,n,r);var s=sH(this._getCircleData(void 0),3),a=s[0],l=s[1],h=s[2],c=a-n,d=l-r;return Math.abs(Math.sqrt(c*c+d*d)-h)}},{key:"_getDistanceToLine",value:function(t,e,i,o,n,r){var s=i-t,a=o-e,l=((n-t)*s+(r-e)*a)/(s*s+a*a);l>1?l=1:l<0&&(l=0);var h=t+l*s-n,c=e+l*a-r;return Math.sqrt(h*h+c*c)}},{key:"getArrowData",value:function(t,e,i,o,n,r){var s,a,l,h,c,d,u,f=r.width;"from"===e?(l=this.from,h=this.to,c=r.fromArrowScale<0,d=Math.abs(r.fromArrowScale),u=r.fromArrowType):"to"===e?(l=this.to,h=this.from,c=r.toArrowScale<0,d=Math.abs(r.toArrowScale),u=r.toArrowType):(l=this.to,h=this.from,c=r.middleArrowScale<0,d=Math.abs(r.middleArrowScale),u=r.middleArrowType);var p=15*d+3*f;if(l!=h){var v=p/v$(l.x-h.x,l.y-h.y);if("middle"!==e)if(!0===this.options.smooth.enabled){var g=this._findBorderPosition(l,t,{via:i}),y=this.getPoint(g.t+v*("from"===e?1:-1),i);s=Math.atan2(g.y-y.y,g.x-y.x),a=g}else s=Math.atan2(l.y-h.y,l.x-h.x),a=this._findBorderPosition(l,t);else{var m=(c?-v:v)/2,b=this.getPoint(.5+m,i),w=this.getPoint(.5-m,i);s=Math.atan2(b.y-w.y,b.x-w.x),a=this.getPoint(.5,i)}}else{var A=sH(this._getCircleData(t),3),E=A[0],k=A[1],C=A[2];if("from"===e){var x=this.options.selfReference.angle,S=this.options.selfReference.angle+Math.PI,I=this._findBorderPositionCircle(this.from,t,{x:E,y:k,low:x,high:S,direction:-1});s=-2*I.t*Math.PI+1.5*Math.PI+.1*Math.PI,a=I}else if("to"===e){var M=this.options.selfReference.angle,O=this.options.selfReference.angle+Math.PI,D=this._findBorderPositionCircle(this.from,t,{x:E,y:k,low:M,high:O,direction:1});s=-2*D.t*Math.PI+1.5*Math.PI-1.1*Math.PI,a=D}else{var R=this.options.selfReference.angle/(2*Math.PI);a=this._pointOnCircle(E,k,C,R),s=-2*R*Math.PI+1.5*Math.PI+.1*Math.PI}}return{point:a,core:{x:a.x-.9*p*Math.cos(s),y:a.y-.9*p*Math.sin(s)},angle:s,length:p,type:u}}},{key:"drawArrowHead",value:function(t,e,i,o,n){t.strokeStyle=this.getColor(t,e),t.fillStyle=t.strokeStyle,t.lineWidth=e.width,D$.draw(t,n)&&(this.enableShadow(t,e),CG(t).call(t),this.disableShadow(t,e))}},{key:"enableShadow",value:function(t,e){!0===e.shadow&&(t.shadowColor=e.shadowColor,t.shadowBlur=e.shadowSize,t.shadowOffsetX=e.shadowX,t.shadowOffsetY=e.shadowY)}},{key:"disableShadow",value:function(t,e){!0===e.shadow&&(t.shadowColor="rgba(0,0,0,0)",t.shadowBlur=0,t.shadowOffsetX=0,t.shadowOffsetY=0)}},{key:"drawBackground",value:function(t,e){if(!1!==e.background){var i={strokeStyle:t.strokeStyle,lineWidth:t.lineWidth,dashes:t.dashes};t.strokeStyle=e.backgroundColor,t.lineWidth=e.backgroundSize,this.setStrokeDashed(t,e.backgroundDashes),t.stroke(),t.strokeStyle=i.strokeStyle,t.lineWidth=i.lineWidth,t.dashes=i.dashes,this.setStrokeDashed(t,e.dashes)}}},{key:"setStrokeDashed",value:function(t,e){if(!1!==e)if(void 0!==t.setLineDash){var i=EH(e)?e:[5,5];t.setLineDash(i)}else console.warn("setLineDash is not supported in this browser. The dashed stroke cannot be used.");else void 0!==t.setLineDash?t.setLineDash([]):console.warn("setLineDash is not supported in this browser. The dashed stroke cannot be used.")}}]),t}();function P$(t,e){var i=BH(t);if(RJ){var o=RJ(t);e&&(o=aW(o).call(o,(function(e){return QJ(t,e).enumerable}))),i.push.apply(i,o)}return i}function F$(t){for(var e=1;e2&&void 0!==arguments[2]?arguments[2]:this._getViaCoordinates(),r=!1,s=1,a=0,l=this.to,h=this.options.endPointOffset?this.options.endPointOffset.to:0;t.id===this.from.id&&(l=this.from,r=!0,h=this.options.endPointOffset?this.options.endPointOffset.from:0),!1===this.options.arrowStrikethrough&&(h=0);var c=0;do{o=.5*(a+s),i=this.getPoint(o,n);var d=Math.atan2(l.y-i.y,l.x-i.x),u=l.distanceToBorder(e,d)+h-Math.sqrt(Math.pow(i.x-l.x,2)+Math.pow(i.y-l.y,2));if(Math.abs(u)<.2)break;u<0?!1===r?a=o:s=o:!1===r?s=o:a=o,++c}while(a<=s&&c<10);return F$(F$({},i),{},{t:o})}},{key:"_getDistanceToBezierEdge",value:function(t,e,i,o,n,r,s){var a,l,h,c,d,u=1e9,f=t,p=e;for(l=1;l<10;l++)h=.1*l,c=Math.pow(1-h,2)*t+2*h*(1-h)*s.x+Math.pow(h,2)*i,d=Math.pow(1-h,2)*e+2*h*(1-h)*s.y+Math.pow(h,2)*o,l>0&&(u=(a=this._getDistanceToLine(f,p,c,d,n,r))1&&void 0!==arguments[1]?arguments[1]:this.via;if(this.from===this.to){var i=sH(this._getCircleData(),3),o=i[0],n=i[1],r=i[2],s=2*Math.PI*(1-t);return{x:o+r*Math.sin(s),y:n+r-r*(1-Math.cos(s))}}return{x:Math.pow(1-t,2)*this.fromPoint.x+2*t*(1-t)*e.x+Math.pow(t,2)*this.toPoint.x,y:Math.pow(1-t,2)*this.fromPoint.y+2*t*(1-t)*e.y+Math.pow(t,2)*this.toPoint.y}}},{key:"_findBorderPosition",value:function(t,e){return this._findBorderPositionBezier(t,e,this.via)}},{key:"_getDistanceToEdge",value:function(t,e,i,o,n,r){return this._getDistanceToBezierEdge(t,e,i,o,n,r,this.via)}}]),i}(N$);function L$(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var Q$=function(t){s_(i,t);var e=L$(i);function i(t,o,n){return fN(this,i),e.call(this,t,o,n)}return mQ(i,[{key:"_line",value:function(t,e,i){this._bezierCurve(t,e,i)}},{key:"getViaNode",value:function(){return this._getViaCoordinates()}},{key:"_getViaCoordinates",value:function(){var t,e,i=this.options.smooth.roundness,o=this.options.smooth.type,n=Math.abs(this.from.x-this.to.x),r=Math.abs(this.from.y-this.to.y);if("discrete"===o||"diagonalCross"===o){var s,a;s=a=n<=r?i*r:i*n,this.from.x>this.to.x&&(s=-s),this.from.y>=this.to.y&&(a=-a);var l=this.from.x+s,h=this.from.y+a;return"discrete"===o&&(n<=r?l=nthis.to.x&&(t=-t),this.from.y>=this.to.y&&(e=-e);var w=this.from.x+t,A=this.from.y+e;return n<=r?w=this.from.x<=this.to.x?this.to.xw?this.to.x:w:A=this.from.y>=this.to.y?this.to.y>A?this.to.y:A:this.to.y2&&void 0!==arguments[2]?arguments[2]:{};return this._findBorderPositionBezier(t,e,i.via)}},{key:"_getDistanceToEdge",value:function(t,e,i,o,n,r){var s=arguments.length>6&&void 0!==arguments[6]?arguments[6]:this._getViaCoordinates();return this._getDistanceToBezierEdge(t,e,i,o,n,r,s)}},{key:"getPoint",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this._getViaCoordinates(),i=t;return{x:Math.pow(1-i,2)*this.fromPoint.x+2*i*(1-i)*e.x+Math.pow(i,2)*this.toPoint.x,y:Math.pow(1-i,2)*this.fromPoint.y+2*i*(1-i)*e.y+Math.pow(i,2)*this.toPoint.y}}}]),i}(N$);function H$(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var V$=function(t){s_(i,t);var e=H$(i);function i(t,o,n){return fN(this,i),e.call(this,t,o,n)}return mQ(i,[{key:"_getDistanceToBezierEdge2",value:function(t,e,i,o,n,r,s,a){for(var l=1e9,h=t,c=e,d=[0,0,0,0],u=1;u<10;u++){var f=.1*u;d[0]=Math.pow(1-f,3),d[1]=3*f*Math.pow(1-f,2),d[2]=3*Math.pow(f,2)*(1-f),d[3]=Math.pow(f,3);var p=d[0]*t+d[1]*s.x+d[2]*a.x+d[3]*i,v=d[0]*e+d[1]*s.y+d[2]*a.y+d[3]*o;if(u>0){var g=this._getDistanceToLine(h,c,p,v,n,r);l=gMath.abs(r)||!0===this.options.smooth.forceDirection||"horizontal"===this.options.smooth.forceDirection)&&"vertical"!==this.options.smooth.forceDirection?(e=this.from.y,o=this.to.y,t=this.from.x-s*n,i=this.to.x+s*n):(e=this.from.y-s*r,o=this.to.y+s*r,t=this.from.x,i=this.to.x),[{x:t,y:e},{x:i,y:o}]}},{key:"getViaNode",value:function(){return this._getViaCoordinates()}},{key:"_findBorderPosition",value:function(t,e){return this._findBorderPositionBezier(t,e)}},{key:"_getDistanceToEdge",value:function(t,e,i,o,n,r){var s=sH(arguments.length>6&&void 0!==arguments[6]?arguments[6]:this._getViaCoordinates(),2),a=s[0],l=s[1];return this._getDistanceToBezierEdge2(t,e,i,o,n,r,a,l)}},{key:"getPoint",value:function(t){var e=sH(arguments.length>1&&void 0!==arguments[1]?arguments[1]:this._getViaCoordinates(),2),i=e[0],o=e[1],n=t,r=[Math.pow(1-n,3),3*n*Math.pow(1-n,2),3*Math.pow(n,2)*(1-n),Math.pow(n,3)];return{x:r[0]*this.fromPoint.x+r[1]*i.x+r[2]*o.x+r[3]*this.toPoint.x,y:r[0]*this.fromPoint.y+r[1]*i.y+r[2]*o.y+r[3]*this.toPoint.y}}}]),i}(V$);function K$(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var q$=function(t){s_(i,t);var e=K$(i);function i(t,o,n){return fN(this,i),e.call(this,t,o,n)}return mQ(i,[{key:"_line",value:function(t,e){t.beginPath(),t.moveTo(this.fromPoint.x,this.fromPoint.y),t.lineTo(this.toPoint.x,this.toPoint.y),this.enableShadow(t,e),t.stroke(),this.disableShadow(t,e)}},{key:"getViaNode",value:function(){}},{key:"getPoint",value:function(t){return{x:(1-t)*this.fromPoint.x+t*this.toPoint.x,y:(1-t)*this.fromPoint.y+t*this.toPoint.y}}},{key:"_findBorderPosition",value:function(t,e){var i=this.to,o=this.from;t.id===this.from.id&&(i=this.from,o=this.to);var n=Math.atan2(i.y-o.y,i.x-o.x),r=i.x-o.x,s=i.y-o.y,a=Math.sqrt(r*r+s*s),l=(a-t.distanceToBorder(e,n))/a;return{x:(1-l)*o.x+l*i.x,y:(1-l)*o.y+l*i.y,t:0}}},{key:"_getDistanceToEdge",value:function(t,e,i,o,n,r){return this._getDistanceToLine(t,e,i,o,n,r)}}]),i}(z$),Y$=function(){function t(e,i,o,n,r){if(fN(this,t),void 0===i)throw new Error("No body provided");this.options=Zq(n),this.globalOptions=n,this.defaultOptions=r,this.body=i,this.imagelist=o,this.id=void 0,this.fromId=void 0,this.toId=void 0,this.selected=!1,this.hover=!1,this.labelDirty=!0,this.baseWidth=this.options.width,this.baseFontSize=this.options.font.size,this.from=void 0,this.to=void 0,this.edgeType=void 0,this.connected=!1,this.labelModule=new NX(this.body,this.options,!0),this.setOptions(e)}return mQ(t,[{key:"setOptions",value:function(e){if(e){var i=void 0!==e.physics&&this.options.physics!==e.physics||void 0!==e.hidden&&(this.options.hidden||!1)!==(e.hidden||!1)||void 0!==e.from&&this.options.from!==e.from||void 0!==e.to&&this.options.to!==e.to;t.parseOptions(this.options,e,!0,this.globalOptions),void 0!==e.id&&(this.id=e.id),void 0!==e.from&&(this.fromId=e.from),void 0!==e.to&&(this.toId=e.to),void 0!==e.title&&(this.title=e.title),void 0!==e.value&&(e.value=uX(e.value));var o=[e,this.options,this.defaultOptions];return this.chooser=bX("edge",o),this.updateLabelModule(e),i=this.updateEdgeType()||i,this._setInteractionWidths(),this.connect(),i}}},{key:"getFormattingValues",value:function(){var t=!0===this.options.arrows.to||!0===this.options.arrows.to.enabled,e=!0===this.options.arrows.from||!0===this.options.arrows.from.enabled,i=!0===this.options.arrows.middle||!0===this.options.arrows.middle.enabled,o=this.options.color.inherit,n={toArrow:t,toArrowScale:this.options.arrows.to.scaleFactor,toArrowType:this.options.arrows.to.type,toArrowSrc:this.options.arrows.to.src,toArrowImageWidth:this.options.arrows.to.imageWidth,toArrowImageHeight:this.options.arrows.to.imageHeight,middleArrow:i,middleArrowScale:this.options.arrows.middle.scaleFactor,middleArrowType:this.options.arrows.middle.type,middleArrowSrc:this.options.arrows.middle.src,middleArrowImageWidth:this.options.arrows.middle.imageWidth,middleArrowImageHeight:this.options.arrows.middle.imageHeight,fromArrow:e,fromArrowScale:this.options.arrows.from.scaleFactor,fromArrowType:this.options.arrows.from.type,fromArrowSrc:this.options.arrows.from.src,fromArrowImageWidth:this.options.arrows.from.imageWidth,fromArrowImageHeight:this.options.arrows.from.imageHeight,arrowStrikethrough:this.options.arrowStrikethrough,color:o?void 0:this.options.color.color,inheritsColor:o,opacity:this.options.color.opacity,hidden:this.options.hidden,length:this.options.length,shadow:this.options.shadow.enabled,shadowColor:this.options.shadow.color,shadowSize:this.options.shadow.size,shadowX:this.options.shadow.x,shadowY:this.options.shadow.y,dashes:this.options.dashes,width:this.options.width,background:this.options.background.enabled,backgroundColor:this.options.background.color,backgroundSize:this.options.background.size,backgroundDashes:this.options.background.dashes};if(this.selected||this.hover)if(!0===this.chooser){if(this.selected){var r=this.options.selectionWidth;"function"==typeof r?n.width=r(n.width):"number"==typeof r&&(n.width+=r),n.width=Math.max(n.width,.3/this.body.view.scale),n.color=this.options.color.highlight,n.shadow=this.options.shadow.enabled}else if(this.hover){var s=this.options.hoverWidth;"function"==typeof s?n.width=s(n.width):"number"==typeof s&&(n.width+=s),n.width=Math.max(n.width,.3/this.body.view.scale),n.color=this.options.color.hover,n.shadow=this.options.shadow.enabled}}else"function"==typeof this.chooser&&(this.chooser(n,this.options.id,this.selected,this.hover),void 0!==n.color&&(n.inheritsColor=!1),!1===n.shadow&&(n.shadowColor===this.options.shadow.color&&n.shadowSize===this.options.shadow.size&&n.shadowX===this.options.shadow.x&&n.shadowY===this.options.shadow.y||(n.shadow=!0)));else n.shadow=this.options.shadow.enabled,n.width=Math.max(n.width,.3/this.body.view.scale);return n}},{key:"updateLabelModule",value:function(t){var e=[t,this.options,this.globalOptions,this.defaultOptions];this.labelModule.update(this.options,e),void 0!==this.labelModule.baseSize&&(this.baseFontSize=this.labelModule.baseSize)}},{key:"updateEdgeType",value:function(){var t=this.options.smooth,e=!1,i=!0;return void 0!==this.edgeType&&((this.edgeType instanceof U$&&!0===t.enabled&&"dynamic"===t.type||this.edgeType instanceof G$&&!0===t.enabled&&"cubicBezier"===t.type||this.edgeType instanceof Q$&&!0===t.enabled&&"dynamic"!==t.type&&"cubicBezier"!==t.type||this.edgeType instanceof q$&&!1===t.type.enabled)&&(i=!1),!0===i&&(e=this.cleanup())),!0===i?!0===t.enabled?"dynamic"===t.type?(e=!0,this.edgeType=new U$(this.options,this.body,this.labelModule)):"cubicBezier"===t.type?this.edgeType=new G$(this.options,this.body,this.labelModule):this.edgeType=new Q$(this.options,this.body,this.labelModule):this.edgeType=new q$(this.options,this.body,this.labelModule):this.edgeType.setOptions(this.options),e}},{key:"connect",value:function(){this.disconnect(),this.from=this.body.nodes[this.fromId]||void 0,this.to=this.body.nodes[this.toId]||void 0,this.connected=void 0!==this.from&&void 0!==this.to,!0===this.connected?(this.from.attachEdge(this),this.to.attachEdge(this)):(this.from&&this.from.detachEdge(this),this.to&&this.to.detachEdge(this)),this.edgeType.connect()}},{key:"disconnect",value:function(){this.from&&(this.from.detachEdge(this),this.from=void 0),this.to&&(this.to.detachEdge(this),this.to=void 0),this.connected=!1}},{key:"getTitle",value:function(){return this.title}},{key:"isSelected",value:function(){return this.selected}},{key:"getValue",value:function(){return this.options.value}},{key:"setValueRange",value:function(t,e,i){if(void 0!==this.options.value){var o=this.options.scaling.customScalingFunction(t,e,i,this.options.value),n=this.options.scaling.max-this.options.scaling.min;if(!0===this.options.scaling.label.enabled){var r=this.options.scaling.label.max-this.options.scaling.label.min;this.options.font.size=this.options.scaling.label.min+o*r}this.options.width=this.options.scaling.min+o*n}else this.options.width=this.baseWidth,this.options.font.size=this.baseFontSize;this._setInteractionWidths(),this.updateLabelModule()}},{key:"_setInteractionWidths",value:function(){"function"==typeof this.options.hoverWidth?this.edgeType.hoverWidth=this.options.hoverWidth(this.options.width):this.edgeType.hoverWidth=this.options.hoverWidth+this.options.width,"function"==typeof this.options.selectionWidth?this.edgeType.selectionWidth=this.options.selectionWidth(this.options.width):this.edgeType.selectionWidth=this.options.selectionWidth+this.options.width}},{key:"draw",value:function(t){var e=this.getFormattingValues();if(!e.hidden){var i=this.edgeType.getViaNode();this.edgeType.drawLine(t,e,this.selected,this.hover,i),this.drawLabel(t,i)}}},{key:"drawArrows",value:function(t){var e=this.getFormattingValues();if(!e.hidden){var i=this.edgeType.getViaNode(),o={};this.edgeType.fromPoint=this.edgeType.from,this.edgeType.toPoint=this.edgeType.to,e.fromArrow&&(o.from=this.edgeType.getArrowData(t,"from",i,this.selected,this.hover,e),!1===e.arrowStrikethrough&&(this.edgeType.fromPoint=o.from.core),e.fromArrowSrc&&(o.from.image=this.imagelist.load(e.fromArrowSrc)),e.fromArrowImageWidth&&(o.from.imageWidth=e.fromArrowImageWidth),e.fromArrowImageHeight&&(o.from.imageHeight=e.fromArrowImageHeight)),e.toArrow&&(o.to=this.edgeType.getArrowData(t,"to",i,this.selected,this.hover,e),!1===e.arrowStrikethrough&&(this.edgeType.toPoint=o.to.core),e.toArrowSrc&&(o.to.image=this.imagelist.load(e.toArrowSrc)),e.toArrowImageWidth&&(o.to.imageWidth=e.toArrowImageWidth),e.toArrowImageHeight&&(o.to.imageHeight=e.toArrowImageHeight)),e.middleArrow&&(o.middle=this.edgeType.getArrowData(t,"middle",i,this.selected,this.hover,e),e.middleArrowSrc&&(o.middle.image=this.imagelist.load(e.middleArrowSrc)),e.middleArrowImageWidth&&(o.middle.imageWidth=e.middleArrowImageWidth),e.middleArrowImageHeight&&(o.middle.imageHeight=e.middleArrowImageHeight)),e.fromArrow&&this.edgeType.drawArrowHead(t,e,this.selected,this.hover,o.from),e.middleArrow&&this.edgeType.drawArrowHead(t,e,this.selected,this.hover,o.middle),e.toArrow&&this.edgeType.drawArrowHead(t,e,this.selected,this.hover,o.to)}}},{key:"drawLabel",value:function(t,e){if(void 0!==this.options.label){var i,o=this.from,n=this.to;if(this.labelModule.differentState(this.selected,this.hover)&&this.labelModule.getTextSize(t,this.selected,this.hover),o.id!=n.id){this.labelModule.pointToSelf=!1,i=this.edgeType.getPoint(.5,e),t.save();var r=this._getRotation(t);0!=r.angle&&(t.translate(r.x,r.y),t.rotate(r.angle)),this.labelModule.draw(t,i.x,i.y,this.selected,this.hover),t.restore()}else{this.labelModule.pointToSelf=!0;var s=EX(t,this.options.selfReference.angle,this.options.selfReference.size,o);i=this._pointOnCircle(s.x,s.y,this.options.selfReference.size,this.options.selfReference.angle),this.labelModule.draw(t,i.x,i.y,this.selected,this.hover)}}}},{key:"getItemsOnPoint",value:function(t){var e=[];if(this.labelModule.visible()){var i=this._getRotation();wX(this.labelModule.getSize(),t,i)&&e.push({edgeId:this.id,labelId:0})}var o={left:t.x,top:t.y};return this.isOverlappingWith(o)&&e.push({edgeId:this.id}),e}},{key:"isOverlappingWith",value:function(t){if(this.connected){var e=this.from.x,i=this.from.y,o=this.to.x,n=this.to.y,r=t.left,s=t.top;return this.edgeType.getDistanceToEdge(e,i,o,n,r,s)<10}return!1}},{key:"_getRotation",value:function(t){var e=this.edgeType.getViaNode(),i=this.edgeType.getPoint(.5,e);void 0!==t&&this.labelModule.calculateLabelSize(t,this.selected,this.hover,i.x,i.y);var o={x:i.x,y:this.labelModule.size.yLine,angle:0};if(!this.labelModule.visible())return o;if("horizontal"===this.options.font.align)return o;var n=this.from.y-this.to.y,r=this.from.x-this.to.x,s=Math.atan2(n,r);return(s<-1&&r<0||s>0&&r<0)&&(s+=Math.PI),o.angle=s,o}},{key:"_pointOnCircle",value:function(t,e,i,o){return{x:t+i*Math.cos(o),y:e-i*Math.sin(o)}}},{key:"select",value:function(){this.selected=!0}},{key:"unselect",value:function(){this.selected=!1}},{key:"cleanup",value:function(){return this.edgeType.cleanup()}},{key:"remove",value:function(){this.cleanup(),this.disconnect(),delete this.body.edges[this.id]}},{key:"endPointsValid",value:function(){return void 0!==this.body.nodes[this.fromId]&&void 0!==this.body.nodes[this.toId]}}],[{key:"parseOptions",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},n=arguments.length>4&&void 0!==arguments[4]&&arguments[4];if(Pq(["endPointOffset","arrowStrikethrough","id","from","hidden","hoverWidth","labelHighlightBold","length","line","opacity","physics","scaling","selectionWidth","selfReferenceSize","selfReference","to","title","value","width","font","chosen","widthConstraint"],t,e,i),void 0!==e.endPointOffset&&void 0!==e.endPointOffset.from&&(kJ(e.endPointOffset.from)?t.endPointOffset.from=e.endPointOffset.from:(t.endPointOffset.from=void 0!==o.endPointOffset.from?o.endPointOffset.from:0,console.error("endPointOffset.from is not a valid number"))),void 0!==e.endPointOffset&&void 0!==e.endPointOffset.to&&(kJ(e.endPointOffset.to)?t.endPointOffset.to=e.endPointOffset.to:(t.endPointOffset.to=void 0!==o.endPointOffset.to?o.endPointOffset.to:0,console.error("endPointOffset.to is not a valid number"))),AX(e.label)?t.label=e.label:AX(t.label)||(t.label=void 0),Jq(t,e,"smooth",o),Jq(t,e,"shadow",o),Jq(t,e,"background",o),void 0!==e.dashes&&null!==e.dashes?t.dashes=e.dashes:!0===i&&null===e.dashes&&(t.dashes=WW(o.dashes)),void 0!==e.scaling&&null!==e.scaling?(void 0!==e.scaling.min&&(t.scaling.min=e.scaling.min),void 0!==e.scaling.max&&(t.scaling.max=e.scaling.max),Jq(t.scaling,e.scaling,"label",o.scaling)):!0===i&&null===e.scaling&&(t.scaling=WW(o.scaling)),void 0!==e.arrows&&null!==e.arrows)if("string"==typeof e.arrows){var r=e.arrows.toLowerCase();t.arrows.to.enabled=-1!=LW(r).call(r,"to"),t.arrows.middle.enabled=-1!=LW(r).call(r,"middle"),t.arrows.from.enabled=-1!=LW(r).call(r,"from")}else{if("object"!==pQ(e.arrows))throw new Error("The arrow newOptions can only be an object or a string. Refer to the documentation. You used:"+YW(e.arrows));Jq(t.arrows,e.arrows,"to",o.arrows),Jq(t.arrows,e.arrows,"middle",o.arrows),Jq(t.arrows,e.arrows,"from",o.arrows)}else!0===i&&null===e.arrows&&(t.arrows=WW(o.arrows));if(void 0!==e.color&&null!==e.color){var s=Dq(e.color)?{color:e.color,highlight:e.color,hover:e.color,inherit:!1,opacity:1}:e.color,a=t.color;if(n)Tq(a,o.color,!1,i);else for(var l in a)Object.prototype.hasOwnProperty.call(a,l)&&delete a[l];if(Dq(a))a.color=a,a.highlight=a,a.hover=a,a.inherit=!1,void 0===s.opacity&&(a.opacity=1);else{var h=!1;void 0!==s.color&&(a.color=s.color,h=!0),void 0!==s.highlight&&(a.highlight=s.highlight,h=!0),void 0!==s.hover&&(a.hover=s.hover,h=!0),void 0!==s.inherit&&(a.inherit=s.inherit),void 0!==s.opacity&&(a.opacity=Math.min(1,Math.max(0,s.opacity))),!0===h?a.inherit=!1:void 0===a.inherit&&(a.inherit="from")}}else!0===i&&null===e.color&&(t.color=Zq(o.color));!0===i&&null===e.font&&(t.font=Zq(o.font)),Object.prototype.hasOwnProperty.call(e,"selfReferenceSize")&&(console.warn("The selfReferenceSize property has been deprecated. Please use selfReference property instead. The selfReference can be set like thise selfReference:{size:30, angle:Math.PI / 4}"),t.selfReference.size=e.selfReferenceSize)}}]),t}(),Z$=function(){function t(e,i,o){var n,r=this;fN(this,t),this.body=e,this.images=i,this.groups=o,this.body.functions.createEdge=VB(n=this.create).call(n,this),this.edgesListeners={add:function(t,e){r.add(e.items)},update:function(t,e){r.update(e.items)},remove:function(t,e){r.remove(e.items)}},this.options={},this.defaultOptions={arrows:{to:{enabled:!1,scaleFactor:1,type:"arrow"},middle:{enabled:!1,scaleFactor:1,type:"arrow"},from:{enabled:!1,scaleFactor:1,type:"arrow"}},endPointOffset:{from:0,to:0},arrowStrikethrough:!0,color:{color:"#848484",highlight:"#848484",hover:"#848484",inherit:"from",opacity:1},dashes:!1,font:{color:"#343434",size:14,face:"arial",background:"none",strokeWidth:2,strokeColor:"#ffffff",align:"horizontal",multi:!1,vadjust:0,bold:{mod:"bold"},boldital:{mod:"bold italic"},ital:{mod:"italic"},mono:{mod:"",size:15,face:"courier new",vadjust:2}},hidden:!1,hoverWidth:1.5,label:void 0,labelHighlightBold:!0,length:void 0,physics:!0,scaling:{min:1,max:15,label:{enabled:!0,min:14,max:30,maxVisible:30,drawThreshold:5},customScalingFunction:function(t,e,i,o){if(e===t)return.5;var n=1/(e-t);return Math.max(0,(o-t)*n)}},selectionWidth:1.5,selfReference:{size:20,angle:Math.PI/4,renderBehindTheNode:!0},shadow:{enabled:!1,color:"rgba(0,0,0,0.5)",size:10,x:5,y:5},background:{enabled:!1,color:"rgba(111,111,111,1)",size:10,dashes:!1},smooth:{enabled:!0,type:"dynamic",forceDirection:"none",roundness:.5},title:void 0,width:1,value:void 0},Tq(this.options,this.defaultOptions),this.bindEventListeners()}return mQ(t,[{key:"bindEventListeners",value:function(){var t,e,i=this;this.body.emitter.on("_forceDisableDynamicCurves",(function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];"dynamic"===t&&(t="continuous");var o=!1;for(var n in i.body.edges)if(Object.prototype.hasOwnProperty.call(i.body.edges,n)){var r=i.body.edges[n],s=i.body.data.edges.get(n);if(null!=s){var a=s.smooth;void 0!==a&&!0===a.enabled&&"dynamic"===a.type&&(void 0===t?r.setOptions({smooth:!1}):r.setOptions({smooth:{type:t}}),o=!0)}}!0===e&&!0===o&&i.body.emitter.emit("_dataChanged")})),this.body.emitter.on("_dataUpdated",(function(){i.reconnectEdges()})),this.body.emitter.on("refreshEdges",VB(t=this.refresh).call(t,this)),this.body.emitter.on("refresh",VB(e=this.refresh).call(e,this)),this.body.emitter.on("destroy",(function(){Uq(i.edgesListeners,(function(t,e){i.body.data.edges&&i.body.data.edges.off(e,t)})),delete i.body.functions.createEdge,delete i.edgesListeners.add,delete i.edgesListeners.update,delete i.edgesListeners.remove,delete i.edgesListeners}))}},{key:"setOptions",value:function(t){if(void 0!==t){Y$.parseOptions(this.options,t,!0,this.defaultOptions,!0);var e=!1;if(void 0!==t.smooth)for(var i in this.body.edges)Object.prototype.hasOwnProperty.call(this.body.edges,i)&&(e=this.body.edges[i].updateEdgeType()||e);if(void 0!==t.font)for(var o in this.body.edges)Object.prototype.hasOwnProperty.call(this.body.edges,o)&&this.body.edges[o].updateLabelModule();void 0===t.hidden&&void 0===t.physics&&!0!==e||this.body.emitter.emit("_dataChanged")}}},{key:"setData",value:function(t){var e=this,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],o=this.body.data.edges;if(iM("id",t))this.body.data.edges=t;else if(EH(t))this.body.data.edges=new eM,this.body.data.edges.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.body.data.edges=new eM}if(o&&Uq(this.edgesListeners,(function(t,e){o.off(e,t)})),this.body.edges={},this.body.data.edges){Uq(this.edgesListeners,(function(t,i){e.body.data.edges.on(i,t)}));var n=this.body.data.edges.getIds();this.add(n,!0)}this.body.emitter.emit("_adjustEdgesForHierarchicalLayout"),!1===i&&this.body.emitter.emit("_dataChanged")}},{key:"add",value:function(t){for(var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=this.body.edges,o=this.body.data.edges,n=0;n1&&void 0!==arguments[1])||arguments[1];if(0!==t.length){var i=this.body.edges;Uq(t,(function(t){var e=i[t];void 0!==e&&e.remove()})),e&&this.body.emitter.emit("_dataChanged")}}},{key:"refresh",value:function(){var t=this;Uq(this.body.edges,(function(e,i){var o=t.body.data.edges.get(i);void 0!==o&&e.setOptions(o)}))}},{key:"create",value:function(t){return new Y$(t,this.body,this.images,this.options,this.defaultOptions)}},{key:"reconnectEdges",value:function(){var t,e=this.body.nodes,i=this.body.edges;for(t in e)Object.prototype.hasOwnProperty.call(e,t)&&(e[t].edges=[]);for(t in i)if(Object.prototype.hasOwnProperty.call(i,t)){var o=i[t];o.from=null,o.to=null,o.connect()}}},{key:"getConnectedNodes",value:function(t){var e=[];if(void 0!==this.body.edges[t]){var i=this.body.edges[t];void 0!==i.fromId&&e.push(i.fromId),void 0!==i.toId&&e.push(i.toId)}return e}},{key:"_updateState",value:function(){this._addMissingEdges(),this._removeInvalidEdges()}},{key:"_removeInvalidEdges",value:function(){var t=this,e=[];Uq(this.body.edges,(function(i,o){var n=t.body.nodes[i.toId],r=t.body.nodes[i.fromId];void 0!==n&&!0===n.isCluster||void 0!==r&&!0===r.isCluster||void 0!==n&&void 0!==r||e.push(o)})),this.remove(e,!1)}},{key:"_addMissingEdges",value:function(){var t=this.body.data.edges;if(null!=t){var e=this.body.edges,i=[];ZH(t).call(t,(function(t,o){void 0===e[o]&&i.push(o)})),this.add(i,!0)}}}]),t}(),J$=function(){function t(e,i,o){fN(this,t),this.body=e,this.physicsBody=i,this.barnesHutTree,this.setOptions(o),this._rng=Eq("BARNES HUT SOLVER")}return mQ(t,[{key:"setOptions",value:function(t){this.options=t,this.thetaInversed=1/this.options.theta,this.overlapAvoidanceFactor=1-Math.max(0,Math.min(1,this.options.avoidOverlap))}},{key:"solve",value:function(){if(0!==this.options.gravitationalConstant&&this.physicsBody.physicsNodeIndices.length>0){var t,e=this.body.nodes,i=this.physicsBody.physicsNodeIndices,o=i.length,n=this._formBarnesHutTree(e,i);this.barnesHutTree=n;for(var r=0;r0&&this._getForceContributions(n.root,t)}}},{key:"_getForceContributions",value:function(t,e){this._getForceContribution(t.children.NW,e),this._getForceContribution(t.children.NE,e),this._getForceContribution(t.children.SW,e),this._getForceContribution(t.children.SE,e)}},{key:"_getForceContribution",value:function(t,e){if(t.childrenCount>0){var i=t.centerOfMass.x-e.x,o=t.centerOfMass.y-e.y,n=Math.sqrt(i*i+o*o);n*t.calcSize>this.thetaInversed?this._calculateForces(n,i,o,e,t):4===t.childrenCount?this._getForceContributions(t,e):t.children.data.id!=e.id&&this._calculateForces(n,i,o,e,t)}}},{key:"_calculateForces",value:function(t,e,i,o,n){0===t&&(e=t=.1),this.overlapAvoidanceFactor<1&&o.shape.radius&&(t=Math.max(.1+this.overlapAvoidanceFactor*o.shape.radius,t-o.shape.radius));var r=this.options.gravitationalConstant*n.mass*o.options.mass/Math.pow(t,3),s=e*r,a=i*r;this.physicsBody.forces[o.id].x+=s,this.physicsBody.forces[o.id].y+=a}},{key:"_formBarnesHutTree",value:function(t,e){for(var i,o=e.length,n=t[e[0]].x,r=t[e[0]].y,s=t[e[0]].x,a=t[e[0]].y,l=1;l0&&(cs&&(s=c),da&&(a=d))}var u=Math.abs(s-n)-Math.abs(a-r);u>0?(r-=.5*u,a+=.5*u):(n+=.5*u,s-=.5*u);var f=Math.max(1e-5,Math.abs(s-n)),p=.5*f,v=.5*(n+s),g=.5*(r+a),y={root:{centerOfMass:{x:0,y:0},mass:0,range:{minX:v-p,maxX:v+p,minY:g-p,maxY:g+p},size:f,calcSize:1/f,children:{data:null},maxWidth:0,level:0,childrenCount:4}};this._splitBranch(y.root);for(var m=0;m0&&this._placeInTree(y.root,i);return y}},{key:"_updateBranchMass",value:function(t,e){var i=t.centerOfMass,o=t.mass+e.options.mass,n=1/o;i.x=i.x*t.mass+e.x*e.options.mass,i.x*=n,i.y=i.y*t.mass+e.y*e.options.mass,i.y*=n,t.mass=o;var r=Math.max(Math.max(e.height,e.radius),e.width);t.maxWidth=t.maxWidthe.x?n.maxY>e.y?"NW":"SW":n.maxY>e.y?"NE":"SE",this._placeInRegion(t,e,o)}},{key:"_placeInRegion",value:function(t,e,i){var o=t.children[i];switch(o.childrenCount){case 0:o.children.data=e,o.childrenCount=1,this._updateBranchMass(o,e);break;case 1:o.children.data.x===e.x&&o.children.data.y===e.y?(e.x+=this._rng(),e.y+=this._rng()):(this._splitBranch(o),this._placeInTree(o,e));break;case 4:this._placeInTree(o,e)}}},{key:"_splitBranch",value:function(t){var e=null;1===t.childrenCount&&(e=t.children.data,t.mass=0,t.centerOfMass.x=0,t.centerOfMass.y=0),t.childrenCount=4,t.children.data=null,this._insertRegion(t,"NW"),this._insertRegion(t,"NE"),this._insertRegion(t,"SW"),this._insertRegion(t,"SE"),null!=e&&this._placeInTree(t,e)}},{key:"_insertRegion",value:function(t,e){var i,o,n,r,s=.5*t.size;switch(e){case"NW":i=t.range.minX,o=t.range.minX+s,n=t.range.minY,r=t.range.minY+s;break;case"NE":i=t.range.minX+s,o=t.range.maxX,n=t.range.minY,r=t.range.minY+s;break;case"SW":i=t.range.minX,o=t.range.minX+s,n=t.range.minY+s,r=t.range.maxY;break;case"SE":i=t.range.minX+s,o=t.range.maxX,n=t.range.minY+s,r=t.range.maxY}t.children[e]={centerOfMass:{x:0,y:0},mass:0,range:{minX:i,maxX:o,minY:n,maxY:r},size:.5*t.size,calcSize:2*t.calcSize,children:{data:null},maxWidth:0,level:t.level+1,childrenCount:0}}},{key:"_debug",value:function(t,e){void 0!==this.barnesHutTree&&(t.lineWidth=1,this._drawBranch(this.barnesHutTree.root,t,e))}},{key:"_drawBranch",value:function(t,e,i){void 0===i&&(i="#FF0000"),4===t.childrenCount&&(this._drawBranch(t.children.NW,e),this._drawBranch(t.children.NE,e),this._drawBranch(t.children.SE,e),this._drawBranch(t.children.SW,e)),e.strokeStyle=i,e.beginPath(),e.moveTo(t.range.minX,t.range.minY),e.lineTo(t.range.maxX,t.range.minY),e.stroke(),e.beginPath(),e.moveTo(t.range.maxX,t.range.minY),e.lineTo(t.range.maxX,t.range.maxY),e.stroke(),e.beginPath(),e.moveTo(t.range.maxX,t.range.maxY),e.lineTo(t.range.minX,t.range.maxY),e.stroke(),e.beginPath(),e.moveTo(t.range.minX,t.range.maxY),e.lineTo(t.range.minX,t.range.minY),e.stroke()}}]),t}(),X$=function(){function t(e,i,o){fN(this,t),this._rng=Eq("REPULSION SOLVER"),this.body=e,this.physicsBody=i,this.setOptions(o)}return mQ(t,[{key:"setOptions",value:function(t){this.options=t}},{key:"solve",value:function(){for(var t,e,i,o,n,r,s,a,l=this.body.nodes,h=this.physicsBody.physicsNodeIndices,c=this.physicsBody.forces,d=this.options.nodeDistance,u=-2/3/d,f=4/3,p=0;p0){var r=n.edges.length+1,s=this.options.centralGravity*r*n.options.mass;o[n.id].x=e*s,o[n.id].y=i*s}}}]),i}(e0),s0=function(){function t(e){fN(this,t),this.body=e,this.physicsBody={physicsNodeIndices:[],physicsEdgeIndices:[],forces:{},velocities:{}},this.physicsEnabled=!0,this.simulationInterval=1e3/60,this.requiresTimeout=!0,this.previousStates={},this.referenceState={},this.freezeCache={},this.renderTimer=void 0,this.adaptiveTimestep=!1,this.adaptiveTimestepEnabled=!1,this.adaptiveCounter=0,this.adaptiveInterval=3,this.stabilized=!1,this.startedStabilization=!1,this.stabilizationIterations=0,this.ready=!1,this.options={},this.defaultOptions={enabled:!0,barnesHut:{theta:.5,gravitationalConstant:-2e3,centralGravity:.3,springLength:95,springConstant:.04,damping:.09,avoidOverlap:0},forceAtlas2Based:{theta:.5,gravitationalConstant:-50,centralGravity:.01,springConstant:.08,springLength:100,damping:.4,avoidOverlap:0},repulsion:{centralGravity:.2,springLength:200,springConstant:.05,nodeDistance:100,damping:.09,avoidOverlap:0},hierarchicalRepulsion:{centralGravity:0,springLength:100,springConstant:.01,nodeDistance:120,damping:.09},maxVelocity:50,minVelocity:.75,solver:"barnesHut",stabilization:{enabled:!0,iterations:1e3,updateInterval:50,onlyDynamicEdges:!1,fit:!0},timestep:.5,adaptiveTimestep:!0,wind:{x:0,y:0}},AB(this.options,this.defaultOptions),this.timestep=.5,this.layoutFailed=!1,this.bindEventListeners()}return mQ(t,[{key:"bindEventListeners",value:function(){var t=this;this.body.emitter.on("initPhysics",(function(){t.initPhysics()})),this.body.emitter.on("_layoutFailed",(function(){t.layoutFailed=!0})),this.body.emitter.on("resetPhysics",(function(){t.stopSimulation(),t.ready=!1})),this.body.emitter.on("disablePhysics",(function(){t.physicsEnabled=!1,t.stopSimulation()})),this.body.emitter.on("restorePhysics",(function(){t.setOptions(t.options),!0===t.ready&&t.startSimulation()})),this.body.emitter.on("startSimulation",(function(){!0===t.ready&&t.startSimulation()})),this.body.emitter.on("stopSimulation",(function(){t.stopSimulation()})),this.body.emitter.on("destroy",(function(){t.stopSimulation(!1),t.body.emitter.off()})),this.body.emitter.on("_dataChanged",(function(){t.updatePhysicsData()}))}},{key:"setOptions",value:function(t){if(void 0!==t)if(!1===t)this.options.enabled=!1,this.physicsEnabled=!1,this.stopSimulation();else if(!0===t)this.options.enabled=!0,this.physicsEnabled=!0,this.startSimulation();else{this.physicsEnabled=!0,Fq(["stabilization"],this.options,t),Jq(this.options,t,"stabilization"),void 0===t.enabled&&(this.options.enabled=!0),!1===this.options.enabled&&(this.physicsEnabled=!1,this.stopSimulation());var e=this.options.wind;e&&(("number"!=typeof e.x||wJ(e.x))&&(e.x=0),("number"!=typeof e.y||wJ(e.y))&&(e.y=0)),this.timestep=this.options.timestep}this.init()}},{key:"init",value:function(){var t;"forceAtlas2Based"===this.options.solver?(t=this.options.forceAtlas2Based,this.nodesSolver=new o0(this.body,this.physicsBody,t),this.edgesSolver=new $$(this.body,this.physicsBody,t),this.gravitySolver=new r0(this.body,this.physicsBody,t)):"repulsion"===this.options.solver?(t=this.options.repulsion,this.nodesSolver=new X$(this.body,this.physicsBody,t),this.edgesSolver=new $$(this.body,this.physicsBody,t),this.gravitySolver=new e0(this.body,this.physicsBody,t)):"hierarchicalRepulsion"===this.options.solver?(t=this.options.hierarchicalRepulsion,this.nodesSolver=new _$(this.body,this.physicsBody,t),this.edgesSolver=new t0(this.body,this.physicsBody,t),this.gravitySolver=new e0(this.body,this.physicsBody,t)):(t=this.options.barnesHut,this.nodesSolver=new J$(this.body,this.physicsBody,t),this.edgesSolver=new $$(this.body,this.physicsBody,t),this.gravitySolver=new e0(this.body,this.physicsBody,t)),this.modelOptions=t}},{key:"initPhysics",value:function(){!0===this.physicsEnabled&&!0===this.options.enabled?!0===this.options.stabilization.enabled?this.stabilize():(this.stabilized=!1,this.ready=!0,this.body.emitter.emit("fit",{},this.layoutFailed),this.startSimulation()):(this.ready=!0,this.body.emitter.emit("fit"))}},{key:"startSimulation",value:function(){var t;!0===this.physicsEnabled&&!0===this.options.enabled?(this.stabilized=!1,this.adaptiveTimestep=!1,this.body.emitter.emit("_resizeNodes"),void 0===this.viewFunction&&(this.viewFunction=VB(t=this.simulationStep).call(t,this),this.body.emitter.on("initRedraw",this.viewFunction),this.body.emitter.emit("_startRendering"))):this.body.emitter.emit("_redraw")}},{key:"stopSimulation",value:function(){var t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];this.stabilized=!0,!0===t&&this._emitStabilized(),void 0!==this.viewFunction&&(this.body.emitter.off("initRedraw",this.viewFunction),this.viewFunction=void 0,!0===t&&this.body.emitter.emit("_stopRendering"))}},{key:"simulationStep",value:function(){var t=TH();this.physicsTick(),(TH()-t<.4*this.simulationInterval||!0===this.runDoubleSpeed)&&!1===this.stabilized&&(this.physicsTick(),this.runDoubleSpeed=!0),!0===this.stabilized&&this.stopSimulation()}},{key:"_emitStabilized",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.stabilizationIterations;(this.stabilizationIterations>1||!0===this.startedStabilization)&&fG((function(){t.body.emitter.emit("stabilized",{iterations:e}),t.startedStabilization=!1,t.stabilizationIterations=0}),0)}},{key:"physicsStep",value:function(){this.gravitySolver.solve(),this.nodesSolver.solve(),this.edgesSolver.solve(),this.moveNodes()}},{key:"adjustTimeStep",value:function(){!0===this._evaluateStepQuality()?this.timestep=1.2*this.timestep:this.timestep/1.2.3))return!1;return!0}},{key:"moveNodes",value:function(){for(var t=this.physicsBody.physicsNodeIndices,e=0,i=0,o=0;oo&&(t=t>0?o:-o),t}},{key:"_performStep",value:function(t){var e=this.body.nodes[t],i=this.physicsBody.forces[t];this.options.wind&&(i.x+=this.options.wind.x,i.y+=this.options.wind.y);var o=this.physicsBody.velocities[t];return this.previousStates[t]={x:e.x,y:e.y,vx:o.x,vy:o.y},!1===e.options.fixed.x?(o.x=this.calculateComponentVelocity(o.x,i.x,e.options.mass),e.x+=o.x*this.timestep):(i.x=0,o.x=0),!1===e.options.fixed.y?(o.y=this.calculateComponentVelocity(o.y,i.y,e.options.mass),e.y+=o.y*this.timestep):(i.y=0,o.y=0),Math.sqrt(Math.pow(o.x,2)+Math.pow(o.y,2))}},{key:"_freezeNodes",value:function(){var t=this.body.nodes;for(var e in t)if(Object.prototype.hasOwnProperty.call(t,e)&&t[e].x&&t[e].y){var i=t[e].options.fixed;this.freezeCache[e]={x:i.x,y:i.y},i.x=!0,i.y=!0}}},{key:"_restoreFrozenNodes",value:function(){var t=this.body.nodes;for(var e in t)Object.prototype.hasOwnProperty.call(t,e)&&void 0!==this.freezeCache[e]&&(t[e].options.fixed.x=this.freezeCache[e].x,t[e].options.fixed.y=this.freezeCache[e].y);this.freezeCache={}}},{key:"stabilize",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.options.stabilization.iterations;"number"!=typeof e&&(e=this.options.stabilization.iterations,console.error("The stabilize method needs a numeric amount of iterations. Switching to default: ",e)),0!==this.physicsBody.physicsNodeIndices.length?(this.adaptiveTimestep=this.options.adaptiveTimestep,this.body.emitter.emit("_resizeNodes"),this.stopSimulation(),this.stabilized=!1,this.body.emitter.emit("_blockRedraw"),this.targetIterations=e,!0===this.options.stabilization.onlyDynamicEdges&&this._freezeNodes(),this.stabilizationIterations=0,fG((function(){return t._stabilizationBatch()}),0)):this.ready=!0}},{key:"_startStabilizing",value:function(){return!0!==this.startedStabilization&&(this.body.emitter.emit("startStabilizing"),this.startedStabilization=!0,!0)}},{key:"_stabilizationBatch",value:function(){var t=this,e=function(){return!1===t.stabilized&&t.stabilizationIterations1&&void 0!==arguments[1]?arguments[1]:[],o=1e9,n=-1e9,r=1e9,s=-1e9;if(i.length>0)for(var a=0;a(e=t[i[a]]).shape.boundingBox.left&&(r=e.shape.boundingBox.left),se.shape.boundingBox.top&&(o=e.shape.boundingBox.top),n1&&void 0!==arguments[1]?arguments[1]:[],o=1e9,n=-1e9,r=1e9,s=-1e9;if(i.length>0)for(var a=0;a(e=t[i[a]]).x&&(r=e.x),se.y&&(o=e.y),n=t&&i.push(n.id)}for(var r=0;r0&&void 0!==arguments[0]?arguments[0]:{},i=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(void 0===e.joinCondition)throw new Error("Cannot call clusterByNodeData without a joinCondition function in the options.");e=this._checkOptions(e);var o={},n={};Uq(this.body.nodes,(function(i,r){i.options&&!0===e.joinCondition(i.options)&&(o[r]=i,Uq(i.edges,(function(e){void 0===t.clusteredEdges[e.id]&&(n[e.id]=e)})))})),this._cluster(o,n,e,i)}},{key:"clusterByEdgeCount",value:function(t,e){var i=this,o=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];e=this._checkOptions(e);for(var n,r,s,a=[],l={},h=function(){var o={},h={},d=i.body.nodeIndices[c],u=i.body.nodes[d];if(void 0===l[d]){s=0,r=[];for(var f=0;f0&&BH(h).length>0&&!0===v){var m=function(){for(var t=0;t1&&void 0!==arguments[1])||arguments[1];this.clusterByEdgeCount(1,t,e)}},{key:"clusterBridges",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];this.clusterByEdgeCount(2,t,e)}},{key:"clusterByConnection",value:function(t,e){var i,o=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];if(void 0===t)throw new Error("No nodeId supplied to clusterByConnection!");if(void 0===this.body.nodes[t])throw new Error("The nodeId given to clusterByConnection does not exist!");var n=this.body.nodes[t];void 0===(e=this._checkOptions(e,n)).clusterNodeProperties.x&&(e.clusterNodeProperties.x=n.x),void 0===e.clusterNodeProperties.y&&(e.clusterNodeProperties.y=n.y),void 0===e.clusterNodeProperties.fixed&&(e.clusterNodeProperties.fixed={},e.clusterNodeProperties.fixed.x=n.options.fixed.x,e.clusterNodeProperties.fixed.y=n.options.fixed.y);var r={},s={},a=n.id,l=f0.cloneOptions(n);r[a]=n;for(var h=0;h-1&&(s[y.id]=y)}this._cluster(r,s,e,o)}},{key:"_createClusterEdges",value:function(t,e,i,o){for(var n,r,s,a,l,h,c=BH(t),d=[],u=0;u0&&void 0!==arguments[0]?arguments[0]:{};return void 0===t.clusterEdgeProperties&&(t.clusterEdgeProperties={}),void 0===t.clusterNodeProperties&&(t.clusterNodeProperties={}),t}},{key:"_cluster",value:function(t,e,i){var o=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],n=[];for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&void 0!==this.clusteredNodes[r]&&n.push(r);for(var s=0;sn?e.x:n,r=e.ys?e.y:s;return{x:.5*(o+n),y:.5*(r+s)}}},{key:"openCluster",value:function(t,e){var i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];if(void 0===t)throw new Error("No clusterNodeId supplied to openCluster.");var o=this.body.nodes[t];if(void 0===o)throw new Error("The clusterNodeId supplied to openCluster does not exist.");if(!0!==o.isCluster||void 0===o.containedNodes||void 0===o.containedEdges)throw new Error("The node:"+t+" is not a valid cluster.");var n=this.findNode(t),r=LW(n).call(n,t)-1;if(r>=0){var s=n[r];return this.body.nodes[s]._openChildCluster(t),delete this.body.nodes[t],void(!0===i&&this.body.emitter.emit("_dataChanged"))}var a=o.containedNodes,l=o.containedEdges;if(void 0!==e&&void 0!==e.releaseFunction&&"function"==typeof e.releaseFunction){var h={},c={x:o.x,y:o.y};for(var d in a)if(Object.prototype.hasOwnProperty.call(a,d)){var u=this.body.nodes[d];h[d]={x:u.x,y:u.y}}var f=e.releaseFunction(c,h);for(var p in a)if(Object.prototype.hasOwnProperty.call(a,p)){var v=this.body.nodes[p];void 0!==f[p]&&(v.x=void 0===f[p].x?o.x:f[p].x,v.y=void 0===f[p].y?o.y:f[p].y)}}else Uq(a,(function(t){!1===t.options.fixed.x&&(t.x=o.x),!1===t.options.fixed.y&&(t.y=o.y)}));for(var g in a)if(Object.prototype.hasOwnProperty.call(a,g)){var y=this.body.nodes[g];y.vx=o.vx,y.vy=o.vy,y.setOptions({physics:!0}),delete this.clusteredNodes[g]}for(var m=[],b=0;b0&&n<100;){var r=e.pop();if(void 0!==r){var s=this.body.edges[r];if(void 0!==s){n++;var a=s.clusteringEdgeReplacingIds;if(void 0===a)o.push(r);else for(var l=0;lo&&(o=r.edges.length),t+=r.edges.length,e+=Math.pow(r.edges.length,2),i+=1}t/=i;var s=(e/=i)-Math.pow(t,2),a=Math.sqrt(s),l=Math.floor(t+2*a);return l>o&&(l=o),l}},{key:"_createClusteredEdge",value:function(t,e,i,o,n){var r=f0.cloneOptions(i,"edge");Tq(r,o),r.from=t,r.to=e,r.id="clusterEdge:"+u0(),void 0!==n&&Tq(r,n);var s=this.body.functions.createEdge(r);return s.clusteringEdgeReplacingIds=[i.id],s.connect(),this.body.edges[s.id]=s,s}},{key:"_clusterEdges",value:function(t,e,i,o){if(e instanceof Y$){var n=e,r={};r[n.id]=n,e=r}if(t instanceof X_){var s=t,a={};a[s.id]=s,t=a}if(null==i)throw new Error("_clusterEdges: parameter clusterNode required");for(var l in void 0===o&&(o=i.clusterEdgeProperties),this._createClusterEdges(t,e,i,o),e)if(Object.prototype.hasOwnProperty.call(e,l)&&void 0!==this.body.edges[l]){var h=this.body.edges[l];this._backupEdgeOptions(h),h.setOptions({physics:!1})}for(var c in t)Object.prototype.hasOwnProperty.call(t,c)&&(this.clusteredNodes[c]={clusterId:i.id,node:this.body.nodes[c]},this.body.nodes[c].setOptions({physics:!1}))}},{key:"_getClusterNodeForNode",value:function(t){if(void 0!==t){var e=this.clusteredNodes[t];if(void 0!==e){var i=e.clusterId;if(void 0!==i)return this.body.nodes[i]}}}},{key:"_filter",value:function(t,e){var i=[];return Uq(t,(function(t){e(t)&&i.push(t)})),i}},{key:"_updateState",value:function(){var t,e=this,i=[],o={},n=function(t){Uq(e.body.nodes,(function(e){!0===e.isCluster&&t(e)}))};for(t in this.clusteredNodes){if(Object.prototype.hasOwnProperty.call(this.clusteredNodes,t))void 0===this.body.nodes[t]&&i.push(t)}n((function(t){for(var e=0;e0}t.endPointsValid()&&n||(o[i]=i)})),n((function(t){Uq(o,(function(i){delete t.containedEdges[i],Uq(t.edges,(function(n,r){n.id!==i?n.clusteringEdgeReplacingIds=e._filter(n.clusteringEdgeReplacingIds,(function(t){return!o[t]})):t.edges[r]=null})),t.edges=e._filter(t.edges,(function(t){return null!==t}))}))})),Uq(o,(function(t){delete e.clusteredEdges[t]})),Uq(o,(function(t){delete e.body.edges[t]})),Uq(BH(this.body.edges),(function(t){var i=e.body.edges[t],o=e._isClusteredNode(i.fromId)||e._isClusteredNode(i.toId);if(o!==e._isClusteredEdge(i.id))if(o){var n=e._getClusterNodeForNode(i.fromId);void 0!==n&&e._clusterEdges(e.body.nodes[i.fromId],i,n);var r=e._getClusterNodeForNode(i.toId);void 0!==r&&e._clusterEdges(e.body.nodes[i.toId],i,r)}else delete e._clusterEdges[t],e._restoreEdge(i)}));for(var s=!1,a=!0,l=function(){var t=[];n((function(e){var i=BH(e.containedNodes).length,o=!0===e.options.allowSingleNodeCluster;(o&&i<1||!o&&i<2)&&t.push(e.id)}));for(var i=0;i0,s=s||a};a;)l();s&&this._updateState()}},{key:"_isClusteredNode",value:function(t){return void 0!==this.clusteredNodes[t]}},{key:"_isClusteredEdge",value:function(t){return void 0!==this.clusteredEdges[t]}}]),t}();var y0=function(){function t(e,i){var o;fN(this,t),void 0!==window&&(o=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame),window.requestAnimationFrame=void 0===o?function(t){t()}:o,this.body=e,this.canvas=i,this.redrawRequested=!1,this.renderTimer=void 0,this.requiresTimeout=!0,this.renderingActive=!1,this.renderRequests=0,this.allowRedraw=!0,this.dragging=!1,this.zooming=!1,this.options={},this.defaultOptions={hideEdgesOnDrag:!1,hideEdgesOnZoom:!1,hideNodesOnDrag:!1},AB(this.options,this.defaultOptions),this._determineBrowserMethod(),this.bindEventListeners()}return mQ(t,[{key:"bindEventListeners",value:function(){var t,e=this;this.body.emitter.on("dragStart",(function(){e.dragging=!0})),this.body.emitter.on("dragEnd",(function(){e.dragging=!1})),this.body.emitter.on("zoom",(function(){e.zooming=!0,window.clearTimeout(e.zoomTimeoutId),e.zoomTimeoutId=fG((function(){var t;e.zooming=!1,VB(t=e._requestRedraw).call(t,e)()}),250)})),this.body.emitter.on("_resizeNodes",(function(){e._resizeNodes()})),this.body.emitter.on("_redraw",(function(){!1===e.renderingActive&&e._redraw()})),this.body.emitter.on("_blockRedraw",(function(){e.allowRedraw=!1})),this.body.emitter.on("_allowRedraw",(function(){e.allowRedraw=!0,e.redrawRequested=!1})),this.body.emitter.on("_requestRedraw",VB(t=this._requestRedraw).call(t,this)),this.body.emitter.on("_startRendering",(function(){e.renderRequests+=1,e.renderingActive=!0,e._startRendering()})),this.body.emitter.on("_stopRendering",(function(){e.renderRequests-=1,e.renderingActive=e.renderRequests>0,e.renderTimer=void 0})),this.body.emitter.on("destroy",(function(){e.renderRequests=0,e.allowRedraw=!1,e.renderingActive=!1,!0===e.requiresTimeout?clearTimeout(e.renderTimer):window.cancelAnimationFrame(e.renderTimer),e.body.emitter.off()}))}},{key:"setOptions",value:function(t){if(void 0!==t){Pq(["hideEdgesOnDrag","hideEdgesOnZoom","hideNodesOnDrag"],this.options,t)}}},{key:"_requestNextFrame",value:function(t,e){if("undefined"!=typeof window){var i,o=window;return!0===this.requiresTimeout?i=fG(t,e):o.requestAnimationFrame&&(i=o.requestAnimationFrame(t)),i}}},{key:"_startRendering",value:function(){var t;!0===this.renderingActive&&(void 0===this.renderTimer&&(this.renderTimer=this._requestNextFrame(VB(t=this._renderStep).call(t,this),this.simulationInterval)))}},{key:"_renderStep",value:function(){!0===this.renderingActive&&(this.renderTimer=void 0,!0===this.requiresTimeout&&this._startRendering(),this._redraw(),!1===this.requiresTimeout&&this._startRendering())}},{key:"redraw",value:function(){this.body.emitter.emit("setSize"),this._redraw()}},{key:"_requestRedraw",value:function(){var t=this;!0!==this.redrawRequested&&!1===this.renderingActive&&!0===this.allowRedraw&&(this.redrawRequested=!0,this._requestNextFrame((function(){t._redraw(!1)}),0))}},{key:"_redraw",value:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(!0===this.allowRedraw){this.body.emitter.emit("initRedraw"),this.redrawRequested=!1;var e={drawExternalLabels:null};0!==this.canvas.frame.canvas.width&&0!==this.canvas.frame.canvas.height||this.canvas.setSize(),this.canvas.setTransform();var i=this.canvas.getContext(),o=this.canvas.frame.canvas.clientWidth,n=this.canvas.frame.canvas.clientHeight;if(i.clearRect(0,0,o,n),0===this.canvas.frame.clientWidth)return;if(i.save(),i.translate(this.body.view.translation.x,this.body.view.translation.y),i.scale(this.body.view.scale,this.body.view.scale),i.beginPath(),this.body.emitter.emit("beforeDrawing",i),i.closePath(),!1===t&&(!1===this.dragging||!0===this.dragging&&!1===this.options.hideEdgesOnDrag)&&(!1===this.zooming||!0===this.zooming&&!1===this.options.hideEdgesOnZoom)&&this._drawEdges(i),!1===this.dragging||!0===this.dragging&&!1===this.options.hideNodesOnDrag){var r=this._drawNodes(i,t).drawExternalLabels;e.drawExternalLabels=r}!1===t&&(!1===this.dragging||!0===this.dragging&&!1===this.options.hideEdgesOnDrag)&&(!1===this.zooming||!0===this.zooming&&!1===this.options.hideEdgesOnZoom)&&this._drawArrows(i),null!=e.drawExternalLabels&&e.drawExternalLabels(),!1===t&&this._drawSelectionBox(i),i.beginPath(),this.body.emitter.emit("afterDrawing",i),i.closePath(),i.restore(),!0===t&&i.clearRect(0,0,o,n)}}},{key:"_resizeNodes",value:function(){this.canvas.setTransform();var t=this.canvas.getContext();t.save(),t.translate(this.body.view.translation.x,this.body.view.translation.y),t.scale(this.body.view.scale,this.body.view.scale);var e,i=this.body.nodes;for(var o in i)Object.prototype.hasOwnProperty.call(i,o)&&((e=i[o]).resize(t),e.updateBoundingBox(t,e.selected));t.restore()}},{key:"_drawNodes",value:function(t){for(var e,i,o=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=this.body.nodes,r=this.body.nodeIndices,s=[],a=[],l=this.canvas.DOMtoCanvas({x:-20,y:-20}),h=this.canvas.DOMtoCanvas({x:this.canvas.frame.canvas.clientWidth+20,y:this.canvas.frame.canvas.clientHeight+20}),c={top:l.y,left:l.x,bottom:h.y,right:h.x},d=[],u=0;u0&&void 0!==arguments[0]?arguments[0]:this.pixelRatio;!0===this.initialized&&(this.cameraState.previousWidth=this.frame.canvas.width/t,this.cameraState.previousHeight=this.frame.canvas.height/t,this.cameraState.scale=this.body.view.scale,this.cameraState.position=this.DOMtoCanvas({x:.5*this.frame.canvas.width/t,y:.5*this.frame.canvas.height/t}))}},{key:"_setCameraState",value:function(){if(void 0!==this.cameraState.scale&&0!==this.frame.canvas.clientWidth&&0!==this.frame.canvas.clientHeight&&0!==this.pixelRatio&&this.cameraState.previousWidth>0&&this.cameraState.previousHeight>0){var t=this.frame.canvas.width/this.pixelRatio/this.cameraState.previousWidth,e=this.frame.canvas.height/this.pixelRatio/this.cameraState.previousHeight,i=this.cameraState.scale;1!=t&&1!=e?i=.5*this.cameraState.scale*(t+e):1!=t?i=this.cameraState.scale*t:1!=e&&(i=this.cameraState.scale*e),this.body.view.scale=i;var o=this.DOMtoCanvas({x:.5*this.frame.canvas.clientWidth,y:.5*this.frame.canvas.clientHeight}),n={x:o.x-this.cameraState.position.x,y:o.y-this.cameraState.position.y};this.body.view.translation.x+=n.x*this.body.view.scale,this.body.view.translation.y+=n.y*this.body.view.scale}}},{key:"_prepareValue",value:function(t){if("number"==typeof t)return t+"px";if("string"==typeof t){if(-1!==LW(t).call(t,"%")||-1!==LW(t).call(t,"px"))return t;if(-1===LW(t).call(t,"%"))return t+"px"}throw new Error("Could not use the value supplied for width or height:"+t)}},{key:"_create",value:function(){for(;this.body.container.hasChildNodes();)this.body.container.removeChild(this.body.container.firstChild);if(this.frame=document.createElement("div"),this.frame.className="vis-network",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.tabIndex=0,this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),this.frame.canvas.getContext)this._setPixelRatio(),this.setTransform();else{var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerText="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t)}this.body.container.appendChild(this.frame),this.body.view.scale=1,this.body.view.translation={x:.5*this.frame.canvas.clientWidth,y:.5*this.frame.canvas.clientHeight},this._bindHammer()}},{key:"_bindHammer",value:function(){var t=this;void 0!==this.hammer&&this.hammer.destroy(),this.drag={},this.pinch={},this.hammer=new cY(this.frame.canvas),this.hammer.get("pinch").set({enable:!0}),this.hammer.get("pan").set({threshold:5,direction:cY.DIRECTION_ALL}),b0(this.hammer,(function(e){t.body.eventListeners.onTouch(e)})),this.hammer.on("tap",(function(e){t.body.eventListeners.onTap(e)})),this.hammer.on("doubletap",(function(e){t.body.eventListeners.onDoubleTap(e)})),this.hammer.on("press",(function(e){t.body.eventListeners.onHold(e)})),this.hammer.on("panstart",(function(e){t.body.eventListeners.onDragStart(e)})),this.hammer.on("panmove",(function(e){t.body.eventListeners.onDrag(e)})),this.hammer.on("panend",(function(e){t.body.eventListeners.onDragEnd(e)})),this.hammer.on("pinch",(function(e){t.body.eventListeners.onPinch(e)})),this.frame.canvas.addEventListener("wheel",(function(e){t.body.eventListeners.onMouseWheel(e)})),this.frame.canvas.addEventListener("mousemove",(function(e){t.body.eventListeners.onMouseMove(e)})),this.frame.canvas.addEventListener("contextmenu",(function(e){t.body.eventListeners.onContext(e)})),this.hammerFrame=new cY(this.frame),w0(this.hammerFrame,(function(e){t.body.eventListeners.onRelease(e)}))}},{key:"setSize",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.options.width,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.options.height;t=this._prepareValue(t),e=this._prepareValue(e);var i=!1,o=this.frame.canvas.width,n=this.frame.canvas.height,r=this.pixelRatio;if(this._setPixelRatio(),t!=this.options.width||e!=this.options.height||this.frame.style.width!=t||this.frame.style.height!=e)this._getCameraState(r),this.frame.style.width=t,this.frame.style.height=e,this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=Math.round(this.frame.canvas.clientWidth*this.pixelRatio),this.frame.canvas.height=Math.round(this.frame.canvas.clientHeight*this.pixelRatio),this.options.width=t,this.options.height=e,this.canvasViewCenter={x:.5*this.frame.clientWidth,y:.5*this.frame.clientHeight},i=!0;else{var s=Math.round(this.frame.canvas.clientWidth*this.pixelRatio),a=Math.round(this.frame.canvas.clientHeight*this.pixelRatio);this.frame.canvas.width===s&&this.frame.canvas.height===a||this._getCameraState(r),this.frame.canvas.width!==s&&(this.frame.canvas.width=s,i=!0),this.frame.canvas.height!==a&&(this.frame.canvas.height=a,i=!0)}return!0===i&&(this.body.emitter.emit("resize",{width:Math.round(this.frame.canvas.width/this.pixelRatio),height:Math.round(this.frame.canvas.height/this.pixelRatio),oldWidth:Math.round(o/this.pixelRatio),oldHeight:Math.round(n/this.pixelRatio)}),this._setCameraState()),this.initialized=!0,i}},{key:"getContext",value:function(){return this.frame.canvas.getContext("2d")}},{key:"_determinePixelRatio",value:function(){var t=this.getContext();if(void 0===t)throw new Error("Could not get canvax context");var e=1;return"undefined"!=typeof window&&(e=window.devicePixelRatio||1),e/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1)}},{key:"_setPixelRatio",value:function(){this.pixelRatio=this._determinePixelRatio()}},{key:"setTransform",value:function(){var t=this.getContext();if(void 0===t)throw new Error("Could not get canvax context");t.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0)}},{key:"_XconvertDOMtoCanvas",value:function(t){return(t-this.body.view.translation.x)/this.body.view.scale}},{key:"_XconvertCanvasToDOM",value:function(t){return t*this.body.view.scale+this.body.view.translation.x}},{key:"_YconvertDOMtoCanvas",value:function(t){return(t-this.body.view.translation.y)/this.body.view.scale}},{key:"_YconvertCanvasToDOM",value:function(t){return t*this.body.view.scale+this.body.view.translation.y}},{key:"canvasToDOM",value:function(t){return{x:this._XconvertCanvasToDOM(t.x),y:this._YconvertCanvasToDOM(t.y)}}},{key:"DOMtoCanvas",value:function(t){return{x:this._XconvertDOMtoCanvas(t.x),y:this._YconvertDOMtoCanvas(t.y)}}}]),t}();var E0=function(){function t(e,i){var o,n,r=this;fN(this,t),this.body=e,this.canvas=i,this.animationSpeed=1/this.renderRefreshRate,this.animationEasingFunction="easeInOutQuint",this.easingTime=0,this.sourceScale=0,this.targetScale=0,this.sourceTranslation=0,this.targetTranslation=0,this.lockedOnNodeId=void 0,this.lockedOnNodeOffset=void 0,this.touchTime=0,this.viewFunction=void 0,this.body.emitter.on("fit",VB(o=this.fit).call(o,this)),this.body.emitter.on("animationFinished",(function(){r.body.emitter.emit("_stopRendering")})),this.body.emitter.on("unlockNode",VB(n=this.releaseNode).call(n,this))}return mQ(t,[{key:"setOptions",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.options=t}},{key:"fit",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];t=function(t,e){var i=AB({nodes:e,minZoomLevel:Number.MIN_VALUE,maxZoomLevel:1},null!=t?t:{});if(!EH(i.nodes))throw new TypeError("Nodes has to be an array of ids.");if(0===i.nodes.length&&(i.nodes=e),!("number"==typeof i.minZoomLevel&&i.minZoomLevel>0))throw new TypeError("Min zoom level has to be a number higher than zero.");if(!("number"==typeof i.maxZoomLevel&&i.minZoomLevel<=i.maxZoomLevel))throw new TypeError("Max zoom level has to be a number higher than min zoom level.");return i}(t,this.body.nodeIndices);var i,o,n=this.canvas.frame.canvas.clientWidth,r=this.canvas.frame.canvas.clientHeight;if(0===n||0===r)o=1,i=f0.getRange(this.body.nodes,t.nodes);else if(!0===e){var s=0;for(var a in this.body.nodes){if(Object.prototype.hasOwnProperty.call(this.body.nodes,a))!0===this.body.nodes[a].predefinedPosition&&(s+=1)}if(s>.5*this.body.nodeIndices.length)return void this.fit(t,!1);i=f0.getRange(this.body.nodes,t.nodes),o=12.662/(this.body.nodeIndices.length+7.4147)+.0964822,o*=Math.min(n/600,r/600)}else{this.body.emitter.emit("_resizeNodes"),i=f0.getRange(this.body.nodes,t.nodes);var l=n/(1.1*Math.abs(i.maxX-i.minX)),h=r/(1.1*Math.abs(i.maxY-i.minY));o=l<=h?l:h}o>t.maxZoomLevel?o=t.maxZoomLevel:o1&&void 0!==arguments[1]?arguments[1]:{};if(void 0!==this.body.nodes[t]){var i={x:this.body.nodes[t].x,y:this.body.nodes[t].y};e.position=i,e.lockedOnNode=t,this.moveTo(e)}else console.error("Node: "+t+" cannot be found.")}},{key:"moveTo",value:function(t){if(void 0!==t){if(null!=t.offset){if(null!=t.offset.x){if(t.offset.x=+t.offset.x,!kJ(t.offset.x))throw new TypeError('The option "offset.x" has to be a finite number.')}else t.offset.x=0;if(null!=t.offset.y){if(t.offset.y=+t.offset.y,!kJ(t.offset.y))throw new TypeError('The option "offset.y" has to be a finite number.')}else t.offset.x=0}else t.offset={x:0,y:0};if(null!=t.position){if(null!=t.position.x){if(t.position.x=+t.position.x,!kJ(t.position.x))throw new TypeError('The option "position.x" has to be a finite number.')}else t.position.x=0;if(null!=t.position.y){if(t.position.y=+t.position.y,!kJ(t.position.y))throw new TypeError('The option "position.y" has to be a finite number.')}else t.position.x=0}else t.position=this.getViewPosition();if(null!=t.scale){if(t.scale=+t.scale,!(t.scale>0))throw new TypeError('The option "scale" has to be a number greater than zero.')}else t.scale=this.body.view.scale;void 0===t.animation&&(t.animation={duration:0}),!1===t.animation&&(t.animation={duration:0}),!0===t.animation&&(t.animation={}),void 0===t.animation.duration&&(t.animation.duration=1e3),void 0===t.animation.easingFunction&&(t.animation.easingFunction="easeInOutQuad"),this.animateView(t)}else t={}}},{key:"animateView",value:function(t){if(void 0!==t){this.animationEasingFunction=t.animation.easingFunction,this.releaseNode(),!0===t.locked&&(this.lockedOnNodeId=t.lockedOnNode,this.lockedOnNodeOffset=t.offset),0!=this.easingTime&&this._transitionRedraw(!0),this.sourceScale=this.body.view.scale,this.sourceTranslation=this.body.view.translation,this.targetScale=t.scale,this.body.view.scale=this.targetScale;var e,i,o=this.canvas.DOMtoCanvas({x:.5*this.canvas.frame.canvas.clientWidth,y:.5*this.canvas.frame.canvas.clientHeight}),n=o.x-t.position.x,r=o.y-t.position.y;if(this.targetTranslation={x:this.sourceTranslation.x+n*this.targetScale+t.offset.x,y:this.sourceTranslation.y+r*this.targetScale+t.offset.y},0===t.animation.duration)if(null!=this.lockedOnNodeId)this.viewFunction=VB(e=this._lockedRedraw).call(e,this),this.body.emitter.on("initRedraw",this.viewFunction);else this.body.view.scale=this.targetScale,this.body.view.translation=this.targetTranslation,this.body.emitter.emit("_requestRedraw");else this.animationSpeed=1/(60*t.animation.duration*.001)||1/60,this.animationEasingFunction=t.animation.easingFunction,this.viewFunction=VB(i=this._transitionRedraw).call(i,this),this.body.emitter.on("initRedraw",this.viewFunction),this.body.emitter.emit("_startRendering")}}},{key:"_lockedRedraw",value:function(){var t=this.body.nodes[this.lockedOnNodeId].x,e=this.body.nodes[this.lockedOnNodeId].y,i=this.canvas.DOMtoCanvas({x:.5*this.canvas.frame.canvas.clientWidth,y:.5*this.canvas.frame.canvas.clientHeight}),o=i.x-t,n=i.y-e,r=this.body.view.translation,s={x:r.x+o*this.body.view.scale+this.lockedOnNodeOffset.x,y:r.y+n*this.body.view.scale+this.lockedOnNodeOffset.y};this.body.view.translation=s}},{key:"releaseNode",value:function(){void 0!==this.lockedOnNodeId&&void 0!==this.viewFunction&&(this.body.emitter.off("initRedraw",this.viewFunction),this.lockedOnNodeId=void 0,this.lockedOnNodeOffset=void 0)}},{key:"_transitionRedraw",value:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];this.easingTime+=this.animationSpeed,this.easingTime=!0===t?1:this.easingTime;var e=Xq[this.animationEasingFunction](this.easingTime);if(this.body.view.scale=this.sourceScale+(this.targetScale-this.sourceScale)*e,this.body.view.translation={x:this.sourceTranslation.x+(this.targetTranslation.x-this.sourceTranslation.x)*e,y:this.sourceTranslation.y+(this.targetTranslation.y-this.sourceTranslation.y)*e},this.easingTime>=1){var i;if(this.body.emitter.off("initRedraw",this.viewFunction),this.easingTime=0,null!=this.lockedOnNodeId)this.viewFunction=VB(i=this._lockedRedraw).call(i,this),this.body.emitter.on("initRedraw",this.viewFunction);this.body.emitter.emit("animationFinished")}}},{key:"getScale",value:function(){return this.body.view.scale}},{key:"getViewPosition",value:function(){return this.canvas.DOMtoCanvas({x:.5*this.canvas.frame.canvas.clientWidth,y:.5*this.canvas.frame.canvas.clientHeight})}}]),t}();function k0(t){var e,i=t&&t.preventDefault||!1,o=t&&t.container||window,n={},r={keydown:{},keyup:{}},s={};for(e=97;e<=122;e++)s[String.fromCharCode(e)]={code:e-97+65,shift:!1};for(e=65;e<=90;e++)s[String.fromCharCode(e)]={code:e,shift:!0};for(e=0;e<=9;e++)s[""+e]={code:48+e,shift:!1};for(e=1;e<=12;e++)s["F"+e]={code:111+e,shift:!1};for(e=0;e<=9;e++)s["num"+e]={code:96+e,shift:!1};s["num*"]={code:106,shift:!1},s["num+"]={code:107,shift:!1},s["num-"]={code:109,shift:!1},s["num/"]={code:111,shift:!1},s["num."]={code:110,shift:!1},s.left={code:37,shift:!1},s.up={code:38,shift:!1},s.right={code:39,shift:!1},s.down={code:40,shift:!1},s.space={code:32,shift:!1},s.enter={code:13,shift:!1},s.shift={code:16,shift:void 0},s.esc={code:27,shift:!1},s.backspace={code:8,shift:!1},s.tab={code:9,shift:!1},s.ctrl={code:17,shift:!1},s.alt={code:18,shift:!1},s.delete={code:46,shift:!1},s.pageup={code:33,shift:!1},s.pagedown={code:34,shift:!1},s["="]={code:187,shift:!1},s["-"]={code:189,shift:!1},s["]"]={code:221,shift:!1},s["["]={code:219,shift:!1};var a=function(t){h(t,"keydown")},l=function(t){h(t,"keyup")},h=function(t,e){if(void 0!==r[e][t.keyCode]){for(var o=r[e][t.keyCode],n=0;n700&&(this.body.emitter.emit("fit",{duration:700}),this.touchTime=(new Date).valueOf())}},{key:"_stopMovement",value:function(){for(var t in this.boundFunctions)Object.prototype.hasOwnProperty.call(this.boundFunctions,t)&&(this.body.emitter.off("initRedraw",this.boundFunctions[t]),this.body.emitter.emit("_stopRendering"));this.boundFunctions={}}},{key:"_moveUp",value:function(){this.body.view.translation.y+=this.options.keyboard.speed.y}},{key:"_moveDown",value:function(){this.body.view.translation.y-=this.options.keyboard.speed.y}},{key:"_moveLeft",value:function(){this.body.view.translation.x+=this.options.keyboard.speed.x}},{key:"_moveRight",value:function(){this.body.view.translation.x-=this.options.keyboard.speed.x}},{key:"_zoomIn",value:function(){var t=this.body.view.scale,e=this.body.view.scale*(1+this.options.keyboard.speed.zoom),i=this.body.view.translation,o=e/t,n=(1-o)*this.canvas.canvasViewCenter.x+i.x*o,r=(1-o)*this.canvas.canvasViewCenter.y+i.y*o;this.body.view.scale=e,this.body.view.translation={x:n,y:r},this.body.emitter.emit("zoom",{direction:"+",scale:this.body.view.scale,pointer:null})}},{key:"_zoomOut",value:function(){var t=this.body.view.scale,e=this.body.view.scale/(1+this.options.keyboard.speed.zoom),i=this.body.view.translation,o=e/t,n=(1-o)*this.canvas.canvasViewCenter.x+i.x*o,r=(1-o)*this.canvas.canvasViewCenter.y+i.y*o;this.body.view.scale=e,this.body.view.translation={x:n,y:r},this.body.emitter.emit("zoom",{direction:"-",scale:this.body.view.scale,pointer:null})}},{key:"configureKeyboardBindings",value:function(){var t,e,i,o,n,r,s,a,l,h,c,d,u,f,p,v,g,y,m,b,w,A,E,k,C=this;(void 0!==this.keycharm&&this.keycharm.destroy(),!0===this.options.keyboard.enabled)&&(!0===this.options.keyboard.bindToWindow?this.keycharm=k0({container:window,preventDefault:!0}):this.keycharm=k0({container:this.canvas.frame,preventDefault:!0}),this.keycharm.reset(),!0===this.activated&&(VB(t=this.keycharm).call(t,"up",(function(){C.bindToRedraw("_moveUp")}),"keydown"),VB(e=this.keycharm).call(e,"down",(function(){C.bindToRedraw("_moveDown")}),"keydown"),VB(i=this.keycharm).call(i,"left",(function(){C.bindToRedraw("_moveLeft")}),"keydown"),VB(o=this.keycharm).call(o,"right",(function(){C.bindToRedraw("_moveRight")}),"keydown"),VB(n=this.keycharm).call(n,"=",(function(){C.bindToRedraw("_zoomIn")}),"keydown"),VB(r=this.keycharm).call(r,"num+",(function(){C.bindToRedraw("_zoomIn")}),"keydown"),VB(s=this.keycharm).call(s,"num-",(function(){C.bindToRedraw("_zoomOut")}),"keydown"),VB(a=this.keycharm).call(a,"-",(function(){C.bindToRedraw("_zoomOut")}),"keydown"),VB(l=this.keycharm).call(l,"[",(function(){C.bindToRedraw("_zoomOut")}),"keydown"),VB(h=this.keycharm).call(h,"]",(function(){C.bindToRedraw("_zoomIn")}),"keydown"),VB(c=this.keycharm).call(c,"pageup",(function(){C.bindToRedraw("_zoomIn")}),"keydown"),VB(d=this.keycharm).call(d,"pagedown",(function(){C.bindToRedraw("_zoomOut")}),"keydown"),VB(u=this.keycharm).call(u,"up",(function(){C.unbindFromRedraw("_moveUp")}),"keyup"),VB(f=this.keycharm).call(f,"down",(function(){C.unbindFromRedraw("_moveDown")}),"keyup"),VB(p=this.keycharm).call(p,"left",(function(){C.unbindFromRedraw("_moveLeft")}),"keyup"),VB(v=this.keycharm).call(v,"right",(function(){C.unbindFromRedraw("_moveRight")}),"keyup"),VB(g=this.keycharm).call(g,"=",(function(){C.unbindFromRedraw("_zoomIn")}),"keyup"),VB(y=this.keycharm).call(y,"num+",(function(){C.unbindFromRedraw("_zoomIn")}),"keyup"),VB(m=this.keycharm).call(m,"num-",(function(){C.unbindFromRedraw("_zoomOut")}),"keyup"),VB(b=this.keycharm).call(b,"-",(function(){C.unbindFromRedraw("_zoomOut")}),"keyup"),VB(w=this.keycharm).call(w,"[",(function(){C.unbindFromRedraw("_zoomOut")}),"keyup"),VB(A=this.keycharm).call(A,"]",(function(){C.unbindFromRedraw("_zoomIn")}),"keyup"),VB(E=this.keycharm).call(E,"pageup",(function(){C.unbindFromRedraw("_zoomIn")}),"keyup"),VB(k=this.keycharm).call(k,"pagedown",(function(){C.unbindFromRedraw("_zoomOut")}),"keyup")))}}]),t}();function x0(t,e){var i=void 0!==lH&&uN(t)||t["@@iterator"];if(!i){if(EH(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return S0(t,e);var o=vH(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===o&&t.constructor&&(o=t.constructor.name);if("Map"===o||"Set"===o)return GT(t);if("Arguments"===o||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(o))return S0(t,e)}(t))||e){i&&(t=i);var o=0,n=function(){};return{s:n,n:function(){return o>=t.length?{done:!0}:{done:!1,value:t[o++]}},e:function(t){throw t},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function S0(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,o=new Array(e);i50&&(this.drag.pointer=this.getPointer(t.center),this.drag.pinched=!1,this.pinch.scale=this.body.view.scale,this.touchTime=(new Date).valueOf())}},{key:"onTap",value:function(t){var e=this.getPointer(t.center),i=this.selectionHandler.options.multiselect&&(t.changedPointers[0].ctrlKey||t.changedPointers[0].metaKey);this.checkSelectionChanges(e,i),this.selectionHandler.commitAndEmit(e,t),this.selectionHandler.generateClickEvent("click",t,e)}},{key:"onDoubleTap",value:function(t){var e=this.getPointer(t.center);this.selectionHandler.generateClickEvent("doubleClick",t,e)}},{key:"onHold",value:function(t){var e=this.getPointer(t.center),i=this.selectionHandler.options.multiselect;this.checkSelectionChanges(e,i),this.selectionHandler.commitAndEmit(e,t),this.selectionHandler.generateClickEvent("click",t,e),this.selectionHandler.generateClickEvent("hold",t,e)}},{key:"onRelease",value:function(t){if((new Date).valueOf()-this.touchTime>10){var e=this.getPointer(t.center);this.selectionHandler.generateClickEvent("release",t,e),this.touchTime=(new Date).valueOf()}}},{key:"onContext",value:function(t){var e=this.getPointer({x:t.clientX,y:t.clientY});this.selectionHandler.generateClickEvent("oncontext",t,e)}},{key:"checkSelectionChanges",value:function(t){!0===(arguments.length>1&&void 0!==arguments[1]&&arguments[1])?this.selectionHandler.selectAdditionalOnPoint(t):this.selectionHandler.selectOnPoint(t)}},{key:"_determineDifference",value:function(t,e){var i=function(t,e){for(var i=[],o=0;o=n.minX&&i.x<=n.maxX&&i.y>=n.minY&&i.y<=n.maxY}));ZH(r).call(r,(function(t){return e.selectionHandler.selectObject(e.body.nodes[t])}));var s=this.getPointer(t.center);this.selectionHandler.commitAndEmit(s,t),this.selectionHandler.generateClickEvent("dragEnd",t,this.getPointer(t.center),void 0,!0),this.body.emitter.emit("_requestRedraw")}else{var a=this.drag.selection;a&&a.length?(ZH(a).call(a,(function(t){t.node.options.fixed.x=t.xFixed,t.node.options.fixed.y=t.yFixed})),this.selectionHandler.generateClickEvent("dragEnd",t,this.getPointer(t.center)),this.body.emitter.emit("startSimulation")):(this.selectionHandler.generateClickEvent("dragEnd",t,this.getPointer(t.center),void 0,!0),this.body.emitter.emit("_requestRedraw"))}}},{key:"onPinch",value:function(t){var e=this.getPointer(t.center);this.drag.pinched=!0,void 0===this.pinch.scale&&(this.pinch.scale=1);var i=this.pinch.scale*t.scale;this.zoom(i,e)}},{key:"zoom",value:function(t,e){if(!0===this.options.zoomView){var i=this.body.view.scale;t<1e-5&&(t=1e-5),t>10&&(t=10);var o=void 0;void 0!==this.drag&&!0===this.drag.dragging&&(o=this.canvas.DOMtoCanvas(this.drag.pointer));var n=this.body.view.translation,r=t/i,s=(1-r)*e.x+n.x*r,a=(1-r)*e.y+n.y*r;if(this.body.view.scale=t,this.body.view.translation={x:s,y:a},null!=o){var l=this.canvas.canvasToDOM(o);this.drag.pointer.x=l.x,this.drag.pointer.y=l.y}this.body.emitter.emit("_requestRedraw"),i0&&(this.popupObj=h[c[c.length-1]],r=!0)}if(void 0===this.popupObj&&!1===r){for(var u,f=this.body.edgeIndices,p=this.body.edges,v=[],g=0;g0&&(this.popupObj=p[v[v.length-1]],s="edge")}void 0!==this.popupObj?this.popupObj.id!==n&&(void 0===this.popup&&(this.popup=new dY(this.canvas.frame)),this.popup.popupTargetType=s,this.popup.popupTargetId=this.popupObj.id,this.popup.setPosition(t.x+3,t.y-5),this.popup.setText(this.popupObj.getTitle()),this.popup.show(),this.body.emitter.emit("showPopup",this.popupObj.id)):void 0!==this.popup&&(this.popup.hide(),this.body.emitter.emit("hidePopup"))}},{key:"_checkHidePopup",value:function(t){var e=this.selectionHandler._pointerToPositionObject(t),i=!1;if("node"===this.popup.popupTargetType){if(void 0!==this.body.nodes[this.popup.popupTargetId]&&!0===(i=this.body.nodes[this.popup.popupTargetId].isOverlappingWith(e))){var o=this.selectionHandler.getNodeAt(t);i=void 0!==o&&o.id===this.popup.popupTargetId}}else void 0===this.selectionHandler.getNodeAt(t)&&void 0!==this.body.edges[this.popup.popupTargetId]&&(i=this.body.edges[this.popup.popupTargetId].isOverlappingWith(e));!1===i&&(this.popupObj=void 0,this.popup.hide(),this.body.emitter.emit("hidePopup"))}}]),t}();JZ("Set",(function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}}),yJ);var M0=nM(oO.Set),O0=mM,D0=_Z,R0=gZ.getWeakData,B0=zZ,z0=nR,P0=qM,F0=iO,T0=DZ,N0=tD,j0=Qz.set,U0=Qz.getterFor,L0=zj.find,Q0=zj.findIndex,H0=O0([].splice),V0=0,W0=function(t){return t.frozen||(t.frozen=new G0)},G0=function(){this.entries=[]},K0=function(t,e){return L0(t.entries,(function(t){return t[0]===e}))};G0.prototype={get:function(t){var e=K0(this,t);if(e)return e[1]},has:function(t){return!!K0(this,t)},set:function(t,e){var i=K0(this,t);i?i[1]=e:this.entries.push([t,e])},delete:function(t){var e=Q0(this.entries,(function(e){return e[0]===t}));return~e&&H0(this.entries,e,1),!!~e}};var q0,Y0={getConstructor:function(t,e,i,o){var n=t((function(t,n){B0(t,r),j0(t,{type:e,id:V0++,frozen:void 0}),P0(n)||T0(n,t[o],{that:t,AS_ENTRIES:i})})),r=n.prototype,s=U0(e),a=function(t,e,i){var o=s(t),n=R0(z0(e),!0);return!0===n?W0(o).set(e,i):n[o.id]=i,t};return D0(r,{delete:function(t){var e=s(this);if(!F0(t))return!1;var i=R0(t);return!0===i?W0(e).delete(t):i&&N0(i,e.id)&&delete i[e.id]},has:function(t){var e=s(this);if(!F0(t))return!1;var i=R0(t);return!0===i?W0(e).has(t):i&&N0(i,e.id)}}),D0(r,i?{get:function(t){var e=s(this);if(F0(t)){var i=R0(t);return!0===i?W0(e).get(t):i?i[e.id]:void 0}},set:function(t,e){return a(this,t,e)}}:{add:function(t){return a(this,t,!0)}}),n}},Z0=tZ,J0=sM,X0=mM,_0=_Z,$0=gZ,t1=JZ,e1=Y0,i1=iO,o1=Qz.enforce,n1=aM,r1=Cz,s1=Object,a1=Array.isArray,l1=s1.isExtensible,h1=s1.isFrozen,c1=s1.isSealed,d1=s1.freeze,u1=s1.seal,f1={},p1={},v1=!J0.ActiveXObject&&"ActiveXObject"in J0,g1=function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}},y1=t1("WeakMap",g1,e1),m1=y1.prototype,b1=X0(m1.set);if(r1)if(v1){q0=e1.getConstructor(g1,"WeakMap",!0),$0.enable();var w1=X0(m1.delete),A1=X0(m1.has),E1=X0(m1.get);_0(m1,{delete:function(t){if(i1(t)&&!l1(t)){var e=o1(this);return e.frozen||(e.frozen=new q0),w1(this,t)||e.frozen.delete(t)}return w1(this,t)},has:function(t){if(i1(t)&&!l1(t)){var e=o1(this);return e.frozen||(e.frozen=new q0),A1(this,t)||e.frozen.has(t)}return A1(this,t)},get:function(t){if(i1(t)&&!l1(t)){var e=o1(this);return e.frozen||(e.frozen=new q0),A1(this,t)?E1(this,t):e.frozen.get(t)}return E1(this,t)},set:function(t,e){if(i1(t)&&!l1(t)){var i=o1(this);i.frozen||(i.frozen=new q0),A1(this,t)?b1(this,t,e):i.frozen.set(t,e)}else b1(this,t,e);return this}})}else Z0&&n1((function(){var t=d1([]);return b1(new y1,t,1),!h1(t)}))&&_0(m1,{set:function(t,e){var i;return a1(t)&&(h1(t)?i=f1:c1(t)&&(i=p1)),b1(this,t,e),i===f1&&d1(t),i===p1&&u1(t),this}});var k1,C1,x1,S1,I1,M1=nM(oO.WeakMap);function O1(t,e,i,o){if("a"===i&&!o)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!o:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===i?o:"a"===i?o.call(t):o?o.value:e.get(t)}function D1(t,e,i,o,n){if("function"==typeof e?t!==e||!n:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return e.set(t,i),i}function R1(t,e){var i=void 0!==lH&&uN(t)||t["@@iterator"];if(!i){if(EH(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return B1(t,e);var o=vH(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===o&&t.constructor&&(o=t.constructor.name);if("Map"===o||"Set"===o)return GT(t);if("Arguments"===o||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(o))return B1(t,e)}(t))||e){i&&(t=i);var o=0,n=function(){};return{s:n,n:function(){return o>=t.length?{done:!0}:{done:!1,value:t[o++]}},e:function(t){throw t},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function B1(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,o=new Array(e);i0&&void 0!==arguments[0]?arguments[0]:function(){};fN(this,t),x1.set(this,new P1),S1.set(this,new P1),I1.set(this,void 0),D1(this,I1,e)}return mQ(t,[{key:"sizeNodes",get:function(){return O1(this,x1,"f").size}},{key:"sizeEdges",get:function(){return O1(this,S1,"f").size}},{key:"getNodes",value:function(){return O1(this,x1,"f").getSelection()}},{key:"getEdges",value:function(){return O1(this,S1,"f").getSelection()}},{key:"addNodes",value:function(){var t;(t=O1(this,x1,"f")).add.apply(t,arguments)}},{key:"addEdges",value:function(){var t;(t=O1(this,S1,"f")).add.apply(t,arguments)}},{key:"deleteNodes",value:function(t){O1(this,x1,"f").delete(t)}},{key:"deleteEdges",value:function(t){O1(this,S1,"f").delete(t)}},{key:"clear",value:function(){O1(this,x1,"f").clear(),O1(this,S1,"f").clear()}},{key:"commit",value:function(){for(var t,e,i={nodes:O1(this,x1,"f").commit(),edges:O1(this,S1,"f").commit()},o=arguments.length,n=new Array(o),r=0;r=t.length?{done:!0}:{done:!1,value:t[o++]}},e:function(t){throw t},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function N1(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,o=new Array(e);i4&&void 0!==arguments[4]&&arguments[4],r=this._initBaseEvent(e,i);if(!0===n)r.nodes=[],r.edges=[];else{var s=this.getSelection();r.nodes=s.nodes,r.edges=s.edges}void 0!==o&&(r.previousSelection=o),"click"==t&&(r.items=this.getClickedItems(i)),void 0!==e.controlEdge&&(r.controlEdge=e.controlEdge),this.body.emitter.emit(t,r)}},{key:"selectObject",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.options.selectConnectedEdges;if(void 0!==t){if(t instanceof X_){var i;if(!0===e)(i=this._selectionAccumulator).addEdges.apply(i,aH(t.edges));this._selectionAccumulator.addNodes(t)}else this._selectionAccumulator.addEdges(t);return!0}return!1}},{key:"deselectObject",value:function(t){!0===t.isSelected()&&(t.selected=!1,this._removeFromSelection(t))}},{key:"_getAllNodesOverlappingWith",value:function(t){for(var e=[],i=this.body.nodes,o=0;o1&&void 0!==arguments[1])||arguments[1],i=this._pointerToPositionObject(t),o=this._getAllNodesOverlappingWith(i);return o.length>0?!0===e?this.body.nodes[o[o.length-1]]:o[o.length-1]:void 0}},{key:"_getEdgesOverlappingWith",value:function(t,e){for(var i=this.body.edges,o=0;o1&&void 0!==arguments[1])||arguments[1],i=this.canvas.DOMtoCanvas(t),o=10,n=null,r=this.body.edges,s=0;s0&&(this.generateClickEvent("deselectEdge",e,t,n),i=!0),o.nodes.deleted.length>0&&(this.generateClickEvent("deselectNode",e,t,n),i=!0),o.nodes.added.length>0&&(this.generateClickEvent("selectNode",e,t),i=!0),o.edges.added.length>0&&(this.generateClickEvent("selectEdge",e,t),i=!0),!0===i&&this.generateClickEvent("select",e,t)}},{key:"getSelection",value:function(){return{nodes:this.getSelectedNodeIds(),edges:this.getSelectedEdgeIds()}}},{key:"getSelectedNodes",value:function(){return this._selectionAccumulator.getNodes()}},{key:"getSelectedEdges",value:function(){return this._selectionAccumulator.getEdges()}},{key:"getSelectedNodeIds",value:function(){var t;return OH(t=this._selectionAccumulator.getNodes()).call(t,(function(t){return t.id}))}},{key:"getSelectedEdgeIds",value:function(){var t;return OH(t=this._selectionAccumulator.getEdges()).call(t,(function(t){return t.id}))}},{key:"setSelection",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!t||!t.nodes&&!t.edges)throw new TypeError("Selection must be an object with nodes and/or edges properties");if((e.unselectAll||void 0===e.unselectAll)&&this.unselectAll(),t.nodes){var i,o=T1(t.nodes);try{for(o.s();!(i=o.n()).done;){var n=i.value,r=this.body.nodes[n];if(!r)throw new RangeError('Node with id "'+n+'" not found');this.selectObject(r,e.highlightEdges)}}catch(t){o.e(t)}finally{o.f()}}if(t.edges){var s,a=T1(t.edges);try{for(a.s();!(s=a.n()).done;){var l=s.value,h=this.body.edges[l];if(!h)throw new RangeError('Edge with id "'+l+'" not found');this.selectObject(h)}}catch(t){a.e(t)}finally{a.f()}}this.body.emitter.emit("_requestRedraw"),this._selectionAccumulator.commit()}},{key:"selectNodes",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(!t||void 0===t.length)throw"Selection must be an array with ids";this.setSelection({nodes:t},{highlightEdges:e})}},{key:"selectEdges",value:function(t){if(!t||void 0===t.length)throw"Selection must be an array with ids";this.setSelection({edges:t})}},{key:"updateSelection",value:function(){for(var t in this._selectionAccumulator.getNodes())Object.prototype.hasOwnProperty.call(this.body.nodes,t.id)||this._selectionAccumulator.deleteNodes(t);for(var e in this._selectionAccumulator.getEdges())Object.prototype.hasOwnProperty.call(this.body.edges,e.id)||this._selectionAccumulator.deleteEdges(e)}},{key:"getClickedItems",value:function(t){for(var e=this.canvas.DOMtoCanvas(t),i=[],o=this.body.nodeIndices,n=this.body.nodes,r=o.length-1;r>=0;r--){var s=n[o[r]].getItemsOnPoint(e);i.push.apply(i,s)}for(var a=this.body.edgeIndices,l=this.body.edges,h=a.length-1;h>=0;h--){var c=l[a[h]].getItemsOnPoint(e);i.push.apply(i,c)}return i}}]),t}(),U1=sj,L1=Math.floor,Q1=function(t,e){var i=t.length,o=L1(i/2);return i<8?H1(t,e):V1(t,Q1(U1(t,0,o),e),Q1(U1(t,o),e),e)},H1=function(t,e){for(var i,o,n=t.length,r=1;r0;)t[o]=t[--o];o!==r++&&(t[o]=i)}return t},V1=function(t,e,i,o){for(var n=e.length,r=i.length,s=0,a=0;s3)){if(a2)return!0;if(h2)return h2<603;var t,e,i,o,n="";for(t=65;t<76;t++){switch(e=String.fromCharCode(t),t){case 66:case 69:case 70:case 72:i=3;break;case 68:case 71:i=4;break;default:i=2}for(o=0;o<47;o++)c2.push({k:e+o,v:i})}for(c2.sort((function(t,e){return e.v-t.v})),o=0;oi2(i)?1:-1}}(t)),i=t2(n),o=0;o=0:a>l;l+=h)l in s&&(n=i(n,s[l],l,r));return n}},O2={left:M2(!1),right:M2(!0)},D2="process"===EM(sM.process),R2=O2.left;DR({target:"Array",proto:!0,forced:!D2&&yO>79&&yO<83||!jH("reduce")},{reduce:function(t){var e=arguments.length;return R2(this,t,e,e>1?arguments[1]:void 0)}});var B2=TB("Array").reduce,z2=hO,P2=B2,F2=Array.prototype,T2=function(t){var e=t.reduce;return t===F2||z2(F2,t)&&e===F2.reduce?P2:e},N2=nM(T2);function j2(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var U2=function(){function t(){fN(this,t)}return mQ(t,[{key:"abstract",value:function(){throw new Error("Can't instantiate abstract class!")}},{key:"fake_use",value:function(){}},{key:"curveType",value:function(){return this.abstract()}},{key:"getPosition",value:function(t){return this.fake_use(t),this.abstract()}},{key:"setPosition",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0;this.fake_use(t,e,i),this.abstract()}},{key:"getTreeSize",value:function(t){return this.fake_use(t),this.abstract()}},{key:"sort",value:function(t){this.fake_use(t),this.abstract()}},{key:"fix",value:function(t,e){this.fake_use(t,e),this.abstract()}},{key:"shift",value:function(t,e){this.fake_use(t,e),this.abstract()}}]),t}(),L2=function(t){s_(i,t);var e=j2(i);function i(t){var o;return fN(this,i),(o=e.call(this)).layout=t,o}return mQ(i,[{key:"curveType",value:function(){return"horizontal"}},{key:"getPosition",value:function(t){return t.x}},{key:"setPosition",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0;void 0!==i&&this.layout.hierarchical.addToOrdering(t,i),t.x=e}},{key:"getTreeSize",value:function(t){var e=this.layout.hierarchical.getTreeSize(this.layout.body.nodes,t);return{min:e.min_x,max:e.max_x}}},{key:"sort",value:function(t){E2(t).call(t,(function(t,e){return t.x-e.x}))}},{key:"fix",value:function(t,e){t.y=this.layout.options.hierarchical.levelSeparation*e,t.options.fixed.y=!0}},{key:"shift",value:function(t,e){this.layout.body.nodes[t].x+=e}}]),i}(U2),Q2=function(t){s_(i,t);var e=j2(i);function i(t){var o;return fN(this,i),(o=e.call(this)).layout=t,o}return mQ(i,[{key:"curveType",value:function(){return"vertical"}},{key:"getPosition",value:function(t){return t.y}},{key:"setPosition",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0;void 0!==i&&this.layout.hierarchical.addToOrdering(t,i),t.y=e}},{key:"getTreeSize",value:function(t){var e=this.layout.hierarchical.getTreeSize(this.layout.body.nodes,t);return{min:e.min_y,max:e.max_y}}},{key:"sort",value:function(t){E2(t).call(t,(function(t,e){return t.y-e.y}))}},{key:"fix",value:function(t,e){t.x=this.layout.options.hierarchical.levelSeparation*e,t.options.fixed.x=!0}},{key:"shift",value:function(t,e){this.layout.body.nodes[t].y+=e}}]),i}(U2),H2=zj.every;DR({target:"Array",proto:!0,forced:!jH("every")},{every:function(t){return H2(this,t,arguments.length>1?arguments[1]:void 0)}});var V2=TB("Array").every,W2=hO,G2=V2,K2=Array.prototype,q2=function(t){var e=t.every;return t===K2||W2(K2,t)&&e===K2.every?G2:e},Y2=nM(q2);function Z2(t,e){var i=void 0!==lH&&uN(t)||t["@@iterator"];if(!i){if(EH(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return J2(t,e);var o=vH(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===o&&t.constructor&&(o=t.constructor.name);if("Map"===o||"Set"===o)return GT(t);if("Arguments"===o||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(o))return J2(t,e)}(t))||e){i&&(t=i);var o=0,n=function(){};return{s:n,n:function(){return o>=t.length?{done:!0}:{done:!1,value:t[o++]}},e:function(t){throw t},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function J2(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,o=new Array(e);i=e[o])&&(e[o]=e[i]+1)})),e}function _2(t,e,i,o){var n,r,s=WW(null),a=N2(n=aH(RX(o).call(o))).call(n,(function(t,e){return t+1+e.edges.length}),0),l=i+"Id",h="to"===i?1:-1,c=Z2(o);try{var d,u=function(){var n=sH(r.value,2),c=n[0],d=n[1];if(!o.has(c)||!t(d))return 0;s[c]=0;for(var u,f,p=[d],v=0,g=function(){var t,n;if(!o.has(c))return 0;var r=s[u.id]+h;if(ZH(t=aW(n=u.edges).call(n,(function(t){return t.connected&&t.to!==t.from&&t[i]!==u&&o.has(t.toId)&&o.has(t.fromId)}))).call(t,(function(t){var o=t[l],n=s[o];(null==n||e(r,n))&&(s[o]=r,p.push(t[i]))})),v>a)return{v:{v:X2(o,s)}};++v};u=p.pop();)if(0!==(f=g())&&f)return f.v};for(c.s();!(r=c.n()).done;)if(0!==(d=u())&&d)return d.v}catch(t){c.e(t)}finally{c.f()}return s}var $2=function(){function t(){fN(this,t),this.childrenReference={},this.parentReference={},this.trees={},this.distributionOrdering={},this.levels={},this.distributionIndex={},this.isTree=!1,this.treeIndex=-1}return mQ(t,[{key:"addRelation",value:function(t,e){void 0===this.childrenReference[t]&&(this.childrenReference[t]=[]),this.childrenReference[t].push(e),void 0===this.parentReference[e]&&(this.parentReference[e]=[]),this.parentReference[e].push(t)}},{key:"checkIfTree",value:function(){for(var t in this.parentReference)if(this.parentReference[t].length>1)return void(this.isTree=!1);this.isTree=!0}},{key:"numTrees",value:function(){return this.treeIndex+1}},{key:"setTreeIndex",value:function(t,e){void 0!==e&&void 0===this.trees[t.id]&&(this.trees[t.id]=e,this.treeIndex=Math.max(e,this.treeIndex))}},{key:"ensureLevel",value:function(t){void 0===this.levels[t]&&(this.levels[t]=0)}},{key:"getMaxLevel",value:function(t){var e=this,i={};return function t(o){if(void 0!==i[o])return i[o];var n=e.levels[o];if(e.childrenReference[o]){var r=e.childrenReference[o];if(r.length>0)for(var s=0;s0&&(i.levelSeparation*=-1):i.levelSeparation<0&&(i.levelSeparation*=-1),this.setDirectionStrategy(),this.body.emitter.emit("_resetHierarchicalLayout"),this.adaptAllOptionsForHierarchicalLayout(e);if(!0===o)return this.body.emitter.emit("refresh"),Tq(e,this.optionsBackup)}return e}},{key:"_resetRNG",value:function(t){this.initialRandomSeed=t,this._rng=Eq(this.initialRandomSeed)}},{key:"adaptAllOptionsForHierarchicalLayout",value:function(t){if(!0===this.options.hierarchical.enabled){var e=this.optionsBackup.physics;void 0===t.physics||!0===t.physics?(t.physics={enabled:void 0===e.enabled||e.enabled,solver:"hierarchicalRepulsion"},e.enabled=void 0===e.enabled||e.enabled,e.solver=e.solver||"barnesHut"):"object"===pQ(t.physics)?(e.enabled=void 0===t.physics.enabled||t.physics.enabled,e.solver=t.physics.solver||"barnesHut",t.physics.solver="hierarchicalRepulsion"):!1!==t.physics&&(e.solver="barnesHut",t.physics={solver:"hierarchicalRepulsion"});var i=this.direction.curveType();if(void 0===t.edges)this.optionsBackup.edges={smooth:{enabled:!0,type:"dynamic"}},t.edges={smooth:!1};else if(void 0===t.edges.smooth)this.optionsBackup.edges={smooth:{enabled:!0,type:"dynamic"}},t.edges.smooth=!1;else if("boolean"==typeof t.edges.smooth)this.optionsBackup.edges={smooth:t.edges.smooth},t.edges.smooth={enabled:t.edges.smooth,type:i};else{var o=t.edges.smooth;void 0!==o.type&&"dynamic"!==o.type&&(i=o.type),this.optionsBackup.edges={smooth:{enabled:void 0===o.enabled||o.enabled,type:void 0===o.type?"dynamic":o.type,roundness:void 0===o.roundness?.5:o.roundness,forceDirection:void 0!==o.forceDirection&&o.forceDirection}},t.edges.smooth={enabled:void 0===o.enabled||o.enabled,type:i,roundness:void 0===o.roundness?.5:o.roundness,forceDirection:void 0!==o.forceDirection&&o.forceDirection}}this.body.emitter.emit("_forceDisableDynamicCurves",i)}return t}},{key:"positionInitially",value:function(t){if(!0!==this.options.hierarchical.enabled){this._resetRNG(this.initialRandomSeed);for(var e=t.length+50,i=0;in){for(var s=t.length;t.length>n&&o<=10;){o+=1;var a=t.length;if(o%3==0?this.body.modules.clustering.clusterBridges(r):this.body.modules.clustering.clusterOutliers(r),a==t.length&&o%3!=0)return this._declusterAll(),this.body.emitter.emit("_layoutFailed"),void console.info("This network could not be positioned by this version of the improved layout algorithm. Please disable improvedLayout for better performance.")}this.body.modules.kamadaKawai.setOptions({springLength:Math.max(150,2*s)})}o>10&&console.info("The clustering didn't succeed within the amount of interations allowed, progressing with partial result."),this.body.modules.kamadaKawai.solve(t,this.body.edgeIndices,!0),this._shiftToCenter();for(var l=0;l0){var t,e,i=!1,o=!1;for(e in this.lastNodeOnLevel={},this.hierarchical=new $2,this.body.nodes)Object.prototype.hasOwnProperty.call(this.body.nodes,e)&&(void 0!==(t=this.body.nodes[e]).options.level?(i=!0,this.hierarchical.levels[e]=t.options.level):o=!0);if(!0===o&&!0===i)throw new Error("To use the hierarchical layout, nodes require either no predefined levels or levels have to be defined for all nodes.");if(!0===o){var n=this.options.hierarchical.sortMethod;"hubsize"===n?this._determineLevelsByHubsize():"directed"===n?this._determineLevelsDirected():"custom"===n&&this._determineLevelsCustomCallback()}for(var r in this.body.nodes)Object.prototype.hasOwnProperty.call(this.body.nodes,r)&&this.hierarchical.ensureLevel(r);var s=this._getDistribution();this._generateMap(),this._placeNodesByHierarchy(s),this._condenseHierarchy(),this._shiftToCenter()}}},{key:"_condenseHierarchy",value:function(){var t=this,e=!1,i={},o=function(e,i){var o=t.hierarchical.trees;for(var n in o)Object.prototype.hasOwnProperty.call(o,n)&&o[n]===e&&t.direction.shift(n,i)},n=function(){for(var e=[],i=0;i0)for(var r=0;r1&&void 0!==arguments[1]?arguments[1]:1e9,o=1e9,n=1e9,r=1e9,s=-1e9;for(var a in e)if(Object.prototype.hasOwnProperty.call(e,a)){var l=t.body.nodes[a],h=t.hierarchical.levels[l.id],c=t.direction.getPosition(l),d=sH(t._getSpaceAroundNode(l,e),2),u=d[0],f=d[1];o=Math.min(u,o),n=Math.min(f,n),h<=i&&(r=Math.min(c,r),s=Math.max(c,s))}return[r,s,o,n]},a=function(e,i,o){for(var n=t.hierarchical,r=0;r1)for(var l=0;l2&&void 0!==arguments[2]&&arguments[2],a=t.direction.getPosition(i),l=t.direction.getPosition(o),h=Math.abs(l-a),c=t.options.hierarchical.nodeSpacing;if(h>c){var d={},u={};r(i,d),r(o,u);var f=function(e,i){var o=t.hierarchical.getMaxLevel(e.id),n=t.hierarchical.getMaxLevel(i.id);return Math.min(o,n)}(i,o),p=s(d,f),v=s(u,f),g=p[1],y=v[0],m=v[2];if(Math.abs(g-y)>c){var b=g-y+c;b<-m+c&&(b=-m+c),b<0&&(t._shiftBlock(o.id,b),e=!0,!0===n&&t._centerParent(o))}}},h=function(o,n){for(var a=n.id,l=n.edges,h=t.hierarchical.levels[n.id],c=t.options.hierarchical.levelSeparation*t.options.hierarchical.levelSeparation,d={},u=[],f=0;f0?f=Math.min(u,d-t.options.hierarchical.nodeSpacing):u<0&&(f=-Math.min(-u,c-t.options.hierarchical.nodeSpacing)),0!=f&&(t._shiftBlock(n.id,f),e=!0)}(b),function(i){var o=t.direction.getPosition(n),r=sH(t._getSpaceAroundNode(n),2),s=r[0],a=r[1],l=i-o,h=o;l>0?h=Math.min(o+(a-t.options.hierarchical.nodeSpacing),i):l<0&&(h=Math.max(o-(s-t.options.hierarchical.nodeSpacing),i)),h!==o&&(t.direction.setPosition(n,h),e=!0)}(b=m(o,l))};!0===this.options.hierarchical.blockShifting&&(function(i){var o=t.hierarchical.getLevels();o=rV(o).call(o);for(var n=0;n0&&Math.abs(d)0&&(l=this.direction.getPosition(o[r-1])+a),this.direction.setPosition(s,l,e),this._validatePositionAndContinue(s,e,l),n++}}}}},{key:"_placeBranchNodes",value:function(t,e){var i,o=this.hierarchical.childrenReference[t];if(void 0!==o){for(var n=[],r=0;re&&void 0===this.positionedNodes[a.id]))return;var h=this.options.hierarchical.nodeSpacing,c=void 0;c=0===s?this.direction.getPosition(this.body.nodes[t]):this.direction.getPosition(n[s-1])+h,this.direction.setPosition(a,c,l),this._validatePositionAndContinue(a,l,c)}var d=this._getCenterPosition(n);this.direction.setPosition(this.body.nodes[t],d,e)}}},{key:"_validatePositionAndContinue",value:function(t,e,i){if(this.hierarchical.isTree){if(void 0!==this.lastNodeOnLevel[e]){var o=this.direction.getPosition(this.body.nodes[this.lastNodeOnLevel[e]]);if(i-ot}),"from",t)}(i),this.hierarchical.setMinLevelToZero(this.body.nodes)}},{key:"_generateMap",value:function(){var t=this;this._crawlNetwork((function(e,i){t.hierarchical.levels[i.id]>t.hierarchical.levels[e.id]&&t.hierarchical.addRelation(e.id,i.id)})),this.hierarchical.checkIfTree()}},{key:"_crawlNetwork",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:function(){},i=arguments.length>1?arguments[1]:void 0,o={},n=function i(n,r){if(void 0===o[n.id]){var s;t.hierarchical.setTreeIndex(n,r),o[n.id]=!0;for(var a=t._getActiveEdges(n),l=0;l=t.length?{done:!0}:{done:!1,value:t[o++]}},e:function(t){throw t},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function i3(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,o=new Array(e);i0&&!1!==this.options.deleteNode||0===i&&!1!==this.options.deleteEdge)&&(!0===s&&this._createSeperator(4),this._createDeleteButton(r)),this._bindElementEvents(this.closeDiv,VB(t=this.toggleEditMode).call(t,this)),this._temporaryBindEvent("select",VB(e=this.showManipulatorToolbar).call(e,this))}this.body.emitter.emit("_redraw")}},{key:"addNodeMode",value:function(){var t;if(!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="addNode",!0===this.guiEnabled){var e,i=this.options.locales[this.options.locale];this.manipulationDOM={},this._createBackButton(i),this._createSeperator(),this._createDescription(i.addDescription||this.options.locales.en.addDescription),this._bindElementEvents(this.closeDiv,VB(e=this.toggleEditMode).call(e,this))}this._temporaryBindEvent("click",VB(t=this._performAddNode).call(t,this))}},{key:"editNode",value:function(){var t=this;!0!==this.editMode&&this.enableEditMode(),this._clean();var e=this.selectionHandler.getSelectedNodes()[0];if(void 0!==e){if(this.inMode="editNode","function"!=typeof this.options.editNode)throw new Error("No function has been configured to handle the editing of nodes.");if(!0!==e.isCluster){var i=Tq({},e.options,!1);if(i.x=e.x,i.y=e.y,2!==this.options.editNode.length)throw new Error("The function for edit does not support two arguments (data, callback)");this.options.editNode(i,(function(e){null!=e&&"editNode"===t.inMode&&t.body.data.nodes.getDataSet().update(e),t.showManipulatorToolbar()}))}else alert(this.options.locales[this.options.locale].editClusterError||this.options.locales.en.editClusterError)}else this.showManipulatorToolbar()}},{key:"addEdgeMode",value:function(){var t,e,i,o,n;if(!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="addEdge",!0===this.guiEnabled){var r,s=this.options.locales[this.options.locale];this.manipulationDOM={},this._createBackButton(s),this._createSeperator(),this._createDescription(s.edgeDescription||this.options.locales.en.edgeDescription),this._bindElementEvents(this.closeDiv,VB(r=this.toggleEditMode).call(r,this))}this._temporaryBindUI("onTouch",VB(t=this._handleConnect).call(t,this)),this._temporaryBindUI("onDragEnd",VB(e=this._finishConnect).call(e,this)),this._temporaryBindUI("onDrag",VB(i=this._dragControlNode).call(i,this)),this._temporaryBindUI("onRelease",VB(o=this._finishConnect).call(o,this)),this._temporaryBindUI("onDragStart",VB(n=this._dragStartEdge).call(n,this)),this._temporaryBindUI("onHold",(function(){}))}},{key:"editEdgeMode",value:function(){if(!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="editEdge","object"!==pQ(this.options.editEdge)||"function"!=typeof this.options.editEdge.editWithoutDrag||(this.edgeBeingEditedId=this.selectionHandler.getSelectedEdgeIds()[0],void 0===this.edgeBeingEditedId)){if(!0===this.guiEnabled){var t,e=this.options.locales[this.options.locale];this.manipulationDOM={},this._createBackButton(e),this._createSeperator(),this._createDescription(e.editEdgeDescription||this.options.locales.en.editEdgeDescription),this._bindElementEvents(this.closeDiv,VB(t=this.toggleEditMode).call(t,this))}if(this.edgeBeingEditedId=this.selectionHandler.getSelectedEdgeIds()[0],void 0!==this.edgeBeingEditedId){var i,o,n,r,s=this.body.edges[this.edgeBeingEditedId],a=this._getNewTargetNode(s.from.x,s.from.y),l=this._getNewTargetNode(s.to.x,s.to.y);this.temporaryIds.nodes.push(a.id),this.temporaryIds.nodes.push(l.id),this.body.nodes[a.id]=a,this.body.nodeIndices.push(a.id),this.body.nodes[l.id]=l,this.body.nodeIndices.push(l.id),this._temporaryBindUI("onTouch",VB(i=this._controlNodeTouch).call(i,this)),this._temporaryBindUI("onTap",(function(){})),this._temporaryBindUI("onHold",(function(){})),this._temporaryBindUI("onDragStart",VB(o=this._controlNodeDragStart).call(o,this)),this._temporaryBindUI("onDrag",VB(n=this._controlNodeDrag).call(n,this)),this._temporaryBindUI("onDragEnd",VB(r=this._controlNodeDragEnd).call(r,this)),this._temporaryBindUI("onMouseMove",(function(){})),this._temporaryBindEvent("beforeDrawing",(function(t){var e=s.edgeType.findBorderPositions(t);!1===a.selected&&(a.x=e.from.x,a.y=e.from.y),!1===l.selected&&(l.x=e.to.x,l.y=e.to.y)})),this.body.emitter.emit("_redraw")}else this.showManipulatorToolbar()}else{var h=this.body.edges[this.edgeBeingEditedId];this._performEditEdge(h.from.id,h.to.id)}}},{key:"deleteSelected",value:function(){var t=this;!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="delete";var e=this.selectionHandler.getSelectedNodeIds(),i=this.selectionHandler.getSelectedEdgeIds(),o=void 0;if(e.length>0){for(var n=0;n0&&"function"==typeof this.options.deleteEdge&&(o=this.options.deleteEdge);if("function"==typeof o){var r={nodes:e,edges:i};if(2!==o.length)throw new Error("The function for delete does not support two arguments (data, callback)");o(r,(function(e){null!=e&&"delete"===t.inMode?(t.body.data.edges.getDataSet().remove(e.edges),t.body.data.nodes.getDataSet().remove(e.nodes),t.body.emitter.emit("startSimulation"),t.showManipulatorToolbar()):(t.body.emitter.emit("startSimulation"),t.showManipulatorToolbar())}))}else this.body.data.edges.getDataSet().remove(i),this.body.data.nodes.getDataSet().remove(e),this.body.emitter.emit("startSimulation"),this.showManipulatorToolbar()}},{key:"_setup",value:function(){!0===this.options.enabled?(this.guiEnabled=!0,this._createWrappers(),!1===this.editMode?this._createEditButton():this.showManipulatorToolbar()):(this._removeManipulationDOM(),this.guiEnabled=!1)}},{key:"_createWrappers",value:function(){var t,e;(void 0===this.manipulationDiv&&(this.manipulationDiv=document.createElement("div"),this.manipulationDiv.className="vis-manipulation",!0===this.editMode?this.manipulationDiv.style.display="block":this.manipulationDiv.style.display="none",this.canvas.frame.appendChild(this.manipulationDiv)),void 0===this.editModeDiv&&(this.editModeDiv=document.createElement("div"),this.editModeDiv.className="vis-edit-mode",!0===this.editMode?this.editModeDiv.style.display="none":this.editModeDiv.style.display="block",this.canvas.frame.appendChild(this.editModeDiv)),void 0===this.closeDiv)&&(this.closeDiv=document.createElement("button"),this.closeDiv.className="vis-close",this.closeDiv.setAttribute("aria-label",null!==(t=null===(e=this.options.locales[this.options.locale])||void 0===e?void 0:e.close)&&void 0!==t?t:this.options.locales.en.close),this.closeDiv.style.display=this.manipulationDiv.style.display,this.canvas.frame.appendChild(this.closeDiv))}},{key:"_getNewTargetNode",value:function(t,e){var i=Tq({},this.options.controlNodeStyle);i.id="targetNode"+u0(),i.hidden=!1,i.physics=!1,i.x=t,i.y=e;var o=this.body.functions.createNode(i);return o.shape.boundingBox={left:t,right:t,top:e,bottom:e},o}},{key:"_createEditButton",value:function(){var t;this._clean(),this.manipulationDOM={},Oq(this.editModeDiv);var e=this.options.locales[this.options.locale],i=this._createButton("editMode","vis-edit vis-edit-mode",e.edit||this.options.locales.en.edit);this.editModeDiv.appendChild(i),this._bindElementEvents(i,VB(t=this.toggleEditMode).call(t,this))}},{key:"_clean",value:function(){this.inMode=!1,!0===this.guiEnabled&&(Oq(this.editModeDiv),Oq(this.manipulationDiv),this._cleanupDOMEventListeners()),this._cleanupTemporaryNodesAndEdges(),this._unbindTemporaryUIs(),this._unbindTemporaryEvents(),this.body.emitter.emit("restorePhysics")}},{key:"_cleanupDOMEventListeners",value:function(){var t,e,i=e3(IV(t=this._domEventListenerCleanupQueue).call(t,0));try{for(i.s();!(e=i.n()).done;){(0,e.value)()}}catch(t){i.e(t)}finally{i.f()}}},{key:"_removeManipulationDOM",value:function(){this._clean(),Oq(this.manipulationDiv),Oq(this.editModeDiv),Oq(this.closeDiv),this.manipulationDiv&&this.canvas.frame.removeChild(this.manipulationDiv),this.editModeDiv&&this.canvas.frame.removeChild(this.editModeDiv),this.closeDiv&&this.canvas.frame.removeChild(this.closeDiv),this.manipulationDiv=void 0,this.editModeDiv=void 0,this.closeDiv=void 0}},{key:"_createSeperator",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1;this.manipulationDOM["seperatorLineDiv"+t]=document.createElement("div"),this.manipulationDOM["seperatorLineDiv"+t].className="vis-separator-line",this.manipulationDiv.appendChild(this.manipulationDOM["seperatorLineDiv"+t])}},{key:"_createAddNodeButton",value:function(t){var e,i=this._createButton("addNode","vis-add",t.addNode||this.options.locales.en.addNode);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,VB(e=this.addNodeMode).call(e,this))}},{key:"_createAddEdgeButton",value:function(t){var e,i=this._createButton("addEdge","vis-connect",t.addEdge||this.options.locales.en.addEdge);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,VB(e=this.addEdgeMode).call(e,this))}},{key:"_createEditNodeButton",value:function(t){var e,i=this._createButton("editNode","vis-edit",t.editNode||this.options.locales.en.editNode);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,VB(e=this.editNode).call(e,this))}},{key:"_createEditEdgeButton",value:function(t){var e,i=this._createButton("editEdge","vis-edit",t.editEdge||this.options.locales.en.editEdge);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,VB(e=this.editEdgeMode).call(e,this))}},{key:"_createDeleteButton",value:function(t){var e,i;i=this.options.rtl?"vis-delete-rtl":"vis-delete";var o=this._createButton("delete",i,t.del||this.options.locales.en.del);this.manipulationDiv.appendChild(o),this._bindElementEvents(o,VB(e=this.deleteSelected).call(e,this))}},{key:"_createBackButton",value:function(t){var e,i=this._createButton("back","vis-back",t.back||this.options.locales.en.back);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,VB(e=this.showManipulatorToolbar).call(e,this))}},{key:"_createButton",value:function(t,e,i){var o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"vis-label";return this.manipulationDOM[t+"Div"]=document.createElement("button"),this.manipulationDOM[t+"Div"].className="vis-button "+e,this.manipulationDOM[t+"Label"]=document.createElement("div"),this.manipulationDOM[t+"Label"].className=o,this.manipulationDOM[t+"Label"].innerText=i,this.manipulationDOM[t+"Div"].appendChild(this.manipulationDOM[t+"Label"]),this.manipulationDOM[t+"Div"]}},{key:"_createDescription",value:function(t){this.manipulationDOM.descriptionLabel=document.createElement("div"),this.manipulationDOM.descriptionLabel.className="vis-none",this.manipulationDOM.descriptionLabel.innerText=t,this.manipulationDiv.appendChild(this.manipulationDOM.descriptionLabel)}},{key:"_temporaryBindEvent",value:function(t,e){this.temporaryEventFunctions.push({event:t,boundFunction:e}),this.body.emitter.on(t,e)}},{key:"_temporaryBindUI",value:function(t,e){if(void 0===this.body.eventListeners[t])throw new Error("This UI function does not exist. Typo? You tried: "+t+" possible are: "+YW(BH(this.body.eventListeners)));this.temporaryUIFunctions[t]=this.body.eventListeners[t],this.body.eventListeners[t]=e}},{key:"_unbindTemporaryUIs",value:function(){for(var t in this.temporaryUIFunctions)Object.prototype.hasOwnProperty.call(this.temporaryUIFunctions,t)&&(this.body.eventListeners[t]=this.temporaryUIFunctions[t],delete this.temporaryUIFunctions[t]);this.temporaryUIFunctions={}}},{key:"_unbindTemporaryEvents",value:function(){for(var t=0;t=0;s--)if(n[s]!==this.selectedControlNode.id){r=this.body.nodes[n[s]];break}if(void 0!==r&&void 0!==this.selectedControlNode)if(!0===r.isCluster)alert(this.options.locales[this.options.locale].createEdgeError||this.options.locales.en.createEdgeError);else{var a=this.body.nodes[this.temporaryIds.nodes[0]];this.selectedControlNode.id===a.id?this._performEditEdge(r.id,o.to.id):this._performEditEdge(o.from.id,r.id)}else o.updateEdgeType(),this.body.emitter.emit("restorePhysics");this.body.emitter.emit("_redraw")}}},{key:"_handleConnect",value:function(t){if((new Date).valueOf()-this.touchTime>100){this.lastTouch=this.body.functions.getPointer(t.center),this.lastTouch.translation=AB({},this.body.view.translation),this.interactionHandler.drag.pointer=this.lastTouch,this.interactionHandler.drag.translation=this.lastTouch.translation;var e=this.lastTouch,i=this.selectionHandler.getNodeAt(e);if(void 0!==i)if(!0===i.isCluster)alert(this.options.locales[this.options.locale].createEdgeError||this.options.locales.en.createEdgeError);else{var o=this._getNewTargetNode(i.x,i.y);this.body.nodes[o.id]=o,this.body.nodeIndices.push(o.id);var n=this.body.functions.createEdge({id:"connectionEdge"+u0(),from:i.id,to:o.id,physics:!1,smooth:{enabled:!0,type:"continuous",roundness:.5}});this.body.edges[n.id]=n,this.body.edgeIndices.push(n.id),this.temporaryIds.nodes.push(o.id),this.temporaryIds.edges.push(n.id)}this.touchTime=(new Date).valueOf()}}},{key:"_dragControlNode",value:function(t){var e=this.body.functions.getPointer(t.center),i=this.selectionHandler._pointerToPositionObject(e),o=void 0;void 0!==this.temporaryIds.edges[0]&&(o=this.body.edges[this.temporaryIds.edges[0]].fromId);for(var n=this.selectionHandler._getAllNodesOverlappingWith(i),r=void 0,s=n.length-1;s>=0;s--){var a;if(-1===LW(a=this.temporaryIds.nodes).call(a,n[s])){r=this.body.nodes[n[s]];break}}if(t.controlEdge={from:o,to:r?r.id:void 0},this.selectionHandler.generateClickEvent("controlNodeDragging",t,e),void 0!==this.temporaryIds.nodes[0]){var l=this.body.nodes[this.temporaryIds.nodes[0]];l.x=this.canvas._XconvertDOMtoCanvas(e.x),l.y=this.canvas._YconvertDOMtoCanvas(e.y),this.body.emitter.emit("_redraw")}else this.interactionHandler.onDrag(t)}},{key:"_finishConnect",value:function(t){var e=this.body.functions.getPointer(t.center),i=this.selectionHandler._pointerToPositionObject(e),o=void 0;void 0!==this.temporaryIds.edges[0]&&(o=this.body.edges[this.temporaryIds.edges[0]].fromId);for(var n=this.selectionHandler._getAllNodesOverlappingWith(i),r=void 0,s=n.length-1;s>=0;s--){var a;if(-1===LW(a=this.temporaryIds.nodes).call(a,n[s])){r=this.body.nodes[n[s]];break}}this._cleanupTemporaryNodesAndEdges(),void 0!==r&&(!0===r.isCluster?alert(this.options.locales[this.options.locale].createEdgeError||this.options.locales.en.createEdgeError):void 0!==this.body.nodes[o]&&void 0!==this.body.nodes[r.id]&&this._performAddEdge(o,r.id)),t.controlEdge={from:o,to:r?r.id:void 0},this.selectionHandler.generateClickEvent("controlNodeDragEnd",t,e),this.body.emitter.emit("_redraw")}},{key:"_dragStartEdge",value:function(t){var e=this.lastTouch;this.selectionHandler.generateClickEvent("dragStart",t,e,void 0,!0)}},{key:"_performAddNode",value:function(t){var e=this,i={id:u0(),x:t.pointer.canvas.x,y:t.pointer.canvas.y,label:"new"};if("function"==typeof this.options.addNode){if(2!==this.options.addNode.length)throw this.showManipulatorToolbar(),new Error("The function for add does not support two arguments (data,callback)");this.options.addNode(i,(function(t){null!=t&&"addNode"===e.inMode&&e.body.data.nodes.getDataSet().add(t),e.showManipulatorToolbar()}))}else this.body.data.nodes.getDataSet().add(i),this.showManipulatorToolbar()}},{key:"_performAddEdge",value:function(t,e){var i=this,o={from:t,to:e};if("function"==typeof this.options.addEdge){if(2!==this.options.addEdge.length)throw new Error("The function for connect does not support two arguments (data,callback)");this.options.addEdge(o,(function(t){null!=t&&"addEdge"===i.inMode&&(i.body.data.edges.getDataSet().add(t),i.selectionHandler.unselectAll(),i.showManipulatorToolbar())}))}else this.body.data.edges.getDataSet().add(o),this.selectionHandler.unselectAll(),this.showManipulatorToolbar()}},{key:"_performEditEdge",value:function(t,e){var i=this,o={id:this.edgeBeingEditedId,from:t,to:e,label:this.body.data.edges.get(this.edgeBeingEditedId).label},n=this.options.editEdge;if("object"===pQ(n)&&(n=n.editWithoutDrag),"function"==typeof n){if(2!==n.length)throw new Error("The function for edit does not support two arguments (data, callback)");n(o,(function(t){null==t||"editEdge"!==i.inMode?(i.body.edges[o.id].updateEdgeType(),i.body.emitter.emit("_redraw"),i.showManipulatorToolbar()):(i.body.data.edges.getDataSet().update(t),i.selectionHandler.unselectAll(),i.showManipulatorToolbar())}))}else this.body.data.edges.getDataSet().update(o),this.selectionHandler.unselectAll(),this.showManipulatorToolbar()}}]),t}(),n3="string",r3="boolean",s3="number",a3="array",l3="object",h3=["arrow","bar","box","circle","crow","curve","diamond","image","inv_curve","inv_triangle","triangle","vee"],c3={borderWidth:{number:s3},borderWidthSelected:{number:s3,undefined:"undefined"},brokenImage:{string:n3,undefined:"undefined"},chosen:{label:{boolean:r3,function:"function"},node:{boolean:r3,function:"function"},__type__:{object:l3,boolean:r3}},color:{border:{string:n3},background:{string:n3},highlight:{border:{string:n3},background:{string:n3},__type__:{object:l3,string:n3}},hover:{border:{string:n3},background:{string:n3},__type__:{object:l3,string:n3}},__type__:{object:l3,string:n3}},opacity:{number:s3,undefined:"undefined"},fixed:{x:{boolean:r3},y:{boolean:r3},__type__:{object:l3,boolean:r3}},font:{align:{string:n3},color:{string:n3},size:{number:s3},face:{string:n3},background:{string:n3},strokeWidth:{number:s3},strokeColor:{string:n3},vadjust:{number:s3},multi:{boolean:r3,string:n3},bold:{color:{string:n3},size:{number:s3},face:{string:n3},mod:{string:n3},vadjust:{number:s3},__type__:{object:l3,string:n3}},boldital:{color:{string:n3},size:{number:s3},face:{string:n3},mod:{string:n3},vadjust:{number:s3},__type__:{object:l3,string:n3}},ital:{color:{string:n3},size:{number:s3},face:{string:n3},mod:{string:n3},vadjust:{number:s3},__type__:{object:l3,string:n3}},mono:{color:{string:n3},size:{number:s3},face:{string:n3},mod:{string:n3},vadjust:{number:s3},__type__:{object:l3,string:n3}},__type__:{object:l3,string:n3}},group:{string:n3,number:s3,undefined:"undefined"},heightConstraint:{minimum:{number:s3},valign:{string:n3},__type__:{object:l3,boolean:r3,number:s3}},hidden:{boolean:r3},icon:{face:{string:n3},code:{string:n3},size:{number:s3},color:{string:n3},weight:{string:n3,number:s3},__type__:{object:l3}},id:{string:n3,number:s3},image:{selected:{string:n3,undefined:"undefined"},unselected:{string:n3,undefined:"undefined"},__type__:{object:l3,string:n3}},imagePadding:{top:{number:s3},right:{number:s3},bottom:{number:s3},left:{number:s3},__type__:{object:l3,number:s3}},label:{string:n3,undefined:"undefined"},labelHighlightBold:{boolean:r3},level:{number:s3,undefined:"undefined"},margin:{top:{number:s3},right:{number:s3},bottom:{number:s3},left:{number:s3},__type__:{object:l3,number:s3}},mass:{number:s3},physics:{boolean:r3},scaling:{min:{number:s3},max:{number:s3},label:{enabled:{boolean:r3},min:{number:s3},max:{number:s3},maxVisible:{number:s3},drawThreshold:{number:s3},__type__:{object:l3,boolean:r3}},customScalingFunction:{function:"function"},__type__:{object:l3}},shadow:{enabled:{boolean:r3},color:{string:n3},size:{number:s3},x:{number:s3},y:{number:s3},__type__:{object:l3,boolean:r3}},shape:{string:["custom","ellipse","circle","database","box","text","image","circularImage","diamond","dot","star","triangle","triangleDown","square","icon","hexagon"]},ctxRenderer:{function:"function"},shapeProperties:{borderDashes:{boolean:r3,array:a3},borderRadius:{number:s3},interpolation:{boolean:r3},useImageSize:{boolean:r3},useBorderWithImage:{boolean:r3},coordinateOrigin:{string:["center","top-left"]},__type__:{object:l3}},size:{number:s3},title:{string:n3,dom:"dom",undefined:"undefined"},value:{number:s3,undefined:"undefined"},widthConstraint:{minimum:{number:s3},maximum:{number:s3},__type__:{object:l3,boolean:r3,number:s3}},x:{number:s3},y:{number:s3},__type__:{object:l3}},d3={configure:{enabled:{boolean:r3},filter:{boolean:r3,string:n3,array:a3,function:"function"},container:{dom:"dom"},showButton:{boolean:r3},__type__:{object:l3,boolean:r3,string:n3,array:a3,function:"function"}},edges:{arrows:{to:{enabled:{boolean:r3},scaleFactor:{number:s3},type:{string:h3},imageHeight:{number:s3},imageWidth:{number:s3},src:{string:n3},__type__:{object:l3,boolean:r3}},middle:{enabled:{boolean:r3},scaleFactor:{number:s3},type:{string:h3},imageWidth:{number:s3},imageHeight:{number:s3},src:{string:n3},__type__:{object:l3,boolean:r3}},from:{enabled:{boolean:r3},scaleFactor:{number:s3},type:{string:h3},imageWidth:{number:s3},imageHeight:{number:s3},src:{string:n3},__type__:{object:l3,boolean:r3}},__type__:{string:["from","to","middle"],object:l3}},endPointOffset:{from:{number:s3},to:{number:s3},__type__:{object:l3,number:s3}},arrowStrikethrough:{boolean:r3},background:{enabled:{boolean:r3},color:{string:n3},size:{number:s3},dashes:{boolean:r3,array:a3},__type__:{object:l3,boolean:r3}},chosen:{label:{boolean:r3,function:"function"},edge:{boolean:r3,function:"function"},__type__:{object:l3,boolean:r3}},color:{color:{string:n3},highlight:{string:n3},hover:{string:n3},inherit:{string:["from","to","both"],boolean:r3},opacity:{number:s3},__type__:{object:l3,string:n3}},dashes:{boolean:r3,array:a3},font:{color:{string:n3},size:{number:s3},face:{string:n3},background:{string:n3},strokeWidth:{number:s3},strokeColor:{string:n3},align:{string:["horizontal","top","middle","bottom"]},vadjust:{number:s3},multi:{boolean:r3,string:n3},bold:{color:{string:n3},size:{number:s3},face:{string:n3},mod:{string:n3},vadjust:{number:s3},__type__:{object:l3,string:n3}},boldital:{color:{string:n3},size:{number:s3},face:{string:n3},mod:{string:n3},vadjust:{number:s3},__type__:{object:l3,string:n3}},ital:{color:{string:n3},size:{number:s3},face:{string:n3},mod:{string:n3},vadjust:{number:s3},__type__:{object:l3,string:n3}},mono:{color:{string:n3},size:{number:s3},face:{string:n3},mod:{string:n3},vadjust:{number:s3},__type__:{object:l3,string:n3}},__type__:{object:l3,string:n3}},hidden:{boolean:r3},hoverWidth:{function:"function",number:s3},label:{string:n3,undefined:"undefined"},labelHighlightBold:{boolean:r3},length:{number:s3,undefined:"undefined"},physics:{boolean:r3},scaling:{min:{number:s3},max:{number:s3},label:{enabled:{boolean:r3},min:{number:s3},max:{number:s3},maxVisible:{number:s3},drawThreshold:{number:s3},__type__:{object:l3,boolean:r3}},customScalingFunction:{function:"function"},__type__:{object:l3}},selectionWidth:{function:"function",number:s3},selfReferenceSize:{number:s3},selfReference:{size:{number:s3},angle:{number:s3},renderBehindTheNode:{boolean:r3},__type__:{object:l3}},shadow:{enabled:{boolean:r3},color:{string:n3},size:{number:s3},x:{number:s3},y:{number:s3},__type__:{object:l3,boolean:r3}},smooth:{enabled:{boolean:r3},type:{string:["dynamic","continuous","discrete","diagonalCross","straightCross","horizontal","vertical","curvedCW","curvedCCW","cubicBezier"]},roundness:{number:s3},forceDirection:{string:["horizontal","vertical","none"],boolean:r3},__type__:{object:l3,boolean:r3}},title:{string:n3,undefined:"undefined"},width:{number:s3},widthConstraint:{maximum:{number:s3},__type__:{object:l3,boolean:r3,number:s3}},value:{number:s3,undefined:"undefined"},__type__:{object:l3}},groups:{useDefaultGroups:{boolean:r3},__any__:c3,__type__:{object:l3}},interaction:{dragNodes:{boolean:r3},dragView:{boolean:r3},hideEdgesOnDrag:{boolean:r3},hideEdgesOnZoom:{boolean:r3},hideNodesOnDrag:{boolean:r3},hover:{boolean:r3},keyboard:{enabled:{boolean:r3},speed:{x:{number:s3},y:{number:s3},zoom:{number:s3},__type__:{object:l3}},bindToWindow:{boolean:r3},autoFocus:{boolean:r3},__type__:{object:l3,boolean:r3}},multiselect:{boolean:r3},navigationButtons:{boolean:r3},selectable:{boolean:r3},selectConnectedEdges:{boolean:r3},hoverConnectedEdges:{boolean:r3},tooltipDelay:{number:s3},zoomView:{boolean:r3},zoomSpeed:{number:s3},__type__:{object:l3}},layout:{randomSeed:{undefined:"undefined",number:s3,string:n3},improvedLayout:{boolean:r3},clusterThreshold:{number:s3},hierarchical:{enabled:{boolean:r3},levelSeparation:{number:s3},nodeSpacing:{number:s3},treeSpacing:{number:s3},blockShifting:{boolean:r3},edgeMinimization:{boolean:r3},parentCentralization:{boolean:r3},direction:{string:["UD","DU","LR","RL"]},sortMethod:{string:["hubsize","directed"]},shakeTowards:{string:["leaves","roots"]},__type__:{object:l3,boolean:r3}},__type__:{object:l3}},manipulation:{enabled:{boolean:r3},initiallyActive:{boolean:r3},addNode:{boolean:r3,function:"function"},addEdge:{boolean:r3,function:"function"},editNode:{function:"function"},editEdge:{editWithoutDrag:{function:"function"},__type__:{object:l3,boolean:r3,function:"function"}},deleteNode:{boolean:r3,function:"function"},deleteEdge:{boolean:r3,function:"function"},controlNodeStyle:c3,__type__:{object:l3,boolean:r3}},nodes:c3,physics:{enabled:{boolean:r3},barnesHut:{theta:{number:s3},gravitationalConstant:{number:s3},centralGravity:{number:s3},springLength:{number:s3},springConstant:{number:s3},damping:{number:s3},avoidOverlap:{number:s3},__type__:{object:l3}},forceAtlas2Based:{theta:{number:s3},gravitationalConstant:{number:s3},centralGravity:{number:s3},springLength:{number:s3},springConstant:{number:s3},damping:{number:s3},avoidOverlap:{number:s3},__type__:{object:l3}},repulsion:{centralGravity:{number:s3},springLength:{number:s3},springConstant:{number:s3},nodeDistance:{number:s3},damping:{number:s3},__type__:{object:l3}},hierarchicalRepulsion:{centralGravity:{number:s3},springLength:{number:s3},springConstant:{number:s3},nodeDistance:{number:s3},damping:{number:s3},avoidOverlap:{number:s3},__type__:{object:l3}},maxVelocity:{number:s3},minVelocity:{number:s3},solver:{string:["barnesHut","repulsion","hierarchicalRepulsion","forceAtlas2Based"]},stabilization:{enabled:{boolean:r3},iterations:{number:s3},updateInterval:{number:s3},onlyDynamicEdges:{boolean:r3},fit:{boolean:r3},__type__:{object:l3,boolean:r3}},timestep:{number:s3},adaptiveTimestep:{boolean:r3},wind:{x:{number:s3},y:{number:s3},__type__:{object:l3}},__type__:{object:l3,boolean:r3}},autoResize:{boolean:r3},clickToUse:{boolean:r3},locale:{string:n3},locales:{__any__:{any:"any"},__type__:{object:l3}},height:{string:n3},width:{string:n3},__type__:{object:l3}},u3={nodes:{borderWidth:[1,0,10,1],borderWidthSelected:[2,0,10,1],color:{border:["color","#2B7CE9"],background:["color","#97C2FC"],highlight:{border:["color","#2B7CE9"],background:["color","#D2E5FF"]},hover:{border:["color","#2B7CE9"],background:["color","#D2E5FF"]}},opacity:[0,0,1,.1],fixed:{x:!1,y:!1},font:{color:["color","#343434"],size:[14,0,100,1],face:["arial","verdana","tahoma"],background:["color","none"],strokeWidth:[0,0,50,1],strokeColor:["color","#ffffff"]},hidden:!1,labelHighlightBold:!0,physics:!0,scaling:{min:[10,0,200,1],max:[30,0,200,1],label:{enabled:!1,min:[14,0,200,1],max:[30,0,200,1],maxVisible:[30,0,200,1],drawThreshold:[5,0,20,1]}},shadow:{enabled:!1,color:"rgba(0,0,0,0.5)",size:[10,0,20,1],x:[5,-30,30,1],y:[5,-30,30,1]},shape:["ellipse","box","circle","database","diamond","dot","square","star","text","triangle","triangleDown","hexagon"],shapeProperties:{borderDashes:!1,borderRadius:[6,0,20,1],interpolation:!0,useImageSize:!1},size:[25,0,200,1]},edges:{arrows:{to:{enabled:!1,scaleFactor:[1,0,3,.05],type:"arrow"},middle:{enabled:!1,scaleFactor:[1,0,3,.05],type:"arrow"},from:{enabled:!1,scaleFactor:[1,0,3,.05],type:"arrow"}},endPointOffset:{from:[0,-10,10,1],to:[0,-10,10,1]},arrowStrikethrough:!0,color:{color:["color","#848484"],highlight:["color","#848484"],hover:["color","#848484"],inherit:["from","to","both",!0,!1],opacity:[1,0,1,.05]},dashes:!1,font:{color:["color","#343434"],size:[14,0,100,1],face:["arial","verdana","tahoma"],background:["color","none"],strokeWidth:[2,0,50,1],strokeColor:["color","#ffffff"],align:["horizontal","top","middle","bottom"]},hidden:!1,hoverWidth:[1.5,0,5,.1],labelHighlightBold:!0,physics:!0,scaling:{min:[1,0,100,1],max:[15,0,100,1],label:{enabled:!0,min:[14,0,200,1],max:[30,0,200,1],maxVisible:[30,0,200,1],drawThreshold:[5,0,20,1]}},selectionWidth:[1.5,0,5,.1],selfReferenceSize:[20,0,200,1],selfReference:{size:[20,0,200,1],angle:[Math.PI/2,-6*Math.PI,6*Math.PI,Math.PI/8],renderBehindTheNode:!0},shadow:{enabled:!1,color:"rgba(0,0,0,0.5)",size:[10,0,20,1],x:[5,-30,30,1],y:[5,-30,30,1]},smooth:{enabled:!0,type:["dynamic","continuous","discrete","diagonalCross","straightCross","horizontal","vertical","curvedCW","curvedCCW","cubicBezier"],forceDirection:["horizontal","vertical","none"],roundness:[.5,0,1,.05]},width:[1,0,30,1]},layout:{hierarchical:{enabled:!1,levelSeparation:[150,20,500,5],nodeSpacing:[100,20,500,5],treeSpacing:[200,20,500,5],blockShifting:!0,edgeMinimization:!0,parentCentralization:!0,direction:["UD","DU","LR","RL"],sortMethod:["hubsize","directed"],shakeTowards:["leaves","roots"]}},interaction:{dragNodes:!0,dragView:!0,hideEdgesOnDrag:!1,hideEdgesOnZoom:!1,hideNodesOnDrag:!1,hover:!1,keyboard:{enabled:!1,speed:{x:[10,0,40,1],y:[10,0,40,1],zoom:[.02,0,.1,.005]},bindToWindow:!0,autoFocus:!0},multiselect:!1,navigationButtons:!1,selectable:!0,selectConnectedEdges:!0,hoverConnectedEdges:!0,tooltipDelay:[300,0,1e3,25],zoomView:!0,zoomSpeed:[1,.1,2,.1]},manipulation:{enabled:!1,initiallyActive:!1},physics:{enabled:!0,barnesHut:{theta:[.5,.1,1,.05],gravitationalConstant:[-2e3,-3e4,0,50],centralGravity:[.3,0,10,.05],springLength:[95,0,500,5],springConstant:[.04,0,1.2,.005],damping:[.09,0,1,.01],avoidOverlap:[0,0,1,.01]},forceAtlas2Based:{theta:[.5,.1,1,.05],gravitationalConstant:[-50,-500,0,1],centralGravity:[.01,0,1,.005],springLength:[95,0,500,5],springConstant:[.08,0,1.2,.005],damping:[.4,0,1,.01],avoidOverlap:[0,0,1,.01]},repulsion:{centralGravity:[.2,0,10,.05],springLength:[200,0,500,5],springConstant:[.05,0,1.2,.005],nodeDistance:[100,0,500,5],damping:[.09,0,1,.01]},hierarchicalRepulsion:{centralGravity:[.2,0,10,.05],springLength:[100,0,500,5],springConstant:[.01,0,1.2,.005],nodeDistance:[120,0,500,5],damping:[.09,0,1,.01],avoidOverlap:[0,0,1,.01]},maxVelocity:[50,0,150,1],minVelocity:[.1,.01,.5,.01],solver:["barnesHut","forceAtlas2Based","repulsion","hierarchicalRepulsion"],timestep:[.5,.01,1,.01],wind:{x:[0,-10,10,.1],y:[0,-10,10,.1]}}},f3=function(t,e,i){var o;return!(!ZV(t).call(t,"physics")||!ZV(o=u3.physics.solver).call(o,e)||i.physics.solver===e||"wind"===e)},p3=function(){function t(){fN(this,t)}return mQ(t,[{key:"getDistances",value:function(t,e,i){for(var o={},n=t.edges,r=0;r2&&void 0!==arguments[2]&&arguments[2],o=this.distanceSolver.getDistances(this.body,t,e);this._createL_matrix(o),this._createK_matrix(o),this._createE_matrix();for(var n=0,r=Math.max(1e3,Math.min(10*this.body.nodeIndices.length,6e3)),s=1e9,a=0,l=0,h=0,c=0,d=0;s>.01&&n1&&d<5;){d+=1,this._moveNode(a,l,h);var f=sH(this._getEnergy(a),3);c=f[0],l=f[1],h=f[2]}}}},{key:"_getHighestEnergyNode",value:function(t){for(var e=this.body.nodeIndices,i=this.body.nodes,o=0,n=e[0],r=0,s=0,a=0;a{var e;let i=t;for(;i;){if(["hui-card-preview","hui-dialog-edit-card"].includes(i.localName))return!0;const t=i.getRootNode();i=null!==(e=i.parentElement)&&void 0!==e?e:t instanceof ShadowRoot?t.host:null}return!1};var m3={Controller:"data:image/png;base64,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",RoomStat:"data:image/png;base64,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",SmartPlug:"data:image/png;base64,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",TemperatureHumiditySensor:"data:image/png;base64,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",iTRV:"data:image/png;base64,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",UnderFloorHeating:"data:image/png;base64,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",HeatingActuator:"data:image/png;base64,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",DimmableLight:"data:image/png;base64,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",OnOffLight:"data:image/png;base64,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",LoadControl:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAACgCAYAAACLz2ctAAA+VklEQVR42u29d3xcZ5U3/j23TR+VUbWqZbn3bsdOcRwnIYQ4EBLYdQhOlt628IP3BZbOsgUWfmxYeiAEWEhCAoSQhDTHSey4JO6WbNnqlq020ow09ZbnvH/cmfGouBGCzfp+9bkfzZ1b57nnnn7OAzhw4MCBAwcOHDhw4MCBAwcOHDhw4MCBAwcOHDhw4MCBAwcOHDhw4MCBAwcOHDhw4MCBAwcOHDhw4MCBAwcOHDhw4MCBAwcOHDhw4MCBAwcOHDhwcKmALrUb2rhxY+6e1q27bsy2LVuezX3W/rHwot/r/Wu+e9HvYfO2DwIA9G9Gxnw/fuyy4/e73/2OHbKfBBs23CBt2HCD5IzEGz/O+S+5wwEzg/LMM38UANA4Y3otACxesohvf9sdY/Z7+NGHsHfPPlq8ZBErHwpe9Pv++ZofXvR7uHPbewEAu9/z4phn+dWvfJVvu+223PojjzyCT//zp+l4y7Gu8WN+2RLgxo0bKSsSPv/5L9Q//vgTHzp65Mj7stsDwcAEcTE6MkrlV1b7Z3983uil8PJcXXYlApr/L37dUT2Grf0v5dY7v3RMat/Tyvlj53K5rex6Op2SAWDu3HmfXbNm9eNf/OIXOi5rDpglvs2b75FOnOj5kJFO39vf34+Tfb25fQxdH3OMqmnQoylR9Dd10tz3LgclYxd9ABNG/KJd28duBgBRUEBt//6qdfKPHaQVuKXJxi47fvV1dRBBjJS7yj7z7LN//PbFHj/lYl04y/n27dv/07SevjMWiyGdSLIeTZ1RSdaTqdNvTjIGJEwhyafVRiYmYmIm/rO8WMR0ToXdD89FfYDCEqBkLPd79WhKnG38BgcHwQMcNAuNe5cuXVH72mu7PpkviS4LDpjVP6677oaP9JzsuVdPpTiVTrN7foCTxSyf6/jAgmL4lpRB043LyoCwzkBarCoY3T+A0QND5zzHguEG7Nn9KqsujYP+gFRVU/PRZ5/947cvlk5IF0v0vve979Oeeea5k8lkIgQAmsuF4OdngOe5z3mOVCoFxZAvSSKhPwMfsfjCTqIwQT+t7sHtdk86Zm63G3QoBf1fO9E/OABD11FSUnKkq6tj9mUjgouKQgSAN23a9JGFCxaFZFlGVVUVnirfg99HtsA3fG7C0iTlvF8dBoOyO/+lhAzz63woF3C/BCTNFMqiPhQpGgBgOKqji8NwK264JBcstkAAzISO0Yok/umRj0QajlUXHmvrQDqVnlVXW33P5s13/njz5nuk++//sbgsjBBmfhXAUmZmIqLPNd2LBzp+A492bp1KEEPiv9Ct8yVAqDzuSWUOM8kCW4wVgQUoUgsQEwlbL5W8AIA9g7twiuLwyG4IZkgSYTgVwX/M/z+4a+pG6AZjJBrnrq7WbUuXLrpy3/4j8qKFs6zLwghh5qQQAqZlkUvTGAAJ+fyI7UKIj/MoaAInpLyHO+47EyIzQLaRY0LkPucTUNQ8bYlrUOBRPaeJi2jsf8D+nE98+dt4HFvI3htNQogEGKaBN4fWYdiI4umR7ZAkgqlakNISpmilWFtxNV4Y2IZhEYdM8piXSVhANDLKsViMiNTRy84KBgBJkqAQ8dk48fkQ26REdi7xm0d0JmeIi+zPAKCQlDvOZBOKpMAUZmabYn/HMt5Tfzs2lF2JaGIUD/c8gW2R16Aq6hjiM9mEQgrAjLhIwkUqFMgAEeIiCQ+77N+ategFwxAmChQ/BkQELlLBFqNA8SNqxqBKCpJmClcEl6BLP4nXRg9DmCb8L1pInRpF0foatFedQEyP4drSNXhs4LmJ4yoDsqpaEgnlsnTDEBH4depK+QSW/T+eGHPrBGS9M0xsfybAFCZuDW3ArtgBnEz3oUD2467K2xC3EtAtA89HX8FtpTcibiXgk714ZOApnEz3QRISvjbnU5g6Wo7ffOcRlJSG8J+3f4b/q/8n9EDHb2xOmCGwdcGVWFO0FCmh47XoQRiWgWtKViFsRDCkR/D80Ha8u+rtiFu2CH184DlcUbAUxZod737g1KO4tng1qr2VAIBf9z6BgC6jSC3A7uhBCNOE+2tDCO/rhaxpGH5hFIGP1WFgUQQ9yV7M8NXj4OhReOSJxolg6fL0A75e4ssnunxCG+8CpEmYa/4+aTYw3VePI4lWtLMBn+JDkRLEd0/+AgBQpoZQpARx74mf4orAEryn8g584shX8a6qt2F6sgpvvWMjmpsOAwBajrfRZ774OTzXux2DegSSLMG0TDR4arE/2owdI3vxD3X3oC3RjWPxDvys51F8bdankTCTOcJKII1iOYirS1fi80e/iXn+mWj01OGaktX4947vYq53BtyyC36FMGxEIdyA/2kLkaYhFJWW2BZvMgnzhWHLtaRWHjQHUOmacsm6li7Z4D/n/U1Y5zxOx6eJ6k/1P6eEjnSG+5iWgSJ3Ae4qfytuLloHAEgK2wG+a3S/PWiKgvnF0/HK9pfR3dkV9ZBHAMD2l7dCH01yo6ceaZHOKRYxK45VRYvx9oqbsGN4L2JWHAsCs/C1WZ9GW6Ib++JNqHSV4e0VN+GdpTdjyIjiyVMv4B/q7kGDpxYt8Q483v8c/r7mbjR4ajFkRMGeseE/WZJybzRJEsyYJYMF4kJ/Iwz1//0ESHl/Y9YzRDaG2Pj1WbhuSUOaGKZlQpFVnEz04cenHsaDg08AADySG3EziUZPnS22TBORZBz19fVjTjdv/kL4/UEaMiNjzu+XfWhLdOOR/ifxm/Az8Ms+7Bjeiyf7X0CRVmC7TowI7jvxEH5y8mHUuEoREwl84shXUaQV4G8rboFhGbn1awtXYzg1giK1AEbSgHtOIVxeD6WSSaTTaaRTaSgrCyDcQLFaCMO6dB32yqV0M6ZlAvJp3W6CccGTGxGvF2EjYut5xQlsj7wGALin8nYAwPbIa0iKFD5acxdCaiEe6vsDNJcbD/b+Hu+Y+y187T//q+DRX/8SM2fPxac/9WneOryDDo4ehUdx59hMf3oQw0YUJ9MD0KCgPz2ImEjg+aHtmF8wC42eeqSEjr+rvgO6ZWBbZAdm+adhln8a4lYCTw+9iJtL12N+wSzErQT2xZswIKLwKh6USoWI1aUQ/PwMpB4+YZkxS/asnAL5TSGkYynMKp+G7dHXbCPISUjNU36FeAnAWsHMsiTR55ruxY86HkaBFpicsOgN8MnlySGfbLtP4hlx65PcE9bjVhKGZUJVVBimgdn+afjk7PdjjnsGAOD5vu34t7bvYITjtpXLZxjlfHcIM6SMa8an2PcwaiRgsYVyVwhDRhRGxvqebP2KgqV4fPB5xJGC6lFz57VitosmJhLYOrwTLskFiQjDadsP+K76jRiOJs3o8LASiUSeXLJk7k2XlR/wvOiD+DTne6OIL/Pwo1YsMyDyGdcVyFBl252iygqaY624e/cnUe4KIWWlETYicEkuKJI81r94lnuXiCAy9zJqJHLfq5KCvnQYMslQJQWCObcuk31PPak+7JcO4uaSa9GT7EWn3pN5WTQsLJ+PnmQvto/sgUtyOSL4vG5GVs5orb4RRJfvMM765bL7ZAnv9EBN9JKrmfvtS4dtXVFxj+Vw53hpstxPIpp0W5bwsgSaJbwsXJILLYludKcHsNg3B40eWyc1LAPPD23PvRCXMi5JHfANdD5O/vl1mobquBdnQuSCz8z9zodAxVnuKxtm2z6yZ+yDJSW3zSHAszijsw99Q9mV+FHHw3a0gSSA/7KZQZI4t0NASOKCNezzOS8mZMNYkEmGxRYsPte+p7mhxVaOU1ps5XTFLEZFCn7Vj+vKV/2lh/fS5oDMjCtLFuHfZn8c93U9grh5EbKM/0yclwW/Ied93S+YxWjwVOJjDe/BFG85kil2CDBfDDEz7pq6Ee+oehPC5jAc/PlRqoagqgosy7pkXMAXnQAFM2RJAjPDEoI1VaMpWvlkyUh8DrfRGfJaLr3a5wtMwDqf343JE7YmHsfMIJL/gsmRfyUimIiYmIjozHkrlmUBRCwRkWBmYQmSZInBTEIwKYpsnyF3Wv6rI8KsXxQAJxIJ8nq9ZAmR/S5/vCYQKjNT3vG57ZZlQZbl3HGXkl2iXDr1DgKyJKG5uYWKiwsxNBSBJCkoLPSjo72TKioqUVdfnXNwyEQkSzkxwrIM9PX1066du6FqKl911Vryer35D+vSZnlZV4skwTBMfPRj/0RrVq/Eu+7aBIkIiUQCba3tUDUPZs5sQE9PHwYG+ikUKkIwGIDb4yGXprFMROHwEPwBPyzTJADwer0Ih4dQVFQ8Jv3QIcCx1V0kSxK/uns3WZaFAwcOCEVzSwsXzENHZzduvGEDJBl0+HATX3XVWopGk7xnzy5at+5q6uw8gba2VixYMB9ujxu9p3rJMAz8lYpg+sH3f4gjhw9i6eKFtj+eiJ57dgtSqRRUVcXhQwfQ39+P+qn1HAoV0eOPP4mVK1egsbEBAPCtb/03rrzyCixZshi/f+xxrFy1Cnv27MGmTe+EJQQDEjkEmHM2S0QSIMkSA6DVV6zGN775LZSXhiRLEF7bsw9rr1iFbS+/jOHhIQwORam0tAwPPvRrMk0Trcdb0dF1AuUVFVi37mps2LAe+SKJzpHweklRHhEMw8SHP/JBlmWZdLu2N6dGhMNhyLKMefPmorOzE6lkijRNg6bmQnDU3NyCmuopaD3eig0b1iMUCuH7P/gR/u1fv5zRZyRiJx1roviRMgmqjY0NfGDfXkyZUoWiwiDaWo6gpqYWvX0DWLlqFRMRXty6FdHhISxdsghlZWVQFAUfeN/d8Hq9sCwLzJyn75xfOCUrArPHTvb5L5igS4MDYeh5xeWGYaCmtga6rkNz2RGXxsZpKCgowMjoCIaHIgDAzz/3HCRZQl9fL3bv2oMlS5dh7uyZcLtdbBimLYL/Ar/nr0oEZwlFMLNMRO9///uxYuVqGHoSdXV1qK2rxpo1qwAAU+tqsGHDdVi+fBm27diNGzash8/ng2laEyzDPOI5Wx4NZcQc8oyWMZwn//A3SqfMnjdrP6xcvQIuLRdGo7r6etTX1+Kqq67Ejh07MWPmDBw6dBhp3cCc2bNx+PAhhIcGMWPmDGzYsJ7D4SFqOdoCv9+NefPmZkogbANkPO3ZbpnLMBuGiNYKy65PyJeZ53IlnKl8J584spa1JQSkzJdEBEsIlvIoiJkgSch9n92UZ3mOoV8iojeCCLPXsE/PyN5I5nvOux6NPSx3L5RPULIs54e6WYi87QIwDIFUOn3Rs2GkS8gKZiKinp4+/OqXD+GZZ54jIUCZp5+/wBJiDPH19fXTo4/8FkTEv/3NY+jsOAEiYiFAsiQREXHmwXL+OhGx7YI8/f2hg4eRSqUhSxL19fWjra2L8pF5Sd6YsGTmRcpeJ/vbM8RIWQ5tGxIZFZrtbWldh2HYoTdZljn7mQicGa8zEL7piOB89PaegizL6OrqwkMPPgSfz0dlZWVQVBUi05uit/cUlZWVoaurC7Nnz6Ki4hK88OLLWLlqNW3fsQvFxcXo7++nnp4TqKqqRkdHO1VWVqC/fwA1NbVoOdZChq6jqroKhQVF6Ohox7z583H0yBHq6elBPJ5AdU0tDh7YD03T0Nx8GB63B9euvybLafM59Z+LAzJlXCj//h/fwH/8+1foxa0vo6mpCR/44Ps4Go1SQUEBP/XU07jxxuuRSCTgcrtZliSkUmk6caIHpaUheL0+GIZOXq8Xo6MxyLJEXq/XfsGR70vMSqKLK4KVSycz1hZ3sixTf38/Vq1eje6uLkydWo/nn9+SEymapuXEzMjoCObNn8vd3SeosaEeL7ywBfPnzsbRo0fhdrtx+x1vxzNPP4vKygpER0Ywe84cPPb4E1iyaD4sy+LRkVHq6urCunXrcf/9P8Vdd22CLMtob28HAISHhpBKJWHoBioqKmAYJqmq8mdX4JkzESEimKaJvt6TaGvrQmdnJ5LJJJ555jlqPd6KmtoaOnioGaHiEhw4uB/BQJACwQB3tHdgxowZONF9AocPH4bP58OixYtxpLkZ4XAYq1avxtKli8gwgbxeThCmJUsScmN7WRMgw/ZPeTw+XLt+PWbPnoGBgX4+fryVrr12HdrbOyDJEmbOnInmpmZMqapCZWVlpgZHxew5s2FZFvt9PkqmUvC43Xjm6WcRCAQwfcZ0dHWewKGDB7Fm1XKESkphmQaZlkBv7ynet3cPveXmN+PQwUMAgLKyMhw4cAD1U+tRWFCE3t5TqKioRIb4xuib44iRJ7O8s/uNZ5rZmvX8FzCV1GnF8uV47tlnEAgEoGkadr+6D0sWzUckEsGKZUtw+PChXA/A1uOtdN2GGzAU7kdTczOWLFkMAHj00d/i7+65GydPnkBv7ykAiwA27Ueen5EtLnMjJF/ZFwIkSWOt0FQqTW63a4zRkUgkIEky3G4XW5ZFIOJMVCSrM4KIkDk2Z1CkUmn7mEzUJStJ07oOl6blxJpEhGQySV6vlzPXI1XVoKoKCwFinBZn9otz7oSLPP2RxjdLyL6CRITu7hNoPd6G7u5u1NXVIa2nc9x6wcLF2LvnVRQWFXJkOEJ1dbWIxeOYNWsmwuFh9PScQEPDNCQSCQwM9HMqmaIjLcexYtkSXLv+GhiGCZIUsAB0QyCZSHAkMkSRSPTJ5csXXJ4p+cT2g8wSX1tbF6XTKTQ2NmDnjp20cNFCuN2uMZaf1+vNEaMsy2Piofm62cDAAGpqqlmWJOrp6UNRUQAASJYkCAFIEnE0GqVUKo3y8jLOC91R5hoAQF6vl6PRKAWDQZIkykYSOEteF6LjZYluvBTPcsmammqurq7KOtAzLxVoaGgIoVAx10+tJkVRkIgnIMsSvF4vmxZQVVVN8xfMZWYJSiYsueX5FxAqKsC0aY2ZS8pE44r3L3s/IJMtepktADIdPnQQx48fx1tueQt+/j8PoqKyEk2HmxGPx1EcCmEoHCaPx410Wkd5RQU1NzVBkiRMnzELsdEoJZNJTJ8xEy+8sAWpVBLXX7+BAODwoSZUVFZiYKAfU6dORWNjAw4dPExbt76I2bNno6O9kxRVxdKli7Bv30Eca2nBvPnzye/3Qlig4cgwkok4JEmmUEkIXZ1dNHfeHBw+1ISyslJEIhEMD0ewYuVyvLJ9B+bNn4dodASjIyO4+porOcsBgYnmi+2bs9+jrPjOuk2yHDYUKiYhQJqqgRkUCPjBzGxZIIkAwWCJ7JfBsoCyslJef92N0DSmgoICNkyQJJFTmH4ulJWVQdM0HNh/APPnzsaW57dgODLMy1csw8EDBwAA0ZERdrk0PPP005AkCbIsY8eObRgMD0JRZPzs57/AypUrIEsy2ts60Hq8DYlEArt37UJXVxfa29uRSqXR3HwE165fj1d27sbx1la0tbYCQJb4sPWFF9B6vA2dnR040tyMEyd60NLSgvb2drS2tuLokRaEw2Fs3foi2ts7oKoq/ucXv8TSZUswPBTBi1u3ore3F/39A5RfCZB1Bk/mFM76JscZZ7BEpjqEbaI0LbAQRGznwDIBlFUGGGDTIiotDaKgoIB1gyn/umACXyIp0ZeMCM6OvcvtprKyshwxut1uWJZFe/fsQ2lpKebOm4NXX32NBgfDmDFzBpeWlpFLU+Hz+RCJRBDFCBYtmIcD+w8gGAwiGo2ip6cH0xqnwevzciqZourqGrjdLnh9Xhw6eBAzGhvg9XlREirJWdiHDh7EtMZp6O3tRTwRR21tLVyaC52dnbA5UghtbW1wu90IBoOoq6tDcXERUqkUDh9uYr/PR1OnTkVhYSECAT/yxOkZ1fGM9nomD8GY9VzvI4AmqYMiIsAwQafF+2SELhwCzIpgKWNEzF8wl+cvmGsHzdn26BuGiaGhIZSUhCDLMtauvQKpVBolpSUwMm16Z8+dzYl4gnRdRyhUjJ6ePpSVhZBIxGGaFvwBPxRZpt7ewawuyOvWXU3h8BBqaqq5r6+f3G479FVRUYGSkhDmzZ/L4fAQAUBRUTHi8RjmzpuDYDCI/v4wpkwpQ3//AAIBP2RFyXRHsN1CFRUVSKVSSCQS8Hq9mdxEOqMb5kK8iuO7ub2ec13When5obismyIajUKSZMiyhNHRGE6d6oPH48PMmQ1IJBIYHY2hvLxs0nMahglVVRgAjbeUx/u6sqG6PJdKNn6cTeo8RwfBs47fmFizEEDG/JiUCM/LrcgTCY4v9Dx8OhRnmiaSiQRHo5HL2wo+bYQQiMAtR1tJ1VT4/T68/NLLKCwsxMDAAPx+H4JBH17c+hJuv+M2dHacQH9/P2rrqnHqVB8UWcL+AwexcuUKSqdNhAf7UVxchGQyTR0d7Vi8ZDGGhyKorqnj1uNHaOWqlVBVhTIx4JzyT0QsZ+K9Z8snzNq0+Z0Nsvtms8CYCQz7/Ke3nR+HG++mOVMi6fkS74R+iY4VPFYHzDqiAcDlcsHj8UHVNISHwphSNQXDQ4Po6mxHYZHdM28wPIiXX34Jla2ViCfimFo/FcFAAOHBMF599VUEg0Fs2fI8Nt76VuiGgfb2dnjcbvzqlz+n5cuXQVUVZmayiYPyG8/k+xLziYbympvm0hsmq+3N0hvRaf3tXIQynuiy6+IMbpvz5XaXOi4ZDphdD5WUYNfOHfD5fCgsLIAsF/ONN15PfX39SOsGOg4dRnNzCzo7OuDxeODz+eB2u9Hf3w9ZlnG8tRVujxuWZWHOnLmIDA9DU1WkMnOMFBUVYfac2bZoZM5kxkyMaghmSDm/YoYdclaE8qTV5xkuPmb72QhlTCRkHIfjccf+WaJ/TOBMfi4LJx8Q4/rbkSUENzTUQgiTDMPE7NkzOJFIEDOjvLwM5eVl7NJUSqfTWL5iGdJpHUVFhejvH0R19RREIhEIy86WKSjw5yIGtj6oIpmMY82a1eN5BBMRhMjWydsCVM6mZVkWiGSyuZE4rYmxIBAxQSLLMqEoMksSYFoAQRBBniC8mS2YmbCXRBIkSRnD6SxLhyxrnC+uxzdzyHFIATB0SJIdGzfNTEsRmSbtLoasa4fpkklGvbREcKY8M5FIUENDAyQJiEaj5PZ4kJdWT/Pmz51wjlCoGAAQCPjHh+woFCrmUKg4U1lWntuWb5hkLNXsJhodjaGr6ySmTq3OfG+HgLMhw3HJqqyqClmWRYZhwrakZbYsjCkGYLajNplrkt2KJFu1xlAVsCJrZJhj48yc51fJZWExwc7J0KDrgCUYHrd9oWSKIUuZ0kLKEFzm+uP90EI4bpicCBZCQJZl2rJlK072nMQtG9+Cf/+3/xD/5/9+UjJNpkgkioqKEgwORuB2aTBMHeXlZejssP1ydfV16OzopP7+AVy7/hq8uPVlDA4O4sY3XU+SJGPHKzupuqYa6bSJ2topCAT8iEaj2PL8VlRVVaO2rhqmyaiqKsdzzz6PVCqFpsMHsXjJYgQCftq1czcWLV4IwxBUWlqMvr5+AoCa2mpqbjqKosIiSDKQTusIBPxUXl5mE6HdczwXHvved7+HtvYOXLd+Pf5m0yYCwJpK1NfXTw/+6iF84IMfgaYRdIOhyJlkWQv2ukJQ7SfGTz35NA0MDOBdd21igOipJ59GIpHA22671U4wEIBpAooCQACyAjZN0KUWDFEulVqQLAL+AJLJJJqbjiBUWi69sn0HZFnG1Kn1eObpZyHLMtxuNyRZwssvvQzDMCBlLOBgIABVU/lnD/yCqqqqMBwZxsEDdv/moaEhDA0NweV24eTJblx33bW85fmtpGoqDhzcjyNHmmFZFjbffRcLIUiWZYTDYTQ32d+Pjo5ixys7EYlE4PX5kIjHEQgEsHfPXlRWViA2OgIhGNFoFF1dXfjwRz5ImU7CZFk6FFnDxz/+CRw/1oKvfvVf0dLSAiEYzAYND6X41Kk++p//+QVue/vtCIUKoaoupNICoyMj7PP7ye9TkEql0dnRh8bGWkqlUii2OT/F4iZ++9jjkCTC2267FR0dXSgOlaGwwI3RUQOqpiIWjZPf74NgOCI436TMZqbkIiEuF2maho6ODlSUl2BgYABTqqYgECiALMtYumx5LkEUABYsWABFVXGspQWGYcDn89HIyAjmzJ0LWZJx6tQphIfCCAaC0A0DZWWliI6MwDQtEkKguKgILUdbUFdXh0DQTlawLAvTZ8zAisIiNDc3QZIl+Hw+DEeGUVFRAQComjIFPp8fu3btxLz58zHQ34/uEydyemNa1yHL2hgtbMXy5fTMH//Iv3ro1/jiF76I9rZ2+tAH34/KKVPouvXroSgqPvvP/4zI8DDufNed+N73vofGGTMpPNCPL335X/CN//w6SFYwf+5syLIMy7LwX9/6NrZt24a+3l5cd931+NkDv8CWLS/AFwjiHbe/DT/80X3QdQOBYAF/7zvfprTBjiMaAAYHwy9pmrbW7/flNCUi4nB4iBKJRG4yFbdHw9BQBJHhIdTWTUVFRQlaWloRG42hYVo9TDMzd4ei4NTJU0jrBmbMaLQLd6bPxOhoFENDw5g5awYURcHBA4cwe84slJeXoa2tC62tx7BkyWJ0d/fA7/ehsbEhF8lQVQWvbN+B4lAZ/H4fksk4otERlIRK4PZoUBQFiUQCx1qOY9q0RiiqihPdXfD5vJg5ey6yaYD5Ol3T4UP4ype+jONtx1FfU4uGxkbxjW9+nY4ebaN337UJj2Ty+ObMW4A9u3fiwYd/w+++62+prq4e+/fvxd/93Xuwd/8ByLKC+OgImpoO4ZlnX8RPfvx9HD7chP379+LmN9+CvsFBTJ82FQ899BDuvPNOvPNv74KmaZAkCUIIWKaFRCLOkcgQjY7GLz9HdGdnN2bNmj6hMi5rNOT7ODKRj9yrO3v2jEm78GWMEQKADRvWZ/avHrPfNeuuAgA2LaChoRYNDbUAQJlj2bIsqqmphhC2kbD6ilXjrzUmQhIKFaOmpjr3O6qqypE1MGy3DcBsQFM1/MtXv450KoXaulrR29crLVu+ElteeF56+KFHYFkWFEVFVVU5Nm3aBN3QsWLZErjcbhJCYMGC+Th8+BAkWcJbb70Fv/ntY/AFgqirq8d/f+devLpzByqrazBnzjx0n+jGDTdcnzWgsO7a61BY4EYiKYDLPRQXNxLkU708OBh+KRQqziWk5nMJkXUE5yd9MhORDCK2rbdM6Gz8PgyZiUQupYQhMwuTJEkBA8zCJJIUlgjEbEEIBklKzs8nS7YCn1XWhTBz24VgIlhgyGP8hswGiNTTn6GBJOQ4IBhQVXBnxwl69NFHkEjpeMcdt6GxsYEffugROtbagavWroWuJ9HV1YUHH34IPrcXM2bNxqc/81n8/IEf4+prrkF4cADbduzG6hXL4HK5IEkyqmvq+Fe//DmVlJRg/oIFqK6eyr/73cMkSzJWX7EWLUebsWbtNQgEfDAzzQSFYBiGjnQqddE54EXDa6/te4mZ2bQska0AE4JZCHGOxd7Hsvh1L6ZpL5N9Z5rMxhkW3biARWc2TBa6bv/EvIVTaR6D3t5hMXvmHH766Wf5uWe38N2b38PHjrXyD77/I9679wAfOnSU+/ujgpnFyIh9whMnepmZeWRE55MnB0UqzTwaM1jXmbu6+gQzi9bWTo4nLE4kBSeSgmNxi4cjSe7tHRZHjrTy7t0HngCAffuPyJeNETIwMADLsiBlWrONmYXvHO2d+XX0jj5bPJX/HBO68ESBzZnk0rQOsjKVfUQEWQYSyawDWcL9D9xP66+/ERs2rMe7330P3n3XXSguLseJU324riCEnhPdGIkO0S//51VUVlZi+owZOHjgAG67/W/w2988hDlz59KxlmYMDg5iwcIlaG8/RocPWXC73ZhSVTum04PNCa3LOyHVPEcxzGRJmxdKEPnnyMYxzriMux6/nglweOLMTxLZhKYoBFkigAmyLMGlSYjF4njlxRewYtkS/NM//n+ir7cXS5atApGEwoAPQ0P98HhdCBYUw+f3IRQKwePxwbIs6LqOqVMbkUyk4XK5sGbtNRwIBFmWbJfV6OjoWZ3Ol2VZZmlpKVRFG/Ok/hTimiy9/UyTY14IdzvrvfAFTBPLZE+jznmND7OTJmbuSzcYxcU+fPhjH8VPf/oApjdOk35y/884GHCTbgCb734fLMtin99HikyY2tCIdCqNggIPSkvLIUsyli5fgWQiAY/Xa+uqBKxec7Wd4haJZAwivmQSUS8aAWaNELtXiR1GsivU/vSm9+OD+OegmZxrJGswXIhk5fPKbLEnh87VFZ1BZcieT5YIqbRtuWe6e5EQoFRaQJIk+P0egECWBZgW575LpQXynct+vw+mJXL9ZbIit6iokExL4FJsmH/ROGAoVHRenO288ucu7FjKEogia2fL+eOzMNBzJKQShAB0w7bRzzRbw3hunUgKslUAkfNtMjNMayKBG5nkA9MSeSrNxE5ezIBhXnrul4tGgFnuFw4Po6KyApqqIlstNl7Xu2D9n8+dlp519wgLePiRR6AbRn6n1fN1UZ3VCoon4rj22htQXz8FqbRN7OfDObMGmSwp0DRwIinGlNCNL24/25zL5+TSl3s6VihUhFQymWuueDZLdHJLeFKRnBOvZ6MRRQYGh0e4tb2TNv3tHUgkdGQz9i0Luc/ptAkWBkhSJ5zD5XLDssxx2SUmCgtD/Men/kBNTfsxdeoU2894HkUaWUJSVUJfbx9279pJt771FsQTwk5sHUeIZ+pZ+NdWE3LRCLCurjY/Fkz5HO98sofzCY4IbBhMskQEYghBmNDuZNw5TdNAfW11Nooxoe6ju7ufXS5AkphMw4AkayxJtjKXTqdRWlqJQEDF2PZwABFo/oIFiMdieT35JmvLked4F6eNA8sCSsvK0NPTg5898Au8665NHIub41p9SJMaX+dSW5gFiCSnLjhfQZbGvNkXLHLJ7n3H5HETNA2syAS3KyPVeRKXCBNMC6isDOGGG98CXQeSKaZU2v5vWkBPTx+EpVPllDJUVZWju7sTiiKjsqIcpaXlqKisRldXOxJJgWSKoeugoaE4EkkBwwAWLFiEtVeuxeioAdMwoak0abdVIWyDweeV4PNK8PsU+H0KKxLhwx/5IA8PD+PRR35Lme9ziyxLk7qmzkZ4Wb2SWYwRv0KYl/dUXZYQkM+XCCfxrbEg0jTihx96hObMnU/BYCHveOUluv2O2zitn2YUWbEty8BoLIWnnniMbrzpFkjy6RIPYZfskCQprLkU24EsA/v3H4DH66PKyhCEaetqHo8bmRxGaBrw5JO/x6xZszA0FEbL0Ra4Pe5cyehdm98zQV9jZiiy7f/bsmtbbsMfnvgjvfMdf4MrrlhGH/v7j+Bzn/syHn/8D7jjHbfn9lm6dBUCwWDOqX0movtrgHTpZESfKRRx9ilPhUgDAO677z58/rP/jM6OY/SLn/0s48pg2weH045oSQKSiTj/8Ic/xOjICCvyxGJxIUwSwswWkHFf/yAAYGBghBPxOGTJ7iqV38E0PDiI7373e5AlGY8/8Qc8/cen4fP58MqOHXjst7+Gx01jnMFCCGga+FhLE7Zv30l+XwGd1lEZlgBbFrBp0ya47d7X5PV46dVdr9HRI83kdoHF63AgMwsIYZKTki/ZVRjn4+jNOndzpYVM4IwfL5uu9MKWF1FRXXt6ohqWJuhKkiSjqLAoL2uFKdvBlvPcMkS2JfqlL32W9+07SI/8+ld05133TMalqaysDMWhEgQCQaxZtQaKy4WqqiosWrgQbrd7TFu3/OMMQ2DJ4oVYe+VKAKAbb7wepgVOpwXZmd4N+M5/f4vzO4OZZnqCJf6ncDwhLv4MAsqlNDfVmYiPx3ndmMdbj7Yo37z5btx//08wZ868MQ9I5FuGDAC63e2guJgUGbCnFAHGW88sQF6PxN/77g9oKDKKT37y42Ax1q8mSRKSKcbNt7wNN950C4Rl4eOfXGx36xeMBQuXsaIqlEzxmPLMjB7GACiVSgEAR6IpkiUZJBFljQXTNDGqM1nCQmGBOzt7Up7hIy54MkVLWI4InjRmOy4sNz4ODKYxUQWRt32wrxfz5i3EqiuuxIkT3Tkxl19XK4SA/bg07u3rxVf/5ct49JHf2pVkGSOBGSQEsSQpnM0bOHmqDxvWr4MiA6mUcboRuuDccbYuqKG42IdDB/ai+fABBAIqCgr95PO5oSoSXJoCTZWgqRJUTc1IADnX81qWZEiyPMFSJYkg253cKZtQmqucE3xWn152+5n2u9h1SZdWj2gm8HmGxKyMf02WJQgB+tRnPoOGaTP5U//30+hoP0ZCTGw9S0SwLMDn99NXvvIV9Pb2ori4eEKZgKLISKXSlGn3ghtueBOqa+pYCJDLrcAwGIaRgpLXrlcIhq2TSZxOGzQ42IfavgYeHR0hWVZyzcDtvoT2/0AgiEQiimAgcL4GBAshcrzcEhYpijIpYV0qjuZLujcMQGuzHizTmjhH9XgFJVvCLhjQVPtIy7LX3S4gO6+LpgGp9OStIwXbfZLVPN9yKp3fzRTQDRO9p07idLaICdM04fX6wWwimUyhuDjEJSWhMQaMYCCZSAIAYrFRBgC32z2mBDKPg0HOzLSuqAr5fG5MZlNk/YWmad9Dz4kuKIqC6pr6TLyZIEtAWjfPm+gsYUFYFuLxOI+MRCgWSzy5atXiy7E3TJ7rmU+3BD1bcoFpCXg9El57bR++/IUv2A9VVjA0FEZ5pmCor7cXxcUhCGtyH1dK1yGEQOWUKehsb0dhQcHEgVE1xOIxCCGQSCRQP3UqTnR1QVYUqKoKv89PpqFDUU8nM6guF+bNt53Q/kCQYqMjaDnSDFmZPM/T0A0Iy0RJeQW6OjsQDATP9LIiUBDEjJmzkU6l4PZ4Mdh/SnR1dknxVALvuP0ObLrzLsQTqayoPg8GwH8lzTveQA5oWcy6brCuG7lM3bMtozGDM5nA4kc/+jEDxKHiUvZ6/bxyxSpuajrKR4608soVq9jr9XNBYTEX+gsmLGUl5eInP/4pJ1PM733fh4XX6590v+zyiU9+hg2Txbf+/3u5rKRcnG3fL3/xqyyEEMeOdfK1667js507VFzK9/73D3k4kuS7N7/nnPt++97vMDPzq6/u5ZUrVnGhv4AB4tveejsnkoKHhhLntYTDMe7tHRZtbT186NBR3rFj7+WXEU2Uad5D9hy/tkik87GZGACVlZahqqpaBAsKJFgC199wE17dvRsAcP0NN2EkOnIG7pfGypWrSZZlPPDAz7B86WJqOnQAvb2nWFM1Gr/v1PqpmDljGn5y331UVFSENWvW0oGD+1lTNRqfUCuExd/+zr00NBzmpqYmOnTwINfV1JJu6CxJ8oRzr165CkUFfvz20YewevUqNDUdQv/AABRZGXNOSZLJtEx89V+/is7uHux6ZRva29q5sqqKPFEfSsor4HETPG7PeblVmAHDAKkul2lZphKLJS4fHXDDhhukZ575o7j//p/fs33btvuyE/FlXQPnk52rqRo6OztwrPU43JoLQlgci8cplbaVObfLBb/PZztcMnPmZveTJJkSyYSIxeMSACiSjGBBEBIRC2ZKp+2sYimjEeimSSMjp4k5GAzCrblgWibiozEmWRrTe1BWFIwODUNzu9nl9ZCVKRtluxSSFU3NjbmpGxxLxHPrhYWFyN+Wf24iEgAQj45ILp8XmstuppmIxVFdU4158+bDsgRk+fwdG5YlICwTs+fOe/sXv/DPj2zefI90//0/Fv+rRe+GDTdIALBw4eIrp0ypzolQO2RxfsuUKdX8iU9+hu+4/Z3n3PfGN72ZP/HJz5zXNaqqaqzPfvZLPHvOvPO6jw9+6GN821tvP699N1x3A3/qU587r/uYOnUaf/azX+KFCxefdT+v188f/NDH+B//4eOWh7zWhYxhdgkVl/L8+YsW5T+by8YIKSgshKkbMC0TpmVBjAtuMo8NY8iKgkTM7gW4ZNECVFXXwu3xwOcPQDs9s2QOiUSCp8+YSaFQKe5812bIsjTpfgCg62n4/QFp5szpuPnmjbhyzZVwebyQJskVFEJA13UsWrQM0YYIggUF8AWCYzJe8o9LxmOorZ+Kyik1uPNdm0FEUFV1QoaMJEnQ9TTcbg+mNzbgppvegmXLVsDj9Y1tUJhNSjUMzJu/CACk6mk1udYj588BrRwnvTz9gJaAEBablkWWaYKFOOsbaJkmzIyoTqQFYqNRXHn1erQcbUYsNjqBuIRlkp5OIZGIgZlZlhUaTxxjU7RMjMbSdrcFSYYkSRP2zY/nxuKj0NOpjPOYzry/JCOdsu8jOyVrVrTm7589t2maGE3oMC0LsiTlzj3+vKahIx6P5ZJgvX4f9HQaEhHGdW6d/PcaJhRFEY4jeozXX5rM+5r7r0gyYvEYfvHAfYjHY3jfB/8er+3eif3798Pr92WC+TLcHg9isRje/vZ3oKi4BLt2bic9E3MzM1kquUHQVMASqGuYinnzF6GrvQ1NTYehuV1IxBMT981gWuN0xGMxvLj1BXh9Xuip9JhKP0WWobldGBkZwYbr34Tqmnrs27MbI5lcwTPdR+WUKViwcDFO9nRj186dUDQVpm5ACItFpiZVImLN7aaGadPh9nhw29vfgZraOnz3v7+FkegINE2Fk5CKc3alBIzJiY/zOE32exYCmqbiVM9J3r9/Hy1cuAhCWCgrr8D69SUIlZYhlUjg5Mke9Pb1QlMUVhSb67ldLrs5UagElVXVKCouhmUJRIYG0dnZgaGhYXg0d0bUyzljpqG+AaVlZZBVFSPRCE50daE/PIig35/jYlmirK6pQXV1DdxeL/R0Gj0nT+DUyZNQZCVnHLhdboxER1AcCqGmtg4FhUUQQnB0OEydnR028WTEaG6CRlXFrOkzUVxSQrKiIh4bQUd7Ow2Fw2AWcLs9WLR4GUzDGGNBn+kFZyEcArwQbpidRI4kCfFEArNmzKA7/mYTjh1thmmYWL/hxowep2ca8MjoaDuGxx77TTbQj1Q6jSWLl+CKtddA0zToug6JJGguFyKRITz95OOIZcTZSGwUZWVleNNbNqK0tAJ6Og3BApqmwTRM7H1tJ17a9hIs63TH0+tvuAkzZs6GsAR0Iw1FVrFKVdDV0YbHHvsNUpmGS5GRKBYuXoI1V14Nt9uDVCoJSZJJ0zSMjETxzNNPIBmL22J1NIaysjLcdPNGlJVXQNd1CGFBU124Yq2JPa/uBJGEeDyG3z/2CObPXwTzDM53kqRL8hn/xR2P06Y1UltbK1dUVNZZhnm3JSxYQtD4t5Ky03xnMkmzCrhhGKgor8BNN9+KqdOmQbBAW+txhMODME0TA/29GAoPoqFxJqqqqqGpKhRVRTBYgCvWXI3eUyfR2dkOEhYi0WGcONGNouIQ5s1bCMGMgoICmIaBtVdfC0VRcfTIYSTiMei6ju7uTrv39LyFCAaD8Pl8YMvCjBkzMWPWXBw90oT+/j4wM/r6TiEcHkRD4wzU1dWDAfj8AXi9HqxZezWGwmG0t7fCEhZiI1H09JyAz+/HggVLICAQLCiEYIFVV6yF1+dDy9EjGBmJgk0D3T3d0NMpzJ6zAJrLhXQ6iYcf/BV2v7oLhDNMv5rJ7MhreQ3LElBUhT0e7w/6+3t7s8/G4YDngGka0DM+v7bW41i9cjlWrFgJry/IqVQKL774PO0/cAiNjTNtZd0ysHDREnS0HYMvEMB73/MeVFZWQQjmI82H6Yknn0BRqATz5y+CbqRt63YkgoH+Ptx6y82YN38Jy7JM4fAAHnv8cRxvacacufORSiURCBRAIgmHDu7DgnlzsP66G9nvD5Cup/mV7S/Siy9vR+P0mSgqLoFhGFiydAW6u+2urpvf/S7U1jZACOb2thb6/eN/gJGxrpOpJGbNmotEMo7jx1qwft3VWLZ8FSuKimg0Qk89/TSOHz+Khga7w1iwIHhG5/ulKHov2bnizmfwFEWFoiro6uzAVWuvwK1vvQ0FRSWQZZkCwSC9453v5IUL5qGj/XjGGFDR39cLt8eLD3/oI2iYNh2qqsHlctGatSuxadMmnDrZA91IQ5Jk6EYaA/19ePddd+GadVfB7XGToiiora3FB97/ARQUFaGv9yQkSYZEEro627B0ySJsvvsuDpWUkKIo8AeCdOtbb8H1112LjvZWSCRBVVWEwwNgy8JHP/wxnjN3HiRZhsvlokVLluDuu/8OsdERxOKjkGUJpmXgRHcXbn/7HbjpzW+G2+0lWZapvLwSd2++B1XVtejv74WqauducyKEk5L/p+BMA5dKJVFcXIyly1bx0FCEk4k4W5bF6VSKR6Jxuuqqa7m8sgqmZVs5qWQCG9avs90no6NsGDoMQ0c4HOP6qY1Ye8UqJJNJKLKCkWgUCxfMw7TGGRgaisPQ7UhNLKObvfnGDTkxl9bTKCgqwrXXbuDRUYPSqTQsYUFPpxGJprBi5RrU1tUjkYxDIgnpVBrXb7geXp+XopFRFpYFw9ARGR7h8ooKrF61AslEHIqsIh6PYc7c+ZgzZy4GByOs62k2DINjsRFOp5K47tprIMuS3VvwHLOeX6o6oHSpEt253lhd1zGjsQEejxemmaZ8P1o6neLCwiJatXwxdF1HWk8jVFqOxumzkUwkOD/hU5KIDEPHmrXXsKa5oBtpyIqMRYuW5LqvkmTPq0EkIZVMYuq02Zg2tQ6GYSCZiGHh/DlcUhIiw9BzXcBJIpiGyV6fD8uXLEQqmURaT6M4FMK8Bfa6LMuUX2qZTqUxb/5i+AMFuRdn9crlkxSwy0gmYygvn8L1dTXQ06k/+UV2CPBPhNvtQUf3ScRjERKC2DQtmGaa9ExSYCQyzHv3N0HTNHjcHkQjw2hrOwpZlskw0jAMgw3D4HQ6xSwYu3Zuo2wUgoXAwQP7wILt/XSdTdNgXU8zkYSO9uNobe+ES3PB4/Xj4OGj1Nvbz0Iwp1MpNnSdDV1nZrvJ+P6DR+D2eHL3cfjQIZvg0inO3odh2Drt0aOHOJmIQVPtBpQ7d++BaRpsmmnKLrquQ5IU7us7SSd7B6C53LnY9Z/qa73sCDCejHVCliCYKRuCy76lWZdLdhmj/2Uc0RJJiEYjOHT4IPz+AGWLxhVFht8fpNde3UH9/b2wLIHhSBgerxcvb98FSZbh8fpIlhXIsoKCwiIKhwew+9U98Hg86Os9CX8giKbmozh5shtFRYWkKCopikper4/cHje2vrQNsqIiOjIMyzIRi41i967tVFTkJ5fbndu/uDhIzU0HqOdkNzRNw+BgPzxeH17YugWWZXEgWECqqpIsK/D7gxSLjfJre/aTx+vHwEAvNM2F4y3NOHqkmYLBYkiZTq2KIkNVXXhl524IYcHQdaTSaT5f6WJZFqxMIxkhxMisudPDAOD1uvl/vRsma+bf8pZbRzva228wTLM60x6VxOmmygDbrXiZ7UoRYQk2DJMUVcGpU6fQ3nYM69ZtwNGWFggrjaKiYkiSyrpu0K6d27D/YBNKSstw3w+/g6ee+AOWLl0OFhY6OrtQWVGRiRQwTnS10u8e/wNCJWXYtWMbvv/978Lr8WD23HnYu3cPigqDKCgoBMCIx6N48snH7eaapoVvffPraG4+jCuvXIeOzk7ER0dQUTGFJUkiyzJ53959tGXrSygrq8DDv/w5Hn34QcycPRv+QADNR47QlIpyaJqLAUZv7wn63e8fJ7fbi+PHjuK/vvUN6Kkklq9ag/3798LrUVFQUAxmQjKZpJdf2kLdJ07A5fbgv771n2J4eFhSFRWWJXILGMx2RRYxkBtHy7JIIoJEhEAwsP/lF1/6xsaNG+l3v/sdXxaO6A0bbpDuv//H4rrrbvjF0Zajq5hZEswwDROyJHGmZQdNljpmGiY0SUaoOAQAKC+vxP4DTTh6rB1ej48SyTj0dAolpWWQSEKoOISh4WEAQElpOcLhATz064dQECwi0zIwEo3C7fHA7fbA5fay3+uDLEvk9fqh6zr+8MRTKCgsgqa6EB2JQAgLxcWlGBzsRzAQRNDvz93HgUNNOHKsjQqChUimkhSPjaI4FIJEEtweD7zBABRZRihUinB4AA8+9CCKiksIACLDQ1A1DcGgnZ3t9/q4oKCAFFlBYXEIL7y4Da/uPUButwfxeAyWaaCouATxeAwlJSXS8PBwLk6ec1cJixRJHl95lJ2BnVxuF0pLS79w/HgLEokUXYwpDi9KTcjGjRuprKxc/eEPf6AvWrT0Z/39fXeaunEmwsufT45jiThNnz4d7/vAR5FKJXO1FZZlwrLsCa5lWYGup3NzaVimAc3lzm3PzzvMX5dlGalkEm6PZ8K+QlhQM+n32W16OgVZUXPXyf4XwsrMeSyPyW80dH3MubP7AoCqamOuk0zEobncp3+7LMMw9JwRkl2XJPs+vvude0UsHpeUc6Tky5LEadMgr9uNKVXVX3vttV2fzOZoXjahuKKiEAHAPffc4wP4Y3v2HEB4KHynnk6ftU7QEoJUTcPAwAB2vvISfP4ALrwUgHMNHLPrYy1MmvDdmb7PnkcIPmsruOx/SSJYlhjTpiMb4Rnf6cp2r5yt9QZn9UHq7elBKpk6J/EhL6m2rLQsR3wXQ/e7aAS4cePGzGSBpgqwNpqI+TdufMtnt217Zefg4ODKoaHwMk3Tztm2tKenx11fP3WKJCtMNs7a9ix/uxB8xr56pil4spNZFk+6b3ZeYT7DCfMbEo1r53HGFmv2ua1ztDQRZAkB3TIxEhs96fP7Rs5j3Pr9/sBxj8f98/vu+97Wr3/9mz5ZVoz+/j7jsknJ37hxIyUSKaqpqfKMJkaLg76gX5aVwrwaCFWSJO85CpoSgYLQ/wXjTX+umR/fyJkj/5xzs9GkE2Tzd1LJ+M8BLjjH0dHKyspTANB09LAV8AaGhEByeDjMF8MAuWgiuKqqCgAQ8PpjI/ERBLwBt6KobiEsNUtgZ+8kKhvZFraWEOGMbjMuGfXCCOpCaineKOL6U4iQCCHLMmCaRkqSJPVcY9bd3VVERKmA19+Ly7UwffPmeyRVVZR8MRz0Bf0X+ODdiqK64QCmaaSIKHU++47ER2IBrz8GkC7LimEYpnkxC5EuCgccHg5zUVHIVFXbeg14A0PMInbhA6871HeBnDjgDegZz4FhGKY5PBzmy7I1R1YfLCoKUU9PDwCgvr5OyRoosqwYNoe0Byv/s0NukxUYnXusOjo6zaz6czH1vkuGAM/HWnbw+nApEJkDBw4cOHDgwIEDBw4cOHDgwIEDBw4cOHDgwIEDBw4cOHDgwIEDBw4cOHDgwIEDBw4cOHDgwIEDBw4cOHDgwIEDBw4cOHDgwIEDBw4cOHDgwIEDBw4cODgn/h89QICwvkowUwAAAABJRU5ErkJggg==",Shutter:"data:image/png;base64,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",SmokeAlarmDevice:"data:image/png;base64,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",WaterLeakageSensor:"data:image/png;base64,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",MotionLightSensor:"data:image/png;base64,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",WindowDoorSensor:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAACgCAYAAACLz2ctAAAM/ElEQVR42u1dyZLkVhU990k5Z1V1G2jCCxPAwmEvDDt2DgMLDMEXsOdr4Bf4Cla2CYObJljAAhxe4HAQ4fYQrOxu2x1VykpJ77LQ9KSUsrq7lFKmdM6iu4asKuXT1R3OnQCCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIGogYz+AMAzlo/9+YhbzKVar9WjP4Xx9ZhfLiQ5eAN+7/0C+c+9Fs5hPb/V7Xvzui70cGEENmCO4CuW2Qvjxw89eU8Vr69XKKNQ3YnwIAE1Pp/o/0o9R+dw9yX2f656fq+JpXlv3Gvd/NP+cVRsJJAKAy6vL93/w/Zc+6Poe+l39obfefsf75Zu/iO//9W8/v3v37m/vvvBCDJjav29ETH5OakvHJ2LUaryNwuh3i+Xkg+z3Pu91ffb5//5wdnb2E1XA9z1MptPRaB9jDCa+B1XFcrl8C8Cv2nioj1IAMzx+/OWvp7Ppb9brM4gkb16kUMjJ587jqwKIQlUgovB9H2EYIwyDewDefOP1n9nbXI+NY2utQlVjVUB1RFY9ea8xgKm1GgOAPxmoBsxFzHib9N1vAPhSsQ+SS6MUJgTZqwSQyIrIVMS8+tbb73iL5SS+pRPiXoDJr0EVzpMxQNlTlAx1+lajcOAC6AiaD8BTaC5omfBlWkgk1YgQKBRGAKiY1MeJvnzysIU7Aa3ziXVUFEHxsA9eA9YFQYnCcb3mQgwSmSzEQVWV7FHr+rDyHHboh/brftR/XSQTyk4eAUqzcwxdm2BzPL6wa4bF0XiocB/EQU3iZDQ+YPnjJAIFRDQXOjc6xoGMhBFKdp9BiMER+SFJ0OGa4DLDKpmGFGYRWw4IYeO4Fw1ouje3tsYHlFzOcm0IST6upB8Knk6ZDGrRBRJjxhGEOEmOSj4p+TchnJNTUUf86AUe2Pr09CAeRxCSGlgRzX3AhAwuUzBSkcQoClr524T0lgHqxQTLzq1P/brU58sJaNll710f0PcXNMCnHnX3pfHcWy9OhFsrnO7P2kIjtqEBhRKYOt8YiQmuUfUKQFLfr6Bj3OxIkZoTU5xUGxpwVMUHN0TC48gF16icxKJqEYCg4ASrmjARGGn94AmMJwiRRmFQhxNU1uRSAI/MTzmMxqIEOlHw4InohN97PmJED+Kz0QmEUxI3fCLaeHtEQfaLxUFkhQoQY6JhslRcUxmWW4iwW5RADM0PNsdDAyAnnzMKhhEqg5Au2ZjKE6lORTQpk6ES0X5f0ex+E6xPZXbbyIQQozPBUpuBcBvRXDJ6X9zRRiaEUUh69tZiNLngpvvuar19XZEtW2JlPWBTmdygMyFac+/l5rztDVqReM56QDOipiTNhU1qKwO1UphA2riDe2LHkgnJJVD39Ibojj9YVMNQWIYUh5jjerOy4+ep1uXj6LodajLCiHpC5KnigXJgouUWQtIwIBHdUiruqfkCyaZaWSaDB0AEmJN6sxV7/M+//4OyQyL6eeVPn08Y0+DEtkecKonoMeWCpYWnTmk1254V2Fee3fTdDfzM/RtSTIn5/PNHlB72BXdn/bJMCCeqHaIUzo61HlCfKbuRyKCynZK54BZHI0pTrwc13dCDEP8YrG4+C+ZZGpRU8fDj/5wkB5E5/XUPXTGWRLq9ntEUI8jt/cFTLcdyBc792BW2ptccPAjpqRihHw2odYMpxWlGb17zk3CAJ7kSoaT1TDqPT1VzjZcJorV2R0sOtR3B7594l9Jo3vJoDmks3T/FuSuuad1sNgi3W9iKkpvNppjNZh3zc/2Z4J4rom0ahEjeC1IMJBJH2KqcoZysBrSxRRAEMMZguVyVhi3FUYyrIEBwtcHZ2Qqe73emAfuajOD3rf3cN2+MVzpoa+Od9kx74guMrLVYrVaAAMFVgDCK8u9NfB/n52eIwgiXVwHOz88ag5WhbKvw+y1IldLTvbneYnt9CVULz5tiuVxAxC/dACMFF3iKJngynSCOY2yuNvB8D+vZKnd5r6+v8dXjr7Fer3BxcQ5rbeIbdiAcfZ1nzzRMsRcuCJ4gCC5zpxy4RhA8wZ079+D7ZSE8NXqwZIJToVqvVzuzblbrFWbzGWxs86934wf2V5DqH0cmRDGfL2EtEMdbAEAYbjGfr9NoUU+6FskVIEnHEcc1oXwcxzDGwBhTErzDC+GoGtN3p41nfs5yuYIx5zDGIIpCqCK/GYOoxky9DpdiSeiXrAFLdxc1igxaA5pjKITM5MsYg2++eYSPH34EVVVj8pulLoGYbdDEidZ9usJlrcWXX3yB6+vrnBvMBK477m9EGtA2arPkBJbLVVqZkdffa761GpoPydcTrCOtS8GJCJbLNXzP2/H7uuMBR6QBTbr/ozjYpA3TGIMw3KrnTfXu3XuwNlJrrRpjJJ1pKRk3mG4VAQZSCLpYLkqc35iq8nvzAQuSOXnnV1dPsNkE4nkeRAy2240Y4+Hi4luOEFoBTMlXOsVUXObXZSm3Es2UmuEsWu4sEtbRmWAt5XujKIK1cRYPYjKZIopCxHEsnudBNZZiY1Kbjrl2ygMaYxCFIcIwxGK53Hnt1eUVxAgWi0XBAx7cDPdXku/375VbqFqcn7+AMAxxfR2kKaEZ7sxnsNbCWlXAE0CTTEirPuDhT97VgHEcw3geoiDA40dfYTabwngGajUXOM8YxFEMMR0WI8goeUCbPn0G1sbwfQ+TyXkeeMRxlB2+4weiXCxzQsZHRBBcBYitxcXFGeLYYrsNodbC8zzMF/P8NZeXT3Bx57yzVFxfLo3fiz+k1WFEmvclqMZpwi0pEy8W0yStcEbSDdNyWtUwqomGW61X2AQbPH70NabTCSYTHyITqFoEVwGstVgsFlgsF222noLlWDtZAXFywe73yuot+Z7NX5sXI7T2wGp3bY8p2bxYLjCbz7DdbhGGURp8CCaTCSbTCYDCHPfZMjlIATQilbZMbRAI4wQq8lxtnMfi/JSiXxT54Pl8Xl3HnWs992cOL4QyHgHcjYLrVlLX1f5JXg1jtU3mXnspSm2ikuqol040oGJEPmDJBGtqYs3OhPyy5ks+tqVl1qf39JcKE2orvrvK/454Qupug4g0CIM0z5GRYaxHxZFs7xzPrri9l+AKmjrBhxzSZLD5OKW6RqEBxa0xAADEDT0fUuIKq1LXoqbgdCwRaOqcD14D1hOexhG0qjAaRxC56XxIJHR/GrCkfEzlUqTE+5XaN53L5douDim/ZSZEa9JydVSMlkSw/aeWmnRUM6LLmZCqjyc7eeI64VRVhg4Hui+Db0wvay6t0XRaszWzPFm/XetLSXYHVI6ChtndlKRO6m3/PuEDlJBTAqHjaUxP8qF1o3ptgxm+aYQb0eZjOI5MiGDPokLXHzS186TbTc6TzxmVCS6iYKnJcuxJvVVI6BYroil/Y4uCtXFYoDZUwdQI6wnVA56SDzh4E5w0lbs0i9QInKl8f5cTpOI6UFAwGU0uWCr+XrUIoa44YVjFmNwT0hMPWLzXatWzNBQmKE3lQEdzmH5pGGkgousqYMpzZMgDsiS/pUyI1vB+piEokQOtaSHU2vFOx9oVLL3xySQp3XZJvhlPY7qWNJ405IUVgHdw/4/6b4TzAaWxL6TasGRromSWY3E+4EFuvDz1Xrl2hYamPCnJH60P6AYXZk8DellDtuUD0pfMdsWNaVvmjfvidKcANduklFlePdXGYGrAY+wLRkNWZM/X6bpxX3B7fr82ZDykVIx6GHPJOLhPV8QcJwtPv2wsrZl+vyX5TaVYWrsh8xCHRP3X74jeHrvidO9e4O40IiUwaXjVEfUF702/7fqGifbLOMD2SzFH7PjtaMBR7AuWp9I8UjMlgb7hYfwPgdrRTse6uVCh2Kjefi2WJhuyCRlRLlhrNV1dHlgdGkaYteggCBmFCX7W0iuCbZkdanvdGcVGHF4JZCvCRqYBxdmEuV9E0526Mphd9UdXEd2PBuyhJN/aRIxMtDuS7WbWIFnl6hlV9Q7lD7hrUweedpO+n8POBdD3/GVyX+385mxE3biOZK/ubDb98N//ehiHYSiTyeRWp2dMfh/sWAKdoj02ec+DX1Y4ny8sAGw2wR+/evzo254nUY24SYUiMTUHZxVQ3/N+DwDv/vkvBsmg6ed1SCWKYkRx7BljYGM7onjIILbWc7V91z7gSR/1e/cfyE/feP1W2u9P7z740Ww2fQUAVqvVorq3t+hlLhz1qml2v7cvuZ9pGWtt6XdVtyG525LQsDUpuyZ393CTJnOvxb1WYwxEsEm//v6PX3v1w8HTj+/dfyCbTWBefvmVW/2eTz/9xN5W+IgxdyQfkRbdbALz0vd+OMr3v5hP+UATBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQxPHh/6ndY8IEYh1QAAAAAElFTkSuQmCC",CFMT:"data:image/png;base64,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",PowerTagE:"data:image/png;base64,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",ButtonPanel:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAACgCAYAAACLz2ctAABX2UlEQVR42u29abBl13Ue9q29z3jnN/V73Y3uRqPRjZEAKHAWLaFNUYlJy1biEKlocDyoJNmuOFWxyyk7idFwqlyRYzuOM1i0S7YjyZHTkEjJskhJFoGmKM4gCRBsAATYaDR6fPN7dzzT3is/9j7nnnvffT1PlN+puuiHN9zhnHXW8K1vfQvYOXaOnWPn2Dl2jp1j59g5do6dY+fYOXaOnWPn2Dl2jp1j59g5do6dY+fYOe6Cg5npMj+Tl/v59+PxwgsvOABw/vzih1dXV3/1zJkz0YUL5/WFCxf+1eLi4v2XOyfMTDfzcas+o/N9ZHyCiDQz+51O5z/d2Nj4iUql0kyS5HXP836HiP4DADzzzDPi2Wef1TfrNQHQc889d9M+x9zcHD311FNX/L2TJ0+KRx99NDl79uyzSsV/PY5Vq9frAgA3GvW/oHX2Z8+ePfuviOhvPPPMM+LYsWNMRAwAx48fl0SkbsX5v9nXle6EtwIgr/Z5Tpw4gaeeqhPRe7I33njD8zzvt2dmZj/abm8CAIQQcF0JpdQ/Z6a/u7CwsMjMlF+M3DsC4Gt5/8eOHcPNMuTrPU6dOvVhZv2FbrcLIspc13GUUtBac7VaoV275nHu3PnnHn74kadzAzl+/Lh8+umnFXN7DqiLbrcLAOj1ehNeoYeJ3x6eNz506BAR0aL9f4eIsrveA77wwgtXeqPZdRi0++abb/yWUtlHT516I3EcVwIamhkqU1hYWPjZwSD6oaWlpT8D4BQzIzfC6/UGcRw/4Xme1+/3AQBpmpo3n2X2/wEgHflZ/m/594Y3u8NTU7Wng8CfjaIEAKC1sXGlGICG1hrMTEqlnGXpf5ZlSiuVwfd9RykFIQSUUkmn0/tall10hBBT9obTzCyJSL399tv/8Pz59s8rtS5yJ8PM+XMDYDADzDo/tyV/NPyamfns2Xd4eXn55SiK/g4RnXjhhReco0ePZnelByx7HmZ2AdDJkycBAJ7nUZIkvLCwMDczM/PU5uYma62L11dKQSm15essyyQzK9/3/mshxEfPnTubhWFobxwGA2DNWmvdb7WmQoCePnjw4KeY2Xnuuef46aefVmfPnv0pIvp5pZQwF1rZk65hzr2A1vn3QESCiUiEYfh+3/eK95JfuPwiMXNxYYnEhJ8Pvyai/DxACGFfS4BZQ2tVXI7894iATqeDNE3BzFBKA9DsOB47jmzff/+Rx4jobO7hT548KR999NHk5MmTf4kEfmkwGCAMK3CkY99X/p40AIKUjn0t856Jyiah7fcIWmvU6w30er3I87y/un///n+VG/pdZYDW+ACAV1ZW/k4U9X82iiLXGBkBYPMfouquXQsNpbLijstvQGZtHzz23EAcR+j1+lprLbQ2xgMgnZ6ZclWGZ/bt2/eLg8HAr1QqZ5lZfvazn3U+9rGPxd/+9rc+MTMzd7zf7yEMQxCJkmEMLwwRgUiWvk/odjs8dAlUGKF5CBAR0jRFkkSo1aoYzTrIvkcBkDZ/wwJEQhsjYAASWmdI0xhpmoGIIISw74VARJJI0NArMZih6vW6FIK+sX//wfeUz9P58+d/RqnsX1xaWlQEFkFYAbQe9WskIKWEEE7p8+TvW28xCSIirbWSUspGo4H19fWPPPjgg8+/+OKL7nve8570rjBAZqbnnntOPP300+r06dO/XK/Xf3p9fRVSuhg5f9DQmpGmWUa09W1orZAkMbIsA5GAEPZCCAKBhBBkja84VBCEwnGcL6Zp9iNHjhyJyz88d+7cB7vd7m93Ou2mlAKe59HY+waIIYU075VGQ5DJVcvfE/ZrXTLAGFEUoV5vjHi80YtLEy4u2+cDtM4wGAygtYYQYsQIh96TYNIKQGvFvh9QEFSeV0r9AnM26/vh071e/89qrTlNU0hJNH4jA4CUDqR0xt7H+A1mXk8IIMsUGAwppXYcqaSQ6WAQ/djNMkK6mcZ37tw7v0yEn15ZWU2CoOIwY+TuNedTIHeVE54NSilE0QB5vkMkICRAKHkoYutQAa1Zz87OCCndFwH8naWl+MVdu/yniOhHoyj+6SjqVaMoYikl2bxw9AQIwJG+fX80lgtxyejGvza/p3WG/mCAeq2Ze+WSIQrkr2n+HTdkG3YBpFmCKI5AoOJzl8Pi8DmoiBb1egOO40II873NzTYzazJpgTnf5m9E8d5c18e2p3/kumqsrq4gTTNESQRixtzcvG40WkJKEUdR9PEHH3zwczdqhHSzjO/8+fO/DOifXl1dTX0/cKWUIJIg+8GVZmjW9nRPuvNKFUqWYDAYFF5ACAFBwiYqwwtqLgwjy5RutVoCIMRxvF6tVqdc18PGxgaSNGJBgvJkP8/V8td2HAdClItk3uINjDGQNSw9EsKzLEO320O93igu8tBry+JiCzE0vPy9DI0VABSSNEYaawgpQMSF5zNpQ9mbmZxTa1ZEsO9fMLNyyinNMP80rzv8rLSNKQzTkk6ng9nZWezZsxf9QQ9/+IU/RJZm2HfPPXpqaoZc14m05o8fPHjwhbzyvq0GyMx07NgxevbZZ/WFCxf+DTP/xMrKUup5viulQK/XQ7vTQZZl8H0f09Mz8FwXSml7Z9NED5gnv0kSI0nisbxIjBlg6ZKw1oKIfD+gLMu0KTBZMpjAekuSz8yQ0oHjOGNhcmiA5nU04jiBUllRdOQvTcTQzOh1e6g36ibNsz/U2qQb5gPBhlZjkJ7nwnEcMBPMjUpgzsAMpEkKpRWIcsMpn3MqvCKXPtP4uRtGm/xzSEgJG3ppm5DLxfnp9zuYnp7FPffsK1673dnE8yeeBwHYt3efrtfrIgwrURCEf3pubu5z12uEdL3G941vfMN58skn+dKlS/+amX9ycfFS6nmeK6VEu70JxYyFXfOQUuLN772J9Y113Lv/XrRaU9YD8BXfVhwPkGVZkQua8D3pri1gg+KMDi9AHrLHq0wBx5GFlxl9LvNzU/h0i7xMCGENZvQ9MHOR6xpjyitJBoOhtUIcJVBKIQxDtFpTaDabYAY2NtaQZQqOI6EUW4+ejUA4edVcDu25tyo8OmmARXHjaA1rxAQp87xSXjby5EcURbjvvvtQqVSKm1UIgZOvnsRLL38Texb2YNeu+bTVarpRFP3moUOH/xwAcT0Y4XXhgCdOnJBHjx5NT58+/fO1Wu0nz5x5O/E81wMYm5sbqNVqeOihR4qLPT09jc989jN46+23cOjgfWg2p6CUmpCLjBql53kgIiil7N09zKtGK1IqFQe2FGeM5HUMtuHfeFTj+TD2t6IoFpIkQbfbRRD4kNIpYJphKKdSfsXgzHi6HNYBFAo8BYyZmRncc88+BEE48hmr1QpeeulbqNXqCMMKlMrgOAaqyXE7pRRc13xvay46ni7kuSnArEqGp6/C5xgjF8IUhOW8k5nRaDRAw/flbG5usuM4fxLANBGtjDcAbokBHj9+XB49ejQ7derUj/X63X+8ubmRSkkuM2MwGKBWq+Ohhx4uwhdAqFZraDQb2Fhfx+raGmr15jYJ/zgEIOF5AkqlUEoXVWAeNs3z515xDM8iYRwDABBbrI0ghAMhRnNIZl16P8KG3QhB4JunYUa1WoPjOPA8F67r2fAti/Qgv/ha59igQpYpZFmKLMswN7cLrusWQHD+WYMgxOHDh/HFL30RRw4/CEdKc7OQgJQEBnD+wjnM71pAo9EsPscwGqkxr5vfZBoGZuWJ8MrW8DtMK4QA1tfXUavVR4xwfX0NYRCiWqsVgQYgr9Pp0G3rhMzNzREAXLp04ScbjUaotcpAREopSOng0KH7R4yLiJBlGZRSaLVakFIgSSIEflgCg4cgaR5uiAhMANk8ySbaWFlZQr3eQK1WLy4GYQRJtSHJGCBrDRCgVDmvQwlyoVK1agzcAM/mZ57r48CBexGGlZuD/BchfwgFzczModls4e0zp/HAkQeQJglA5pMlSYz+YIC19TV0+12oTBWFAueunod5hxAElSlUKlW0Wq2icCqnH+U8sIyD5lFGOg56vR4uXLiAvXv3goiwvLKCpeVl7Nq1C64/UkkzUL/9rbjFxaVuEAQspYS2yXm1WoHv+1t7mm+dguu4qDfrSNPUhrEhCG3Ci4TrOuh2O3BcFyrLAJ33OlDghOsbG0VOkmWpzY3MnT/8mu3vmOfMsgxBEMB1/cIrj+ZRVGpNCWSZshAGsHfvPQjDSuF9J0BrW4qqSfjblaCPPbt342tf/zoGgwE8z4PWGUgIZJkGa8B1XMzvWoAQEkKUCjMI82mkwNLSEj73wn9Aq9XCDzzxA6WQzGPvQ1ivz7YYgk2JuOjQOA6h02nj7NkMaZpifX0Du2ZnrXeWxfkTQnC9fgd6wUQkhoQDtokvF2Bq/mHfOfsOlpcXMTc7Z6o7hoFUYIzF83y8/sZ3sby0iB/96I8iDKv48le/hPe9531IkniklZVlCZRK0el1jUFIYU6/MM9ZgLdEcF0X6+trOPXWKezZvQf3HbyvlAeNV5WjvVBjxIDvuwiCykgeNLkow8Si6mrwtiLf9X1oKHT7XcwEM+bmY8B1JKQUaLamcOi++y/7HEmSIooSSOnA8/wS/jqMKkppxHG/eL+rq2vwPBezs3MWKhp+Tikd9PsDiznWoLIMSufpis6revdG0JSbQkZge6clSYylpUXMzs6BGVhdW8GlS5dQq1aMaxcC5BgIQukUlbCCl19+Gd96+WX82I/9GJaWljE/P4+11RV885vfxPvf/350ux0IIUueizA7PYvHn3g3XOfyb/+7330dX/zyl3DfwUNwCwgoNzJV6t/ySIVdhDKloFQG13Wu2aCu9UjTFETCVL8lqMcLAvhBgH6/OzFPHiFPJDHSNEEURej2emg2WiPtRqUUfN/HvfceALPJpZ9//nP45ksv4uhTH0Gj3oDWWRFNiJR1JgSlVRHmGQwpJJ87d46azdbrhw5h8Mwzz4hrZRzdFANkzrEuUxSsb6yh1+tBKY00TVAJAyiVAdbb+H5ggF0w0iTDF/7oj3D0qaOYm5lDv99Hu72JH/6hp/Arv/orOHjfQTQbTShlgHbf9xCGockViSYAxygwOCJClmZwpFNUkyPQzBYsbdilyKtepRSWli5hYWFPYYxpmiHLTBphqVEjRYiUEo69yTzPQxgGV+UgNjbW4boeCCZnzpQCQYGEQJqm6Pd6GAwGhcfNq/G86yEEIYkTPPTQwyaEK4UkiUZSBKUUgiCA7wcAgOXlZayurcBxXWSZ+Wx55Zy/hiFv2IKP8s4NgZmp0Wii2WzuA+A9++yznWPHjtFtNUAhBTzfQ5IkYG1A2TROIUhazMyB1hkAD0pnEBZUVjpFrVrHF7/0RbRaLTz0yCMwnDdTRVarNfyJD38YL37j6/joRz6KJNG2QHAgpcTq2hqUyiClLBl/uWFvvk6yBJ7rYmNjA/25OXieB+bsMnBouZVm8LPNzQ30ej0wG3wuD2XlfLAcnse/bjSaOHDg3m1vXiJCu93GpcUlVMIQvu+ZPNne2GRQdoRhiPPnLyDLVKlwG61gXVfiyXc/WXRooigueW1zA0ZRhCgaYHFpGV/5+tfQ7vbx8IOPoFKpFDf6MCceQyh49L3X63X4vl+7Fn7nTTNAhsZ333gDS0tLePI970GtUoXWGhkr6EEfjuOO9C1zUFRrc4cNBn0sLS/iA+9/Pwb9AdIkLkJgFEU4fOQwTr72Kl5/7TXce99BRHECQSkGgwhhGGB5aRlKa4C1OUXMJa6befi+hx/90f8EjnSQqRRxHJu7u1wHlsJqnthLaXqxmcos/y6z0MY4CD0hGlDuIwyEstHeRGtzA81maySHzPPVNE3xnZOvAGDMTs/Acz1jmNZ1aa2R6QxRHEGpDEplIz1izvNaW0jEUTxSuJU/nwnxKd5447u4ePESds3O4MHD98N13BK8w6Ui8QomACal1BKA9Hpp+9fvAYXAwvwCWo0mPMc1cAczIADWjDSJC5edX1xNunDvSZLih//ED8FxXCRxZCswgG3+1e/18Sd+8MMQQiBNE5P9EUHajkR/0Ld5U6mRVGqz5S08R5qWF1ljyr1XgdbQaPXKYOhMD59XW4jHFib5dSHQyOcb8UX2Bshf6/z5c3AciWp1tFzsdLo49dYpKK2xZ2E3arW6BZ4NbEUgpGkCrRX6gz4uLp4f9pHZIgT2X2Yu3oBSGmEQYmZmdktaZlqQEgcP3gswI1NZiY/IpfM3KUqUPyXrer0u1tfXP0NE69fLlr5+A9RAq9mENzdnQjBsO0qXug+lnGuYK9kLrRlsXb0QBBISxIC2uYYQAvV6vfBmJIxhNppNbG5uoNNpQ2kFrXTeCy5dfPP/rBkaDFYKtVoNvh+YsMKj72VSM6b8bUEEkBzxcEWYBRUepyiomQpDFTb3OnPmDKZnZhAGFWRZhk6njc12B9JxMDczW5wfsu0+k4NqZD0FKSSSJCnIqeOGQWOZhCAHQRBsmxowM+I4vsbCahLNDCCDydwBGAZAphQ4iUsXjUfBMeYRTz7E5wT6cR9CSHgVD6w14jgGs0YQhGCtkaYpPNe1GJeEVhqOdKCyDHES4+z5s1AqQxiG0JohSUKzgmaGgACIQRDQ0HCkREPWr7vIyvuyQzLCEATeDpoph9kcjL9w/nxBPiAiOI4AWCNJUguWZxZ0N0boeS6qtSqaaRMqVXmzbeS5R14LBAhCpVJBGASlImvrjVbmGl7uM4xyFydS98UdmwkhMvjb0PvYXJV52/5u/rN2exOt1hQEEaI0xbnzZ1Gr1iBIoNvvYXNjE7t27YJWxqh838dGu40kSTDVnEK310Xoh/BcD9KR6A8iNKsNNBoN603K2UKeVPNlmDgY8RDlRw60gxmszRwKlxCA4u8AEBvPDjIcCCphotLMc1i6FYEyKnI9CIIozZHkRVzgB9izew9UpqEyhUxlEz1XYVD2+SYVKeN/x1e4gbaSPmik0JNSQkoxuCMGyGNhqpTVj94pE0BarTUiGwJYM4QUCIMQcZxgaXkZvu/DcR0sLS8VTXmtNbLMXDxHSgShjziK0ev14HoeXM9FpRKWqEgokUZ523BTBplzuGb8X8UanA/0MAovJaSE67rD/xdi5HxoZdKATCuTLmQGtsmNSJAoPKLQBG3/Pv/MSsXIMmGhHQfSl3C06eyUOYVbAmVBXN1ajFydwW3PFSwVbCJJUlQq4fuZuQpgcFvICMN3kNsXjzk6HoPmeIJhmjwpz+3SKIN0JLwggEpSsNaoV2sYxBFUplCv1hDFMaSURWjRDNSrddO6cj1UKhU4jjPxwuReb4SsUPJiOZ5XNjyttencCGPwXhgiCAJ4rgfXdS25U9j8cNiBoW08a/4weFuKJEkQx3GR25nOgxzphec3Rt5Lz1k8juNAKTUCC6EEEg8dH23Ln7w+A4R9nwJSOpQkCXzfexxAjYh611MJX78BKpNbuY6HOI5Kd5itl5hG4IAhaIYRWEBrhu95mJ2ehWPhAGZGt9sFK23o+TqD7/qQQth5EfMkSZxACok0TbG6uoqZmZltKF40NqmGoXfTyhQrY8Cy53lohA1UKhV4ngnzeZ5VvphmKk9PDGnjBYCBeIzXrFarRXciTVP0+30MBgOkqWHPmPAmRwzRcRxIR0KKoaHmE4TMbFEBGvP2VOII6olh+aoqzhJUJaVbXD+l9KDTgb4DvWCTEHueD2ZDo+eS62drfoQrfV4uYVRDjKvT7YCIMDs3Z8BXe5HjODYeyHWhlUKtWjVhzszOjlxwO0M7MqubG4nSJqxqrZGqDKwZruOgXq+jWq0WVWTxd9rcWZrLHQg9Mpq5XU65XW+4THJttVpoNptI0xS9Xg/9fr8wKCIgrAT4oy/9EV597STCILQdG0BKF8waSZriT3/s43Bdz7xXjEYnIkKlUt0Cr1yddxRF79dx5MjYplJKAJ07U4Tkyb7vGw+RxJG5QJYqJniUzTJ6Ubg094CRPixAmJudAxEKAxfCeA8uVdxCELrdDjbbGwARNjY3oJWybSyg1+ujXq/j/vvvL7xbkT8xI0lTMDQCP0C9Vi/C+CRPNsngxgeFrpWMkHvd8u87joNms4lWq4WLFy/htddeBcAIwhDRIMKe3Xst68ikA57vwpEulFJwHBdSSLAw5FsSeVpA2GhvggShWqlN9NJXA8Hknaph7sy56sKdISMoPRzsdiQgQ1NIZFla5FjbQRMAsLK6hr17QovjmYpS2+eUQkJDI4oiaK0QRTHSnH5lPV4YVvDiN17E5z9/As2mGYuU0ni9Xbt2YXVlFfv27YdmjW63O8ztshRxmmFubg6PPvIowiAYJv52jjYPj2Wj2w7GuHF+4CgpIU1TCCEwNzeLubkfRpal6Ha6eODwA/ADv5iYGy8s0iQtbvhhRQ9IRwBkUpac6XPlt01jeJ+052FIVWMW0FpxmobZ9ZIR6HpkN44ePZp9+tOf+pe79+7+i1PNqYyInDxXYDattMxSryZaveNidW0Ny8uLcF0zqWU8J1lYQ0OzRppmRV7UbDRRrdbA0JBCACThOg4c14HrOJZTSAV8QQRT4CSpxRhNvmfmMgI0Gk1Uwyoc1xmCwOYTGKPTfIOJ+02Zty6Kk1zfpdvtDvPBUo54xZvBjjaIy/7+xBkb24aksclBU+0EQZhUq7WHdu/effp6FBOcGzk92noIYQdyciq55/ngOIKC3pID2hFrTLVa8FwHSZogJzSTEEWLi4iQpCmWlpZw38Ju7F5YAJeq7JxAWsbuyty8PEwKIeB5HpI4gStdzM7Mol6vGw/LegSGyWxeeLccuYHk8zO1Wg1hGGIwGGAwGNiw62yLCY70nvOOzhbPS6WRhmE+ns8S55N5WquReRiAiFkpKaUnpfyHvV7vvwFw8TaGYPKZWZs+otjCRHEcBzpJtuUPSinQaDRGktzxkxYlMbrdLhqNhgnFpbni0YFv2nITK62hLOSRpimq1Sqmp6ct29hALEUuZsHuu/XIP1+OAORFUq/XQ5IkpWk9mlh9b1eVF7QSndPIpO29G7qZ5zlIEkNwFUKODZIxiITc3NzUruv95/1+/9EDBw58AMD6taJ513WEYeU0QCJJUg0IZEqb4XObWI93CVBqYeVcsyH0kZVwuDwxJ2xubKLX6xUhqMx6Lg+tj7OTlcqQZikGcQylFeZm5zAzM1NUxeUiIMuyO2p8dJ0eUQhzA9ctH7445xNC+HaGmN98G5vrWFldRhxHSNMEQeDDdSVe+PwLeOv0W0iSuPT8NNKAkI4Qy8uLmePII6dPn/5r1wMnX9Nx9OjRjJlFu90+xpn+JUB7vX43I/thjEGZN+q4XgGuOq5bALiOdEZ6nqPtoSHrYrO9OUI/KgO62+FuKsuQJimiwQCOI7GwsBu1em2Y59mLkRcYd/q4HtMXpc6N7/totVpwLal0Ut56ue/l88ZspwOV0ti7dx92796D5eVlS5+TKLMtRiIOA67ryo2Ndc2s/vtbboD5y548eZI//EM/9DPSdX9pbW3N6fd7StBQdiyOY/QHfXieB8/zimFrpTSYjDG4rl90FMan8w042zMh9wpXyRBcTMcgThL04wiVShV7FnbD97widORg7FAn7/vz4Ans73q9jrBSuWybbvz7I5CYzc7J/l6SpvB9D0I4KNS8eKSPzCRIw1wryrJMOI5Tuy05IBGxffPOY48+/jOf/ezvPNLudD7g+74y7FhGu9NGp9uGIwRcz0MYVuC6LjrdDr5z8hUc2HegGK0c5nPDOdc8NJoC5/IVKdtQHqcJkjRFq9nCdGvKqhLoApTm73PD2zaE51OJYQhXSnQtg7tc7SZJgrPnzuHee+8dFTmyIHuOGXJO3tC6YLaXeGa2t67h+x51e1165eQrmGpO8ZHDRziK4uXb4gGtHCxbrWNqTU//epzE6A/6LEhA6wy9ftdMY8FUt4fuvx+HDt2P/fv2Y9Af2L6lHlFj2kIT0iXqU8E+wZYwnFO0kjjBTGsK01NTQ4aO7ThYsDFvYW95YOzru9ngioftP+cPpTU8zyt4lOOeXluAfutMD7awxJXSBQeTSq/KzOy6DivFF1ZWVt/cWF/TmnVSr9dFmmZ/95YboMV6NAAsLy8zM+PUm6c+p5RCkiREgopme7kyyCyZMtMawqp20kgeV+olEyGOY1TDiuX76bJ4xJB/aIuIOE6QJClmZ2bQbDRGuwvF8DabUH2lQoDorjDEcUMrj5wWjwlFirYYYV6cjHI0J0M0bK9F/ookDCFWWJWvMuoAkJqenqGZmZm/JaT81w888LBYmF/w19c3TkxNTf3qLTXAHGg8e/bsYWaWTz/9tCIiHDiw73HXdUFCcM5OHo90o4Dp5f1NHjL/3W//O6ytrRZgccGytiycTKuCUTI7PY16vV6aWx1vXG//4DFy5yQjuNmwynCSbvLjcoZ2NQC2lLIwwpyE0O/3jWzcBE4gl7JLkRMXaFRNgZm157nO6urq2/Pz87/10Y989H+fbs38yWaj+Y9mZmY/vnfv3v4tNUAiUq+++up/lSTJi++8884/P336dMDMJKT4n5gZQRBQeTZhSMsf5dKWlOgmnIghONzudJCm2dZwYbl2cZogSRJMT02jVq8Xnq9s7HytDIsJBstbbiAa8UzF56KhItXlHtvJdNzsLoqTG6Ed1oqiAbQFr4sUBgxtybP57+WCUNgieQJdrdbg+8EXiKh77NixwQc+8IEXHnnkXX9z7969/VtOx/re9157T6+X/JLWKty9e89fmp6e/gevvPLyj6ZZdigMQuW7nhx3+eDtw1w5nysujI3GQpBlXqDEZrYFiWYkSYIkitFoNlBv1EdgllsFBI98PbGrMAxqprd8pVvg1hZEWhvKXLVWw8bGBqIkQRTHmAorxXwJc86NNCmKjbjIlNErHJ2/Nrm64zieleiTjzzyCNndJ+payajXbICbm71/rlmFIhNqdWVFLy4u/4P1jc0/QyDdmmqJkQuFLddprOS/XP5DcBx3TEHeGiuZhn2UxKhUKphqtkYGnoYK9HfuEEJiEBkISgpnGym629NByQuTIAgQR5EpRCwvMY8Yo2saRAH8K6UL8N/k5iY69fsDh4j4M5/5jHj66advSCP6mkJwFA3evba+zq7ryiiOXBL4M/ValaenpoQQgsaJmhNTfSYDepYKe94yRzIGFpdoXSpTiOMIUkpMT08X8xl5V+ROGh8RQRBheXkJ77xzBufOvYM4jkpahLcfL8zDaa1Ww8LCApIkKcLwELcdzrwAGt/61jfw0ksvIQyrI5LKzCQ7nQ47Dn38zTffvP9jH/tY/MlPftLF7ZoJiZMEeVpMUgCkle/78mqA3fEuBmGYd9CEofe8K5KPQpr+rjKhN0kxMz1dUKgmteRuv9czhNoLF89DZRn279+Pzc1NnDnzNnbNL2Cq1SqoZnfq5nj/e9+Pjc1NRHEMz/MhpCjIHSQIjivhSBeDKMLC/Dx2LyyYgs+Scc3KBtYgBFLi04uLi39lfn7+j65nFuS6DFBl2ZsAHWIGWCmhlZLbkhp5lInveq7tfgzpT4VTtGG5PLaZpDHe9773olKtDcmkaYY4jhF4Pmq1WlEZ32njIyL0ez1cvHQBQRjinr33QJBEOF9FGFSxuHgR/UEXC7t2gyDAuP1WqLWG67poNRpod7oFk0ZrRrfXhYxNSBYYYopaafQHfSRJgpnpWUtAJdHvDTgMw0eJ8IXFxcU/T0S/cr3La67pykkp/rbjSNEf9BUJGlvyQlsiLpdA5gsXLuD8hfM49dZbELmxaYyIfpfBZSkcdDptJHZ6TimFJE2QKYWZ2ZmirbZlGu0OHEbEaAmt1hT27rnHAvBGJbXVauHAgXtBLAyB9yocxa3aTam1hut5Vn8mAUDwXQ/EQDyIsLqygna3jcFggCRJ0O5sgrVGo9YYkTwRQlC/308Ggz53OpsfvxG9cefaiAg/8luf//znfsX3/Z/OMqUcx5HlgZwRwBMmH5JSgITAd7/7GrrdLlKl7PCQgHQkGFtp6SrLUAlDfPBDH8Tbp88Ymn2WodvvYWZmBlLKYjYkT5jvqAcUAvfs21dM5WmlsdnZQLPRBFjB83zs3r2nyGevNBZEfGs9YRiGSBIjmu75HqrVKhQzmo0mwtCH63gAgI3NDXiuBz/wLRu9NBnMLJRSlCRJ97blgFb7489/+6WX3ry0svj3ms0mh36wZSNPTirN0hS9XheO46LeaKDZbEIrIIr76PQ6iOMISZKgWqvB97zhsA8XO+AsHGDDhBCo14zKai5/dre0x4Q0+ajjOEh0gm63g6nWFBzHzvGWuYxXMfxItxCkEUIgCAIkSQrf962eIxfFUq6w32q2CqiMQMhUNhx8t6QOz/PpthlgvpjmsSee+J8/9elP/ZAQ4kcCLycgDPM5tjTyJElw7vyFgkyptbbrDEx4cl0jO+s6zsiQT3G3ZoYaHycxOt0u7t1/wNDxLcv5boBcRnmICr1eB6nKoDWwvr4BIqBWr8N13KuS7qUJOgTjL8Q3AaQOggBpmhailTkuOEynSoJHZORRKNctLBlgpVJxbqcH5BdffFEwM//Gp3/9lOPIH8myjF3XKUimOeuEAHiuiyAIAGbUa3W0pqZQqVSKTTwqyxCEPrTSI9NW+b/KTq+trW+gVq2h2WzCiKHLu8r4cq8SxRE2NjeRq9fHSWSAXK5dYdR77HsFUM8TdQluhnfMZ5+TJIHrusXNnwvHF5ZHQw6i53nQcWz6+mDR7/ehdfZrAPDcc8/xbZmK63Q6TET6U7/5G35eCGSZGjEcY4gSgR+g2Wzinn37ML9rfkuxkCQJXn75W8XgTVljRcMYYJwkiOMIBw/cW+SK+RzE3WSAWpvxzv377kUSx7i4eAF7FvaYvRpKX9b70XiHaKw1WGYEbauUfh1eMDfAMoxENNxKNc46EkIg8H0kRIiiXH3VvXjbgOixs8ecz15oVfybi+tMTU1henoKDzzwAHYv7C5t+xkODHmeh/n5BVy4dHHMozG0Gk7FtZrNghVzN3q/UUPMoLQys7pamxVf4O37ztsRbOn2eG2jna1KDHWBJDNLeowcijPiOIQUCAIfQRAgCAKen59274w8m/XSQ8FELvA8s5AF2LPnHjQaTauQKib2VO+5Zz++/uKLWF1bxXRr2gomMsAZer0uKmFo1KFs7nGnugrXkgt6nov5+fltGTZ5pavFcIsYbVcFT8r5iECX7TptH6bH80vP89Dv9yGlRKfbwdLSIrr9XiGWXq3WcGDfAQRBAK3MGqV8WVCj0aDbmgNOOttaqaEiqBDFZJXjOJidnS1ta9yOdkWYnprG8soiplpThYfsDfro93o4eN9BOI7Rf/F9fyRU4y6mjV6p9cs0ami5tNvk/UUT/t+ydCZ1kq408FT+vrTXqtNp4/Tpt8xaMM9DpW4EA/r9Pr775ut48MiD8P0gJ7nqMAyp2+19r1ZrnOJ8TdPtlegd5j4aDEc68Fy3yCWmpqau2ls5jkSSpEgzU+anSYrl1VW0Wk089MBDhbbzcNUVvu9o8zyW612NBimu5v9vVJnBAvkXLl5EpVLFwq55tKam0e10zOgqMS5evIgLF87jvvsOAawBIvZ9T2xuts83Go1ly5DXtzcH1Cim2nzXg28XC6Lk2q+kPZKzLHoDM3ppxB81BlEf62trmJmdhR/4iOO4YHDcsdBK1z5quS19/ha+H7rGMVCyXrDVbOGBBx7EDzz5Hhw+fARzc/M4f/4CwqCC/fccADOhP4ggpNm4qZkhpXCvV5z8xg0Qpr/rB8Gop7Nn/EoaxLlhbmysodPp2H0aQJQk2NjcQJLEmJudMb3I1EAFdxRo5smzJNuxmWmccX2z3xNf3tjGZ11Qugly1k4exn3Pw/T0FPbdsx9SGrLqzOwMNtsbaHfa8DwPtXoNaWrXPrAAQQAafL0khJtggLo0UjmyORoEsstq1GWMz5yW115/rdjlxgD6vT7W1lZRrVRRqVSQxDF817c7Pvj2zWGM0/G3o/Rfs7zjZE+5refc5vuX83hlQxt5TLhphF0KWa3W4dqolWOElWoFcTQA7IKhfGMp59ooN6MSv5Fqj8aopVQq75MkwaVLl7bVySMCTr76HZy/cB6AwaTSJEGn3Ua/38fC/AJUZsQj/TDYtpC5JQoF12lowPZTdqMGRdsayXaGPu5dR/6/tFCbhNhiYCREsd4iV3U1ivxWIk/mmyj0yExJrVIrlt24jhzRzWFikLxxv+7czKl+HmHOSCwtXUKz2Sj2X+TgcbvTwdtvn8alxYu2BWeq516vj432BhzHRaPZQJqmJsf0vFvSGaWrxeUmeB2eACbzZdpok37O23mEy4RsGlHF3zpvc02dErZ4qjK4mtIKLlwLm0kElRCb6xsFyxtUahQybmRB0o17wHwIh7fraZYo8hih9W/gK1/9khEMqlQNvOJ50BrodNvo97poNOrwPQeZyuB6rqXn800PsZM8HG0vhz1STIhSWMOEsDb+oG3+FbbrIKwilaCSh8q9nMDEcLrde+YtYvLbq/4PP6MwkFrpGQM/sH1tbd+XKC33vjkk4BtWyafShxyXffV9H0Ewuj94Y3MTURTBcx1stmNoreC4DgZxhF7PAKCtVhOe7yNO4mK5YXnnxbV6OL4GIUme4LFG1beo8FLjHrL8u2wLF01Xqk6H84E0oo8zfCfEdNXrYyaubxy7wSateTQjEKPnOAiCQsqEhAAJw0rP1+3eDBqmc1NC2JjPJ2FUDQxjxRnbCrkBzzNi5NFgYMmnElG/X+B9zfoUpHTheyE817/m8DtxAu86/n7EmIgmjnxSabyAx1TiSr38K74aYXxDE1153mObz0zXWARhyHgf+X8/CArpOiEIgqSl74vLNhhuXyeERpUKSvJC0KzhuluxwG6nA9/zoTKFQTSAtMzqXq9vtyOZlQusGZ7vXTWYTZeb873mG2rMY5RWMNA24XqSk+KrVECd6LGvAWu8WQpcaZaO3HiO4xTSyaND6nyXGCAPb3MqTa7lygf5XtrhhzLD0UEQIk5TJEkK6bhIshRxEkEpZVeW+pZ44Nhl1Xx1oGrenroJRQhNMMQrGUcx60zXtxCGtzMqwpZRViZtWnlEuNrshMdafRgriLIxDyiEgGY1xhMcXUB5d1TBpYb50Ah4C2O5vANjEA2gVAbP85HESTF4VAkrdlmfttqBkyGnibSlqzW6bUgCPOb1eNLvX4YQylfpciZRyQSopCIxYXZ6PM3h0vqICbdEYVgTSAs8oefMliQ8MmNtq8zy7E8u13tXeECynk+PyeTmJ2+8e5FlCqnKIAhIkrjY3RbHCbRVVw3DsHiu8dYbXWeIpct5uNJu3i2Fh/3ZpOSeL+OBx5ktk8Lz5YoiGrO2ocrs8CwwaKsXKxkWj5EUeIInH7+ZlNLFWAEmQU22HSqEvGlt0RsPwWJ7aYpxF51mKVRmkto4SYarsrLMMkEYfhAU+0Pyv6cbyO3Gl/htqQRLLSma1La6hmR/u/B52eGj0pD+yK63YiG1NbaysZQl60rGxpcL6WXjvNwa8hLYbIqSoXRKvjxHCIk0TRCGlTscgrdh+ZrFMmLLXZJlmV1LqpClmZ0FNgBoXml5nmc1m40RE5sxdbpGj8djYO1IF4F5S4Vsfnd0yWKuHp9DIzYAFVuiRuGSyxva5CKlJDW3xZsNV52NGg1vMcCJUZ/58j+/jHhAeQ9M7kjy7ki+K85AbMGdDsHb0YrYAJdi9OdaabtnOBtZeWXA0bwj4owu67tKDC/n15XDaV4MiRLonLfCmCZBNLQNxrSd7fNV5slDEcjtbuBy6FbMxRrsy5l4TtWniVvxrlcCiUsjE/FQHxqA7/vwfd+uvvBBJPQdLkJ4m52zNFF6TFlMKc0yK5KTg66F7D9cz2gSC+GO7LW4Gi+DsTALTN5iyXQ1Rs2jQnJXi89NIpVuQzQty5SMe7pJ/9I2Bsu3SG8rjqIRYffyTjxmDSmpckcNUApZ7N0oDyQZXEBu054zYuKMoShOLsVLZLhphR1Zpobgq6xwabSK3XaH21Xc/blozzjixtiCGE/8ns7zMhrS7rfzUpM8I13B0LYYHl3dQPvV/h4A9AdRscWgLIOSh+M0Tb8IAM8999zt3xVHUqDb7Rren531FSQwNTW1LR5n4BWGytTIPlurUmQZGqK0rYeuaQ4234E27nXEWEWn883mV7mozzyfnmhA49Xn1ibb5XPnK0I6Vwsv8TVGim1HCcSIB3QdE4lSPbJVioWQWF/feB4A5ubmbr8Bsp1qcz3P5G+2RTMu/zpK/6bhIpuyw+BhKKbr3uqNMS3joRcqb8mly+RNo98bonG8TVJ/NYMQpHmbzcW4CzcyDaOI1hr9wQCB5xXd6vHrIqWs3tEQ7Lhm6UyuJ4yxzTzjJzpXB8jsJqRhZj6aZ9zwTGL+2qXBHb6KBv7Wfyd7X74KhQLGndBEvTFEw1S8stjLHEUDNBv1cjtmNDJcD0PkZndCtKX30BhazhMW/7muA2kN1uqZW0PJcSyzt+xGDHAkPI55uxz3u5IR4jI52feDMV2/BxxGMIP5xQj8AGCj8yMdOZLP3wwwWtyopxmvdccVEkZctuPAdR1wseCQh0HMxF4old2QbvcVc6cyF+4KjzJnjic8/rgdjjMsHDc218Fs5n5yqblxNOHOG+Blmv9ZprY0tx3Hged6ZgkKDWdDJMliG3emUpDgkVWsN7r0j6/zgT+mhna51Q65Aa6trdtdzK7N282e5vIC2DtrgLw1MR/JnViPLKvJJb4qYQClswIkzueTctJplma27OdbtvRP3MYNl99HC78K+hwArK6uIAwrheZhphUc6ZSICbizQ0koY27li2IVT7VmJEm85c9q9Ya123z1kwYJY4Ca2cA6PLrG627YUPnHOffLoTDHGZJHDt13CIHnm719KjNtURrthN8MfcYbD8E0FrJsW02zQr+/dXFOs9EwxUlO59cMYUOwIIEoik3Jr/mP3WLBu/kQJOD5QwLx4cNH4Hke2u1NqFRBinFtnzvtAXmIIdN4kq8ZYG0NsLyZ0YjdmD6wXb6sVUEaEAT0+z2b/6kdA7yN+Z8jXThyFBTZNb+AS4tLSLNs+LNSY+hmEFJvOASPxyO2pAPNhMFgUGgHsh1Yb3c6hYi3KUR0gYAKKTGIIrudm+7Ygpf/GA3Q9dwtBtVqNtHrdTGI+vAD36qWGc8jhXMXeMAxyI4x3OdBBAwGfQwis5pVSIFOt4vvnXqzoNzrMZX9XHx8EEXFBNbOcetXTACYyO1jAHESA8TwHNdQ0UBwHA/CbkW9c0D0pD179u5QWoMVI8tSvPLtlzE7N4c0y7C4tFzkhUplVhjRsQCo4Q9GcYRep4d6tWF6xjvHbemAlOd38mNtbRVEApVKxTaRBRzXAZGZ00mShO44I3qcXpS3qZIkBgNYXlnBmXfOAGSEK1WWQbOyYZYL2r4UAtqUw9jc3MTCwh7DmtnJA2+5Afq+X1yHvJeeZRnOnzuPajVENaxBa7bSyLJMT4vubAgmjKz9LO4oKaChMRhE0Jrhuh6kFEjTBFmWQWUKmVJwXQ+O45oKWBgQ1JUSG50NZFlih6LVTau4do7JBhiGlaIXn4fkV05+G51uBzMzc3BdD4LyCUUNrRVlWYpKpfJfwC4uv/0eULNR15QOkiSx6xmG/D7P8xDFETrdLtI0KYBmrU37zvN8BH5g2jxKFFQsx3ER9Qfo9bpoNlrIMhOm/+PpSdx+df9KpTpcEqQ0vnfqTVxaWsTCwjxajSnjAEigvBNQKQ0pnSMA8IlPfOIOGKAw2liBHwIgxElctM9YGyA68ANwndHpdZFlGQQEXFfCdR2j96J03gYphpCklIg04+LiIpqtJpI0ge/7O5Zyq+AXOwIRRQN0u12srK6i2+1ifm4ekkShFwhkI90pE5lEzMzyRrzDjQ8lEeC6PghAFA+gWBdbz7W2W7trdYsNmkBtKmAFTQaaMbJiBEkCWjhwXRfr66tGqoOckVnVnePmer92u4319XU4jkSWGYcQWJTChGW1ZS67RM9PiUgxs3O9GtE3hCQqnU/NM6TjwPMCCEu3yg0uY4ZiI707DNN5JyRnUpNRh7Jou+s4GAxirK9vmP5wlu4YIG7NksU4ji33L7YD58OlQePzIOahAYCiKNJap/edO3fuvySizHrC22mAhlqv9cgWxUKoPPeCYDbytvlw0HAi0qwuZQtCi2EYdhwH0pG4eHERaZaOkBp2jpuH/+ViUGEYmnMuzcC55zmoVoxChev6djRi2P4igojjmAaDeL/vu//23Lkzf8V6QnEbFVIFa2ZonRV3htZmt4R0HLNDpCxcZNirdhwyn4nVAJs1DySkUfG0hloJK3j77dM4d+4cQIxsBxO86fnf5uYmFhcXsb6+Xng7zRpra+t45TvfxqWlC0jTeCjLaxqm+dw3ZVmqlpaWlFLqH/b7/X3Xo5QvboA962tzFHMeSmmkWhVhlbV547kg4nACkwBtZ3MFWZ1BAQjTMRF2sXWaJbhw/iKU0kjS+JbL9P7H5v3iJEG330e727FRhvHgAw9DKY1vn/yOvel5m6F6DSGEzLJMCyEri4sX3ntbQ3CjUX/LcVyRZZlmK2qTExfNetLcK5pQrAqIxhYgNkTn3pNZQ+YqoVKCyEzfr66vYHV1DVmaQvOOF7xRGhkB0EqhPxiYwk8OFSyEcAzYLAhhEFr4ayiDW+ThzFoKyUmaQGtNSmW82e2mt8UAjx49mjGz+MhHPnIsjuJ/4QWhl2SZyin4bFWutDW+LM2MQSrT/ci0keVI0wxpmpikVlgdAFuMCFipWiEBEC5cPIdev1fsC9k5boA/QoT+YGD1eHJBAJT0n42BDlUtaHSjEzMHlYo4e/YcffOb3+JOrwvHdalZq6a30wMyEfEP//AP/2zUH/x3q6urMk1TLg8/53KvUgoolSGOBoiiCEkcF3R8pQxlK0uT4R0qLSTjikIKYmOjjdW1VcRRZOXIvh8utbgrQ2+WZYbsQVQwkoba00OMT0oHopjb4XxUU4eVkJTWL7z19ul2kiVcCSvU3uy8cu+99//B9SytEdf5QZiZ8cwzzzhPPvnk/wbGlweDAVm9dcAumWYA9XodQeDj0KH78fBDD2P3/B7EcYp6rY5atTocXrJKqSBAOhJxFKPX6aFSqZhVUucvIE4SJGl8TZIddwJbMyLjfFeS93u9XpGjF9OWhZxJrv9nhKJynWGGABFpz/MIzK8/9MBDf2rPnj3Pzc7MiKnpablr1/yzRJSdOHFC3hYgmpklEakXXngBAESjUX9udX3tg47rsIDh+ikrMKk1w/N8PPnke+E6Ls68cwavvf4apqamjGqBMAQEaa2X2WzuOX/uHD7/+c/jJ37yJ+B6LtqbbZw79w4qlSPwXA93Y4OYiLCyuoI4jsDMmGpNoVKp3hVAOtkdv0mSjClX2G0vDOQ1XqGKRUNtHK1Zt1otJ0myXyKiGMDPfOPlb/yyK8Wh2dnZ37D74rJbboDPPPOMICIFDJvQr5964w+nGi0kSUqB74O12aLpWIVTMCFNUjjSKShYxUwJkVWrMhigUrkiu4RwJEhKSCERBBWcv3AB09PTcOY9hGF4U9bX36yLmxdUgR/A81xDcbczE/mGzzvF7DHnVaHX61k81gqWMEoheMgyNourCSTyhdmapZRyc7PdbrWmfoOZ6cSJE/LJx5/8QwB/aE7BbVpW+Oyzz+qLFy9+HABOnjzJzz77rD587+Gf8HzP1BIT9N9J2EdOzScuuXxhQenSxdSGHeNIB1KQhWUkhCB879Rb6HY7yFR614S4JEkKIL5araFRb6FWq8N1zXqxpaUlRDbvulOQy/LycumGF6UAIoZXSpQleEfzwvxvwzAkAHjqqaf08ePH5QsvvHBDTBFxjaGXXnnllb8vhPj3p0+f/sVjx44JZt7Vj7o/ppVm1/XESOOQJuzZgNG+GxpcLrNqTkCeewhBcFwjBysEQUpC4IXo9Xo49db3EA2iQmPwTud8GxsbOHv2rK3SDdkWMIqw586/gyge3JFF2/lN0W630el0LNwyrszPhZEJMmMQ0SCyQ+i5gyDKsky1Ws1Gt9v+c0TEb775pvv000+ro0ePZreND/jqq698xPPcv33mzNvp1FTr5wAc/v0/+P2/7QfBYd/1lOM4Qhdcfc5lSsclRUY0BMkud85VRwkESUN5NCltOBamVVSpVLC4tITz5y/cFEr4jR5aa8zOzqJSqeDs2Xewvr4Gx3EwGAxw9uwZeJ6HfffsL1gnt/vmGAwGEEJgenraLI8kjIRb2PRBSom1tTX8+m/8f7iweNGkOKULJqUUa2trnGX6Z9544w3/yJEj8fW03m7IADud/v+ytraqHUeKCxfO66989cufHQz6f12lSreaLadw8YJKQpFDybWS8N/Y//PI+iwNRuD7aLWmhmFDAEIawqrv+Th1+hQWlxa33ch5u8Pc/Pw8FhZ2Y31jDe+88zYuXjqPVmsKuxf23pH8j8jMbHS73aJJMNSLtSFYmHHMfB1GGFZw8OBBPPHY4zh4770gIazknSEEJknKSmVHarXqZ1dXVz9ERPqZZ54Rt42Sz6ye3NzcxJ49e5AkCfzAO3DPnr1wpIRmHg4R8VCsjwRAeugFjYAlF3rMZFURTAlGMOp9Aq7nFpWyFAKaBbSt1HzfwyCK8drrr8JzHezatXDHq0ylFGq1OoIgwMrqMqamZ1Cv1e/IDUI2lHY6nSIMj1biRo02SxWiKIIjHbQ77YKBrhQjjhJ022apkOs6VrObRKfTVq7rHE2S5N8x8/0ANo8dO0bXuzf4mqy33x9k+QtJKRH4gfY93y5L0YX+clkMMV9yVypJisa2XXlnDJBpZOJZSgk/MHrEJGXRGTET+gKBH0AphVdOvoLllZW7okOitdmBsjC/B9VK7Y4aX7vdHjG60X8t8wiELM2wvrGBc+fPYXV1FZ12B532JtY31hBWQniug3K/H4BcXFyMfd+fabfbP27tQd4mQir9XhAEH9daZ0TkcMqioGmXVehLITiX8s37jbn0xnCyjgvlebYLW7TSqNcaePihh+zAul3ZQGya4DB0L9/3EccJvv3tl/DYY09gYWEeWumSsPjkfRu3TiQyh2NuveFNGsvOpXQ7nc7ITHV53oNLszyeZ+As3w/QajThB4EhpqYZur0uGo3GMGqVWnFCCLfdbnfq9cZLAPDcc8/xbdHZOX36ex87deqt32w0Gm4QBDpPQkcZMQpRHGN5ZRlBEGCq0US710U0iKG0wma7Dc9x0JpqgbVGr981HDTXtyfHasuwxurKCpqNJsIgRKYVWCm70kGbJXpagzUhSgYQ5OBd73oU+/bu23ae+I/7hJ3WGu1224w/FFLHJtJoG4rLOtFaG+KI6+ZD6WKkNZefrjSNy0pn2vM8kabJ2fe+9wP7r3VF8Q2F4IMH7/9MEFT+tNY6MY7JtOTGXXz+IQSM2oEgwuraCjbW16HtDmAqBWEiWXhOu1TBUPXtmGYOCZCQ5vmEZcxYKr/vB9DQeOmll/DWW6cmyoaNGx/THx9eX+7hut0uAMDzzJLHvPLe7LQLA2Vzdw8JxJ5XWh02hGQM89k8HMcpwGyljOye47jEzO6YNvutLkLYIaLff/nll398c3Pz1zzfrQd+gLwJnSe7wg6ZpypDf9AHA9g9vwANLlgxaZoCjIKFi9KiGKtZPhTItRihidYCEEaFPye9stYIPA+pzQl7gz4eefghEIktO3CvVdT77la0AsIgRKfbxdLiIpTKiuiRLwvyPNfS22jEWMfDM7aXYAfRUAkrSRKkaYpKpRJgZM0O3XoDJKLsO9/5jvfoo49+9td+7f/91MKehb/oe77JB0u0fCKCFAJpmmFtY70oTIrVCUSFLIfnerZIQQFPm6pYFzR9KkE6AgSQYyscW02zAw0Nx2GIMMCpt76HXr+HJx57AoHvI7WtJfyxYTObwCAdB8+/8DxeevlbuP/+I9AqM8LqgiCFxK65Oezbt8/ALDY/3Lr5chS03k6Ijojg+z6klNp1PaGU/h2zU8fwAm7bVNzy8rJmZvHpT/+60Q622y9HVsJrA0e7rovQCYt54fJc6dY+bmmFljAxUlpFpiFGaJX4bTdFkIAGQ4CNZ9QMFkBYqWBxaRFf/epX8fjjj2NmZgZxHI/c+fi+nmYzSMLpt97CysoKHnzgIRy6/5C5oEJCSjNZ6LluMYXY7vfhex5c1x3ZTLXd9s7tZXxdbjbrWF/f+C4R8YsvviiQs6Bu11gmEelPferXzdoFZsAyosu60J7nwZUOpBDI8twhFy+3KxDE+FbIfC0CAyQJrushjmOEQQAppAm3AARbyIddkCuhdGZfX9uNj2YctNNr4/N/+Ie4//D9eODIEThCIvs+Vdwaqtib/Sxra2vIUoX3vvd9CIMAnW5nmAv2upCOBCsuZq2XVpZRqVZxYN8+xFFcpD25sxhZcUGX21TA+SBTgDu6LZNQiFezpsL4tKXy1CpVSzpVpsdriVq6kPYtbYSk8oZIu/GBAM/30Ov2sLq2hkqlUgDe2hpgvzcwujNgpGmGOIkQRxGSNEUSJ/A8D/cfOoSXvvUtdDqbePThR1GvN5CmaaHMWkxJ3eVFhuMYBYrllRV02m0EQQASAusbG4jDAFppSEnwvABSZFDa7G7p9ftwXAf1Wg2VahW9Xh+u66A/6INIIAyC4c65ogKhEfvbmi8TzP6qO72u1Uo0TMov2HZGSAgINqFRsFG01ENhmSGGCDKchOHtCN/z4TQdQ+nXCpkqb4okOI7AzMyU1TFmsxA7TZEpZWZMHAezs3NwpMTKygq+/JWv4NDB+3DPvn3wPA+ZyooVYXez4WmtsbyygqXFRbPUu1IxIdbz4EiJNDMrFNIsQdxtw3FcqExjMOijVqkiyRKEQYh+t4eu7iDJ0kKtthIEw33PxbW4cpF2M8Qpb4o6llaq2L1R3iuWb8wEabAQBipnBhODslyYctg5GdlhxsPvO1LCEXIo20vGCLVmeK6HWrU+worJyZYMM8qZxAZ/DPwAWabw6uuv4fzFCzh08BDm53fBcV0oZWQn7obQXDY8Zsba2houXLyIXq+HMAxQCY3xSSnR7XWwtLQEPwgRRRFqtYq5CZVCGFQgiJAps6W+P+hBK2B6agpKa3TabSRxYvr09nrhGqYOxfgq1Du1rpUEFbBLucQntrQqImjb5SBBEFoYIxrbobXd8ufhCpvRrebCjnMadQYCsTKyIKUdg0ZlwQVrCaUUHFdAOgLdbgcvvfwSpqZa2L//AHbN7TL7MIqpPb4jRpfneFmWYWVlBYuLi2h32mZOulKB73lmbNUWfYIEFuZ3w/O9wsjmdy2g3W5jqjVVPJfrOsgyhc32Jur1umFF2zxd23Zhzoq+UjZCQx2f5I4boNn74Q69WAmUzjFBtpNukGYOXTCDpTAXelxgMP9SEKC5vPoSNIza5f2lRtxSmx8KEqVq3HhZIoJ0HAgpjbFqQ3DVDGxsbmL9lZfQaDQxPzeP2dkZVCrVAkoqb4m8Gu84CWsr/1tul5XPU/7zQRRhbW0Vq6urZnbD3nS5QLiQDhzXhes4cB3HzMuQKJaAt5ot4z1tFaxZI3ACIxbgO5ifXwBrDT8MEIah5YxouEIgTdJigfZwSIlGAGwpJfd6Pefs2bP68OEHfhcA3nrrLX1HDFBbmCXfFcfjPcrSXc3Mpn9LgG3pgsnQ8DkvOvIPn/+93cCZF2RUIjyU98wVUwuFkZqBIK2HcnGazY0gHQmhnUKrxpGOUQJYX8OgPwADOHhvA57nFgxm3/dHIKTLwxU8cZn3EP4xxi9dWVzYKIqwubmJ9Y0NdNptpFkKISRc14PWGXr9LlrNKQS+jyDwLTvFhWOr2Pyslw05iWP0B30AZsWCFAIqUwV/UmllloeL4SjBPXvvgVKqeJ5cM8ZxHIRhmDsUcl03PXLkATcMK38KwDfuu+++2w/D5EVCfvdtaSqX7p4y9iaIoIUAMUM4EpyZAZjCwwnrRXl859voTl6trAJXLsmU7yvWuhBMMhW5qdKNBK0H1sLko0LCIWN8aZriicfejcfe9Riq1VphSHGcYGlpEa+//hpmZudQrVSKFlc5AR8xSNu9ycN4nsvlxqZUhn6UYDAYoNvpYrO9icFggCRNDbAsTasRbNjUg2gAAqFWq8F1HIBtoWX7stp+TrKaPFqZnHd5daWgsYEIzz//PD70oQ9hqjVlZn7tMHq9VsdnfvczOHDgXuzft79QpF3fWMfK6qoJ4WmKSqWKPbt3F+29arUKIrh3OASXRvloWDjoHFLJJ68EQWDIRxMmg4VgARZ20SEYqTUcKUTpOanYIcdsVteYStcKYtq2U5H4lfVoeLhi1PQwGY4UloRu5h4818WHP/Rh7N17z1hf1Xi+PXv24tuvfBtf/epXEIYBvCBAaB+e58PzPNPJsbkbrNKrZxVhkyTFxsY6oniAbqeHTncTnh9Aa0PbNx0jCddzRzr6+aJYbVeaASZlyJSGW+hpC7jCged52Nhcw9e//RIEEQ7ddwh79uwpVtWGYYgnHn8cZ94+jSM/crgQeqpWq3jxm99ApVrF+973XkSDCEIS+v0+lFL4gSd+AAsLC1hcXMQXvvgFCCLcc889xc0tpXNnYRhhlzgzixHFfCoZpyjhfAUTw3qM3ACF1kjSFPVGA77vo9vpIkvTkf5k/pW2utKO6xUiRkWHhMm+IG1JA6JoYNkg9meCkSQKjz35Huzde09xcwz7o8PdaR/96I/i1VdfRRz3EcepUXOAuQhJkgBM8HwPvusirFRRqVQQhiHCIIDWjM89/wc4f+EcXNdFr9dDtarQaDTNYkDO9+1Z8q5Vj4W0MnWuhFKMJ554N6anZra9Fu+cPYPf/b3fw549u1Gr1lAelel2unjyyScRDQaI4xiBxf3eeecdnD59Gj/ykR9BHMWWKpdAM+PdTzyJZrMJANi3bz+CIMD65gbmdu2C73lGmupuqIIdmxQbiV5bYBSE09xQbRXMbHIOzQYbtGQCpRSeePwHcODAARAR3njjdXzla1/FzNQ0FJfK5HzXiFXOyq0sF0DKf66t1yMQXN8YapZlUNqEHlgZ2laziXsPHNymBzrM4TzXwxOPP3Hdle3U9BQuXDyPMAyhlDLi7VqPMPqovHePAGnljJXWmJ3dhcAPkaap3SygbRhOEMeGGPDdN143z2YpVhCieHZHSvR7fUgp8a1vvQjP89CcaqHd7uAHP/SDCIMAqW2nCungwQePoNlsFjdlHMdQSuWrNRiAs7GxTr5f+XUA+IVf+IU7U4QoMNbbm8jSDFOtlik2SonbiMezOZrWuthBLqVEmiQ4cOAA7r33XkRRBK013njzDZw+fRozM9MgVWJukBmUVpY2LoRjJTzMtk0hTRiUjkng0yTBqbdOQWuFIAzgux7AZuouVQqzM7NXNSjEZVznGjiGuQGvrq6CJBVKsFnGExYbl4ZUpYArHWQqK7ZHPX/ic0jiyBgYE4SNKEVuLSU+9MEPwQ8CuJ6HNE0AGl4PIkKSJJidncXa2hqIBB56+CFIEkiz1GCBzJidmUWrNTXSUHjt9VfBzJiZnoHjSDbXlTpBEFxkZjp27BjfEQOUIKwsL2N5ZQXvfvwJhEEApYdvfBANkCSp6R2SgOf7hinNZJdZm07HyddexZe+8iUwm/xuEEWYmZmxWzNFaYs6gxyJfmcD+/cfwLseeQxCkAVlXUgpxkgTi/j8509gZm4G1XqtYAKDTcFTqVSuYZELTdCYwhXhmZMnT2J5eRnVsFZ4KLMXTwy3y9sUhWA8n3DMFvo0TaG1ydWazSYECNLxIGQp7QCNSNYxA71+F0liDLe8ycBxHBw6dAiHjxxGphRSGxXyvxdCFlrc+Wd68803cPbcOey/x3SOBAk1PT3jttudv7x3794VZpbPPvusumMh+PDhI3jkoUeMm7ahLEkSrKwsm22ZaQKltcGtXBeNesO0lko6w7ksmHTMCag36vD9oCgUkPfFlYZiDd8PsWt2DvV6fcQLqSwrSA9aa5y/cMEKXVbhCgeZVpC56QhCmmZbqvTx/8+ydGSN/TgZXmsuCJpxEqPX66Ld7qDb6WB1Yx3r6+uF+igrjUyl8IMQJAV0Toqw+/aM9zbGJx1ZQE9JbNjIWaagVc+kGEpDQYPVUBIvf75ms1loPCulhgw/ZsRJUsxqF7OwxQAZMBhEBfx04eJ5nD3/DvYs7M4XWWdT09Nut9v9vw8fPvyp48eP3xAN6yYYIBtXb9tjBEKmFZIkwaOPPIbZuVlEUYSTr57ExUsXoYmwvrGOVrNlNGOsfNv09DSmW1PIbH6jc63B3BAEAMXQZHbQua6LV197FW+8+aa5MMruHckypKkpEpLUhK/pmWkz/aWyEU9hesPLYNYWpxylJgHAKydfwffefAN+4MMRTjGTAhgQPbMGn2aJzZN0AbUIIeE4jiEM2B7rIE0ACNSqVUCb/jnnOZ9dd+G4LhwLMgtHIggDtDsdtLvdke2hnLc0mQqwgDVjYX5+xLMrpZDkxIvtVlxaT5qpFFHUwzvvnIFSGZIkxdzsPFSWQmularW6097c/GePPvrYX2Nm8YlPfELf0SKEmXlE95lMjvfYY4+j2WzZUr+GD//gh/GVr30FFy5cgJYS7W4HrXqjCD8qM3MeSmtwZnG8YbS0QF9eZGgIx8Fmu43IgqSi1MJyPRe+7xt1KkEFEzjXFcyhISklNjubePnbL+OBIw+WhrBNd+TNN97Em2+9ASLDd+QchM4hEi51CghwHRe+Z0YPkDO3SQBsvHaSpIjjBK1Wq1j2kvMfhRwan+e68HzPZIN6uL9XK81EpIVJM8yrENkVZyh2vbVarZGOi5QSARHiJLHdl2H6QDnxQLMB/WF0AzOt4TmuUahNUmit0lqt5iql/uDRRx/7q1aKQ13vGOZNM0DP8zwi0mQtJcsUmvUmms1WEcYMNUvi0Ucexfnz58HMyFJLFSpN0Ak2CbMWhiVYxvXKmXqeK01PT+dYiRmusb+b437599hiYY4FcYd0I1PBv/nmG3j77bdQrzXgSAfdfteoxTMhDIIRPJKGkOSII9E5lcmGMZ2/vkqgNBuiQ6bQbDULz597RSGlIVtIWYC8UhjKWSUMDXQEylzPdSqViiSYIixNEy2FMGfL9uJ93x8ldOQohJRwXRdJnJhzIgyRitjitOVcEcBgMOAIAxARa2bVarZcrfn5hx565MefeeYZ8dRTT90047shA5ydnnlHay00mRG0/I4bH1DKIZGcJzhU0R9tbhcqnfnE1rC1YHq8kuGSBzAjGgwKbzRCq9Y5m3qYqgkYGdryvDLb1orrmH7p6vqayR0td5FIQmX27dhuwrjGDVmDz7SCdByQLt0ApY6Q53mQobROnIumv7CjqtIaXlml3hUCvj8NR0g0mk1nZW11HRpfl5JoEEW76/X6owDYkZLKvWae3JtmKSVLR0JnGQzaaN9jec2azQVd6ThCCGgwzU1Pi5WV1f/rfe95339rVfDpZhrfdRngiRMnNDNTt9v9p9998/W/wOA9RJQJIZwoitBut4t50vyCvXP2HROSazX4jltMWJW3rtsRdTCRWWCjbX/XqmOZX5FQbMYy86F3lCA1I7BA5UAzTLpzX6p5rOAQ8Dw57NyM78QYousYrt2mIscSbPFvKSBprDrmElSTM3SKgsMYmyOdwgtKKa2SmGDHcbTWKovjwT+Zn2v80wMHHrqQP/dvfPrXf7vVbH58ZnpGEZEswq7dolXmZDqOIz3fI9/3MYgGEFIKKQ0ITnbbVV5WSyGwtLSUAtSpVCu97sbm//n+977/H+TCVDfb+HC9VGArRqiZ+cgrr7zyPEnsTeMkA4QThiFmZ2dRrVbADFy4eAGvvvYq6rWaATtLDIv8YXq4usD4lNaAtsB13uUoQSCadQZmhwtsxSyyFWXlxTys0FiftjSTUoZB8j8RI2x0ysdTimyASv0ZpRTAYDM8ZWlmTMWsKzMrAnGRVcCA8FJIuFJCuq7BLaUD1zFfS0cSgWj37t2y0+v94yP3H/kbAHDu3Ll9a2tr81/72h9Fvl/9acdz/9b83K5sdnbWyT+T1lpXKqFQWgFMCMMQa2vrm1mWnQnDkGv1Oi0vLf/u5ubaaTfwyPdD9h0XQVBBrRbq2dlZcenS8hcvXrz49sGDB9XevXv7t8rwbngmxBrhGysrKx949fVXj81Mtf5yFEVpFPXdS5cuglkjihMkaYKFXbtMD1Hpoo01EiZyjpktapgILHOtLC5yGwaBWetGre5EUYQgCJgB1qxFmqVIosRijTzMEXN6F+feb+jprPExmTZzaRv9iDJoEajKvWbNGkopCisVWc4ti0CoGbVazRE2/JuQa0gA0nXsThRhAXQbji1zKE1TLC+vfOpd73rsfzx9+nRw7733xt/97qsf6HTbx5utGcRxhPX1dVQqFWdmdiY3PtVoNGSSpF/cWN/4R1rTxgMPzFOzOfW96enpd67nOr/wwgvO9aie3nIPOO4JzZv93C/Ozc39XL/fTx3HdT3XBQRBaYU0TuyaBcthUdqsbdAaWhnIJVc60FoXibG25mJWPhC0Vtxs1EkK+UuNRuufPPDAA712e1leurTyxKWlxb+XJeqBVGcgZjGS85nAqnImtaH1s1BKQzpSVMMK9HAkKofFTAHjuoC06v1kDMmsNzDb3dfW1i55rseua7yY6zpwXM9CPavPKZV1giCgSqXGYRjC8zwz31JiyWitkekMjnBARLrX6/3bRx999NU89OXX6Utf+uK/l474U2EYKkCwVoUCArdaLTeKBr/6wAMP//QkXcf8Zj9+/LiYm5sbue5PPfXUONOOcy1w3CaJkRsyQivRqr7whRc+2WpN/2y/30/tEDvpYu7DuKqcdVwe4bRcO1ZK5f6GiEhoO6nPmnWaZapWrfnzuxb+h0ceeeTvj7+Pr3/96//rmbNv/03XdRWxFcshAc2KBRHVqrWhYWuzzb1Wq6E/GPT7vf7LjuuQ53rs+x5cz+VKpUasdfvMmXd+RQYeGmGAIAhQrTbghR5mp2ahtR587Wtf+539+/fzI488MilSJDd4bovwd/z4cfn000+rr3/9qz/v+/4/C4LALABXyi533Pw3TzzxxE8dP35czs3N0fLyMn/iE58AcIyJnr3zSp63ygDzE3XixAl59OjR7Mtf/uIvViqVn+v2uixIKJipEGZmCjxfmuhk8z9liKEqM3spPM+0gpI0QRRFBjPTGkIK7No1j16/+yvvf+8H//yXvvSl8IMf/GD81a9+9d0rKyv/cml1CYEXPLa6toL5+XlUgtCqAzC7jkuu53VUlv1mUAnU3MwuwYxzKysrv/ne975XVCqVFSI6dStO7jPPPOPs2bOHAODJJ5+86r978sknc6iDJ00pnD59+gOrqys/2263aW5uhjzP+70HHnj416wz4Nvhue44DDNhbYM6fvy4/OAHf/DnX3nl21klrPxcEAQOG5F/AITFpUvnmCmVjmP6uI4LKUhXpmui1+u+vbS09PtaazRajfv37rnnTyZJknme56ysrHw5S9NX3veeD/w/zzzzjPjgBz+YHDt2DD/1Uz+1FEW9XQrTC4uXFlWjXpeCzMovVsgCP3BA9NbDDz1ydO/eve9cTnh9u5899dRTYpvv48SJEzj61FFV3hw/riRxk68XHz9+XB48ePArAL4yKTcHvg+X59zE4RrKFdM7nc5jm73Ne9fX13mq3iDfr/B3vtP9D0ePHoxukncRzz77rO52u7tff/3V39vY3HhXv9fXQgiRqow916VWsxXP7Jr78QcPP/i7n/nMZ3yTOxUKDwyYbd/fbxeOmcWJEydE6WbIP8POWvkreZTL3Qyf/OQn3U9+8pPu8ePH5fjzvfjii+74Jp5cHm5jY2PqxRdf/D++/OUv6t/8rU+nL7zwOfXKKy9/58yZM382r+Z2rsrOsXPsHDvHzrFz7Bw7x86xc+wcO8fOsXPsHDvHzrFz7Bw7x86xc+wcO8fOcXuP/x+6OyyiQTZl7wAAAABJRU5ErkJggg==",BoilerInterface:"data:image/png;base64,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"};const b3="data:image/svg+xml,"+encodeURIComponent(''),w3=Object.assign({},m3);const A3={autoResize:!0,height:"100%",nodes:{shape:"box",color:{background:"#edf2f8",border:"#c9d5e4",highlight:{background:"#dce9f8",border:"#5288bd"}},font:{size:14,face:"system-ui, sans-serif",color:"#26364a"},margin:{top:14,bottom:14,left:18,right:18},widthConstraint:{minimum:100,maximum:160},borderWidth:1,shapeProperties:{borderRadius:12}},groups:{Controller:{color:{background:"#dceee6",border:"#91bba7"}},RoomStat:{color:{background:"#eee6f2",border:"#c9b3d5"}},iTRV:{color:{background:"#f7eadc",border:"#d9bc98"}},SmartPlug:{color:{background:"#dceef0",border:"#94bec4"}},HeatingActuator:{color:{background:"#e1e9fa",border:"#aabce0"}},UnderFloorHeating:{color:{background:"#e1e9fa",border:"#aabce0"}},Shutter:{color:{background:"#e7ebef",border:"#b4bec9"}},OnOffLight:{color:{background:"#f5efd9",border:"#d6c68e"}},DimmableLight:{color:{background:"#f5efd9",border:"#d6c68e"}}},edges:{arrows:{to:{enabled:!0,scaleFactor:.45}},color:{color:"#8a9bac",highlight:"#5288bd",hover:"#5288bd",inherit:!1},smooth:{enabled:!0,type:"cubicBezier",forceDirection:"horizontal",roundness:.45},width:1.5,font:{align:"horizontal",color:"#66788a",size:11,face:"system-ui, sans-serif",strokeWidth:0}},interaction:{hover:!0,dragView:!0,dragNodes:!0,selectConnectedEdges:!0,zoomView:!0,keyboard:!1},physics:{enabled:!1}};const E3="data:image/svg+xml,"+encodeURIComponent('');async function k3(t,e,i){const o=i||(await t.callWS({type:"wiser/hubs"}))[0];if(!o)return;const[n,r]=await Promise.all([t.callWS({type:"config/entity_registry/list"}),t.callWS({type:"config/device_registry/list"})]),s=new Set(r.filter((t=>t.identifiers.some((([t,e])=>"wiser"===t&&e===o)))).map((t=>t.id))),a=n.filter((i=>{if("wiser"!==i.platform||!i.entity_id.startsWith("sensor."))return!1;const n=t.states[i.entity_id],a=null==n?void 0:n.attributes;if(!a||null==a.node_id||Number(a.node_id)!==e.id||void 0===a.displayed_signal_strength)return!1;if("Controller"!==e.group&&a.product_type!==e.group)return!1;const l=r.find((t=>t.id===i.device_id));return!!l&&(s.has(l.id)||null!=l.via_device_id&&s.has(l.via_device_id)||l.identifiers.some((([t,e])=>"wiser"===t&&e.startsWith(`${o} Wiser `))))}));return 1===a.length?a[0].entity_id:void 0}function C3(t,e){const i=t=>"number"==typeof t&&Number.isFinite(t);return 0===t&&0===e?{}:{rssi:i(t)?t:void 0,lqi:i(e)?e:void 0}}function x3(t,e="horizontal",i,o="none"){var n,r;const s=new Map,a=t.nodes.filter((t=>"Controller"===t.group)),l=(a.length?a:t.nodes.slice(0,1)).map((t=>t.id));l.forEach((t=>s.set(t,0)));for(let e=0;e"Area"!==t.group)),s=new Map(r.map((t=>[t.id,t]))),a=new Map,l=new Map;for(const e of r){const o=t.edges.find((t=>t.from===e.id&&s.has(t.to)&&i.has(t.to)&&i.has(e.id)&&i.get(t.to){var i;const o=c.get(t);if(o)return o;const n=null!==(i=a.get(t))&&void 0!==i?i:[],r=Math.max(e?115:65,4*d(s.get(t).label).length+30),l=Math.max(0,...n.map((t=>f(t).radius))),u=n.length?Math.max(r+l+h,n.length>1?(l+h/2)/Math.sin(Math.PI/n.length):0):0,p={radius:u+(n.length?l:r),orbit:u};return c.set(t,p),p},p=[],v=(t,e,i,n)=>{var r;p.push(Object.assign(Object.assign({},s.get(t)),{x:e,y:i}));const l=[...null!==(r=a.get(t))&&void 0!==r?r:[]],h=null==o?void 0:o[t],c=t=>{const e=null==o?void 0:o[t];if(e&&h)return((Math.atan2(e.y-h.y,e.x-h.x)-n)%(2*Math.PI)+2*Math.PI)%(2*Math.PI)};l.sort(((t,e)=>{const i=Number(a.has(e))-Number(a.has(t));if(i)return i;const o=c(t),n=c(e);return void 0!==o&&void 0!==n&&Math.abs(o-n)>1e-6?o-n:s.get(t).label.localeCompare(s.get(e).label)})),l.forEach(((o,r)=>{const s=n+2*r*Math.PI/l.length,a=f(t).orbit;v(o,e+Math.cos(s)*a,i+Math.sin(s)*a,s)}))},g=r.filter((t=>!l.has(t.id))).sort(((t,e)=>Number("Controller"===e.group)-Number("Controller"===t.group)||t.label.localeCompare(e.label)));let y=0;if(g.forEach(((t,e)=>{const i=f(t.id).radius,o=e?y+i+h:0;v(t.id,o,0,0),y=o+i})),e)for(const[t,e]of a){const i=p.find((e=>e.id===t)),o=(t,e=t.x,i=t.y)=>{const o=d(t.label),n=Math.max(40,4.5*o.length+12);return{left:e-n,right:e+n,top:i-42,bottom:i+72}},n=(t,e)=>t.lefte.left&&t.tope.top;for(const t of e.filter((t=>!a.has(t)))){const r=p.find((e=>e.id===t));if(!r.area_id)continue;const l=e.filter((t=>a.has(t)&&s.get(t).area_id===r.area_id)).map((t=>p.find((e=>e.id===t)))).sort(((t,e)=>Math.hypot(t.x-r.x,t.y-r.y)-Math.hypot(e.x-r.x,e.y-r.y)));let h=!1;for(const t of l){const e=Math.atan2(t.y-i.y,t.x-i.x),s=Math.max(150,(o(t).right-o(t).left+o(r).right-o(r).left)/2+20),l=[0,1,2,3].map((t=>({inward:s+90*t,side:65})));for(let t=1;t<5;t++)for(const e of[1,0,2])l.push({inward:s+90*e,side:65+130*t});for(const s of l){if(h)break;for(const l of[1,-1]){const c=s.inward,d=l*s.side,u=t.x-Math.cos(e)*c-Math.sin(e)*d,f=t.y-Math.sin(e)*c+Math.cos(e)*d,v=o(r,u,f);if(p.some((t=>t.id!==r.id&&("Controller"===t.group||a.has(t.id)||t.area_id===r.area_id)&&n(v,o(t)))))continue;const g=o(t),y={left:Math.min(v.left,g.left)-18,right:Math.max(v.right,g.right)+18,top:Math.min(v.top,g.top)-110,bottom:Math.max(v.bottom,g.bottom)+18};if(!n(y,o(i))){r.x=u,r.y=f,h=!0;break}}}if(h)break}}}for(const e of t.nodes.filter((t=>"Area"===t.group))){const t=p.filter((t=>{var i,o;return"Controller"!==t.group&&(null!==(i=t.area_id)&&void 0!==i?i:"")===(null!==(o=e.area_id)&&void 0!==o?o:"")}));p.push(Object.assign(Object.assign({},e),{x:t.length?(Math.min(...t.map((t=>t.x)))+Math.max(...t.map((t=>t.x))))/2:0,y:t.length?Math.min(...t.map((t=>t.y)))-110:0}))}return e&&u(p,new Set(a.keys())),{nodes:p,edges:t.edges.map((t=>Object.assign({},t)))}}(t,"area"===o,s,i);const h=new Map,c=Math.max(0,...s.values())+1;for(const e of t.nodes){if("Area"===e.group)continue;const t=null!==(n=s.get(e.id))&&void 0!==n?n:c;h.set(t,[...null!==(r=h.get(t))&&void 0!==r?r:[],e])}const f=[];for(const[n,r]of[...h].sort((([t],[e])=>t-e))){const s="vertical"===e?"x":"y";r.sort(((e,o)=>{var n,r;const a=e=>{var i,o,n;const r=null===(i=t.edges.find((t=>t.from===e)))||void 0===i?void 0:i.to;return null!==(n=null===(o=f.find((t=>t.id===r)))||void 0===o?void 0:o[s])&&void 0!==n?n:0},l=a(e.id)-a(o.id);if(l)return l;const h=null===(n=null==i?void 0:i[e.id])||void 0===n?void 0:n[s],c=null===(r=null==i?void 0:i[o.id])||void 0===r?void 0:r[s];return Number.isFinite(h)&&Number.isFinite(c)&&h!==c?h-c:e.label.localeCompare(o.label)})),r.forEach(((t,i)=>{let s=i-(r.length-1)/2;f.push(Object.assign(Object.assign({},t),{x:"vertical"===e?s*("area"===o?230:170):n*("area"===o?300:270),y:"vertical"===e?n*("area"===o?300:150):s*("area"===o?260:110)}))}))}for(const e of t.nodes.filter((t=>"Area"===t.group))){const t=f.filter((t=>{var i,o;return"Controller"!==t.group&&(null!==(i=t.area_id)&&void 0!==i?i:"")===(null!==(o=e.area_id)&&void 0!==o?o:"")}));f.push(Object.assign(Object.assign({},e),{x:t.length?(Math.min(...t.map((t=>t.x)))+Math.max(...t.map((t=>t.x))))/2:0,y:t.length?Math.min(...t.map((t=>t.y)))-110:0}))}return{nodes:f,edges:t.edges.map((t=>Object.assign({},t)))}}const S3=t=>{class i extends t{connectedCallback(){super.connectedCallback(),this.__checkSubscribed()}disconnectedCallback(){if(super.disconnectedCallback(),this.__unsubs){for(;this.__unsubs.length;){const t=this.__unsubs.pop();t instanceof Promise?t.then((t=>t())):null!=t&&t()}this.__unsubs=void 0}}updated(t){super.updated(t),t.has("hass")&&this.__checkSubscribed()}hassSubscribe(){return[]}__checkSubscribed(){void 0===this.__unsubs&&this.isConnected&&void 0!==this.hass&&(this.__unsubs=this.hassSubscribe())}}return e([Ut({attribute:!1})],i.prototype,"hass",void 0),i};var I3={"common.version":"Version","card.title":"Zigbee network","card.description":"An interactive map of your Wiser Zigbee network","card.hub":"Wiser Hub","card.devices_one":"{count} device","card.devices_other":"{count} devices","card.connections_one":"{count} connection","card.connections_other":"{count} connections","card.controls":"Network controls","card.fit":"Fit view","card.tidy":"Tidy layout","card.link_labels":"Link labels","card.save_layout":"Save layout","card.load_error":"Unable to load the network. Try refreshing.","card.updating":"Updating network…","card.empty":"No devices found","card.unknown_device":"Unknown device","card.hint":"Double-click to zoom in or out. Drag to rearrange. Tap a device for Zigbee details. Long-press for More info.","map.accessible_only":"Interactive Zigbee network map. Double-click a device or empty area to zoom in, and double-click again to zoom out. Drag to rearrange. Tap a device for Zigbee details. Long-press for More info.","map.accessible_list":"Interactive Zigbee network map. Device and connection details are available in the list below. Tap a device for Zigbee details. Long-press for More info.","map.accessible_details":"Interactive Zigbee network map. Tap a device for Zigbee details. Long-press for More info.","layout.storage_error":"Browser storage unavailable. Copy the layout into your card configuration.","layout.device_list":"All devices & connections","editor.auto_update":"Auto refresh","editor.show_device_list":"Show all devices & connections","editor.orientation":"Network view","editor.loading":"Loading Home Assistant controls…","signal.connected":"Connected","signal.online":"Online","signal.offline":"Offline","signal.no_signal":"No signal","signal.very_good":"Very good","signal.good":"Good","signal.poor":"Poor","zigbee.type":"Device type","zigbee.node":"Zigbee node ID","zigbee.parent":"Parent node ID","zigbee.channel":"Zigbee channel","zigbee.signal":"Signal quality","zigbee.device_rssi":"Device RSSI","zigbee.device_lqi":"Device LQI","zigbee.hub_rssi":"Hub RSSI","zigbee.hub_lqi":"Hub LQI","editor.map_height":"Map height","card.show_detailed_view":"Show detailed view","card.zoom_in":"Zoom in","card.zoom_out":"Zoom out","editor.group_by":"Group","card.unassigned_area":"Unassigned","editor.show_labels":"Show link labels","editor.link_status":"Link status","editor.links":"Links","editor.both":"Both","signal.medium":"Medium","layout.config_save_error":"Unable to save this card’s configuration. Use the card editor to save, or copy the layout YAML for a YAML dashboard.","editor.magnifier":"Magnifying glass","editor.lens_size":"Lens size","layout.copy_error":"Unable to copy the layout. Check clipboard permissions and try again.","panel.menu":"Toggle sidebar","panel.settings":"Panel settings","panel.description":"Customize this panel. Dashboard cards keep their own settings.","panel.editor_error":"Unable to open the editor. Close this dialog and try again.","panel.save_error":"Unable to save settings to Home Assistant. Please try again."};const M3={"en-US":I3,"en-GB":{"common.version":"Version","card.title":"Zigbee network","card.description":"An interactive map of your Wiser Zigbee network","card.hub":"Wiser Hub","card.devices_one":"{count} device","card.devices_other":"{count} devices","card.connections_one":"{count} connection","card.connections_other":"{count} connections","card.controls":"Network controls","card.fit":"Fit view","card.tidy":"Tidy layout","card.link_labels":"Link labels","card.save_layout":"Save layout","card.load_error":"Unable to load the network. Try refreshing.","card.updating":"Updating network…","card.empty":"No devices found","card.unknown_device":"Unknown device","card.hint":"Double-click to zoom in or out. Drag to rearrange. Tap a device for Zigbee details. Long-press for More info.","map.accessible_only":"Interactive Zigbee network map. Double-click a device or empty area to zoom in, and double-click again to zoom out. Drag to rearrange. Tap a device for Zigbee details. Long-press for More info.","map.accessible_list":"Interactive Zigbee network map. Device and connection details are available in the list below. Tap a device for Zigbee details. Long-press for More info.","map.accessible_details":"Interactive Zigbee network map. Tap a device for Zigbee details. Long-press for More info.","layout.storage_error":"Browser storage unavailable. Copy the layout into your card configuration.","layout.device_list":"All devices & connections","editor.auto_update":"Auto refresh","editor.show_device_list":"Show all devices & connections","editor.orientation":"Network view","editor.loading":"Loading Home Assistant controls…","signal.connected":"Connected","signal.online":"Online","signal.offline":"Offline","signal.no_signal":"No signal","signal.very_good":"Very good","signal.good":"Good","signal.poor":"Poor","zigbee.type":"Device type","zigbee.node":"Zigbee node ID","zigbee.parent":"Parent node ID","zigbee.channel":"Zigbee channel","zigbee.signal":"Signal quality","zigbee.device_rssi":"Device RSSI","zigbee.device_lqi":"Device LQI","zigbee.hub_rssi":"Hub RSSI","zigbee.hub_lqi":"Hub LQI","editor.map_height":"Map height","card.show_detailed_view":"Show detailed view","card.zoom_in":"Zoom in","card.zoom_out":"Zoom out","editor.group_by":"Group","card.unassigned_area":"Unassigned","editor.show_labels":"Show link labels","editor.link_status":"Link status","editor.links":"Links","editor.both":"Both","signal.medium":"Medium","layout.config_save_error":"Unable to save this card’s configuration. Use the card editor to save, or copy the layout YAML for a YAML dashboard.","editor.magnifier":"Magnifying glass","editor.lens_size":"Lens size","layout.copy_error":"Unable to copy the layout. Check clipboard permissions and try again.","panel.menu":"Toggle sidebar","panel.settings":"Panel settings","panel.description":"Customise this panel. Dashboard cards keep their own settings.","panel.editor_error":"Unable to open the editor. Close this dialogue and try again.","panel.save_error":"Unable to save settings to Home Assistant. Please try again."},de:{"common.version":"Version","card.title":"Zigbee-Netzwerk","card.description":"Eine interaktive Karte Ihres Wiser-Zigbee-Netzwerks","card.hub":"Wiser Hub","card.devices_one":"{count} Gerät","card.devices_other":"{count} Geräte","card.connections_one":"{count} Verbindung","card.connections_other":"{count} Verbindungen","card.controls":"Netzwerksteuerung","card.fit":"Ansicht einpassen","card.tidy":"Layout anordnen","card.link_labels":"Verbindungsbeschriftungen","card.save_layout":"Layout speichern","card.load_error":"Das Netzwerk konnte nicht geladen werden. Bitte aktualisieren.","card.updating":"Netzwerk wird aktualisiert…","card.empty":"Keine Geräte gefunden","card.unknown_device":"Unbekanntes Gerät","card.hint":"Zum Vergrößern oder Verkleinern doppelklicken. Zum Anordnen ziehen. Für Zigbee-Details auf ein Gerät tippen. Für weitere Informationen gedrückt halten.","map.accessible_only":"Interaktive Zigbee-Netzwerkkarte. Zum Vergrößern auf ein Gerät oder eine freie Stelle doppelklicken, zum Verkleinern erneut doppelklicken. Zum Anordnen ziehen. Für Zigbee-Details auf ein Gerät tippen. Für weitere Informationen gedrückt halten.","map.accessible_list":"Interaktive Zigbee-Netzwerkkarte. Geräte- und Verbindungsdetails stehen in der Liste darunter. Für Zigbee-Details auf ein Gerät tippen. Für weitere Informationen gedrückt halten.","map.accessible_details":"Interaktive Zigbee-Netzwerkkarte. Für Zigbee-Details auf ein Gerät tippen. Für weitere Informationen gedrückt halten.","layout.storage_error":"Browserspeicher nicht verfügbar. Kopieren Sie das Layout in Ihre Kartenkonfiguration.","layout.device_list":"Alle Geräte und Verbindungen","editor.auto_update":"Automatisch aktualisieren","editor.show_device_list":"Alle Geräte und Verbindungen anzeigen","editor.orientation":"Netzwerkansicht","editor.loading":"Home-Assistant-Steuerelemente werden geladen…","signal.connected":"Verbunden","signal.online":"Online","signal.offline":"Offline","signal.no_signal":"Kein Signal","signal.very_good":"Sehr gut","signal.good":"Gut","signal.poor":"Schwach","zigbee.type":"Gerätetyp","zigbee.node":"Zigbee-Knoten-ID","zigbee.parent":"Übergeordnete Knoten-ID","zigbee.channel":"Zigbee-Kanal","zigbee.signal":"Signalqualität","zigbee.device_rssi":"Geräte-RSSI","zigbee.device_lqi":"Geräte-LQI","zigbee.hub_rssi":"Hub-RSSI","zigbee.hub_lqi":"Hub-LQI","editor.map_height":"Kartenhöhe","card.show_detailed_view":"Detailansicht anzeigen","card.zoom_in":"Vergrößern","card.zoom_out":"Verkleinern","editor.group_by":"Gruppieren","card.unassigned_area":"Nicht zugewiesen","editor.show_labels":"Verbindungsbeschriftungen anzeigen","editor.link_status":"Verbindungsstatus","editor.links":"Verbindungen","editor.both":"Beides","signal.medium":"Mittel","layout.config_save_error":"Die Kartenkonfiguration konnte nicht gespeichert werden. Speichere im Karteneditor oder kopiere das Layout-YAML für ein YAML-Dashboard.","editor.magnifier":"Lupe","editor.lens_size":"Lupengröße","layout.copy_error":"Das Layout konnte nicht kopiert werden. Prüfe die Berechtigungen für die Zwischenablage und versuche es erneut.","panel.menu":"Seitenleiste umschalten","panel.settings":"Panel-Einstellungen","panel.description":"Dieses Panel anpassen. Dashboard-Karten behalten ihre eigenen Einstellungen.","panel.editor_error":"Der Editor konnte nicht geöffnet werden. Schließe den Dialog und versuche es erneut.","panel.save_error":"Einstellungen konnten nicht in Home Assistant gespeichert werden. Bitte versuche es erneut."},fr:{"common.version":"Version","card.title":"Réseau Zigbee","card.description":"Une carte interactive de votre réseau Zigbee Wiser","card.hub":"Hub Wiser","card.devices_one":"{count} appareil","card.devices_other":"{count} appareils","card.connections_one":"{count} connexion","card.connections_other":"{count} connexions","card.controls":"Commandes du réseau","card.fit":"Ajuster la vue","card.tidy":"Réorganiser la disposition","card.link_labels":"Libellés des connexions","card.save_layout":"Enregistrer la disposition","card.load_error":"Impossible de charger le réseau. Essayez de l’actualiser.","card.updating":"Actualisation du réseau…","card.empty":"Aucun appareil trouvé","card.unknown_device":"Appareil inconnu","card.hint":"Double-cliquez pour zoomer ou dézoomer. Faites glisser pour réorganiser. Appuyez sur un appareil pour afficher ses détails Zigbee. Maintenez-le enfoncé pour afficher Plus d’informations.","map.accessible_only":"Carte interactive du réseau Zigbee. Double-cliquez sur un appareil ou une zone vide pour zoomer, puis à nouveau pour dézoomer. Faites glisser pour réorganiser. Appuyez sur un appareil pour afficher ses détails Zigbee. Maintenez-le enfoncé pour afficher Plus d’informations.","map.accessible_list":"Carte interactive du réseau Zigbee. Les détails des appareils et des connexions figurent dans la liste ci-dessous. Appuyez sur un appareil pour afficher ses détails Zigbee. Maintenez-le enfoncé pour afficher Plus d’informations.","map.accessible_details":"Carte interactive du réseau Zigbee. Appuyez sur un appareil pour afficher ses détails Zigbee. Maintenez-le enfoncé pour afficher Plus d’informations.","layout.storage_error":"Stockage du navigateur indisponible. Copiez la disposition dans la configuration de votre carte.","layout.device_list":"Tous les appareils et connexions","editor.auto_update":"Actualisation automatique","editor.show_device_list":"Afficher tous les appareils et connexions","editor.orientation":"Vue du réseau","editor.loading":"Chargement des commandes Home Assistant…","signal.connected":"Connecté","signal.online":"En ligne","signal.offline":"Hors ligne","signal.no_signal":"Aucun signal","signal.very_good":"Très bon","signal.good":"Bon","signal.poor":"Faible","zigbee.type":"Type d’appareil","zigbee.node":"ID du nœud Zigbee","zigbee.parent":"ID du nœud parent","zigbee.channel":"Canal Zigbee","zigbee.signal":"Qualité du signal","zigbee.device_rssi":"RSSI de l’appareil","zigbee.device_lqi":"LQI de l’appareil","zigbee.hub_rssi":"RSSI du hub","zigbee.hub_lqi":"LQI du hub","editor.map_height":"Hauteur de la carte","card.show_detailed_view":"Afficher la vue détaillée","card.zoom_in":"Zoom avant","card.zoom_out":"Zoom arrière","editor.group_by":"Grouper","card.unassigned_area":"Non attribué","editor.show_labels":"Afficher les libellés des liaisons","editor.link_status":"État des liaisons","editor.links":"Liaisons","editor.both":"Les deux","signal.medium":"Moyenne","layout.config_save_error":"Impossible d’enregistrer la configuration de cette carte. Utilisez l’éditeur de carte ou copiez le YAML de disposition pour un tableau de bord YAML.","editor.magnifier":"Loupe","editor.lens_size":"Taille de la loupe","layout.copy_error":"Impossible de copier la disposition. Vérifiez les autorisations du presse-papiers et réessayez.","panel.menu":"Afficher ou masquer la barre latérale","panel.settings":"Paramètres du panneau","panel.description":"Personnalisez ce panneau. Les cartes du tableau de bord conservent leurs propres paramètres.","panel.editor_error":"Impossible d’ouvrir l’éditeur. Fermez cette boîte de dialogue et réessayez.","panel.save_error":"Impossible d’enregistrer les paramètres dans Home Assistant. Veuillez réessayer."}},O3={"panel.cancel":"ui.common.cancel","panel.retry":"ui.common.retry","common.copy":"ui.common.copy","common.copied":"ui.common.copied","common.saved":"ui.common.successfully_saved","editor.icons":"ui.panel.lovelace.editor.features.types.climate-preset-modes.style_list.icons","editor.pie":"ui.panel.lovelace.editor.card.energy-devices-graph.mode_options.pie","common.invalid_configuration":"ui.panel.lovelace.editor.condition-editor.visibility_status.invalid.headline","editor.none":"ui.common.none","editor.area":"ui.panel.lovelace.editor.card.area.name","common.refresh":"ui.common.refresh","common.close":"ui.common.close","common.save":"ui.common.save","common.title":"ui.panel.lovelace.editor.card.generic.title","common.loading":"ui.init.loading","editor.horizontal":"ui.panel.lovelace.editor.card.tile.content_layout_options.horizontal","editor.vertical":"ui.panel.lovelace.editor.card.tile.content_layout_options.vertical","signal.unknown":"state.default.unknown"},D3={"zigbee.type":"ui.panel.config.zha.visualization.device_type","card.unassigned_area":"ui.panel.config.automation.editor.unassigned","signal.medium":"ui.panel.config.matter.visualization.strength.medium","common.version":"ui.panel.config.zwave_js.visualization.version","card.empty":"ui.panel.config.zha.groups.no_devices_found","card.unknown_device":"ui.panel.config.integrations.config_entry.unknown_via_device","signal.connected":"ui.panel.config.serial.connected","signal.online":"ui.panel.config.zha.configuration_page.status_online","signal.offline":"ui.panel.config.zha.configuration_page.status_offline"};function R3(t){var e;const i=((null===(e=null==t?void 0:t.locale)||void 0===e?void 0:e.language)||(null==t?void 0:t.language)||("undefined"!=typeof document?document.documentElement.lang:"")||"en-US").replace(/_/g,"-").toLowerCase();return"en-gb"===i?"en-GB":"de"===i||i.startsWith("de-")?"de":"fr"===i||i.startsWith("fr-")?"fr":"en-US"}function B3(t,e,i={}){var o;const n=R3(e);let r;const s=O3[t]||D3[t];if(s){const i=null===(o=null==e?void 0:e.localize)||void 0===o?void 0:o.call(e,s);if(i&&i!==s&&(r=i),O3[t])return null!=r?r:""}return r||(r=M3[n][t]||I3[t]||t),r.replace(/\{(\w+)\}/g,((t,e)=>{var o;return String(null!==(o=i[e])&&void 0!==o?o:t)}))}function z3(t,e,i){const o=R3(i);return B3(`card.${t}_${"one"===new Intl.PluralRules(o).select(e)?"one":"other"}`,i,{count:new Intl.NumberFormat(o).format(e)})}function P3(t,e){if(!t)return B3("signal.connected",e);const i=t.match(/^([a-z\s_-]+?)(\s*\([\d.,]+%\))?$/i);if(!i)return t;const o={connected:"connected",online:"online",offline:"offline",nosignal:"no_signal",verygood:"very_good",good:"good",poor:"poor",medium:"medium",unknown:"unknown"}[i[1].replace(/[\s_-]/g,"").toLowerCase()];return o?B3(`signal.${o}`,e)+(i[2]||""):t}function F3(t,e){const i=t.match(/\(([\d.,]+)%\)\s*$/);if(!i)return P3(t,e);const o=Number(i[1].replace(",","."));return!Number.isFinite(o)||o<0||o>100?P3(t,e):new Intl.NumberFormat(R3(e),{style:"percent",maximumFractionDigits:1}).format(o/100)}function T3(t){for(const e of["ha-icon","ha-button","ha-icon-button","ha-tooltip","ha-expansion-panel","ha-button-toggle-group","ha-alert","ha-dropdown","ha-dropdown-item","ha-slider"])customElements.get(e)||customElements.whenDefined(e).then((()=>{t.isConnected&&t.requestUpdate()}))}class N3 extends Pt{constructor(){super(...arguments),this.hideHubSelector=!1,this._hubs=[],this._formReady=!!customElements.get("ha-form"),this.boundLayoutSaveHandler=this.save_layout.bind(this),this.computeLabel=t=>this.t("name"===t.name?"common.title":"hub"===t.name?"card.hub":"show_detailed_view"===t.name?"card.show_detailed_view":`editor.${t.name}`)}t(t){return B3(t,this.hass)}setConfig(t){var e;this._config=Object.assign(Object.assign({},t),{auto_update:null===(e=t.auto_update)||void 0===e||e}),this.loadNativeForm()}connectedCallback(){super.connectedCallback(),T3(this),window.addEventListener("wiser-zigbee-save-layout",this.boundLayoutSaveHandler)}disconnectedCallback(){window.removeEventListener("wiser-zigbee-save-layout",this.boundLayoutSaveHandler),super.disconnectedCallback()}updated(t){var e;t.has("hass")&&this.hass&&!t.get("hass")&&(e=this.hass,e.callWS({type:"wiser/hubs"})).then((t=>{this._hubs=t})).catch((()=>{this._hubs=[]}))}async loadNativeForm(){if(customElements.get("ha-form"))this._formReady=!0;else{if(this.loadingForm)return this.loadingForm;this.loadingForm=(async()=>{const t=(await window.loadCardHelpers()).createCardElement({type:"button"});await t.constructor.getConfigElement(),await customElements.whenDefined("ha-form"),this._formReady=!0})();try{await this.loadingForm}catch(t){this.loadingForm=void 0}}}render(){var t,e,i,o,n,r,s,a,l;if(!this.hass||!this._config)return X``;if(!this._formReady)return X`

${this.t("editor.loading")}

`;const h=[...new Set([...this._hubs,...this._config.hub?[this._config.hub]:[]])],c=Object.assign(Object.assign({},this._config),{hub:this._config.hub||this._hubs[0],name:null!==(t=this._config.name)&&void 0!==t?t:this.t("card.title"),show_detailed_view:!(null!==(e=this._config.map_only)&&void 0!==e&&e),map_height:null!==(i=this._config.map_height)&&void 0!==i?i:null,show_device_list:null===(o=this._config.show_device_list)||void 0===o||o,show_labels:null!==(n=this._config.show_labels)&&void 0!==n&&n,magnifier:null!==(r=this._config.magnifier)&&void 0!==r&&r}),d=[{name:"hub",required:!0,disabled:0===h.length,selector:{select:{options:h,mode:"dropdown"}}},{name:"name",selector:{text:{}}},{name:"map_height",selector:{number:{min:100,max:2e3,step:1,mode:"box",unit_of_measurement:"px"}}}],u=[{name:"show_labels",selector:{boolean:{}}},{name:"magnifier",selector:{boolean:{}}},{name:"auto_update",selector:{boolean:{}}},{name:"show_detailed_view",selector:{boolean:{}}},{name:"show_device_list",selector:{boolean:{}},disabled:!c.show_detailed_view}];return X` "hub"!==t.name)):d} + .computeLabel=${this.computeLabel} + @value-changed=${this.valueChanged} + > + ({value:t,label:this.t(`editor.${t}`)})))}}}]} + .computeLabel=${this.computeLabel} + @value-changed=${this.valueChanged} + > + ({value:t,label:this.t(`editor.${t}`)})))}}}]} + .computeLabel=${this.computeLabel} + @value-changed=${this.valueChanged} + > + ({value:t,label:this.t(`editor.${t}`)})))}}}]} + .computeLabel=${this.computeLabel} + @value-changed=${this.valueChanged} + > +
+ ${u.map((t=>X``))} +
+
${this.t("common.version")}: ${"3.0.0-dev.67"}
`}setOrientation(t){var e;this._config&&["horizontal","vertical","pie"].includes(t)&&(null!==(e=this._config.orientation)&&void 0!==e?e:"vertical")!==t&&(this._config=Object.assign(Object.assign({},this._config),{orientation:t}),Gt(this,"config-changed",{config:this._config}))}valueChanged(t){var e,i,o,n;if(t.stopPropagation(),!this._config||!t.detail.value)return;const s=Object.assign({},t.detail.value);"show_detailed_view"in s&&(s.map_only=!s.show_detailed_view,delete s.show_detailed_view),!("map_height"in s)||null!=s.map_height&&""!==s.map_height||(s.map_height=null);const a=Object.assign(Object.assign({},this._config),s);(a.hub||this._hubs[0])===(this._config.hub||this._hubs[0])&&(null!==(e=a.group_by)&&void 0!==e?e:"none")===(null!==(i=this._config.group_by)&&void 0!==i?i:"none")&&(null!==(o=a.orientation)&&void 0!==o?o:"vertical")===(null!==(n=this._config.orientation)&&void 0!==n?n:"vertical")||(delete a.layout_data,delete a.layout_orientation,delete a.layout_group_by),null==this._config.name&&a.name===this.t("card.title")&&delete a.name,this._config=r(a),Gt(this,"config-changed",{config:this._config})}save_layout(t){var e,i,o,n,s,a,l,h,c,d,u,f;this._config&&(null!==(e=t.detail.hub)&&void 0!==e?e:"")===(null!==(i=this._config.hub)&&void 0!==i?i:"")&&(null!==(o=t.detail.orientation)&&void 0!==o?o:"horizontal")===(null!==(n=this._config.orientation)&&void 0!==n?n:"vertical")&&(null!==(s=t.detail.group_by)&&void 0!==s?s:"none")===(null!==(a=this._config.group_by)&&void 0!==a?a:"none")&&(null!==(l=t.detail.layout_id)&&void 0!==l?l:"")===(null!==(h=this._config.layout_id)&&void 0!==h?h:"")&&(null!==(c=t.detail.name)&&void 0!==c?c:"Wiser Zigbee Network")===(null!==(d=this._config.name)&&void 0!==d?d:"Wiser Zigbee Network")&&(this._config=r(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},this._config),"boolean"==typeof t.detail.magnifier?{magnifier:t.detail.magnifier}:{}),"boolean"==typeof t.detail.map_only?{map_only:t.detail.map_only}:{}),"boolean"==typeof t.detail.show_labels?{show_labels:t.detail.show_labels}:{}),t.detail.preferences_only?{}:{layout_data:t.detail.layout_data,orientation:null!==(u=t.detail.orientation)&&void 0!==u?u:"vertical",group_by:null!==(f=t.detail.group_by)&&void 0!==f?f:"none",layout_orientation:void 0,layout_group_by:void 0})),Gt(this,"config-changed",{config:this._config}))}}N3.styles=wt` + :host { + color: var(--primary-text-color); + } + .switches { + display: grid; + gap: 0; + } + .orientation-control { + display: block; + margin: 16px 0 8px; + } + .version { + margin-top: 24px; + color: var(--secondary-text-color); + font-size: 12px; + } + `,e([Ut({attribute:!1})],N3.prototype,"hass",void 0),e([Ut({attribute:!1})],N3.prototype,"hideHubSelector",void 0),e([Lt()],N3.prototype,"_config",void 0),e([Lt()],N3.prototype,"_hubs",void 0),e([Lt()],N3.prototype,"_formReady",void 0),customElements.get("wiser-zigbee-card-editor")||customElements.define("wiser-zigbee-card-editor",N3);class j3 extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this.shadowRoot.innerHTML='\n \n
\n

Wiser Zigbee

\n \n \n \n
\n \n

Customize this panel. Dashboard cards keep their own settings.

\n
\n
\n Cancel\n Save\n
\n
\n

Loading Wiser Zigbee network…

',this.shadowRoot.getElementById("menu").addEventListener("click",(()=>{this.dispatchEvent(new CustomEvent("hass-toggle-menu",{bubbles:!0,composed:!0}))})),this.shadowRoot.getElementById("settings").addEventListener("click",(()=>this._openEditor())),this.shadowRoot.getElementById("cancel").addEventListener("click",(()=>this._closeEditor())),this.shadowRoot.getElementById("save").addEventListener("click",(()=>this._saveEditor())),this.shadowRoot.getElementById("editor-dialog").addEventListener("closed",(()=>this._closeEditor())),this.shadowRoot.getElementById("editor-dialog").addEventListener("close-dialog",(()=>this._closeEditor())),this._editors=[],this._cards=[],this._generation=0}_t(t){return B3(t,this._hass)}set hass(t){this._hass=t,this._localizeControls();for(const e of this._cards)e.hass=t;for(const e of this._editors)e.hass=t;this.shadowRoot.getElementById("settings").hidden=!t?.user?.is_admin}_localizeControls(){const t=this.shadowRoot;for(const[e,i]of[["menu","panel.menu"],["settings","panel.settings"]])t.getElementById(e).setAttribute("aria-label",this._t(i)),t.getElementById(e).title=this._t(i);t.getElementById("cancel").textContent=this._t("panel.cancel"),t.getElementById("save").textContent=this._t("common.save"),t.getElementById("editor-description").textContent=this._t("panel.description");const e=t.getElementById("editor-dialog");e.setAttribute("header-title",this._t("panel.settings")),e.heading=this._t("panel.settings")}set panel(t){const e=t.config;JSON.stringify(e)!==JSON.stringify(this._config)&&(this._config=e,this._loadCards())}_cardConfig(t){return{layout_id:`wiser-zigbee-panel:${t}`,...this._config.card_configs?.[t],type:"custom:wiser-zigbee-card",hub:t}}async saveZigbeeCardConfig(t,e){if(!this._hass?.user?.is_admin||!this._cards.includes(t))throw new Error("Only administrators can save panel settings");const i=this._config.hubs[this._cards.indexOf(t)],o={...e,type:"custom:wiser-zigbee-card",hub:i};return await this._hass.callWS({type:"wiser/zigbee_panel/configure",configs:{[i]:o}}),this._config={...this._config,card_configs:{...this._config.card_configs,[i]:o}},o}_selectHub(t){this._activeHub=t,this._cards.forEach(((e,i)=>{const o=this._config.hubs[i]===t;e.hidden=!o,this._tabs[i].setAttribute("aria-selected",String(o)),this._tabs[i].tabIndex=o?0:-1}))}_renderHubTabs(){const t=this._config.hubs,e=this.shadowRoot.getElementById("hub-tabs");e.hidden=0===t.length,this._tabs=t.map(((e,i)=>{const o=document.createElement("ha-button");o.setAttribute("appearance","plain"),o.className="hub-tab",o.textContent=e,o.id=`hub-tab-${i}`,o.setAttribute("role","tab"),o.setAttribute("aria-controls",`hub-panel-${i}`),o.addEventListener("click",(()=>this._selectHub(e))),o.addEventListener("keydown",(e=>{let o;if("ArrowRight"===e.key)o=(i+1)%t.length;else if("ArrowLeft"===e.key)o=(i+t.length-1)%t.length;else if("Home"===e.key)o=0;else{if("End"!==e.key)return;o=t.length-1}e.preventDefault(),this._selectHub(t[o]),this._tabs[o].focus()}));const n=this._cards[i];return n.id=`hub-panel-${i}`,n.setAttribute("role","tabpanel"),n.setAttribute("aria-labelledby",o.id),o})),e.replaceChildren(...this._tabs),this._selectHub(t.includes(this._activeHub)?this._activeHub:t[0])}_closeEditor(){this.shadowRoot.getElementById("editor-dialog").open=!1,this._editors=[],this.shadowRoot.getElementById("editors").replaceChildren()}async _openEditor(){const t=this.shadowRoot.getElementById("editor-dialog");if(t.open||!this._cards.length||!this._hass?.user?.is_admin)return;const e=this.shadowRoot.getElementById("editors"),i=this.shadowRoot.getElementById("editor-error"),o=this.shadowRoot.getElementById("save");this._drafts={},this._editors=[],i.textContent="",e.replaceChildren(),o.disabled=!0,t.heading=this._t("panel.settings"),"headerTitle"in(customElements.get("ha-dialog")?.prototype||{})||this.shadowRoot.getElementById("editor-actions").removeAttribute("slot"),t.open=!0;try{if(!window.loadCardHelpers){const t=document.createElement("partial-panel-resolver"),e=t._getRoutes?.({lovelace:{component_name:"lovelace",url_path:"lovelace"}});await(e?.routes?.lovelace?.load?.())}const i=customElements.get("wiser-zigbee-card");for(const o of this._config.hubs){const n=await i.getConfigElement();if(!t.open)return;const r=this._cardConfig(o);this._drafts[o]=r,n.hass=this._hass,n.hideHubSelector=!0,n.setConfig({...r}),n.addEventListener("config-changed",(t=>{t.stopPropagation(),this._drafts[o]={...t.detail.config,type:"custom:wiser-zigbee-card",hub:o}}));const s=document.createElement("section"),a=document.createElement("h3");a.textContent=o,s.replaceChildren(...this._config.hubs.length>1?[a,n]:[n]),e.append(s),this._editors.push(n)}o.disabled=!1}catch(t){i.textContent=this._t("panel.editor_error"),console.error("Unable to open Wiser editor",t)}}async _saveEditor(){const t=this.shadowRoot.getElementById("save");t.disabled=!0;try{await this._hass.callWS({type:"wiser/zigbee_panel/configure",configs:this._drafts}),this._config={...this._config,card_configs:{...this._config.card_configs,...this._drafts}},this._closeEditor(),this._editors=[],this._loadCards()}catch(t){this.shadowRoot.getElementById("editor-error").textContent=this._t("panel.save_error"),console.error("Unable to save Wiser panel settings",t)}finally{t.disabled=!1}}async _loadCards(){const t=++this._generation,e=this._config,i=this.shadowRoot.querySelector("main");try{const o=customElements.get("wiser-zigbee-card");if(1!==o?.panelApiVersion)throw new Error("Wiser Zigbee needs its matching Zigbee card build. Update the card resource and refresh the browser.");if(t!==this._generation)return;const n=e.hubs.map((t=>{const e=document.createElement("wiser-zigbee-card");return e.setConfig(this._cardConfig(t)),e.hass=this._hass,e}));this._cards=n,i.replaceChildren(...n),this._renderHubTabs(),this.shadowRoot.getElementById("settings").disabled=!n.length}catch(e){if(t!==this._generation)return;this._cards=[],this.shadowRoot.getElementById("hub-tabs").hidden=!0,this.shadowRoot.getElementById("settings").disabled=!0;const o=document.createElement("p");o.setAttribute("role","alert"),o.textContent=e.message||"Unable to load Wiser Zigbee network. Please try again.";const n=document.createElement("ha-button");n.textContent=this._t("panel.retry"),n.addEventListener("click",(()=>this._loadCards())),i.replaceChildren(o,n),console.error("Unable to load Wiser Zigbee network",e)}}}function U3(t,e,i=4){return t.lefte.left&&t.tope.top}function L3(t,e,i,o){const n=o?{x:t.x,y:t.y+.45*(e.y-t.y)}:{x:t.x+.45*(e.x-t.x),y:t.y},r=o?{x:e.x,y:e.y+.45*(t.y-e.y)}:{x:e.x+.45*(t.x-e.x),y:e.y},s=1-i;return{x:s*s*s*t.x+3*s*s*i*n.x+3*s*i*i*r.x+i*i*i*e.x,y:s*s*s*t.y+3*s*s*i*n.y+3*s*i*i*r.y+i*i*i*e.y}}customElements.get("wiser-zigbee-panel")||customElements.define("wiser-zigbee-panel",j3),window.customCards=window.customCards||[],window.customCards.some((t=>"wiser-zigbee-card"===t.type))||window.customCards.push({type:"wiser-zigbee-card",name:"Wiser Zigbee Card",description:B3("card.description")});class Q3 extends(S3(Pt)){constructor(){super(...arguments),this.loading=!1,this.error="",this.showLabels=!1,this.savingConfig=!1,this.magnifier=new n,this.magnifierHeld=!1,this.layoutStatus="",this.textColor="",this.statusPalette="",this.displayLanguage="",this.collapsedAreas=new Set,this.areaPositions={},this.infoRequest=0,this.fitAfterHeightChange=!1,this.requestId=0,this.pendingLoad=!0}t(t){return B3(t,this.hass)}deviceName(t){return t?"Controller"===t.group&&"Wiser Hub"===t.label?this.t("card.hub"):t.label.replace(/\n/g," "):this.t("card.unknown_device")}get visibleData(){var t,e;const i=null!==(t=this.mapData)&&void 0!==t?t:this.zigbeeData;return i&&"area"===(null===(e=this.config)||void 0===e?void 0:e.group_by)?function(t,e){const i=t.nodes.filter((t=>{var i;return"Controller"===t.group||"Area"===t.group||!e.has(null!==(i=t.area_id)&&void 0!==i?i:"")})),o=new Set(i.map((t=>t.id)));return{nodes:i,edges:t.edges.filter((t=>o.has(t.from)&&o.has(t.to)))}}(i,this.collapsedAreas):i}static async getConfigElement(){return document.createElement("wiser-zigbee-card-editor")}static getStubConfig(){return{}}setConfig(t){var e,i,o;if(!t)throw new Error(this.t("common.invalid_configuration"));this.magnifier.hide(),this.suppliedConfig=t;const n=Object.assign(Object.assign({},t),{auto_update:null===(e=t.auto_update)||void 0===e||e}),r=this.config,s=this.mapHeight,a=r&&this.network&&[...new Set([...Object.keys(r),...Object.keys(n)])].filter((t=>"map_height"!==t)).every((t=>JSON.stringify(r[t])===JSON.stringify(n[t])));if(this.config=n,this.showLabels=null!==(i=t.show_labels)&&void 0!==i&&i,void 0===t.map_only)try{const t=localStorage.getItem(`${this.layoutKey}:map-only`);null!==t&&(this.config.map_only="true"===t)}catch(t){}if(void 0===t.show_labels)try{this.showLabels="true"===localStorage.getItem(`${this.layoutKey}:labels`)}catch(t){}a?this.fitAfterHeightChange||(this.fitAfterHeightChange=s!==this.mapHeight):(this.cancelDeviceInfo(),this.areaDrag=void 0,this.mapData=void 0,this.collapsedAreas.clear(),this.areaPositions={},this.fitAfterHeightChange=!1,null===(o=this.network)||void 0===o||o.destroy(),this.network=void 0,this.infoReturnView=void 0,this.zoomReturnView=void 0,this.layoutStatus="",this.pendingLoad=!0,this.requestId++)}get orientation(){var t,e;return"pie"===(null===(t=this.config)||void 0===t?void 0:t.orientation)?"pie":"horizontal"===(null===(e=this.config)||void 0===e?void 0:e.orientation)?"horizontal":"vertical"}get mapHeight(){var t;const e=null===(t=this.config)||void 0===t?void 0:t.map_height;return null==e||""===e?null:"number"==typeof e&&Number.isFinite(e)?Math.min(2e3,Math.max(100,Math.round(e))):null}getGridOptions(){var t;return null===this.mapHeight?{columns:12,rows:(null===(t=this.config)||void 0===t?void 0:t.map_only)?6:9,min_rows:3}:{columns:12}}getCardSize(){var t;return(null===(t=this.config)||void 0===t?void 0:t.map_only)?"vertical"===this.orientation?6:8:"vertical"===this.orientation?7:9}hassSubscribe(){return[this.hass.connection.subscribeMessage((t=>{var e;"wiser_updated"===t.event&&(null===(e=this.config)||void 0===e?void 0:e.auto_update)&&!y3(this)&&this.loadData()}),{type:"wiser_updated"})]}connectedCallback(){super.connectedCallback(),T3(this),this.pendingLoad=!0,this.requestUpdate()}disconnectedCallback(){var t;clearTimeout(this.magnifierHoldTimer),this.magnifier.hide(),clearTimeout(this.activeIconTimer),this.activeIcon=void 0,this.cancelDeviceInfo(),super.disconnectedCallback(),this.requestId++,null===(t=this.network)||void 0===t||t.destroy(),this.network=void 0,this.areaDrag=void 0,this.infoReturnView=void 0,this.zoomReturnView=void 0}updated(t){if(super.updated(t),this.positionAreaIcons(),t.has("hass")&&this.network){(getComputedStyle(this).getPropertyValue("--primary-text-color").trim()||"#273448")===this.textColor&&p(getComputedStyle(this))===this.statusPalette&&R3(this.hass)===this.displayLanguage||this.drawNetwork(!0)}this.fitAfterHeightChange&&this.network&&(this.fitAfterHeightChange=!1,this.network.setSize("100%","100%"),this.fitNetwork()),(t.has("selected")||t.has("selectedEntity")||t.has("config"))&&this.focusAboveInfo(),this.pendingLoad&&this.hass&&this.config&&(this.pendingLoad=!1,this.loadData())}async loadData(){var t,e,i,o,n;if(!this.hass||!this.config)return;const r=++this.requestId;this.loading=!0,this.error="";try{let l=await(s=this.hass,a=this.config.hub,s.callWS({type:"wiser/zigbee",hub:a}));"area"===this.config.group_by&&(l=await async function(t,e,i){const[o,n,r,s]=await Promise.all([t.callWS({type:"config/entity_registry/list"}),t.callWS({type:"config/device_registry/list"}),t.callWS({type:"config/area_registry/list"}),i?Promise.resolve([i]):t.callWS({type:"wiser/hubs"})]),a={"config/entity_registry/list":o,"config/device_registry/list":n,"wiser/hubs":s},l=Object.assign(Object.assign({},t),{callWS:async t=>a[t.type]});return Object.assign(Object.assign({},e),{nodes:await Promise.all(e.nodes.map((async t=>{const e=await k3(l,t,s[0]),i=o.find((t=>t.entity_id===e)),a=n.find((t=>t.id===(null==i?void 0:i.device_id))),h=r.find((t=>t.area_id===((null==a?void 0:a.area_id)||(null==i?void 0:i.area_id))));return Object.assign(Object.assign({},t),{area_id:null==h?void 0:h.area_id,area_name:null==h?void 0:h.name,area_icon:null==h?void 0:h.icon})})))})}(this.hass,l,this.config.hub));const h=x3("area"===this.config.group_by?function(t,e){const i=t.nodes.map((t=>Object.assign({},t))),o=new Set(i.map((t=>t.id))),n=[...new Set(i.filter((t=>"Controller"!==t.group)).map((t=>{var e;return null!==(e=t.area_id)&&void 0!==e?e:""})))].sort(),r=t.edges.map((t=>Object.assign({},t)));for(const r of n){const n=t.nodes.filter((t=>{var e;return"Controller"!==t.group&&(null!==(e=t.area_id)&&void 0!==e?e:"")===r}));let s=2166136261;for(const t of r||"__unassigned__")s=Math.imul(s^t.charCodeAt(0),16777619);let a=-(s>>>0)-1;for(;o.has(a);)a--;o.add(a),i.push({id:a,group:"Area",area_id:r,area_icon:n[0].area_icon||"mdi:floor-plan",label:n[0].area_name||e,x:0,y:0})}return{nodes:i,edges:r}}(l,this.t("card.unassigned_area")):l,this.orientation,void 0,this.config.group_by);if(r!==this.requestId||!this.isConnected)return;let c=(null!==(t=this.config.layout_orientation)&&void 0!==t?t:this.orientation)===this.orientation&&(null!==(i=null!==(e=this.config.layout_group_by)&&void 0!==e?e:this.config.group_by)&&void 0!==i?i:"none")===(null!==(o=this.config.group_by)&&void 0!==o?o:"none")?this.config.layout_data:void 0;if(!c||"object"!=typeof c||Array.isArray(c))try{const t=JSON.parse(localStorage.getItem(this.layoutKey)||"null");t&&"object"==typeof t&&!Array.isArray(t)&&(c=t)}catch(t){}const d=Object.assign(Object.assign({},this.areaPositions),null===(n=this.network)||void 0===n?void 0:n.getPositions());h.nodes=h.nodes.map((t=>{var e;return Object.assign(Object.assign({},t),null!==(e=null==d?void 0:d[t.id])&&void 0!==e?e:this.validPosition(c&&"object"==typeof c?c[t.id]:void 0))})),this.zigbeeData="area"===this.config.group_by?l:h,this.mapData=h,await this.updateComplete,this.drawNetwork()}catch(t){r===this.requestId&&(this.error="card.load_error")}finally{r===this.requestId&&(this.loading=!1)}var s,a}drawNetwork(t=!1){var e,i,o,n;if(!this.zigbeeData)return;const r=t?Object.assign(Object.assign({},this.areaPositions),null===(e=this.network)||void 0===e?void 0:e.getPositions()):void 0,s=this.visibleData;t&&"area"===(null===(i=this.config)||void 0===i?void 0:i.group_by)&&(this.areaPositions=null!=r?r:{});const a=getComputedStyle(this).getPropertyValue("--primary-text-color").trim()||"#273448";this.textColor=a;const l=getComputedStyle(this);this.statusPalette=p(l);const h=null!==(n=null===(o=this.config)||void 0===o?void 0:o.link_status)&&void 0!==n?n:"links",u="links"===h||"both"===h,v="icons"===h||"both"===h;this.displayLanguage=R3(this.hass);const g={nodes:s.nodes.map((t=>{var e,i,o,n;const s=function(t,e){if("Controller"===t.group||"Area"===t.group)return!1;const i=e.edges.filter((e=>e.from===t.id));return!i.length||i.every((t=>{const i=t.label.split("(")[0].replace(/[\s_-]/g,"").toLowerCase();return["nosignal","offline","disconnected","noconnection"].includes(i)||!e.nodes.some((e=>e.id===t.to))}))}(t,this.zigbeeData),h=s?"Offline":null===(e=this.zigbeeData.edges.find((e=>e.from===t.id)))||void 0===e?void 0:e.label,u=v&&"Area"!==t.group&&"Controller"!==t.group?f(h,!0,l):void 0,p="Area"===t.group?E3:null!==(i=w3[t.group])&&void 0!==i?i:b3;return Object.assign(Object.assign(Object.assign({},t),null!==(o=null==r?void 0:r[t.id])&&void 0!==o?o:{}),{shape:"image",image:c(p,u,s),brokenImage:c(b3,u,s),size:32,label:"Area"===t.group?`${t.label} ${this.collapsedAreas.has(null!==(n=t.area_id)&&void 0!==n?n:"")?"▸":"▾"}`:"Controller"===t.group?this.deviceName(t):d(t.label),font:{color:a}})})),edges:s.edges.map((t=>{const e=f(t.label,u,l);return Object.assign(Object.assign({},t),{label:"",color:{color:e,highlight:e,hover:e,inherit:!1}})}))};if(this.network){const t={position:this.network.getViewPosition(),scale:this.network.getScale()};this.hoveredEdge=void 0,this.network.setData(g),this.network.moveTo(Object.assign(Object.assign({},t),{animation:!1})),void 0!==this.selected&&g.nodes.some((t=>t.id===this.selected))?this.network.selectNodes([this.selected]):this.selected=void 0}else this.network=new g3(this.shadowRoot.getElementById("zigbee-network"),g,Object.assign(Object.assign({},A3),{edges:Object.assign(Object.assign({},A3.edges),{smooth:{enabled:!0,type:"cubicBezier",forceDirection:"pie"===this.orientation?"none":this.orientation,roundness:.45}})})),this.network.on("hoverEdge",(t=>this.hoverLink(t.edge))),this.network.on("blurEdge",(()=>this.hoverLink())),this.network.on("click",(t=>this.deviceClick(t.nodes[0]))),this.network.on("hold",(t=>this.deviceHold(t.nodes[0]))),this.network.on("doubleClick",(t=>{var e;this.cancelDeviceInfo(),this.toggleDeviceZoom(t.nodes[0],null===(e=t.pointer)||void 0===e?void 0:e.canvas)})),this.network.on("beforeDrawing",(t=>{this.moveAreaDevices(),this.drawAreaGroups(t)})),this.network.on("afterDrawing",(t=>{this.positionAreaIcons(),this.drawLinkLabels(t),this.magnifier.refresh()})),this.network.on("dragStart",(t=>this.startAreaDrag(t.nodes[0]))),this.network.on("dragEnd",(()=>{this.moveAreaDevices(),this.areaDrag=void 0})),this.network.on("resize",(()=>this.fitNetwork())),this.fitNetwork(),this.requestUpdate()}startAreaDrag(t){var e,i,o,n;if(this.closeDeviceInfo(!1),this.areaDrag=void 0,!this.network||"area"!==(null===(e=this.config)||void 0===e?void 0:e.group_by))return;const r=null===(i=this.mapData)||void 0===i?void 0:i.nodes.find((e=>e.id===t&&"Area"===e.group));if(!r)return;const s=this.currentPositions(),a={};for(const t of this.mapData.nodes)"Area"!==t.group&&"Controller"!==t.group&&(null!==(o=t.area_id)&&void 0!==o?o:"")===(null!==(n=r.area_id)&&void 0!==n?n:"")&&s[t.id]&&(a[t.id]=Object.assign({},s[t.id]));this.areaDrag={headerId:r.id,origin:Object.assign({},s[r.id]),members:a,dx:0,dy:0}}moveAreaDevices(){const t=this.areaDrag;if(!t||!this.network)return;const e=this.network.getPositions(),i=e[t.headerId];if(!i)return;const o=i.x-t.origin.x,n=i.y-t.origin.y;if(o!==t.dx||n!==t.dy){t.dx=o,t.dy=n,this.areaPositions[t.headerId]=Object.assign({},i);for(const[i,r]of Object.entries(t.members)){const t={x:r.x+o,y:r.y+n};this.areaPositions[i]=t,e[i]&&this.network.moveNode(Number(i),t.x,t.y)}}}areaBounds(t){var e,i,o;if(!this.network||"area"!==(null===(e=this.config)||void 0===e?void 0:e.group_by))return[];const n=null!==(o=null===(i=this.visibleData)||void 0===i?void 0:i.nodes)&&void 0!==o?o:[],r=null!=t?t:document.createElement("canvas").getContext("2d"),s=this.network.getPositions(),a=new Set(n.filter((t=>"Area"===t.group)).map((t=>{var e;return null!==(e=t.area_id)&&void 0!==e?e:""})));return[...a].map((t=>{const e=n.filter((e=>{var i;return"Controller"!==e.group&&(null!==(i=e.area_id)&&void 0!==i?i:"")===t})),i=e.map((t=>{var e;const i=s[t.id];if(!i)return this.network.getBoundingBox(t.id);const o={left:i.x-32,right:i.x+32,top:i.y-32,bottom:i.y+60};if(!r)return o;const n="Area"===t.group?`${t.label} ${this.collapsedAreas.has(null!==(e=t.area_id)&&void 0!==e?e:"")?"▸":"▾"}`:d(t.label);r.save(),r.font="bold 14px system-ui, sans-serif";const a=n.split("\n"),l=Math.max(...a.map((t=>r.measureText(t).width)))/2;return r.restore(),o.left=Math.min(o.left,i.x-l),o.right=Math.max(o.right,i.x+l),o.bottom=Math.max(o.bottom,i.y+32+14*(a.length+1)),o})),o=e.findIndex((t=>"Area"===t.group)),a=e[o],l=a&&s[a.id],h=i.filter(((t,e)=>e!==o));if(l&&h.length&&!this.areaDrag&&"vertical"===this.orientation){const t=(Math.min(...h.map((t=>t.left)))+Math.max(...h.map((t=>t.right))))/2,e=t-l.x;Math.abs(e)>.01&&(this.network.moveNode(a.id,t,l.y),this.areaPositions[a.id]={x:t,y:l.y},i[o].left+=e,i[o].right+=e)}return{left:Math.min(...i.map((t=>t.left)))-18,right:Math.max(...i.map((t=>t.right)))+18,top:Math.min(...i.map((t=>t.top)))-18,bottom:Math.max(...i.map((t=>t.bottom)))+18}}))}drawAreaGroups(t){const e=this.areaBounds(t);if(!e.length||!this.network)return;const i=getComputedStyle(this).getPropertyValue("--primary-text-color").trim()||this.textColor;t.save();for(const o of e)t.beginPath(),t.roundRect(o.left,o.top,o.right-o.left,o.bottom-o.top,14),t.fillStyle=i,t.globalAlpha=.04,t.fill(),t.strokeStyle=i,t.lineWidth=1/this.network.getScale(),t.globalAlpha=.22,t.stroke();t.restore()}positionAreaIcons(){var t,e;if(!this.network||"area"!==(null===(t=this.config)||void 0===t?void 0:t.group_by))return;const i=this.network.getPositions(),o=64*this.network.getScale();null===(e=this.shadowRoot)||void 0===e||e.querySelectorAll(".area-icons ha-icon").forEach((t=>{const e=i[Number(t.dataset.node)];if(!e)return;const n=this.network.canvasToDOM(e);t.style.left=`${n.x}px`,t.style.top=`${n.y}px`,t.style.width=`${o}px`,t.style.height=`${o}px`,t.style.setProperty("--mdc-icon-size",`${o}px`),t.style.setProperty("--ha-icon-size",`${o}px`)}))}cancelDeviceInfo(){clearTimeout(this.deviceTapTimer),this.deviceTapTimer=void 0,this.infoRequest++,this.selectedEntity=void 0}closeDeviceInfo(t=!0){var e;this.cancelDeviceInfo(),this.selected=void 0;const i=this.infoReturnView;this.infoReturnView=void 0,t&&(null===(e=this.network)||void 0===e||e.unselectAll(),i&&this.network&&(this.zoomReturnView=i.zoomReturnView,this.network.moveTo({position:i.position,scale:i.scale,animation:!1})))}deviceClick(t){clearTimeout(this.deviceTapTimer),void 0!==t?this.deviceTapTimer=setTimeout((()=>{var e,i;const o=null===(e=this.mapData)||void 0===e?void 0:e.nodes.find((e=>e.id===t));"Area"===(null==o?void 0:o.group)?this.toggleArea(null!==(i=o.area_id)&&void 0!==i?i:""):this.showDeviceDetails(t)}),300):this.closeDeviceInfo()}toggleArea(t){var e;this.closeDeviceInfo(!1),this.areaPositions=Object.assign(Object.assign({},this.areaPositions),null===(e=this.network)||void 0===e?void 0:e.getPositions()),this.collapsedAreas.has(t)?this.collapsedAreas.delete(t):this.collapsedAreas.add(t),this.drawNetwork(!0)}async deviceHold(t){var e,i;this.closeDeviceInfo();const o=null===(e=this.zigbeeData)||void 0===e?void 0:e.nodes.find((e=>e.id===t));if(!o||!this.hass)return;const n=this.infoRequest;try{const t=await k3(this.hass,o,null===(i=this.config)||void 0===i?void 0:i.hub);t&&n===this.infoRequest&&this.isConnected&&Gt(this,"hass-more-info",{entityId:t})}catch(t){}}showDeviceDetails(t){void 0!==t?(!this.infoReturnView&&this.network&&(this.infoReturnView={position:this.network.getViewPosition(),scale:this.network.getScale(),zoomReturnView:this.zoomReturnView}),this.cancelDeviceInfo(),this.selected=t,void 0!==t&&this.openDeviceInfo(t,this.infoRequest)):this.closeDeviceInfo()}async openDeviceInfo(t,e){var i,o;const n=null===(i=this.zigbeeData)||void 0===i?void 0:i.nodes.find((e=>e.id===t));if(n&&this.hass)try{const i=await k3(this.hass,n,null===(o=this.config)||void 0===o?void 0:o.hub);i&&e===this.infoRequest&&this.isConnected&&this.selected===t&&(this.selectedEntity=i)}catch(t){}}toggleDeviceZoom(t,e){if(!this.network)return;const i=!window.matchMedia("(prefers-reduced-motion: reduce)").matches&&{duration:250,easingFunction:"easeInOutQuad"};if(this.zoomReturnView)return this.network.moveTo(Object.assign(Object.assign({},this.zoomReturnView),{animation:i})),void(this.zoomReturnView=void 0);if(!(void 0!==t||e&&Number.isFinite(e.x)&&Number.isFinite(e.y)))return;this.zoomReturnView={position:this.network.getViewPosition(),scale:this.network.getScale()};const o=Math.max(2*this.zoomReturnView.scale,1.25);void 0!==t?this.network.focus(t,{scale:o,locked:!1,animation:i}):this.network.moveTo({position:e,scale:o,animation:i})}focusAboveInfo(){var t,e,i;if(!(null===(t=this.config)||void 0===t?void 0:t.map_only)||void 0===this.selected||!this.network)return;const o=null===(e=this.shadowRoot)||void 0===e?void 0:e.getElementById("zigbee-network"),n=null===(i=this.shadowRoot)||void 0===i?void 0:i.querySelector("footer.map-info");if(!o||!n||n.hidden)return;const r=o.getBoundingClientRect(),s=Math.min(r.bottom,n.getBoundingClientRect().top-12);s<=r.top||this.network.focus(this.selected,{scale:this.network.getScale(),offset:{x:0,y:(s-r.top-r.height)/2},locked:!1,animation:!1})}zoomStep(t){this.network&&(this.prepareGestureZoom(),this.network.moveTo({position:this.network.getViewPosition(),scale:Math.min(10,Math.max(.01,this.network.getScale()*t)),animation:!1}))}prepareGestureZoom(){var t;this.network&&(this.closeDeviceInfo(!1),null!==(t=this.zoomReturnView)&&void 0!==t||(this.zoomReturnView={position:this.network.getViewPosition(),scale:this.network.getScale()}))}touchZoomStart(t){t.touches.length>=2&&this.prepareGestureZoom()}panZoomedView(t){if(t.ctrlKey||t.metaKey)return void this.prepareGestureZoom();if(t.stopPropagation(),!this.network||!this.zoomReturnView)return;t.preventDefault();const e=t.currentTarget,i=this.network.getScale(),o=this.network.getViewPosition(),n=1===t.deltaMode?16:2===t.deltaMode?e.clientWidth:1,r=1===t.deltaMode?16:2===t.deltaMode?e.clientHeight:1,s=t.shiftKey&&0===t.deltaX?t.deltaY*n:t.deltaX*n,a=t.shiftKey&&0===t.deltaX?0:t.deltaY*r;this.network.moveTo({position:{x:o.x+s/i,y:o.y+a/i},scale:i,animation:!1})}fitNetwork(){var t,e,i;if(this.zoomReturnView=void 0,!this.network)return;const o=null===(t=this.shadowRoot)||void 0===t?void 0:t.getElementById("zigbee-network");if(!o||!o.clientWidth||!o.clientHeight)return;this.network.redraw();const n=function(t,e,i,o=8){const n=t.filter((t=>Object.values(t).every(Number.isFinite)));if(!n.length||e<=2*o||i<=2*o)return;const r=Math.min(...n.map((t=>t.left))),s=Math.max(...n.map((t=>t.right))),a=Math.min(...n.map((t=>t.top))),l=Math.max(...n.map((t=>t.bottom))),h={x:(r+s)/2,y:(a+l)/2},c=2*Math.max(Math.abs(r-h.x),Math.abs(s-h.x)),d=2*Math.max(Math.abs(a-h.y),Math.abs(l-h.y));return{position:h,scale:Math.min((e-2*o)/Math.max(c,1),(i-2*o)/Math.max(d,1))}}([...(null!==(i=null===(e=this.visibleData)||void 0===e?void 0:e.nodes)&&void 0!==i?i:[]).map((t=>this.network.getBoundingBox(t.id))),...this.areaBounds()],o.clientWidth,o.clientHeight);n&&this.network.moveTo(Object.assign(Object.assign({},n),{animation:!1}))}hoverLink(t){var e;this.hoveredEdge!==t&&(this.hoveredEdge=t,this.showLabels||null===(e=this.network)||void 0===e||e.redraw())}drawLinkLabels(t){var e,i,o;if(!this.showLabels&&void 0===this.hoveredEdge||!this.network||!this.zigbeeData)return;const n=this.network,r=null===(e=this.shadowRoot)||void 0===e?void 0:e.getElementById("zigbee-network");if(!r)return;const s=n.getScale(),a=n.getPositions(),l=this.visibleData.nodes.map((t=>{const e=n.getBoundingBox(t.id),i=n.canvasToDOM({x:e.left,y:e.top}),o=n.canvasToDOM({x:e.right,y:e.bottom});return{left:i.x,top:i.y,right:o.x,bottom:o.y}})),h=(null===(i=this.config)||void 0===i?void 0:i.map_only)?null===(o=this.shadowRoot)||void 0===o?void 0:o.querySelector("footer.map-info"):void 0;if(h&&!h.hidden){const t=r.getBoundingClientRect(),e=h.getBoundingClientRect();l.push({left:e.left-t.left,right:e.right-t.left,top:e.top-t.top,bottom:e.bottom-t.top})}t.save(),t.font=14/s+"px system-ui, sans-serif";const c=[];for(const e of this.visibleData.edges){if(!e.label||!this.showLabels&&e.id!==this.hoveredEdge)continue;if(!a[e.from]||!a[e.to])continue;const i=F3(e.label,this.hass);c.push({id:e.id,text:i,width:t.measureText(i).width*s,from:n.canvasToDOM(a[e.from]),to:n.canvasToDOM(a[e.to])})}const d=function(t,e,i,o,n){const r=[];for(const s of t){let t;for(const a of[0,14,-14,26,-26,40,-40]){for(const l of[.5,.4,.6,.3,.7,.2,.8]){const h=L3(s.from,s.to,l,n),c=L3(s.from,s.to,l-.01,n),d=L3(s.from,s.to,l+.01,n),u=d.x-c.x,f=d.y-c.y,p=Math.hypot(u,f)||1,v={x:h.x-f/p*a,y:h.y+u/p*a},g={left:v.x-s.width/2-6,right:v.x+s.width/2+6,top:v.y-13,bottom:v.y+13};if(!(g.left<4||g.top<4||g.right>i-4||g.bottom>o-4||[...e,...r].some((t=>U3(g,t))))){t=Object.assign(Object.assign({},g),{id:s.id,text:s.text,anchor:h,center:v});break}}if(t)break}t&&r.push(t)}return r}(c,l,r.clientWidth,r.clientHeight,"vertical"===this.orientation),u=getComputedStyle(this),f=t=>u.getPropertyValue(t).trim(),p=f("--ha-tooltip-background-color")||f("--ha-color-surface-default")||f("--card-background-color")||"#fff",v=f("--ha-tooltip-text-color")||f("--primary-text-color")||this.textColor,g=parseFloat(f("--ha-tooltip-border-radius")||f("--ha-border-radius-md"))||4;t.textAlign="center",t.textBaseline="middle";for(const e of d){const i=n.DOMtoCanvas(e.center),o=n.DOMtoCanvas(e.anchor),r=n.DOMtoCanvas({x:e.left,y:e.top});t.strokeStyle=this.textColor,t.lineWidth=.5/s,t.beginPath(),t.moveTo(o.x,o.y),t.lineTo(i.x,i.y),t.stroke(),t.fillStyle=p,t.beginPath(),t.roundRect(r.x,r.y,(e.right-e.left)/s,(e.bottom-e.top)/s,Math.min(g,(e.bottom-e.top)/2)/s),t.fill(),t.fillStyle=v,t.fillText(e.text,i.x,i.y)}t.restore()}toggleLabels(){this.showLabels=!this.showLabels,this.drawNetwork(!0),this.saveLayoutClick(!0)}tidyLayout(){var t,e,i,o;this.zigbeeData&&(this.mapData=x3(null!==(t=this.mapData)&&void 0!==t?t:this.zigbeeData,this.orientation,null===(e=this.network)||void 0===e?void 0:e.getPositions(),null===(i=this.config)||void 0===i?void 0:i.group_by),this.areaPositions={},"area"!==(null===(o=this.config)||void 0===o?void 0:o.group_by)&&(this.zigbeeData=this.mapData),this.closeDeviceInfo(!1),this.areaDrag=void 0,this.drawNetwork(),this.spaceRenderedAreas(),this.fitNetwork())}spaceRenderedAreas(){var t,e;if(!this.network||"area"!==(null===(t=this.config)||void 0===t?void 0:t.group_by)||"pie"!==this.orientation)return;this.network.redraw();const i=this.visibleData,o=this.network.getPositions(),n=i.nodes.map((t=>Object.assign(Object.assign({},t),o[t.id]))),r=[...new Set(i.nodes.filter((t=>"Area"===t.group)).map((t=>{var e;return null!==(e=t.area_id)&&void 0!==e?e:""})))],s=this.areaBounds(),a=new Map(r.map(((t,e)=>[t,s[e]])));u(n,new Set(i.edges.map((t=>t.to))),(t=>{var e;const i=t[0],n=o[i.id],r=i.x-n.x,s=i.y-n.y,l="Controller"===i.group?this.network.getBoundingBox(i.id):a.get(null!==(e=i.area_id)&&void 0!==e?e:"");return{left:l.left+r,right:l.right+r,top:l.top+s,bottom:l.bottom+s}}));for(const t of n){if(t.x===o[t.id].x&&t.y===o[t.id].y)continue;this.network.moveNode(t.id,t.x,t.y),this.areaPositions[t.id]={x:t.x,y:t.y};const i=null===(e=this.mapData)||void 0===e?void 0:e.nodes.find((e=>e.id===t.id));i&&(i.x=t.x,i.y=t.y)}this.network.redraw()}get layoutKey(){var t,e,i,o,n,r,s;const a=`wiser-zigbee-layout:${JSON.stringify([location.pathname,null!==(e=null===(t=this.config)||void 0===t?void 0:t.hub)&&void 0!==e?e:"",null!==(o=null===(i=this.config)||void 0===i?void 0:i.name)&&void 0!==o?o:"Wiser Zigbee Network",null!==(r=null===(n=this.config)||void 0===n?void 0:n.layout_id)&&void 0!==r?r:""])}`,l="pie"===this.orientation?`${a}:pie`:"vertical"===this.orientation?`${a}:horizontal`:a;return"area"===(null===(s=this.config)||void 0===s?void 0:s.group_by)?`${l}:area-topology`:l}validPosition(t){return t&&Number.isFinite(t.x)&&Number.isFinite(t.y)?{x:t.x,y:t.y}:void 0}currentPositions(){var t,e;if(!this.network)return;const i={};for(const o of null!==(e=null===(t=this.mapData)||void 0===t?void 0:t.nodes)&&void 0!==e?e:[])i[o.id]={x:o.x,y:o.y};return Object.assign(Object.assign(Object.assign({},i),this.areaPositions),this.network.getPositions())}prepareConfirmation(t,e){var i,o;return function(t,e){if(!t)return()=>{};const i=t.ownerDocument,o=t.getBoundingClientRect(),n=getComputedStyle(t),r=["--ha-tooltip-background-color","--ha-tooltip-text-color","--ha-color-surface-default","--primary-text-color","--ha-font-family-body","--ha-tooltip-border-radius","--ha-border-radius-md"].map((t=>[t,n.getPropertyValue(t)]));return()=>{const t=i.createElement("div"),n=i.createElement("span"),s=i.createElement("ha-tooltip"),a=`wiser-confirm-${Math.random().toString(36).slice(2)}`;t.style.cssText=`position:fixed;left:${o.left}px;top:${o.top}px;width:${o.width}px;height:${o.height}px;pointer-events:none;z-index:1000`,r.forEach((([e,i])=>{i&&t.style.setProperty(e,i)})),n.id=a,n.style.cssText="display:block;width:100%;height:100%",s.for=a,s.trigger="manual",s.setAttribute("placement","bottom"),s.textContent=e,s.setAttribute("role","status"),t.append(n,s),i.body.append(t),s.open=!0,setTimeout((()=>t.remove()),2500)}}(null!==(o=null===(i=this.shadowRoot)||void 0===i?void 0:i.querySelector(`[data-action="${t}"]`))&&void 0!==o?o:null,this.t(e))}async copyLayout(){var t,e,i,o,n,r;const s=this.prepareConfirmation("common.copy","common.copied"),a=this.currentPositions();if(!a)return;const l=`magnifier: ${null!==(e=null===(t=this.config)||void 0===t?void 0:t.magnifier)&&void 0!==e&&e}\nshow_labels: ${this.showLabels}\nmap_only: ${null!==(o=null===(i=this.config)||void 0===i?void 0:i.map_only)&&void 0!==o&&o}\norientation: ${this.orientation}\ngroup_by: ${null!==(r=null===(n=this.config)||void 0===n?void 0:n.group_by)&&void 0!==r?r:"none"}\nlayout_data:\n`+Object.entries(a).map((([t,e])=>` ${JSON.stringify(t)}:\n x: ${Math.round(e.x)}\n y: ${Math.round(e.y)}`)).join("\n");try{await async function(t){var e,i;if(null===(e=navigator.clipboard)||void 0===e?void 0:e.writeText)try{return void await navigator.clipboard.writeText(t)}catch(t){}const o=document.createElement("textarea");o.value=t,o.readOnly=!0,o.style.cssText="position:fixed;top:0;left:0;opacity:0;pointer-events:none";const n=document.activeElement;try{if(document.body.appendChild(o),o.focus({preventScroll:!0}),o.select(),!document.execCommand("copy"))throw new Error("Clipboard copy failed")}finally{o.remove(),null===(i=null==n?void 0:n.focus)||void 0===i||i.call(n,{preventScroll:!0})}}(l),this.layoutStatus="",s()}catch(t){this.layoutStatus="layout.copy_error"}}async saveLayoutClick(t=!1){var e,i,o,n,r,s,l,h;const c=this.currentPositions();if(!c||!this.config)return;const d=t?()=>{}:this.prepareConfirmation("card.save_layout","common.saved");try{t||localStorage.setItem(this.layoutKey,JSON.stringify(c)),localStorage.setItem(`${this.layoutKey}:labels`,JSON.stringify(this.showLabels)),localStorage.setItem(`${this.layoutKey}:map-only`,JSON.stringify(null!==(e=this.config.map_only)&&void 0!==e&&e)),this.layoutStatus=""}catch(t){this.layoutStatus="layout.storage_error"}if(t||y3(this))Gt(this,"wiser-zigbee-save-layout",{layout_data:c,show_labels:this.showLabels,map_only:null!==(s=this.config.map_only)&&void 0!==s&&s,magnifier:null!==(l=this.config.magnifier)&&void 0!==l&&l,preferences_only:t,hub:this.config.hub,name:this.config.name,orientation:this.orientation,layout_id:this.config.layout_id,group_by:null!==(h=this.config.group_by)&&void 0!==h?h:"none"}),t||this.layoutStatus||d();else{if(this.savingConfig||!this.suppliedConfig)return;this.savingConfig=!0;try{this.suppliedConfig=await a(this,this.suppliedConfig,{show_labels:this.showLabels,magnifier:null!==(i=this.config.magnifier)&&void 0!==i&&i,map_only:null!==(o=this.config.map_only)&&void 0!==o&&o,layout_data:c,orientation:this.orientation,group_by:null!==(n=this.config.group_by)&&void 0!==n?n:"none",layout_orientation:void 0,layout_group_by:void 0}),this.config=Object.assign(Object.assign({},this.suppliedConfig),{auto_update:null===(r=this.suppliedConfig.auto_update)||void 0===r||r}),this.layoutStatus="",d()}catch(t){this.layoutStatus="layout.config_save_error"}finally{this.savingConfig=!1}}}renderZigbeeDetails(t){var e,i,o,n;const r=this.selectedEntity?null===(i=null===(e=this.hass)||void 0===e?void 0:e.states[this.selectedEntity])||void 0===i?void 0:i.attributes:void 0,s=null===(n=null===(o=this.zigbeeData)||void 0===o?void 0:o.edges.find((e=>e.from===t.id)))||void 0===n?void 0:n.to,a=C3(null==r?void 0:r.device_reception_RSSI,null==r?void 0:r.device_reception_LQI),l=C3(null==r?void 0:r.controller_reception_RSSI,null==r?void 0:r.controller_reception_LQI),h=[["zigbee.type",t.group],["zigbee.node",t.id],["zigbee.parent",s],["zigbee.channel",null==r?void 0:r.zigbee_channel],["zigbee.signal",(null==r?void 0:r.displayed_signal_strength)?P3(r.displayed_signal_strength,this.hass):void 0],["zigbee.device_rssi",null==a.rssi?void 0:`${a.rssi} dBm`],["zigbee.device_lqi",a.lqi],["zigbee.hub_rssi",null==l.rssi?void 0:`${l.rssi} dBm`],["zigbee.hub_lqi",l.lqi]];return X`
+ ${h.filter((([,t])=>null!=t)).map((([t,e])=>X`
+ ${this.t(t)}${e} +
`))} +
`}toggleViewMode(){this.config&&(this.config=Object.assign(Object.assign({},this.config),{map_only:!this.config.map_only}),this.saveLayoutClick(!0))}async openMagnifierMenu(t){var e;clearTimeout(this.magnifierHoldTimer),this.magnifierHeld=!0;const i=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector("#magnifier-menu");i&&(await i.updateComplete,i.anchorElement=t.querySelector("ha-icon-button"),i.open=!0)}magnifierControl(){var t,e;return X`{if(!this.network||0!==t.button)return;clearTimeout(this.magnifierHoldTimer),this.magnifierHeld=!1;const e=t.currentTarget;this.magnifierHoldTimer=setTimeout((()=>{this.openMagnifierMenu(e)}),500)}} + @pointerup=${()=>clearTimeout(this.magnifierHoldTimer)} + @pointerleave=${()=>clearTimeout(this.magnifierHoldTimer)} + @pointercancel=${()=>clearTimeout(this.magnifierHoldTimer)} + @contextmenu=${t=>{t.preventDefault(),this.network&&this.openMagnifierMenu(t.currentTarget)}} + @keydown=${t=>{"ArrowDown"===t.key&&this.network&&(t.preventDefault(),this.openMagnifierMenu(t.currentTarget))}} + >${this.layoutIcon("editor.magnifier","M9.5 3a6.5 6.5 0 1 0 3.98 11.64L19.85 21 21 19.85l-6.36-6.37A6.5 6.5 0 0 0 9.5 3m0 2a4.5 4.5 0 1 1 0 9 4.5 4.5 0 0 1 0-9m-1 1v2.5H6V10h2.5v2.5H10V10h2.5V8.5H10V6Z",(()=>{var t;this.config=Object.assign(Object.assign({},this.config),{magnifier:!(null===(t=this.config)||void 0===t?void 0:t.magnifier)}),this.magnifier.hide(),this.saveLayoutClick(!0)}),null!==(e=null===(t=this.config)||void 0===t?void 0:t.magnifier)&&void 0!==e&&e)} + {this.magnifier.setZoom(Number(t.detail.item.value)),this.requestUpdate()}} + @wa-after-hide=${()=>{var t,e,i;const o=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("#magnifier-menu");(null==o?void 0:o.anchorElement)&&(o.anchorElement.selected=null!==(i=null===(e=this.config)||void 0===e?void 0:e.magnifier)&&void 0!==i&&i)}} + > +
+
+ ${[2,3,4].map((t=>X`${t}×`))} +
+
t.stopPropagation()} + @keydown=${t=>{"Escape"!==t.key&&"Tab"!==t.key&&t.stopPropagation()}} + > + {this.magnifier.setSize(Number(t.target.value)),this.requestUpdate()}} + > + ${this.magnifier.size} px +
+
+
`}layoutIcon(t,e,i,o,n=!this.network){const r=this.t(t),s=null!=o?o:"common.refresh"===t?this.loading:this.activeIcon===t;return X`{n||("editor.magnifier"===t&&this.magnifierHeld?this.magnifierHeld=!1:(void 0===o&&"common.refresh"!==t&&(clearTimeout(this.activeIconTimer),this.activeIcon=t,this.activeIconTimer=setTimeout((()=>{this.activeIcon=void 0}),500)),i()))}} + >`}render(){var t,e,i,o,n,r,s,a,l,h,c,d,u,f,p,v,g,y,m,b;const w=null!==(e=null===(t=this.zigbeeData)||void 0===t?void 0:t.nodes)&&void 0!==e?e:[],A=null!==(o=null===(i=this.zigbeeData)||void 0===i?void 0:i.edges)&&void 0!==o?o:[],E=w.find((t=>t.id===this.selected));return X` +
+
WISER · ZIGBEE
+
+ ${this.layoutIcon("common.refresh","M17.65,6.35C16.2,4.9 14.21,4 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20C15.73,20 18.84,17.45 19.73,14H17.65C16.83,16.33 14.61,18 12,18A6,6 0 0,1 6,12A6,6 0 0,1 12,6C13.66,6 15.14,6.69 16.22,7.78L13,11H20V4L17.65,6.35Z",(()=>{this.loadData()}),void 0,this.loading)} + ${this.layoutIcon("card.fit","M3 3H9V5H5V9H3V3M15 3H21V9H19V5H15V3M3 15H5V19H9V21H3V15M19 15H21V21H15V19H19V15Z",(()=>this.fitNetwork()))} + ${this.layoutIcon("card.zoom_in","M19 13H13V19H11V13H5V11H11V5H13V11H19V13Z",(()=>this.zoomStep(1.1)))} + ${this.layoutIcon("card.zoom_out","M19 13H5V11H19V13Z",(()=>this.zoomStep(.8)))} + ${this.layoutIcon("card.tidy","M3 3H10V10H3V3M14 3H21V10H14V3M3 14H10V21H3V14M14 14H21V21H14V14Z",(()=>this.tidyLayout()))} + ${this.layoutIcon("card.link_labels","M17.63 5.84C17.27 5.33 16.67 5 16 5H5C3.9 5 3 5.9 3 7V17C3 18.1 3.9 19 5 19H16C16.67 19 17.27 18.67 17.63 18.16L22 12L17.63 5.84Z",(()=>this.toggleLabels()),this.showLabels)} + ${this.magnifierControl()} + ${this.layoutIcon("card.show_detailed_view","M3 3H21V21H3V3M5 5V7H19V5H5M5 9V19H19V9H5Z",(()=>this.toggleViewMode()),!(null!==(s=null===(r=this.config)||void 0===r?void 0:r.map_only)&&void 0!==s&&s),!this.config)} + ${this.layoutIcon("common.copy","M19 21H8V7H19M19 5H8A2 2 0 0 0 6 7V21A2 2 0 0 0 8 23H19A2 2 0 0 0 21 21V7A2 2 0 0 0 19 5M16 1H4A2 2 0 0 0 2 3V17H4V3H16Z",(()=>{this.copyLayout()}))} + ${this.layoutIcon("card.save_layout","M17,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V7L17,3M12,19A3,3 0 0,1 9,16A3,3 0 0,1 12,13A3,3 0 0,1 15,16A3,3 0 0,1 12,19M15,9H5V5H15V9Z",(()=>this.saveLayoutClick()))}
-
-
+
+ ${this.layoutStatus?X`

+ ${this.t(this.layoutStatus)} +

`:""} +
+
+ ${""===(null===(l=this.config)||void 0===l?void 0:l.name)?"":X`

${null!==(c=null===(h=this.config)||void 0===h?void 0:h.name)&&void 0!==c?c:this.t("card.title")}

`} +

+ ${z3("devices",w.length,this.hass)} + · ${z3("connections",A.length,this.hass)} +

- ${!this.config.auto_update||this.is_preview?this.render_card_actions():""} - - `}render_card_actions(){return $` -
- ${this.is_preview?this.render_save_layout_button():""} - ${!this.config.auto_update||this.is_preview?this.render_refresh_button():""} +
+
+
{var e;(null===(e=this.config)||void 0===e?void 0:e.magnifier)&&this.magnifier.show(t.currentTarget,t)}} + @pointerleave=${()=>this.magnifier.hide()} + @pointerdown=${()=>this.magnifier.hide()} + @wheel=${this.panZoomedView} + @touchstart=${this.touchZoomStart} + role="img" + aria-label=${this.t((null===(d=this.config)||void 0===d?void 0:d.map_only)?"map.accessible_only":!1!==(null===(u=this.config)||void 0===u?void 0:u.show_device_list)?"map.accessible_list":"map.accessible_details")} + >
+ ${"area"===(null===(f=this.config)||void 0===f?void 0:f.group_by)?X` + + `:""} + ${this.error?X``:this.loading?X`
+ ${this.t("card.updating")} +
`:w.length?"":X`
${this.t("card.empty")}
`}
- `}render_refresh_button(){return $` - - ${this.hass.localize("ui.common.refresh")} - - `}render_save_layout_button(){return $` - Save Layout - `}async refreshClick(){await this.loadData()}async saveLayoutClick(){var t;this.layoutData=null===(t=this.network)||void 0===t?void 0:t.getPositions(),this.config.layout_data=this.layoutData,Ht(this,"wiser-zigbee-save-layout",{layout_data:this.layoutData}),this.need_render=!0,await this.loadData()}},t.WiserZigbeeCard.style=ht` - .zigbee-network { - width: 600px; - height: 400px; - border: 1px solid lightgray; +
+ ${E?X`
+ ${this.deviceName(E)} ${function(t,e,i,o=!1){return X`${t}`}(this.t("common.close"),(()=>{this.closeDeviceInfo()}))} +
+ ${this.renderZigbeeDetails(E)} + ${A.filter((t=>t.from===E.id||t.to===E.id)).map((t=>X`
+ ${this.deviceName(w.find((e=>e.id===(t.from===E.id?t.to:t.from))))}${P3(t.label,this.hass)} +
`))}`:X`

${this.t("card.hint")}

`} + ${(null===(m=this.config)||void 0===m?void 0:m.map_only)||!1===(null===(b=this.config)||void 0===b?void 0:b.show_device_list)?"":(k=this.t("layout.device_list"),C=X` ${w.map((t=>X`
+ ${this.deviceName(t)} ${A.filter((e=>e.from===t.id)).map((t=>X`
+ → + ${this.deviceName(w.find((e=>e.id===t.to)))}${P3(t.label,this.hass)} +
`))} +
`))}`,X`
${C}
`)} +
+ `;var k,C}}return Q3.panelApiVersion=1,Q3.styles=wt` + :host { + display: block; + min-width: 0; + max-width: 100%; + --wiser-muted: var(--secondary-text-color, #7d8795); + } + ha-card { + display: block; + overflow: hidden; + border-radius: var(--ha-card-border-radius, 20px); + color: var(--primary-text-color, #273448); + background: var(--ha-card-background, var(--card-background-color, #fff)); + } + :host(:has(ha-card.auto-height)) { + height: 100%; + min-height: 0; + } + ha-card.auto-height { + height: 100%; + box-sizing: border-box; + display: flex; + flex-direction: column; + } + .auto-height > .brand-row, + .auto-height > header, + .auto-height > .save-status { + flex-shrink: 0; + } + .auto-height .map { + flex: 1 1 340px; + min-height: 100px; + } + .auto-height #zigbee-network { + position: absolute; + inset: 0; + height: 100%; + } + .auto-height > footer:not(.map-info) { + flex: 0 1 auto; + min-height: 0; + max-height: 45%; + overflow-y: auto; + } + [hidden] { + display: none !important; + } + .brand-row { + display: flex; + flex-wrap: wrap; + gap: 4px; + align-items: center; + justify-content: space-between; + padding: 12px 12px 0 24px; + } + .layout-actions { + display: flex; + flex-wrap: wrap; + margin-left: auto; + } + .layout-icon { + --ha-icon-button-size: 36px; + --mdc-icon-button-size: 36px; + --mdc-icon-size: 20px; + --ha-icon-size: 20px; + border-radius: 50%; + } + .brand-row .eyebrow { + margin: 0; + } + .brand-row .layout-icon { + color: var(--wiser-muted); + --mdc-icon-button-icon-color: var(--wiser-muted); + } + .save-status { + padding: 0 24px; + } + + .map-only .map { + margin: 4px 12px; + } + header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + padding: 8px 24px 18px; + } + .eyebrow { + font-size: 10px; + letter-spacing: 1.8px; + font-weight: 700; + color: var(--wiser-muted); + margin-bottom: 8px; + } + h2 { + font-size: 20px; + line-height: 1.3; + font-weight: 600; + margin: 0; + letter-spacing: -0.4px; + } + p { + margin: 8px 0 0; + font-size: 12px; + color: var(--wiser-muted); + } + p span { + margin: 0 6px; + } + .map { + position: relative; + margin: 0 12px; + background: transparent; + } + #zigbee-network { + width: 100%; + height: 340px; + } + .area-icons { + position: absolute; + inset: 0; + overflow: hidden; + pointer-events: none; + color: var(--primary-text-color); + } + .area-icons ha-icon, .magnifier-area-icons ha-icon { + position: absolute; + transform: translate(-50%, -50%); + pointer-events: none; + } + #magnifier-menu { position: absolute; } + .magnifier-options { display: flex; align-items: stretch; } + .magnifier-zoom-options { width: 64px; display: flex; flex-direction: column; } + .lens-size-control { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 4px; + padding: 4px 8px; + border-left: 1px solid var(--divider-color); + color: var(--primary-text-color); + } + .lens-size-control ha-slider { + display: block; + width: 36px; + min-width: 0; + height: 80px; + min-height: 0; + flex: none; + } + .lens-size-control ha-slider::part(slider) { + justify-content: center; + padding: 8px 0; + margin: 0; + } + .lens-size-control ha-slider::part(track) { height: 64px; } + .lens-size-control span { font-size: 12px; color: var(--secondary-text-color); } + .map-magnifier { + position: absolute; + z-index: 2; + overflow: hidden; + border-radius: 50%; + outline: 2px solid var(--primary-color); + box-shadow: 0 3px 12px rgb(0 0 0 / 35%); + background: var(--ha-card-background, var(--card-background-color, #fff)); + pointer-events: none; + } + .magnifier-area-icons { + position: absolute; + left: 0; + top: 0; + transform-origin: 0 0; + color: var(--primary-text-color); + pointer-events: none; + } + .message { + position: absolute; + top: 12px; + left: 12px; + right: 12px; + text-align: center; + padding: 10px; + border-radius: 8px; + background: var(--card-background-color, #fff); + font-size: 12px; + pointer-events: none; + } + footer { + padding: 16px 24px 20px; + } + ha-card.map-only { + position: relative; + } + .map-only footer.map-info { + position: absolute; + z-index: 1; + inset: auto 12px 12px; + box-sizing: border-box; + max-height: 60%; + overflow-y: auto; + overscroll-behavior: contain; + padding: 16px; + border: 1px solid var(--divider-color); + border-radius: var(--ha-card-border-radius, 12px); + background: var(--ha-card-background, var(--card-background-color, #fff)); + color: var(--primary-text-color); + box-shadow: var(--ha-card-box-shadow, 0 2px 8px rgb(0 0 0 / 15%)); + } + .map-info .selection { + position: sticky; + top: -16px; + padding: 8px 0; + background: var(--ha-card-background, var(--card-background-color, #fff)); + } + .hint { + margin: 0; + line-height: 1.5; + } + .selection, + .connection { + display: flex; + justify-content: space-between; + align-items: center; + gap: 12px; + font-size: 12px; + } + .connection { + padding: 8px 0; + color: var(--wiser-muted); + } + .connection strong { + font-weight: 500; + text-align: right; + } + ha-expansion-panel { + display: block; + margin-top: 14px; + --ha-card-background: transparent; + } + .panel-content { + padding: 0 12px 12px; + } + ha-textarea { + display: block; + width: 100%; + margin-top: 12px; + } + ha-button { + flex-shrink: 0; + } + .panel-content ha-button { + margin-top: 12px; + } + .device { + border-top: 1px solid var(--divider-color); + padding: 12px 0; + } + @media (max-width: 400px) { + [hidden] { + display: none !important; + } + .map-brand { + padding: 24px 24px 0; + } + .map-only .map { + margin: 4px 12px; + } + header { + padding: 20px 16px 16px; + } + footer { + padding: 16px; + } + h2 { + font-size: 18px; + } } - `,o([Rt()],t.WiserZigbeeCard.prototype,"config",void 0),o([Rt()],t.WiserZigbeeCard.prototype,"zigbeeData",void 0),o([Rt()],t.WiserZigbeeCard.prototype,"_helpers",void 0),t.WiserZigbeeCard=o([St("wiser-zigbee-card")],t.WiserZigbeeCard),t}({}); + `,e([Lt()],Q3.prototype,"config",void 0),e([Lt()],Q3.prototype,"zigbeeData",void 0),e([Lt()],Q3.prototype,"loading",void 0),e([Lt()],Q3.prototype,"error",void 0),e([Lt()],Q3.prototype,"showLabels",void 0),e([Lt()],Q3.prototype,"activeIcon",void 0),e([Lt()],Q3.prototype,"selected",void 0),e([Lt()],Q3.prototype,"selectedEntity",void 0),e([Lt()],Q3.prototype,"layoutStatus",void 0),e([Qt({capture:!0,passive:!0})],Q3.prototype,"touchZoomStart",null),e([Qt({capture:!0,passive:!1})],Q3.prototype,"panZoomedView",null),customElements.get("wiser-zigbee-card")||customElements.define("wiser-zigbee-card",Q3),t.WiserZigbeeCard=Q3,t}({}); diff --git a/custom_components/wiser/frontend/zigbee_sidebar.py b/custom_components/wiser/frontend/zigbee_sidebar.py new file mode 100644 index 00000000..e7cb3c08 --- /dev/null +++ b/custom_components/wiser/frontend/zigbee_sidebar.py @@ -0,0 +1,153 @@ +"""Manage the shared Wiser zigbee sidebar panel.""" + +import math +from pathlib import Path + +from homeassistant.components import frontend, panel_custom + +from .zigbee_version import zigbee_card_version + +from ..const import ( + CONF_SHOW_ZIGBEE_SIDEBAR, CONF_ZIGBEE_PANEL_CONFIG, + DATA, DOMAIN, JSMODULES, URL_BASE, +) + +PANEL_PATH = "wiser-zigbee" +PANEL_STATE = "wiser_zigbee_panel" + + +async def async_update_zigbee_panel(hass): + """Show zigbee for loaded hubs that have opted into the sidebar.""" + loaded = hass.data.get(DOMAIN, {}) + hubs = [ + loaded[entry.entry_id][DATA].wiserhub.system.name + for entry in hass.config_entries.async_entries(DOMAIN) + if entry.entry_id in loaded + and not entry.disabled_by + and entry.options.get(CONF_SHOW_ZIGBEE_SIDEBAR, False) + ] + card_configs = { + loaded[entry.entry_id][DATA].wiserhub.system.name: + dict(entry.options.get(CONF_ZIGBEE_PANEL_CONFIG, {})) + for entry in hass.config_entries.async_entries(DOMAIN) + if entry.entry_id in loaded + and loaded[entry.entry_id][DATA].wiserhub.system.name in hubs + } + state = {"hubs": hubs, "card_configs": card_configs} + if hubs: + card = next( + module for module in JSMODULES + if module["filename"] == "wiser-zigbee-card.js" + ) + version = await hass.async_add_executor_job( + zigbee_card_version, + Path(__file__).parent / card["filename"], + ) + state["card_url"] = f"{URL_BASE}/{card['filename']}?v={version}" + if state == hass.data.get(PANEL_STATE) or (not hubs and PANEL_STATE not in hass.data): + return + + if not hubs and PANEL_STATE in hass.data: + frontend.async_remove_panel(hass, PANEL_PATH) + hass.data.pop(PANEL_STATE) + + if hubs: + config = dict(state) + module_url = config["card_url"] + if PANEL_STATE in hass.data: + # Keep the route registered while notifying clients of new settings. + frontend.async_register_built_in_panel( + hass, + component_name="custom", + frontend_url_path=PANEL_PATH, + sidebar_title="Wiser Zigbee", + sidebar_icon="mdi:zigbee", + config={ + **config, + "_panel_custom": { + "name": "wiser-zigbee-panel", + "module_url": module_url, + "embed_iframe": False, + "trust_external": False, + }, + }, + update=True, + ) + else: + await panel_custom.async_register_panel( + hass, + frontend_url_path=PANEL_PATH, + webcomponent_name="wiser-zigbee-panel", + sidebar_title="Wiser Zigbee", + sidebar_icon="mdi:zigbee", + module_url=module_url, + config=config, + ) + hass.data[PANEL_STATE] = state + + +def save_zigbee_panel_config(hass, configs): + """Validate all submitted settings before updating integration options.""" + loaded = hass.data.get(DOMAIN, {}) + entries = { + loaded[entry.entry_id][DATA].wiserhub.system.name: entry + for entry in hass.config_entries.async_entries(DOMAIN) + if entry.entry_id in loaded + and not entry.disabled_by + and entry.options.get(CONF_SHOW_ZIGBEE_SIDEBAR, False) + } + field_types = { + "name": str, "layout_id": str, "layout_seed": str, + "auto_update": bool, "log_seed": bool, "map_only": bool, + "show_device_list": bool, "show_labels": bool, "magnifier": bool, + "orientation": str, "group_by": str, "link_status": str, + "map_height": (int, type(None)), "layout_data": dict, + } + choices = { + "orientation": {"vertical", "horizontal", "pie"}, + "group_by": {"none", "area"}, + "link_status": {"links", "icons", "both", "none"}, + } + updates = [] + for hub, config in configs.items(): + if hub not in entries: + raise ValueError("Hub is not enabled in the zigbee panel") + settings = {} + for key, value in config.items(): + if key in {"type", "hub"}: + continue + if key not in field_types or type(value) not in (field_types[key] if isinstance(field_types[key], tuple) else (field_types[key],)): + raise ValueError(f"Invalid Zigbee card setting: {key}") + if key in choices and value not in choices[key]: + raise ValueError(f"Invalid Zigbee card setting: {key}") + if key == "map_height" and value is not None and not 100 <= value <= 2000: + raise ValueError("Map height must be between 100 and 2000") + if key == "layout_data": + for position in value.values(): + if not isinstance(position, dict) or set(position) != {"x", "y"}: + raise ValueError("Invalid layout position") + if any(type(n) not in (int, float) or not math.isfinite(n) for n in position.values()): + raise ValueError("Invalid layout coordinates") + settings[key] = value + updates.append((entries[hub], settings)) + for entry, settings in updates: + hass.config_entries.async_update_entry( + entry, options={**entry.options, CONF_ZIGBEE_PANEL_CONFIG: settings} + ) + + +def integration_reload_settings(entry): + """Exclude panel-only preferences from integration reload decisions.""" + return (dict(entry.data), { + key: value for key, value in entry.options.items() + if key != CONF_ZIGBEE_PANEL_CONFIG + }) + + +async def async_handle_entry_update(hass, entry): + """Save panel preferences live; reload for connection and entity options.""" + loaded = hass.data.get(DOMAIN, {}).get(entry.entry_id) + if loaded is not None and loaded.get("reload_settings") == integration_reload_settings(entry): + await async_update_zigbee_panel(hass) + return + await hass.config_entries.async_reload(entry.entry_id) diff --git a/custom_components/wiser/frontend/zigbee_version.py b/custom_components/wiser/frontend/zigbee_version.py index 4afa476c..8da34fec 100644 --- a/custom_components/wiser/frontend/zigbee_version.py +++ b/custom_components/wiser/frontend/zigbee_version.py @@ -8,12 +8,12 @@ _VERSION = r"\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?" -def zigbee_card_version(path: Path, fallback: str) -> str: +def zigbee_card_version(path: Path) -> str: """Resolve the card's banner variable, ignoring bundled library versions.""" try: contents = path.read_bytes() except OSError: - return fallback + return "missing" source = contents.decode("utf-8", errors="replace") # Explicit build metadata is authoritative; legacy parsing remains below. marker = re.search( diff --git a/custom_components/wiser/strings.json b/custom_components/wiser/strings.json index 4c368777..83150e7f 100755 --- a/custom_components/wiser/strings.json +++ b/custom_components/wiser/strings.json @@ -59,6 +59,7 @@ "description": "Main Parameters", "data": { "show_schedules_sidebar": "Show Wiser Schedules in sidebar", + "show_zigbee_sidebar": "Show Wiser Zigbee in sidebar", "host": "IP Address or Hostname", "port": "Port number", "scan_interval": "Scan Interval (secs)", diff --git a/custom_components/wiser/translations/de.json b/custom_components/wiser/translations/de.json index 793af578..a72204ea 100644 --- a/custom_components/wiser/translations/de.json +++ b/custom_components/wiser/translations/de.json @@ -59,6 +59,7 @@ "description": "Hauptparameter", "data": { "show_schedules_sidebar": "Wiser-Zeitpläne in der Seitenleiste anzeigen", + "show_zigbee_sidebar": "Wiser Zigbee in der Seitenleiste anzeigen", "host": "IP Adresse", "port": "Portnummer", "scan_interval": "Scan Intervall", diff --git a/custom_components/wiser/translations/en.json b/custom_components/wiser/translations/en.json index a9092523..0d5bce28 100755 --- a/custom_components/wiser/translations/en.json +++ b/custom_components/wiser/translations/en.json @@ -59,6 +59,7 @@ "description": "Main Parameters", "data": { "show_schedules_sidebar": "Show Wiser Schedules in sidebar", + "show_zigbee_sidebar": "Show Wiser Zigbee in sidebar", "host": "IP Address or Hostname", "port": "Port number", "scan_interval": "Scan Interval (secs)", diff --git a/custom_components/wiser/translations/fr.json b/custom_components/wiser/translations/fr.json index 2b831123..a60ba92b 100644 --- a/custom_components/wiser/translations/fr.json +++ b/custom_components/wiser/translations/fr.json @@ -59,6 +59,7 @@ "description": "Paramètres principaux", "data": { "show_schedules_sidebar": "Afficher les programmes Wiser dans la barre latérale", + "show_zigbee_sidebar": "Afficher Wiser Zigbee dans la barre latérale", "host": "Adresse IP ou nom d'hote", "port": "Numéro de port", "scan_interval": " Période d'acquisition", diff --git a/custom_components/wiser/websockets.py b/custom_components/wiser/websockets.py index 5e2d8983..a53033c7 100644 --- a/custom_components/wiser/websockets.py +++ b/custom_components/wiser/websockets.py @@ -11,6 +11,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect from .const import DATA, DOMAIN from .frontend.sidebar import save_schedules_panel_config +from .frontend.zigbee_sidebar import save_zigbee_panel_config _LOGGER = logging.getLogger(__name__) @@ -92,6 +93,21 @@ def websocket_configure_schedules_panel(hass, connection, msg): return connection.send_result(msg["id"]) + @callback + @websocket_api.websocket_command({ + vol.Required("type"): "wiser/zigbee_panel/configure", + vol.Required("configs"): {str: dict}, + }) + @websocket_api.require_admin + def websocket_configure_zigbee_panel(hass, connection, msg): + """Save shared panel preferences in the Wiser config entries.""" + try: + save_zigbee_panel_config(hass, msg["configs"]) + except ValueError as err: + connection.send_error(msg["id"], "invalid_config", str(err)) + return + connection.send_result(msg["id"]) + # Get Hubs @websocket_api.websocket_command( { @@ -557,6 +573,7 @@ async def websocket_get_zigbee_data( connection.send_error(msg["id"], "wiser error", "hub not recognised") async_register_command(hass, websocket_configure_schedules_panel) + async_register_command(hass, websocket_configure_zigbee_panel) async_register_command(hass, websocket_get_hubs) async_register_command(hass, websocket_get_suntimes) async_register_command(hass, websocket_get_schedules) diff --git a/tests/test_schedules_sidebar.py b/tests/test_schedules_sidebar.py index bfb9dda3..710485ad 100644 --- a/tests/test_schedules_sidebar.py +++ b/tests/test_schedules_sidebar.py @@ -24,6 +24,10 @@ def setUp(self): constants = ModuleType("sidebar_test.const") constants.CONF_SHOW_SCHEDULES_SIDEBAR = "show_schedules_sidebar" constants.CONF_SCHEDULES_PANEL_CONFIG = "schedules_panel_config" + constants.CONF_ZIGBEE_PANEL_CONFIG = "zigbee_panel_config" + zigbee = ModuleType("sidebar_test.frontend.zigbee_sidebar") + self.update_zigbee = AsyncMock() + zigbee.async_update_zigbee_panel = self.update_zigbee version_module = ModuleType("sidebar_test.frontend.schedule_version") self.version_reader = Mock(return_value="4.5.6-beta.2") version_module.schedule_card_version = self.version_reader @@ -39,6 +43,7 @@ def setUp(self): "sidebar_test": ModuleType("sidebar_test"), "sidebar_test.frontend": ModuleType("sidebar_test.frontend"), "sidebar_test.const": constants, + "sidebar_test.frontend.zigbee_sidebar": zigbee, "sidebar_test.frontend.schedule_version": version_module, }): spec = importlib.util.spec_from_file_location( @@ -197,3 +202,12 @@ async def test_new_bundle_updates_panel_version(self): config = self.frontend.async_register_built_in_panel.call_args.kwargs["config"] self.assertEqual(config["card_url"], "/wiser/wiser-schedule-card.js?v=4.5.6-beta.3") self.assertEqual(config["_panel_custom"]["module_url"], config["card_url"]) + + async def test_zigbee_preferences_update_both_panels_without_reload(self): + entry = self.add_hub("hub", True) + self.hass.data["wiser"]["hub"]["reload_settings"] = self.sidebar.integration_reload_settings(entry) + self.hass.config_entries.async_reload = AsyncMock() + entry.options["zigbee_panel_config"] = {"show_labels": True} + await self.sidebar.async_handle_entry_update(self.hass, entry) + self.update_zigbee.assert_awaited_once_with(self.hass) + self.hass.config_entries.async_reload.assert_not_called() diff --git a/tests/test_zigbee_sidebar.py b/tests/test_zigbee_sidebar.py new file mode 100644 index 00000000..613f6ef8 --- /dev/null +++ b/tests/test_zigbee_sidebar.py @@ -0,0 +1,212 @@ +"""Test sidebar panel lifecycle without Home Assistant runtime dependencies.""" + +import importlib.util +from pathlib import Path +import sys +from types import ModuleType, SimpleNamespace +import unittest +from unittest.mock import AsyncMock, Mock, patch + + +ROOT = Path(__file__).resolve().parents[1] / "custom_components/wiser" + + +class ZigbeeSidebarTest(unittest.IsolatedAsyncioTestCase): + def setUp(self): + self.frontend = ModuleType("homeassistant.components.frontend") + self.frontend.async_remove_panel = Mock() + self.frontend.async_register_built_in_panel = Mock() + self.custom = ModuleType("homeassistant.components.panel_custom") + self.custom.async_register_panel = AsyncMock() + components = ModuleType("homeassistant.components") + components.frontend = self.frontend + components.panel_custom = self.custom + constants = ModuleType("sidebar_test.const") + constants.CONF_SHOW_ZIGBEE_SIDEBAR = "show_zigbee_sidebar" + constants.CONF_ZIGBEE_PANEL_CONFIG = "zigbee_panel_config" + version_module = ModuleType("sidebar_test.frontend.zigbee_version") + self.version_reader = Mock(return_value="4.5.6-beta.2") + version_module.zigbee_card_version = self.version_reader + constants.DATA = "data" + constants.DOMAIN = "wiser" + constants.URL_BASE = "/wiser" + constants.JSMODULES = [ + {"filename": "wiser-zigbee-card.js"} + ] + with patch.dict(sys.modules, { + "homeassistant": ModuleType("homeassistant"), + "homeassistant.components": components, + "sidebar_test": ModuleType("sidebar_test"), + "sidebar_test.frontend": ModuleType("sidebar_test.frontend"), + "sidebar_test.const": constants, + "sidebar_test.frontend.zigbee_version": version_module, + }): + spec = importlib.util.spec_from_file_location( + "sidebar_test.frontend.sidebar", ROOT / "frontend/zigbee_sidebar.py" + ) + self.sidebar = importlib.util.module_from_spec(spec) + spec.loader.exec_module(self.sidebar) + self.entries = [] + self.hass = SimpleNamespace( + data={"wiser": {}}, + async_add_executor_job=AsyncMock(side_effect=lambda fn, *args: fn(*args)), + config_entries=SimpleNamespace(async_entries=lambda _: self.entries), + ) + + def add_hub(self, name, enabled=None, loaded=True, disabled=False): + entry = SimpleNamespace( + entry_id=name, disabled_by=disabled, data={"host": "hub.local"}, + options={} if enabled is None else {"show_zigbee_sidebar": enabled}, + ) + self.entries.append(entry) + if loaded: + self.hass.data["wiser"][name] = { + "data": SimpleNamespace(wiserhub=SimpleNamespace( + system=SimpleNamespace(name=name) + )) + } + return entry + + async def test_default_disabled_and_unloaded_hubs_do_not_register(self): + self.add_hub("default") + self.add_hub("off", False) + self.add_hub("unloaded", True, loaded=False) + self.add_hub("disabled", True, disabled=True) + await self.sidebar.async_update_zigbee_panel(self.hass) + self.custom.async_register_panel.assert_not_called() + self.frontend.async_remove_panel.assert_not_called() + + async def test_enable_registers_dedicated_panel_once(self): + self.add_hub("hub", True) + await self.sidebar.async_update_zigbee_panel(self.hass) + await self.sidebar.async_update_zigbee_panel(self.hass) + self.custom.async_register_panel.assert_awaited_once() + args = self.custom.async_register_panel.call_args.kwargs + self.assertEqual(args["frontend_url_path"], "wiser-zigbee") + self.assertEqual(args["webcomponent_name"], "wiser-zigbee-panel") + self.assertEqual(args["config"]["hubs"], ["hub"]) + self.assertEqual(args["config"]["card_url"], "/wiser/wiser-zigbee-card.js?v=4.5.6-beta.2") + + async def test_disable_last_hub_removes_panel(self): + entry = self.add_hub("hub", True) + await self.sidebar.async_update_zigbee_panel(self.hass) + entry.options["show_zigbee_sidebar"] = False + await self.sidebar.async_update_zigbee_panel(self.hass) + self.frontend.async_remove_panel.assert_called_once_with(self.hass, "wiser-zigbee") + self.assertNotIn(self.sidebar.PANEL_STATE, self.hass.data) + + async def test_unload_keeps_other_hub_then_removes_last(self): + self.add_hub("first", True) + self.add_hub("second", True) + await self.sidebar.async_update_zigbee_panel(self.hass) + self.hass.data["wiser"].pop("first") + await self.sidebar.async_update_zigbee_panel(self.hass) + self.assertEqual( + self.frontend.async_register_built_in_panel.call_args.kwargs["config"]["hubs"], + ["second"], + ) + self.hass.data["wiser"].pop("second") + await self.sidebar.async_update_zigbee_panel(self.hass) + self.assertNotIn(self.sidebar.PANEL_STATE, self.hass.data) + + async def test_registration_failure_can_be_retried(self): + self.add_hub("hub", True) + self.custom.async_register_panel.side_effect = ValueError("registration failed") + with self.assertRaises(ValueError): + await self.sidebar.async_update_zigbee_panel(self.hass) + self.assertNotIn(self.sidebar.PANEL_STATE, self.hass.data) + self.custom.async_register_panel.side_effect = None + await self.sidebar.async_update_zigbee_panel(self.hass) + self.assertEqual(self.hass.data[self.sidebar.PANEL_STATE]["hubs"], ["hub"]) + + async def test_saved_config_is_sent_to_panel(self): + entry = self.add_hub("hub", True) + entry.options["zigbee_panel_config"] = {"show_labels": True} + await self.sidebar.async_update_zigbee_panel(self.hass) + self.assertEqual( + self.custom.async_register_panel.call_args.kwargs["config"]["card_configs"], + {"hub": {"show_labels": True}}, + ) + + def test_save_preserves_other_options(self): + entry = self.add_hub("hub", True) + entry.options["scan_interval"] = 30 + self.hass.config_entries.async_update_entry = Mock() + self.sidebar.save_zigbee_panel_config(self.hass, { + "hub": {"type": "custom:wiser-zigbee-card", "hub": "hub", "show_labels": True}, + }) + options = self.hass.config_entries.async_update_entry.call_args.kwargs["options"] + self.assertEqual(options["scan_interval"], 30) + self.assertTrue(options["show_zigbee_sidebar"]) + self.assertEqual(options["zigbee_panel_config"], {"show_labels": True}) + + def test_invalid_settings_do_not_partially_save(self): + self.add_hub("first", True) + self.add_hub("second", True) + self.hass.config_entries.async_update_entry = Mock() + with self.assertRaises(ValueError): + self.sidebar.save_zigbee_panel_config(self.hass, { + "first": {"name": "Valid"}, "second": {"show_labels": "invalid"}, + }) + self.hass.config_entries.async_update_entry.assert_not_called() + + def test_current_external_card_editor_options_are_supported(self): + self.add_hub("hub", True) + self.hass.config_entries.async_update_entry = Mock() + settings = {"orientation": "pie", "map_only": True, "show_labels": True, "layout_data": {"1": {"x": 12, "y": -30}}} + self.sidebar.save_zigbee_panel_config(self.hass, {"hub": settings}) + self.assertEqual( + self.hass.config_entries.async_update_entry.call_args.kwargs["options"]["zigbee_panel_config"], + settings, + ) + + def test_invalid_coordinates_and_choices_are_rejected(self): + self.add_hub("hub", True) + self.hass.config_entries.async_update_entry = Mock() + for settings in [ + {"orientation": "diagonal"}, {"link_status": "purple"}, + {"map_height": True}, {"map_height": 99}, + {"layout_data": {"1": {"x": float("nan"), "y": 0}}}, + {"layout_data": {"1": {"x": 0}}}, + ]: + with self.assertRaises(ValueError): + self.sidebar.save_zigbee_panel_config(self.hass, {"hub": settings}) + self.hass.config_entries.async_update_entry.assert_not_called() + async def test_save_updates_panel_without_removing_route_or_reloading(self): + entry = self.add_hub("hub", True) + loaded = self.hass.data["wiser"]["hub"] + loaded["reload_settings"] = self.sidebar.integration_reload_settings(entry) + self.hass.config_entries.async_reload = AsyncMock() + await self.sidebar.async_update_zigbee_panel(self.hass) + entry.options = {**entry.options, "zigbee_panel_config": {"orientation": "pie"}} + await self.sidebar.async_handle_entry_update(self.hass, entry) + self.hass.config_entries.async_reload.assert_not_called() + self.frontend.async_remove_panel.assert_not_called() + self.frontend.async_register_built_in_panel.assert_called_once() + update = self.frontend.async_register_built_in_panel.call_args.kwargs + self.assertTrue(update["update"]) + self.assertEqual(update["frontend_url_path"], "wiser-zigbee") + self.assertEqual(update["config"]["card_configs"]["hub"], {"orientation": "pie"}) + + async def test_other_options_and_connection_changes_still_reload(self): + entry = self.add_hub("hub", True) + self.hass.data["wiser"]["hub"]["reload_settings"] = self.sidebar.integration_reload_settings(entry) + self.hass.config_entries.async_reload = AsyncMock() + entry.options = {**entry.options, "scan_interval": 60} + await self.sidebar.async_handle_entry_update(self.hass, entry) + self.hass.config_entries.async_reload.assert_awaited_once_with("hub") + self.hass.config_entries.async_reload.reset_mock() + entry.options.pop("scan_interval") + entry.data = {"host": "other.local"} + await self.sidebar.async_handle_entry_update(self.hass, entry) + self.hass.config_entries.async_reload.assert_awaited_once_with("hub") + + async def test_bundle_version_change_updates_panel_without_settings_change(self): + self.add_hub("hub", True) + await self.sidebar.async_update_zigbee_panel(self.hass) + self.version_reader.assert_called_with(ROOT / "frontend/wiser-zigbee-card.js") + self.version_reader.return_value = "4.5.6-beta.3" + await self.sidebar.async_update_zigbee_panel(self.hass) + update = self.frontend.async_register_built_in_panel.call_args.kwargs + self.assertEqual(update["config"]["card_url"], "/wiser/wiser-zigbee-card.js?v=4.5.6-beta.3") + self.assertEqual(update["config"]["_panel_custom"]["module_url"], update["config"]["card_url"]) diff --git a/tests/test_zigbee_version.py b/tests/test_zigbee_version.py index fe57565a..3fab09eb 100644 --- a/tests/test_zigbee_version.py +++ b/tests/test_zigbee_version.py @@ -3,6 +3,7 @@ from pathlib import Path from tempfile import TemporaryDirectory import unittest +import re ROOT = Path(__file__).resolve().parents[1] spec = importlib.util.spec_from_file_location("card_version", ROOT / "custom_components/wiser/frontend/zigbee_version.py") @@ -15,7 +16,7 @@ def version(self, source): with TemporaryDirectory() as directory: path = Path(directory) / "card.js" path.write_text(source) - return module.zigbee_card_version(path, "1.0.0") + return module.zigbee_card_version(path) def test_unknown_build_uses_stable_content_hash(self): first = self.version('const library="3.3.3"') @@ -23,9 +24,9 @@ def test_unknown_build_uses_stable_content_hash(self): self.assertEqual(first, self.version('const library="3.3.3"')) self.assertNotEqual(first, self.version('const library="4.0.0"')) - def test_missing_file_keeps_fallback(self): + def test_missing_file_returns_missing(self): with TemporaryDirectory() as directory: - self.assertEqual(module.zigbee_card_version(Path(directory) / "missing.js", "2.1.2"), "2.1.2") + self.assertEqual(module.zigbee_card_version(Path(directory) / "missing.js"), "missing") def test_zigbee_banner_ignores_library_versions(self): self.assertEqual(self.version('const library="3.3.3";const $t="2.1.2";console.info(`WISER-ZIGBEE-NETWORK-CARD ${Zt("common.version")} ${$t}`)'), "2.1.2") @@ -34,8 +35,11 @@ def test_zigbee_dev_version(self): self.assertEqual(self.version('const cardBuild="3.0.0-dev.7";console.info(`WISER-ZIGBEE-CARD ${translate("common.version")} ${cardBuild}`)'), "3.0.0-dev.7") def test_installed_zigbee_bundle_has_readable_version(self): - version = module.zigbee_card_version(ROOT / "custom_components/wiser/frontend/wiser-zigbee-card.js", "missing") - self.assertEqual(version, "2.1.2") + version = module.zigbee_card_version(ROOT / "custom_components/wiser/frontend/wiser-zigbee-card.js") + source = (ROOT / "custom_components/wiser/frontend/wiser-zigbee-card.js").read_text() + marker = re.search(r"/\*! WISER-CARD-VERSION wiser-zigbee-card (\S+) \*/", source) + self.assertIsNotNone(marker) + self.assertEqual(version, marker[1]) def test_modern_editor_footer_with_inlined_version(self): source = 'const library="3.3.3";html`
${this.t("common.version")}: ${"3.0.0-dev.65"}
`' From 4715215c1ba4068bd893a30047f9021d087e61d9 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Sat, 12 Sep 2026 17:23:06 +0100 Subject: [PATCH 013/154] Keep bundled development cards in full test builds --- .github/workflows/publish.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index fa6c380e..1f057e6d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -18,20 +18,24 @@ permissions: jobs: package: - name: Build Wiser with published card assets + name: Build Wiser integration runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: '3.13' - - name: Test release selection - run: python -m unittest discover -s tests -p test_card_releases.py + - name: Test packaging and sidebar integration + run: | + python -m unittest discover -s tests -p test_card_releases.py + python -m unittest discover -s tests -p 'test_*sidebar.py' + python -m unittest discover -s tests -p 'test_*version.py' - name: Stage integration run: | mkdir -p dist/wiser cp -a custom_components/wiser/. dist/wiser/ - name: Fetch card release assets + if: github.event_name != 'push' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CARD_CHANNEL: ${{ github.event_name == 'release' && (github.event.release.prerelease && 'dev' || 'stable') || inputs.channel || 'dev' }} From cfc3d381a9f7d5257c5f916e8457c861626b0f2f Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Sat, 12 Sep 2026 17:34:16 +0100 Subject: [PATCH 014/154] Consolidate card version detection in frontend registration --- custom_components/wiser/frontend/__init__.py | 52 ++++++++++++++++--- .../wiser/frontend/schedule_version.py | 38 -------------- custom_components/wiser/frontend/sidebar.py | 4 +- .../wiser/frontend/zigbee_sidebar.py | 4 +- .../wiser/frontend/zigbee_version.py | 48 ----------------- tests/test_frontend_version.py | 21 +++++--- tests/test_schedules_sidebar.py | 5 +- tests/test_zigbee_sidebar.py | 5 +- tests/test_zigbee_version.py | 21 +++++--- 9 files changed, 81 insertions(+), 117 deletions(-) delete mode 100644 custom_components/wiser/frontend/schedule_version.py delete mode 100644 custom_components/wiser/frontend/zigbee_version.py diff --git a/custom_components/wiser/frontend/__init__.py b/custom_components/wiser/frontend/__init__.py index 2b143986..52b545fd 100644 --- a/custom_components/wiser/frontend/__init__.py +++ b/custom_components/wiser/frontend/__init__.py @@ -1,5 +1,7 @@ """View Assist Javascript module registration.""" +from hashlib import sha256 +import re import logging import os from pathlib import Path @@ -12,12 +14,52 @@ from homeassistant.helpers.event import async_call_later from ..const import JSMODULES, URL_BASE # noqa: TID252 -from .schedule_version import schedule_card_version -from .zigbee_version import zigbee_card_version _LOGGER = logging.getLogger(__name__) +def card_version(path: Path) -> str: + """Resolve the card's banner variable, ignoring bundled library versions.""" + version_pattern = r"\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?" + try: + contents = path.read_bytes() + except OSError: + return "missing" + source = contents.decode("utf-8", errors="replace") + # Explicit build metadata is authoritative; legacy parsing remains below. + marker = re.search( + rf"/\*!\s*WISER-CARD-VERSION {re.escape(path.stem)}\s+({version_pattern})\s*\*/", + source, + ) + if marker: + return marker[1] + # New builds inline CARD_VERSION into the editor's version footer and + # no longer emit the legacy startup banner. + footer = re.search( + rf'class=["\']version["\'][^`]*?common\.version["\']\)\}}:\s*' + rf'\$\{{["\']({version_pattern})["\']\}}', + source, + ) + if path.stem == "wiser-zigbee-card" and footer: + return footer[1] + + banner_name = "WISER-ZIGBEE(?:-NETWORK)?-CARD" if path.stem == "wiser-zigbee-card" else re.escape(path.stem.upper()) + banner = re.search( + banner_name + r'[^`]*?common\.version[\"\']\)\}\s*\$\{([\w$]+)\}', + source, + ) + if banner: + assignment = re.search( + rf'(? str: - """Resolve the card's banner variable, ignoring bundled library versions.""" - try: - contents = path.read_bytes() - except OSError: - return "missing" - source = contents.decode("utf-8", errors="replace") - # Explicit build metadata is authoritative; legacy parsing remains below. - marker = re.search( - rf"/\*!\s*WISER-CARD-VERSION wiser-schedule-card\s+({_VERSION})\s*\*/", - source, - ) - if marker: - return marker[1] - banner = re.search( - r'WISER-SCHEDULE-CARD[^`]*?common\.version[\"\']\)\}\s*\$\{([\w$]+)\}', - source, - ) - if banner: - assignment = re.search( - rf'(? str: - """Resolve the card's banner variable, ignoring bundled library versions.""" - try: - contents = path.read_bytes() - except OSError: - return "missing" - source = contents.decode("utf-8", errors="replace") - # Explicit build metadata is authoritative; legacy parsing remains below. - marker = re.search( - rf"/\*!\s*WISER-CARD-VERSION wiser-zigbee-card\s+({_VERSION})\s*\*/", - source, - ) - if marker: - return marker[1] - # New builds inline CARD_VERSION into the editor's version footer and - # no longer emit the legacy startup banner. - footer = re.search( - rf'class=["\']version["\'][^`]*?common\.version["\']\)\}}:\s*' - rf'\$\{{["\']({_VERSION})["\']\}}', - source, - ) - if footer: - return footer[1] - - banner = re.search( - r'WISER-ZIGBEE(?:-NETWORK)?-CARD[^`]*?common\.version[\"\']\)\}\s*\$\{([\w$]+)\}', - source, - ) - if banner: - assignment = re.search( - rf'(? Date: Sat, 12 Sep 2026 19:16:01 +0100 Subject: [PATCH 015/154] Avoid Zigbee sidebar route conflicts breaking integration setup --- .../wiser/frontend/zigbee_sidebar.py | 67 +++++++++++-------- tests/test_zigbee_sidebar.py | 42 ++++++++++-- 2 files changed, 75 insertions(+), 34 deletions(-) diff --git a/custom_components/wiser/frontend/zigbee_sidebar.py b/custom_components/wiser/frontend/zigbee_sidebar.py index 6a981a67..0174c914 100644 --- a/custom_components/wiser/frontend/zigbee_sidebar.py +++ b/custom_components/wiser/frontend/zigbee_sidebar.py @@ -1,5 +1,6 @@ """Manage the shared Wiser zigbee sidebar panel.""" +import logging import math from pathlib import Path @@ -12,7 +13,9 @@ DATA, DOMAIN, JSMODULES, URL_BASE, ) -PANEL_PATH = "wiser-zigbee" +_LOGGER = logging.getLogger(__name__) + +PANEL_PATH = "wiser-zigbee-panel" PANEL_STATE = "wiser_zigbee_panel" @@ -54,35 +57,41 @@ async def async_update_zigbee_panel(hass): if hubs: config = dict(state) module_url = config["card_url"] - if PANEL_STATE in hass.data: - # Keep the route registered while notifying clients of new settings. - frontend.async_register_built_in_panel( - hass, - component_name="custom", - frontend_url_path=PANEL_PATH, - sidebar_title="Wiser Zigbee", - sidebar_icon="mdi:zigbee", - config={ - **config, - "_panel_custom": { - "name": "wiser-zigbee-panel", - "module_url": module_url, - "embed_iframe": False, - "trust_external": False, + try: + if PANEL_STATE in hass.data: + # Keep the route registered while notifying clients of new settings. + frontend.async_register_built_in_panel( + hass, + component_name="custom", + frontend_url_path=PANEL_PATH, + sidebar_title="Wiser Zigbee", + sidebar_icon="mdi:zigbee", + config={ + **config, + "_panel_custom": { + "name": "wiser-zigbee-panel", + "module_url": module_url, + "embed_iframe": False, + "trust_external": False, + }, }, - }, - update=True, - ) - else: - await panel_custom.async_register_panel( - hass, - frontend_url_path=PANEL_PATH, - webcomponent_name="wiser-zigbee-panel", - sidebar_title="Wiser Zigbee", - sidebar_icon="mdi:zigbee", - module_url=module_url, - config=config, - ) + update=True, + ) + else: + await panel_custom.async_register_panel( + hass, + frontend_url_path=PANEL_PATH, + webcomponent_name="wiser-zigbee-panel", + sidebar_title="Wiser Zigbee", + sidebar_icon="mdi:zigbee", + module_url=module_url, + config=config, + ) + except ValueError as err: + # A sidebar route can already belong to a user dashboard. This + # optional UI must not fail setup after entity platforms loaded. + _LOGGER.warning("Unable to register Wiser Zigbee sidebar at %s: %s", PANEL_PATH, err) + return hass.data[PANEL_STATE] = state diff --git a/tests/test_zigbee_sidebar.py b/tests/test_zigbee_sidebar.py index bf9d71a6..8033fd68 100644 --- a/tests/test_zigbee_sidebar.py +++ b/tests/test_zigbee_sidebar.py @@ -81,7 +81,7 @@ async def test_enable_registers_dedicated_panel_once(self): await self.sidebar.async_update_zigbee_panel(self.hass) self.custom.async_register_panel.assert_awaited_once() args = self.custom.async_register_panel.call_args.kwargs - self.assertEqual(args["frontend_url_path"], "wiser-zigbee") + self.assertEqual(args["frontend_url_path"], "wiser-zigbee-panel") self.assertEqual(args["webcomponent_name"], "wiser-zigbee-panel") self.assertEqual(args["config"]["hubs"], ["hub"]) self.assertEqual(args["config"]["card_url"], "/wiser/wiser-zigbee-card.js?v=4.5.6-beta.2") @@ -91,7 +91,7 @@ async def test_disable_last_hub_removes_panel(self): await self.sidebar.async_update_zigbee_panel(self.hass) entry.options["show_zigbee_sidebar"] = False await self.sidebar.async_update_zigbee_panel(self.hass) - self.frontend.async_remove_panel.assert_called_once_with(self.hass, "wiser-zigbee") + self.frontend.async_remove_panel.assert_called_once_with(self.hass, "wiser-zigbee-panel") self.assertNotIn(self.sidebar.PANEL_STATE, self.hass.data) async def test_unload_keeps_other_hub_then_removes_last(self): @@ -110,9 +110,11 @@ async def test_unload_keeps_other_hub_then_removes_last(self): async def test_registration_failure_can_be_retried(self): self.add_hub("hub", True) - self.custom.async_register_panel.side_effect = ValueError("registration failed") - with self.assertRaises(ValueError): + self.custom.async_register_panel.side_effect = ValueError("Overwriting panel wiser-zigbee-panel owned by lovelace") + with self.assertLogs(self.sidebar._LOGGER, level="WARNING") as logs: await self.sidebar.async_update_zigbee_panel(self.hass) + self.assertIn("owned by lovelace", logs.output[0]) + self.frontend.async_remove_panel.assert_not_called() self.assertNotIn(self.sidebar.PANEL_STATE, self.hass.data) self.custom.async_register_panel.side_effect = None await self.sidebar.async_update_zigbee_panel(self.hass) @@ -184,7 +186,7 @@ async def test_save_updates_panel_without_removing_route_or_reloading(self): self.frontend.async_register_built_in_panel.assert_called_once() update = self.frontend.async_register_built_in_panel.call_args.kwargs self.assertTrue(update["update"]) - self.assertEqual(update["frontend_url_path"], "wiser-zigbee") + self.assertEqual(update["frontend_url_path"], "wiser-zigbee-panel") self.assertEqual(update["config"]["card_configs"]["hub"], {"orientation": "pie"}) async def test_other_options_and_connection_changes_still_reload(self): @@ -209,3 +211,33 @@ async def test_bundle_version_change_updates_panel_without_settings_change(self) update = self.frontend.async_register_built_in_panel.call_args.kwargs self.assertEqual(update["config"]["card_url"], "/wiser/wiser-zigbee-card.js?v=4.5.6-beta.3") self.assertEqual(update["config"]["_panel_custom"]["module_url"], update["config"]["card_url"]) + + async def test_existing_lovelace_dashboard_is_not_overwritten(self): + self.add_hub("hub", True) + dashboard = object() + panels = {"wiser-zigbee": dashboard} + + async def register(hass, **kwargs): + path = kwargs["frontend_url_path"] + if path in panels: + raise ValueError(f"Overwriting panel {path} owned by lovelace") + panels[path] = kwargs + + self.custom.async_register_panel.side_effect = register + await self.sidebar.async_update_zigbee_panel(self.hass) + self.assertIs(panels["wiser-zigbee"], dashboard) + self.assertIn("wiser-zigbee-panel", panels) + self.frontend.async_remove_panel.assert_not_called() + + async def test_update_conflict_does_not_abort_and_can_be_retried(self): + entry = self.add_hub("hub", True) + await self.sidebar.async_update_zigbee_panel(self.hass) + previous = self.hass.data[self.sidebar.PANEL_STATE] + entry.options["zigbee_panel_config"] = {"show_labels": True} + self.frontend.async_register_built_in_panel.side_effect = ValueError("owned by lovelace") + with self.assertLogs(self.sidebar._LOGGER, level="WARNING"): + await self.sidebar.async_update_zigbee_panel(self.hass) + self.assertIs(self.hass.data[self.sidebar.PANEL_STATE], previous) + self.frontend.async_register_built_in_panel.side_effect = None + await self.sidebar.async_update_zigbee_panel(self.hass) + self.assertTrue(self.hass.data[self.sidebar.PANEL_STATE]["card_configs"]["hub"]["show_labels"]) From 873a4aaab99f32afd13714b2511f8f0037237010 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Sat, 12 Sep 2026 19:20:18 +0100 Subject: [PATCH 016/154] test: remove obsolete hardcoded schedule version assertion --- tests/test_schedule_card_hide_hw_schedule.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/test_schedule_card_hide_hw_schedule.py b/tests/test_schedule_card_hide_hw_schedule.py index 16cb787d..b9e4bcd0 100644 --- a/tests/test_schedule_card_hide_hw_schedule.py +++ b/tests/test_schedule_card_hide_hw_schedule.py @@ -3,20 +3,16 @@ Card behaviour is tested in the wiser-schedule-card source repository. """ from pathlib import Path -import re import unittest ROOT = Path(__file__).resolve().parents[1] / "custom_components/wiser" CARD = ROOT / "frontend/wiser-schedule-card.js" -CONST = ROOT / "const.py" WEBSOCKETS = ROOT / "websockets.py" class ScheduleCardBundleTest(unittest.TestCase): def test_matching_card_and_panel_are_bundled_together(self): source = CARD.read_text() - version = re.search(r'"filename": "wiser-schedule-card.js",\s*"version": "([^"]+)"', CONST.read_text()).group(1) - self.assertIn(version, source) self.assertIn('wiser-schedules-panel', source) self.assertIn('wiser-schedule-card-editor', source) self.assertIn('panelApiVersion', source) From c05d1d157685fb8cd49f1deeeff19c268562575d Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Sat, 19 Sep 2026 10:23:29 +0100 Subject: [PATCH 017/154] Refactor sidebar panels to share lifecycle and settings logic --- custom_components/wiser/__init__.py | 5 +- .../wiser/frontend/entry_updates.py | 25 +++ custom_components/wiser/frontend/panel.py | 126 +++++++++++ .../wiser/frontend/schedules_sidebar.py | 39 ++++ custom_components/wiser/frontend/sidebar.py | 135 ------------ .../wiser/frontend/zigbee_sidebar.py | 196 +++++------------- custom_components/wiser/websockets.py | 2 +- scripts/fetch_card_releases.py | 2 +- tests/test_card_releases.py | 2 +- tests/test_schedules_sidebar.py | 74 +++++-- tests/test_zigbee_sidebar.py | 45 ++-- 11 files changed, 331 insertions(+), 320 deletions(-) create mode 100644 custom_components/wiser/frontend/entry_updates.py create mode 100644 custom_components/wiser/frontend/panel.py create mode 100644 custom_components/wiser/frontend/schedules_sidebar.py delete mode 100644 custom_components/wiser/frontend/sidebar.py diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index 0bc2001d..ae71be7b 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -45,9 +45,8 @@ ) from .entity_migration import migrate_entity_unique_ids from .frontend import JSModuleRegistration -from .frontend.sidebar import ( - async_handle_entry_update, async_update_schedules_panel, integration_reload_settings, -) +from .frontend.entry_updates import async_handle_entry_update, integration_reload_settings +from .frontend.schedules_sidebar import async_update_schedules_panel from .helpers import ( build_light_unique_id_migration, get_device_name, diff --git a/custom_components/wiser/frontend/entry_updates.py b/custom_components/wiser/frontend/entry_updates.py new file mode 100644 index 00000000..3e8bf391 --- /dev/null +++ b/custom_components/wiser/frontend/entry_updates.py @@ -0,0 +1,25 @@ +"""Apply panel preferences live and reload other integration settings.""" + +from .schedules_sidebar import async_update_schedules_panel +from .zigbee_sidebar import async_update_zigbee_panel +from ..const import CONF_SCHEDULES_PANEL_CONFIG, CONF_ZIGBEE_PANEL_CONFIG, DOMAIN + + +def integration_reload_settings(entry): + """Capture connection and entity options, excluding panel-only preferences.""" + return ( + dict(entry.data), + {key: value for key, value in entry.options.items() + if key not in {CONF_SCHEDULES_PANEL_CONFIG, CONF_ZIGBEE_PANEL_CONFIG}}, + ) + + +async def async_handle_entry_update(hass, entry): + """Apply panel preferences live; retain reloads for other integration changes.""" + loaded = hass.data.get(DOMAIN, {}).get(entry.entry_id) + settings = integration_reload_settings(entry) + if loaded is not None and loaded.get("reload_settings") == settings: + await async_update_schedules_panel(hass) + await async_update_zigbee_panel(hass) + return + await hass.config_entries.async_reload(entry.entry_id) diff --git a/custom_components/wiser/frontend/panel.py b/custom_components/wiser/frontend/panel.py new file mode 100644 index 00000000..d9bb7872 --- /dev/null +++ b/custom_components/wiser/frontend/panel.py @@ -0,0 +1,126 @@ +"""Shared lifecycle and settings persistence for Wiser sidebar panels.""" + +from __future__ import annotations + +from dataclasses import dataclass +from pathlib import Path +from typing import Callable + +from homeassistant.components import frontend, panel_custom + +from . import card_version +from ..const import DATA, DOMAIN, URL_BASE + + +@dataclass(frozen=True) +class SidebarPanel: + """Describe a sidebar panel and the card settings it accepts.""" + + path: str + state_key: str + component: str + title: str + icon: str + filename: str + enabled_option: str + config_option: str + hub_error: str + setting_error: str + field_types: dict + validate_setting: Callable | None = None + + +def _enabled_entries(hass, panel): + """Yield loaded, enabled hubs that opted into this panel.""" + loaded = hass.data.get(DOMAIN, {}) + for entry in hass.config_entries.async_entries(DOMAIN): + if ( + entry.entry_id in loaded + and not entry.disabled_by + and entry.options.get(panel.enabled_option, False) + ): + yield loaded[entry.entry_id][DATA].wiserhub.system.name, entry + + +async def async_update_panel(hass, panel): + """Register, refresh, or remove a panel according to its enabled hubs.""" + entries = list(_enabled_entries(hass, panel)) + if not entries: + if panel.state_key in hass.data: + frontend.async_remove_panel(hass, panel.path) + hass.data.pop(panel.state_key) + return + + version = await hass.async_add_executor_job( + card_version, Path(__file__).parent / panel.filename + ) + module_url = f"{URL_BASE}/{panel.filename}?v={version}" + state = { + "hubs": [hub for hub, _ in entries], + "card_configs": { + hub: dict(entry.options.get(panel.config_option, {})) + for hub, entry in entries + }, + "card_url": module_url, + } + if state == hass.data.get(panel.state_key): + return + + if panel.state_key in hass.data: + # Keep the route registered while notifying clients of new settings. + frontend.async_register_built_in_panel( + hass, + component_name="custom", + frontend_url_path=panel.path, + sidebar_title=panel.title, + sidebar_icon=panel.icon, + config={ + **state, + "_panel_custom": { + "name": panel.component, + "module_url": module_url, + "embed_iframe": False, + "trust_external": False, + }, + }, + update=True, + ) + else: + await panel_custom.async_register_panel( + hass, + frontend_url_path=panel.path, + webcomponent_name=panel.component, + sidebar_title=panel.title, + sidebar_icon=panel.icon, + module_url=module_url, + config=dict(state), + ) + # Only record successfully applied settings so failed updates can be retried. + hass.data[panel.state_key] = state + + +def save_panel_config(hass, panel, configs): + """Validate every hub's settings before persisting any options.""" + entries = dict(_enabled_entries(hass, panel)) + updates = [] + for hub, config in configs.items(): + if hub not in entries: + raise ValueError(panel.hub_error) + settings = {} + for key, value in config.items(): + if key in {"type", "hub"}: + continue + allowed_types = panel.field_types.get(key, ()) + if not isinstance(allowed_types, tuple): + allowed_types = (allowed_types,) + # Exact types prevent booleans from being accepted as integers. + if type(value) not in allowed_types: + raise ValueError(f"{panel.setting_error}: {key}") + if panel.validate_setting is not None: + panel.validate_setting(key, value) + settings[key] = value + updates.append((entries[hub], settings)) + for entry, settings in updates: + hass.config_entries.async_update_entry( + entry, options={**entry.options, panel.config_option: settings} + ) diff --git a/custom_components/wiser/frontend/schedules_sidebar.py b/custom_components/wiser/frontend/schedules_sidebar.py new file mode 100644 index 00000000..51e4c5fc --- /dev/null +++ b/custom_components/wiser/frontend/schedules_sidebar.py @@ -0,0 +1,39 @@ +"""Manage the shared Wiser schedules sidebar panel.""" + +from .panel import SidebarPanel, async_update_panel, save_panel_config +from ..const import ( + CONF_SHOW_SCHEDULES_SIDEBAR, CONF_SCHEDULES_PANEL_CONFIG, +) + +PANEL_PATH = "wiser-schedules" +PANEL_STATE = "wiser_schedules_panel" + +_SCHEDULES_PANEL = SidebarPanel( + path=PANEL_PATH, + state_key=PANEL_STATE, + component="wiser-schedules-panel", + title="Wiser Schedules", + icon="mdi:calendar-clock", + filename="wiser-schedule-card.js", + enabled_option=CONF_SHOW_SCHEDULES_SIDEBAR, + config_option=CONF_SCHEDULES_PANEL_CONFIG, + hub_error="Hub is not enabled in the schedules panel", + setting_error="Invalid schedule card setting", + field_types={ + "name": str, "selected_schedule": str, "view_type": str, "home_screen": str, + "theme_colors": bool, "show_badges": bool, "show_schedule_id": bool, + "display_only": bool, "hide_hw_schedule": bool, "admin_only": bool, + "hide_card_borders": bool, "hide_card_background": bool, "overview_details": bool, + }, +) + + +async def async_update_schedules_panel(hass): + """Show schedules for loaded hubs that have opted into the sidebar.""" + await async_update_panel(hass, _SCHEDULES_PANEL) + + +def save_schedules_panel_config(hass, configs): + """Validate all submitted settings before updating integration options.""" + save_panel_config(hass, _SCHEDULES_PANEL, configs) + diff --git a/custom_components/wiser/frontend/sidebar.py b/custom_components/wiser/frontend/sidebar.py deleted file mode 100644 index c9b98342..00000000 --- a/custom_components/wiser/frontend/sidebar.py +++ /dev/null @@ -1,135 +0,0 @@ -"""Manage the shared Wiser schedules sidebar panel.""" - -from pathlib import Path - -from homeassistant.components import frontend, panel_custom -from . import card_version -from .zigbee_sidebar import async_update_zigbee_panel - -from ..const import ( - CONF_SHOW_SCHEDULES_SIDEBAR, CONF_SCHEDULES_PANEL_CONFIG, CONF_ZIGBEE_PANEL_CONFIG, - DATA, DOMAIN, JSMODULES, URL_BASE, -) - -PANEL_PATH = "wiser-schedules" -PANEL_STATE = "wiser_schedules_panel" - - -async def async_update_schedules_panel(hass): - """Show schedules for loaded hubs that have opted into the sidebar.""" - loaded = hass.data.get(DOMAIN, {}) - hubs = [ - loaded[entry.entry_id][DATA].wiserhub.system.name - for entry in hass.config_entries.async_entries(DOMAIN) - if entry.entry_id in loaded - and not entry.disabled_by - and entry.options.get(CONF_SHOW_SCHEDULES_SIDEBAR, False) - ] - card_configs = { - loaded[entry.entry_id][DATA].wiserhub.system.name: - dict(entry.options.get(CONF_SCHEDULES_PANEL_CONFIG, {})) - for entry in hass.config_entries.async_entries(DOMAIN) - if entry.entry_id in loaded - and loaded[entry.entry_id][DATA].wiserhub.system.name in hubs - } - state = {"hubs": hubs, "card_configs": card_configs} - if hubs: - card = next(module for module in JSMODULES if module["filename"] == "wiser-schedule-card.js") - version = await hass.async_add_executor_job( - card_version, Path(__file__).parent / card["filename"] - ) - state["card_url"] = f"{URL_BASE}/{card['filename']}?v={version}" - if state == hass.data.get(PANEL_STATE) or (not hubs and PANEL_STATE not in hass.data): - return - - if not hubs and PANEL_STATE in hass.data: - frontend.async_remove_panel(hass, PANEL_PATH) - hass.data.pop(PANEL_STATE) - - if hubs: - config = dict(state) - module_url = config["card_url"] - if PANEL_STATE in hass.data: - # Keep the route registered while notifying clients of new settings. - frontend.async_register_built_in_panel( - hass, - component_name="custom", - frontend_url_path=PANEL_PATH, - sidebar_title="Wiser Schedules", - sidebar_icon="mdi:calendar-clock", - config={ - **config, - "_panel_custom": { - "name": "wiser-schedules-panel", - "module_url": module_url, - "embed_iframe": False, - "trust_external": False, - }, - }, - update=True, - ) - else: - await panel_custom.async_register_panel( - hass, - frontend_url_path=PANEL_PATH, - webcomponent_name="wiser-schedules-panel", - sidebar_title="Wiser Schedules", - sidebar_icon="mdi:calendar-clock", - module_url=module_url, - config=config, - ) - hass.data[PANEL_STATE] = state - - -def save_schedules_panel_config(hass, configs): - """Validate all submitted settings before updating integration options.""" - loaded = hass.data.get(DOMAIN, {}) - entries = { - loaded[entry.entry_id][DATA].wiserhub.system.name: entry - for entry in hass.config_entries.async_entries(DOMAIN) - if entry.entry_id in loaded - and not entry.disabled_by - and entry.options.get(CONF_SHOW_SCHEDULES_SIDEBAR, False) - } - field_types = { - "name": str, "selected_schedule": str, "view_type": str, "home_screen": str, - "theme_colors": bool, "show_badges": bool, "show_schedule_id": bool, - "display_only": bool, "hide_hw_schedule": bool, "admin_only": bool, - "hide_card_borders": bool, "hide_card_background": bool, "overview_details": bool, - } - updates = [] - for hub, config in configs.items(): - if hub not in entries: - raise ValueError("Hub is not enabled in the schedules panel") - settings = {} - for key, value in config.items(): - if key in {"type", "hub"}: - continue - if key not in field_types or type(value) is not field_types[key]: - raise ValueError(f"Invalid schedule card setting: {key}") - settings[key] = value - updates.append((entries[hub], settings)) - for entry, settings in updates: - hass.config_entries.async_update_entry( - entry, options={**entry.options, CONF_SCHEDULES_PANEL_CONFIG: settings} - ) - - -def integration_reload_settings(entry): - """Capture connection and entity options, excluding panel-only preferences.""" - return ( - dict(entry.data), - {key: value for key, value in entry.options.items() - if key not in {CONF_SCHEDULES_PANEL_CONFIG, CONF_ZIGBEE_PANEL_CONFIG}}, - ) - - -async def async_handle_entry_update(hass, entry): - """Apply panel preferences live; retain reloads for other integration changes.""" - loaded = hass.data.get(DOMAIN, {}).get(entry.entry_id) - settings = integration_reload_settings(entry) - if loaded is not None and loaded.get("reload_settings") == settings: - await async_update_schedules_panel(hass) - await async_update_zigbee_panel(hass) - return - await hass.config_entries.async_reload(entry.entry_id) diff --git a/custom_components/wiser/frontend/zigbee_sidebar.py b/custom_components/wiser/frontend/zigbee_sidebar.py index 0174c914..ff700720 100644 --- a/custom_components/wiser/frontend/zigbee_sidebar.py +++ b/custom_components/wiser/frontend/zigbee_sidebar.py @@ -2,161 +2,73 @@ import logging import math -from pathlib import Path -from homeassistant.components import frontend, panel_custom - -from . import card_version - -from ..const import ( - CONF_SHOW_ZIGBEE_SIDEBAR, CONF_ZIGBEE_PANEL_CONFIG, - DATA, DOMAIN, JSMODULES, URL_BASE, -) +from .panel import SidebarPanel, async_update_panel, save_panel_config +from ..const import CONF_SHOW_ZIGBEE_SIDEBAR, CONF_ZIGBEE_PANEL_CONFIG _LOGGER = logging.getLogger(__name__) PANEL_PATH = "wiser-zigbee-panel" PANEL_STATE = "wiser_zigbee_panel" - -async def async_update_zigbee_panel(hass): - """Show zigbee for loaded hubs that have opted into the sidebar.""" - loaded = hass.data.get(DOMAIN, {}) - hubs = [ - loaded[entry.entry_id][DATA].wiserhub.system.name - for entry in hass.config_entries.async_entries(DOMAIN) - if entry.entry_id in loaded - and not entry.disabled_by - and entry.options.get(CONF_SHOW_ZIGBEE_SIDEBAR, False) - ] - card_configs = { - loaded[entry.entry_id][DATA].wiserhub.system.name: - dict(entry.options.get(CONF_ZIGBEE_PANEL_CONFIG, {})) - for entry in hass.config_entries.async_entries(DOMAIN) - if entry.entry_id in loaded - and loaded[entry.entry_id][DATA].wiserhub.system.name in hubs - } - state = {"hubs": hubs, "card_configs": card_configs} - if hubs: - card = next( - module for module in JSMODULES - if module["filename"] == "wiser-zigbee-card.js" - ) - version = await hass.async_add_executor_job( - card_version, - Path(__file__).parent / card["filename"], - ) - state["card_url"] = f"{URL_BASE}/{card['filename']}?v={version}" - if state == hass.data.get(PANEL_STATE) or (not hubs and PANEL_STATE not in hass.data): - return - - if not hubs and PANEL_STATE in hass.data: - frontend.async_remove_panel(hass, PANEL_PATH) - hass.data.pop(PANEL_STATE) - - if hubs: - config = dict(state) - module_url = config["card_url"] - try: - if PANEL_STATE in hass.data: - # Keep the route registered while notifying clients of new settings. - frontend.async_register_built_in_panel( - hass, - component_name="custom", - frontend_url_path=PANEL_PATH, - sidebar_title="Wiser Zigbee", - sidebar_icon="mdi:zigbee", - config={ - **config, - "_panel_custom": { - "name": "wiser-zigbee-panel", - "module_url": module_url, - "embed_iframe": False, - "trust_external": False, - }, - }, - update=True, - ) - else: - await panel_custom.async_register_panel( - hass, - frontend_url_path=PANEL_PATH, - webcomponent_name="wiser-zigbee-panel", - sidebar_title="Wiser Zigbee", - sidebar_icon="mdi:zigbee", - module_url=module_url, - config=config, - ) - except ValueError as err: - # A sidebar route can already belong to a user dashboard. This - # optional UI must not fail setup after entity platforms loaded. - _LOGGER.warning("Unable to register Wiser Zigbee sidebar at %s: %s", PANEL_PATH, err) - return - hass.data[PANEL_STATE] = state - - -def save_zigbee_panel_config(hass, configs): - """Validate all submitted settings before updating integration options.""" - loaded = hass.data.get(DOMAIN, {}) - entries = { - loaded[entry.entry_id][DATA].wiserhub.system.name: entry - for entry in hass.config_entries.async_entries(DOMAIN) - if entry.entry_id in loaded - and not entry.disabled_by - and entry.options.get(CONF_SHOW_ZIGBEE_SIDEBAR, False) - } - field_types = { +_CHOICES = { + "orientation": {"vertical", "horizontal", "pie"}, + "group_by": {"none", "area"}, + "link_status": {"links", "icons", "both", "none"}, +} + + +def _validate_setting(key, value): + """Validate Zigbee choices, map bounds, and saved coordinates.""" + if key in _CHOICES and value not in _CHOICES[key]: + raise ValueError(f"Invalid Zigbee card setting: {key}") + if key == "map_height" and value is not None and not 100 <= value <= 2000: + raise ValueError("Map height must be between 100 and 2000") + if key == "layout_data": + for position in value.values(): + if not isinstance(position, dict) or set(position) != {"x", "y"}: + raise ValueError("Invalid layout position") + if any( + type(n) not in (int, float) or not math.isfinite(n) + for n in position.values() + ): + raise ValueError("Invalid layout coordinates") + + +_ZIGBEE_PANEL = SidebarPanel( + path=PANEL_PATH, + state_key=PANEL_STATE, + component="wiser-zigbee-panel", + title="Wiser Zigbee", + icon="mdi:zigbee", + filename="wiser-zigbee-card.js", + enabled_option=CONF_SHOW_ZIGBEE_SIDEBAR, + config_option=CONF_ZIGBEE_PANEL_CONFIG, + hub_error="Hub is not enabled in the zigbee panel", + setting_error="Invalid Zigbee card setting", + field_types={ "name": str, "layout_id": str, "layout_seed": str, "auto_update": bool, "log_seed": bool, "map_only": bool, "show_device_list": bool, "show_labels": bool, "magnifier": bool, "orientation": str, "group_by": str, "link_status": str, "map_height": (int, type(None)), "layout_data": dict, - } - choices = { - "orientation": {"vertical", "horizontal", "pie"}, - "group_by": {"none", "area"}, - "link_status": {"links", "icons", "both", "none"}, - } - updates = [] - for hub, config in configs.items(): - if hub not in entries: - raise ValueError("Hub is not enabled in the zigbee panel") - settings = {} - for key, value in config.items(): - if key in {"type", "hub"}: - continue - if key not in field_types or type(value) not in (field_types[key] if isinstance(field_types[key], tuple) else (field_types[key],)): - raise ValueError(f"Invalid Zigbee card setting: {key}") - if key in choices and value not in choices[key]: - raise ValueError(f"Invalid Zigbee card setting: {key}") - if key == "map_height" and value is not None and not 100 <= value <= 2000: - raise ValueError("Map height must be between 100 and 2000") - if key == "layout_data": - for position in value.values(): - if not isinstance(position, dict) or set(position) != {"x", "y"}: - raise ValueError("Invalid layout position") - if any(type(n) not in (int, float) or not math.isfinite(n) for n in position.values()): - raise ValueError("Invalid layout coordinates") - settings[key] = value - updates.append((entries[hub], settings)) - for entry, settings in updates: - hass.config_entries.async_update_entry( - entry, options={**entry.options, CONF_ZIGBEE_PANEL_CONFIG: settings} - ) + }, + validate_setting=_validate_setting, +) -def integration_reload_settings(entry): - """Exclude panel-only preferences from integration reload decisions.""" - return (dict(entry.data), { - key: value for key, value in entry.options.items() - if key != CONF_ZIGBEE_PANEL_CONFIG - }) +async def async_update_zigbee_panel(hass): + """Show zigbee for loaded hubs that have opted into the sidebar.""" + try: + await async_update_panel(hass, _ZIGBEE_PANEL) + except ValueError as err: + # A sidebar route can already belong to a user dashboard. This + # optional UI must not fail setup after entity platforms loaded. + _LOGGER.warning( + "Unable to register Wiser Zigbee sidebar at %s: %s", PANEL_PATH, err + ) -async def async_handle_entry_update(hass, entry): - """Save panel preferences live; reload for connection and entity options.""" - loaded = hass.data.get(DOMAIN, {}).get(entry.entry_id) - if loaded is not None and loaded.get("reload_settings") == integration_reload_settings(entry): - await async_update_zigbee_panel(hass) - return - await hass.config_entries.async_reload(entry.entry_id) +def save_zigbee_panel_config(hass, configs): + """Validate all submitted settings before updating integration options.""" + save_panel_config(hass, _ZIGBEE_PANEL, configs) diff --git a/custom_components/wiser/websockets.py b/custom_components/wiser/websockets.py index a53033c7..e2b3cb38 100644 --- a/custom_components/wiser/websockets.py +++ b/custom_components/wiser/websockets.py @@ -10,7 +10,7 @@ from aioWiserHeatAPI.schedule import WiserScheduleTypeEnum from homeassistant.helpers.dispatcher import async_dispatcher_connect from .const import DATA, DOMAIN -from .frontend.sidebar import save_schedules_panel_config +from .frontend.schedules_sidebar import save_schedules_panel_config from .frontend.zigbee_sidebar import save_zigbee_panel_config _LOGGER = logging.getLogger(__name__) diff --git a/scripts/fetch_card_releases.py b/scripts/fetch_card_releases.py index 92811c0d..c2255dfb 100644 --- a/scripts/fetch_card_releases.py +++ b/scripts/fetch_card_releases.py @@ -90,7 +90,7 @@ def fetch_cards(channel, output_dir, repositories, plan=False): if not plan: contents, digest = download_asset(repository, asset) # The integration's dedicated panel must have a matching card build. - if asset["name"] == "wiser-schedule-card.js" and (output_dir / "sidebar.py").exists() and b"wiser-schedules-panel" not in contents: + if asset["name"] == "wiser-schedule-card.js" and (output_dir / "schedules_sidebar.py").exists() and b"wiser-schedules-panel" not in contents: raise ValueError("Selected schedule card does not include the sidebar panel required by this integration") payloads[asset["name"]] = contents record["digest"] = digest diff --git a/tests/test_card_releases.py b/tests/test_card_releases.py index 7b966540..26f3e451 100644 --- a/tests/test_card_releases.py +++ b/tests/test_card_releases.py @@ -79,7 +79,7 @@ def test_download_written_to_correct_filename_with_provenance(self): def test_panel_integration_rejects_old_schedule_card(self): with TemporaryDirectory() as directory: out = Path(directory) - (out / "sidebar.py").touch() + (out / "schedules_sidebar.py").touch() with patch.object(FETCH, "list_releases", return_value=[release("old", "2026", card="schedule")]), patch.object(FETCH, "download_asset", return_value=(b"old card", "sha256:test")): with self.assertRaisesRegex(ValueError, "does not include the sidebar panel"): FETCH.fetch_cards("stable", out, {"schedule": "andyblac/wiser-schedule-card"}) diff --git a/tests/test_schedules_sidebar.py b/tests/test_schedules_sidebar.py index fbf5f4b1..8ea03b07 100644 --- a/tests/test_schedules_sidebar.py +++ b/tests/test_schedules_sidebar.py @@ -1,6 +1,6 @@ """Test sidebar panel lifecycle without Home Assistant runtime dependencies.""" -import importlib.util +import importlib from pathlib import Path import sys from types import ModuleType, SimpleNamespace @@ -25,12 +25,11 @@ def setUp(self): constants.CONF_SHOW_SCHEDULES_SIDEBAR = "show_schedules_sidebar" constants.CONF_SCHEDULES_PANEL_CONFIG = "schedules_panel_config" constants.CONF_ZIGBEE_PANEL_CONFIG = "zigbee_panel_config" - zigbee = ModuleType("sidebar_test.frontend.zigbee_sidebar") - self.update_zigbee = AsyncMock() - zigbee.async_update_zigbee_panel = self.update_zigbee + constants.CONF_SHOW_ZIGBEE_SIDEBAR = "show_zigbee_sidebar" version_module = ModuleType("sidebar_test.frontend.schedule_version") self.version_reader = Mock(return_value="4.5.6-beta.2") version_module.card_version = self.version_reader + version_module.__path__ = [str(ROOT / "frontend")] constants.DATA = "data" constants.DOMAIN = "wiser" constants.URL_BASE = "/wiser" @@ -43,13 +42,12 @@ def setUp(self): "sidebar_test": ModuleType("sidebar_test"), "sidebar_test.frontend": version_module, "sidebar_test.const": constants, - "sidebar_test.frontend.zigbee_sidebar": zigbee, }): - spec = importlib.util.spec_from_file_location( - "sidebar_test.frontend.sidebar", ROOT / "frontend/sidebar.py" - ) - self.sidebar = importlib.util.module_from_spec(spec) - spec.loader.exec_module(self.sidebar) + self.zigbee = importlib.import_module("sidebar_test.frontend.zigbee_sidebar") + self.update_zigbee = AsyncMock(wraps=self.zigbee.async_update_zigbee_panel) + self.zigbee.async_update_zigbee_panel = self.update_zigbee + self.sidebar = importlib.import_module("sidebar_test.frontend.schedules_sidebar") + self.entry_updates = importlib.import_module("sidebar_test.frontend.entry_updates") self.entries = [] self.hass = SimpleNamespace( data={"wiser": {}}, @@ -167,11 +165,11 @@ def test_current_external_card_editor_options_are_supported(self): async def test_save_updates_panel_without_removing_route_or_reloading(self): entry = self.add_hub("hub", True) loaded = self.hass.data["wiser"]["hub"] - loaded["reload_settings"] = self.sidebar.integration_reload_settings(entry) + loaded["reload_settings"] = self.entry_updates.integration_reload_settings(entry) self.hass.config_entries.async_reload = AsyncMock() await self.sidebar.async_update_schedules_panel(self.hass) entry.options = {**entry.options, "schedules_panel_config": {"home_screen": "overview"}} - await self.sidebar.async_handle_entry_update(self.hass, entry) + await self.entry_updates.async_handle_entry_update(self.hass, entry) self.hass.config_entries.async_reload.assert_not_called() self.frontend.async_remove_panel.assert_not_called() self.frontend.async_register_built_in_panel.assert_called_once() @@ -182,15 +180,15 @@ async def test_save_updates_panel_without_removing_route_or_reloading(self): async def test_other_options_and_connection_changes_still_reload(self): entry = self.add_hub("hub", True) - self.hass.data["wiser"]["hub"]["reload_settings"] = self.sidebar.integration_reload_settings(entry) + self.hass.data["wiser"]["hub"]["reload_settings"] = self.entry_updates.integration_reload_settings(entry) self.hass.config_entries.async_reload = AsyncMock() entry.options = {**entry.options, "scan_interval": 60} - await self.sidebar.async_handle_entry_update(self.hass, entry) + await self.entry_updates.async_handle_entry_update(self.hass, entry) self.hass.config_entries.async_reload.assert_awaited_once_with("hub") self.hass.config_entries.async_reload.reset_mock() entry.options.pop("scan_interval") entry.data = {"host": "other.local"} - await self.sidebar.async_handle_entry_update(self.hass, entry) + await self.entry_updates.async_handle_entry_update(self.hass, entry) self.hass.config_entries.async_reload.assert_awaited_once_with("hub") async def test_new_bundle_updates_panel_version(self): @@ -204,9 +202,51 @@ async def test_new_bundle_updates_panel_version(self): async def test_zigbee_preferences_update_both_panels_without_reload(self): entry = self.add_hub("hub", True) - self.hass.data["wiser"]["hub"]["reload_settings"] = self.sidebar.integration_reload_settings(entry) + self.hass.data["wiser"]["hub"]["reload_settings"] = self.entry_updates.integration_reload_settings(entry) self.hass.config_entries.async_reload = AsyncMock() entry.options["zigbee_panel_config"] = {"show_labels": True} - await self.sidebar.async_handle_entry_update(self.hass, entry) + await self.entry_updates.async_handle_entry_update(self.hass, entry) self.update_zigbee.assert_awaited_once_with(self.hass) self.hass.config_entries.async_reload.assert_not_called() + + async def test_panel_preferences_remain_independent_during_live_updates(self): + entry = self.add_hub("hub", True) + entry.options["show_zigbee_sidebar"] = True + self.hass.data["wiser"]["hub"]["reload_settings"] = self.entry_updates.integration_reload_settings(entry) + self.hass.config_entries.async_reload = AsyncMock() + await self.entry_updates.async_handle_entry_update(self.hass, entry) + self.assertEqual(self.custom.async_register_panel.await_count, 2) + entry.options["zigbee_panel_config"] = {"orientation": "pie"} + await self.entry_updates.async_handle_entry_update(self.hass, entry) + self.hass.config_entries.async_reload.assert_not_called() + self.frontend.async_register_built_in_panel.assert_called_once() + self.assertEqual( + self.frontend.async_register_built_in_panel.call_args.kwargs["frontend_url_path"], + "wiser-zigbee-panel", + ) + self.assertEqual(self.hass.data[self.sidebar.PANEL_STATE]["card_configs"], {"hub": {}}) + self.assertEqual( + self.hass.data[self.zigbee.PANEL_STATE]["card_configs"], + {"hub": {"orientation": "pie"}}, + ) + + async def test_disabled_hub_with_same_name_cannot_override_settings(self): + enabled = self.add_hub("enabled", True) + enabled.options["schedules_panel_config"] = {"hide_hw_schedule": True} + disabled = self.add_hub("disabled", True, disabled=True) + disabled.options["schedules_panel_config"] = {"hide_hw_schedule": False} + self.hass.data["wiser"]["disabled"]["data"].wiserhub.system.name = "enabled" + await self.sidebar.async_update_schedules_panel(self.hass) + self.assertEqual( + self.custom.async_register_panel.call_args.kwargs["config"]["card_configs"], + {"enabled": {"hide_hw_schedule": True}}, + ) + + def test_disabled_hub_settings_cannot_be_saved(self): + self.add_hub("disabled", True, disabled=True) + self.hass.config_entries.async_update_entry = Mock() + with self.assertRaises(ValueError): + self.sidebar.save_schedules_panel_config( + self.hass, {"disabled": {"hide_hw_schedule": True}} + ) + self.hass.config_entries.async_update_entry.assert_not_called() diff --git a/tests/test_zigbee_sidebar.py b/tests/test_zigbee_sidebar.py index 8033fd68..98104076 100644 --- a/tests/test_zigbee_sidebar.py +++ b/tests/test_zigbee_sidebar.py @@ -27,6 +27,7 @@ def setUp(self): version_module = ModuleType("sidebar_test.frontend.zigbee_version") self.version_reader = Mock(return_value="4.5.6-beta.2") version_module.card_version = self.version_reader + version_module.__path__ = [str(ROOT / "frontend")] constants.DATA = "data" constants.DOMAIN = "wiser" constants.URL_BASE = "/wiser" @@ -41,7 +42,7 @@ def setUp(self): "sidebar_test.const": constants, }): spec = importlib.util.spec_from_file_location( - "sidebar_test.frontend.sidebar", ROOT / "frontend/zigbee_sidebar.py" + "sidebar_test.frontend.zigbee_sidebar", ROOT / "frontend/zigbee_sidebar.py" ) self.sidebar = importlib.util.module_from_spec(spec) spec.loader.exec_module(self.sidebar) @@ -173,15 +174,11 @@ def test_invalid_coordinates_and_choices_are_rejected(self): with self.assertRaises(ValueError): self.sidebar.save_zigbee_panel_config(self.hass, {"hub": settings}) self.hass.config_entries.async_update_entry.assert_not_called() - async def test_save_updates_panel_without_removing_route_or_reloading(self): + async def test_saved_settings_update_panel_without_removing_route(self): entry = self.add_hub("hub", True) - loaded = self.hass.data["wiser"]["hub"] - loaded["reload_settings"] = self.sidebar.integration_reload_settings(entry) - self.hass.config_entries.async_reload = AsyncMock() await self.sidebar.async_update_zigbee_panel(self.hass) entry.options = {**entry.options, "zigbee_panel_config": {"orientation": "pie"}} - await self.sidebar.async_handle_entry_update(self.hass, entry) - self.hass.config_entries.async_reload.assert_not_called() + await self.sidebar.async_update_zigbee_panel(self.hass) self.frontend.async_remove_panel.assert_not_called() self.frontend.async_register_built_in_panel.assert_called_once() update = self.frontend.async_register_built_in_panel.call_args.kwargs @@ -189,19 +186,6 @@ async def test_save_updates_panel_without_removing_route_or_reloading(self): self.assertEqual(update["frontend_url_path"], "wiser-zigbee-panel") self.assertEqual(update["config"]["card_configs"]["hub"], {"orientation": "pie"}) - async def test_other_options_and_connection_changes_still_reload(self): - entry = self.add_hub("hub", True) - self.hass.data["wiser"]["hub"]["reload_settings"] = self.sidebar.integration_reload_settings(entry) - self.hass.config_entries.async_reload = AsyncMock() - entry.options = {**entry.options, "scan_interval": 60} - await self.sidebar.async_handle_entry_update(self.hass, entry) - self.hass.config_entries.async_reload.assert_awaited_once_with("hub") - self.hass.config_entries.async_reload.reset_mock() - entry.options.pop("scan_interval") - entry.data = {"host": "other.local"} - await self.sidebar.async_handle_entry_update(self.hass, entry) - self.hass.config_entries.async_reload.assert_awaited_once_with("hub") - async def test_bundle_version_change_updates_panel_without_settings_change(self): self.add_hub("hub", True) await self.sidebar.async_update_zigbee_panel(self.hass) @@ -241,3 +225,24 @@ async def test_update_conflict_does_not_abort_and_can_be_retried(self): self.frontend.async_register_built_in_panel.side_effect = None await self.sidebar.async_update_zigbee_panel(self.hass) self.assertTrue(self.hass.data[self.sidebar.PANEL_STATE]["card_configs"]["hub"]["show_labels"]) + + async def test_disabled_hub_with_same_name_cannot_override_settings(self): + enabled = self.add_hub("enabled", True) + enabled.options["zigbee_panel_config"] = {"show_labels": True} + disabled = self.add_hub("disabled", True, disabled=True) + disabled.options["zigbee_panel_config"] = {"show_labels": False} + self.hass.data["wiser"]["disabled"]["data"].wiserhub.system.name = "enabled" + await self.sidebar.async_update_zigbee_panel(self.hass) + self.assertEqual( + self.custom.async_register_panel.call_args.kwargs["config"]["card_configs"], + {"enabled": {"show_labels": True}}, + ) + + def test_disabled_hub_settings_cannot_be_saved(self): + self.add_hub("disabled", True, disabled=True) + self.hass.config_entries.async_update_entry = Mock() + with self.assertRaises(ValueError): + self.sidebar.save_zigbee_panel_config( + self.hass, {"disabled": {"show_labels": True}} + ) + self.hass.config_entries.async_update_entry.assert_not_called() From 588f49bc818bfc2da00073d4d38c10e6d26275cf Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Sat, 19 Sep 2026 10:33:05 +0100 Subject: [PATCH 018/154] Move sidebar visibility settings into UI options --- README.md | 2 +- custom_components/wiser/config_flow.py | 18 +++++++++--------- custom_components/wiser/strings.json | 6 +++--- custom_components/wiser/translations/de.json | 6 +++--- custom_components/wiser/translations/en.json | 6 +++--- custom_components/wiser/translations/fr.json | 6 +++--- tests/test_ui_options.py | 19 ++++++++++++++++--- 7 files changed, 38 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 5658d619..0884efed 100755 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ For the latest version of the Wiser Home Assistant Platform please install via H **This integration requires a minimum HA version of 2025.5.** -To open the schedule editor in a dedicated sidebar panel, go to **Settings → Devices & services → Wiser → Configure → Main Parameters** and enable **Show Wiser Schedules in sidebar**. The option is off by default. With multiple hubs, the panel shows schedules for each hub with this option enabled. Use the cog in the panel header to edit its display settings (administrators only). These are saved in the integration configuration for backups and are separate from the configuration of schedule cards on dashboards. +To open the schedule editor in a dedicated sidebar panel, go to **Settings → Devices & services → Wiser → Configure → UI options** and enable **Show Wiser Schedules in sidebar**. The option is off by default. With multiple hubs, the panel shows schedules for each hub with this option enabled. Use the cog in the panel header to edit its display settings (administrators only). These are saved in the integration configuration for backups and are separate from the configuration of schedule cards on dashboards. Detailed information about this integration has now been moved to our [Wiki pages](https://github.com/asantaga/wiserHomeAssistantPlatform/wiki) diff --git a/custom_components/wiser/config_flow.py b/custom_components/wiser/config_flow.py index 17e9030d..e815f334 100755 --- a/custom_components/wiser/config_flow.py +++ b/custom_components/wiser/config_flow.py @@ -277,7 +277,7 @@ async def async_step_init(self, user_input=None): ) async def async_step_ui_options(self, user_input=None): - """Configure device naming for the Home Assistant UI.""" + """Configure Wiser UI options, including legacy naming and sidebar panels.""" if user_input is not None: return self.async_create_entry( data=self.config_entry.options | user_input @@ -293,6 +293,14 @@ async def async_step_ui_options(self, user_input=None): CONF_LEGACY_NAMING, True ), ): BooleanSelector(), + vol.Optional( + CONF_SHOW_SCHEDULES_SIDEBAR, + default=self.config_entry.options.get(CONF_SHOW_SCHEDULES_SIDEBAR, False), + ): BooleanSelector(), + vol.Optional( + CONF_SHOW_ZIGBEE_SIDEBAR, + default=self.config_entry.options.get(CONF_SHOW_ZIGBEE_SIDEBAR, False), + ): BooleanSelector(), } ), ) @@ -393,14 +401,6 @@ async def async_step_main_params(self, user_input=None): return self.async_create_entry(data=options) data_schema = { - vol.Optional( - CONF_SHOW_SCHEDULES_SIDEBAR, - default=self.config_entry.options.get(CONF_SHOW_SCHEDULES_SIDEBAR, False), - ): BooleanSelector(), - vol.Optional( - CONF_SHOW_ZIGBEE_SIDEBAR, - default=self.config_entry.options.get(CONF_SHOW_ZIGBEE_SIDEBAR, False), - ): BooleanSelector(), vol.Required(CONF_HOST, default=self.config_entry.data[CONF_HOST]): str, vol.Optional( CONF_PORT, default=self.config_entry.data.get(CONF_PORT, 80) diff --git a/custom_components/wiser/strings.json b/custom_components/wiser/strings.json index 83150e7f..052be864 100755 --- a/custom_components/wiser/strings.json +++ b/custom_components/wiser/strings.json @@ -48,7 +48,9 @@ "ui_options": { "title": "UI options", "data": { - "legacy_naming": "Legacy naming" + "legacy_naming": "Legacy naming", + "show_schedules_sidebar": "Show Wiser Schedules in sidebar", + "show_zigbee_sidebar": "Show Wiser Zigbee in sidebar" }, "data_description": { "legacy_naming": "Include room names in Wiser device names. If enabled, using Home Assistant to regenerate entity IDs with the default format in Settings → System → Entity ID format (Home Assistant 2026.8 and later) will duplicate area names when the area and Wiser room names match. Changing this option does not rename existing entity IDs." @@ -58,8 +60,6 @@ "title": "Wiser Integration Options", "description": "Main Parameters", "data": { - "show_schedules_sidebar": "Show Wiser Schedules in sidebar", - "show_zigbee_sidebar": "Show Wiser Zigbee in sidebar", "host": "IP Address or Hostname", "port": "Port number", "scan_interval": "Scan Interval (secs)", diff --git a/custom_components/wiser/translations/de.json b/custom_components/wiser/translations/de.json index a72204ea..e7aaf3a3 100644 --- a/custom_components/wiser/translations/de.json +++ b/custom_components/wiser/translations/de.json @@ -48,7 +48,9 @@ "ui_options": { "title": "UI-Optionen", "data": { - "legacy_naming": "Bisherige Namensgebung" + "legacy_naming": "Bisherige Namensgebung", + "show_schedules_sidebar": "Wiser-Zeitpläne in der Seitenleiste anzeigen", + "show_zigbee_sidebar": "Wiser Zigbee in der Seitenleiste anzeigen" }, "data_description": { "legacy_naming": "Raumnamen in Wiser-Gerätenamen aufnehmen. Wenn diese Option aktiviert ist, werden Bereichsnamen beim Neuerstellen der Entitäts-IDs mit dem Standardformat unter Einstellungen → System → Entitäts-ID-Format (Home Assistant 2026.8 und neuer) doppelt verwendet, wenn Bereichs- und Wiser-Raumname übereinstimmen. Diese Option ändert keine bestehenden Entitäts-IDs." @@ -58,8 +60,6 @@ "title": "Wiser Integrationsoptionen", "description": "Hauptparameter", "data": { - "show_schedules_sidebar": "Wiser-Zeitpläne in der Seitenleiste anzeigen", - "show_zigbee_sidebar": "Wiser Zigbee in der Seitenleiste anzeigen", "host": "IP Adresse", "port": "Portnummer", "scan_interval": "Scan Intervall", diff --git a/custom_components/wiser/translations/en.json b/custom_components/wiser/translations/en.json index 0d5bce28..449f4077 100755 --- a/custom_components/wiser/translations/en.json +++ b/custom_components/wiser/translations/en.json @@ -48,7 +48,9 @@ "ui_options": { "title": "UI options", "data": { - "legacy_naming": "Legacy naming" + "legacy_naming": "Legacy naming", + "show_schedules_sidebar": "Show Wiser Schedules in sidebar", + "show_zigbee_sidebar": "Show Wiser Zigbee in sidebar" }, "data_description": { "legacy_naming": "Include room names in Wiser device names. If enabled, using Home Assistant to regenerate entity IDs with the default format in Settings → System → Entity ID format (Home Assistant 2026.8 and later) will duplicate area names when the area and Wiser room names match. Changing this option does not rename existing entity IDs." @@ -58,8 +60,6 @@ "title": "Wiser Integration Options", "description": "Main Parameters", "data": { - "show_schedules_sidebar": "Show Wiser Schedules in sidebar", - "show_zigbee_sidebar": "Show Wiser Zigbee in sidebar", "host": "IP Address or Hostname", "port": "Port number", "scan_interval": "Scan Interval (secs)", diff --git a/custom_components/wiser/translations/fr.json b/custom_components/wiser/translations/fr.json index a60ba92b..9ae09dc5 100644 --- a/custom_components/wiser/translations/fr.json +++ b/custom_components/wiser/translations/fr.json @@ -48,7 +48,9 @@ "ui_options": { "title": "Options de l’interface", "data": { - "legacy_naming": "Nommage historique" + "legacy_naming": "Nommage historique", + "show_schedules_sidebar": "Afficher les programmes Wiser dans la barre latérale", + "show_zigbee_sidebar": "Afficher Wiser Zigbee dans la barre latérale" }, "data_description": { "legacy_naming": "Inclure le nom des pièces dans le nom des appareils Wiser. Si cette option est activée, la régénération des identifiants d’entité avec le format par défaut dans Paramètres → Système → Format des identifiants d’entité (Home Assistant 2026.8 et versions ultérieures) répétera le nom de la zone si celui-ci correspond au nom de la pièce Wiser. Cette option ne renomme pas les identifiants d’entité existants." @@ -58,8 +60,6 @@ "title": "Wiser possibilités d'intégration", "description": "Paramètres principaux", "data": { - "show_schedules_sidebar": "Afficher les programmes Wiser dans la barre latérale", - "show_zigbee_sidebar": "Afficher Wiser Zigbee dans la barre latérale", "host": "Adresse IP ou nom d'hote", "port": "Numéro de port", "scan_interval": " Période d'acquisition", diff --git a/tests/test_ui_options.py b/tests/test_ui_options.py index 11a34c1a..bb4553b6 100644 --- a/tests/test_ui_options.py +++ b/tests/test_ui_options.py @@ -31,6 +31,8 @@ class UIOptionsTest(unittest.IsolatedAsyncioTestCase): def setUp(self): self.namespace = { "CONF_LEGACY_NAMING": "legacy_naming", + "CONF_SHOW_SCHEDULES_SIDEBAR": "show_schedules_sidebar", + "CONF_SHOW_ZIGBEE_SIDEBAR": "show_zigbee_sidebar", "CONF_NAME": "name", "HomeAssistant": object, "ConfigEntry": object, @@ -83,8 +85,13 @@ async def test_saving_ui_options_preserves_other_options(self): config_entry=SimpleNamespace(options={"scan_interval": 30}), async_create_entry=lambda **kwargs: kwargs, ) - result = await functions.async_step_ui_options(flow, {"legacy_naming": enabled}) - self.assertEqual(result["data"], {"scan_interval": 30, "legacy_naming": enabled}) + preferences = { + "legacy_naming": enabled, + "show_schedules_sidebar": enabled, + "show_zigbee_sidebar": not enabled, + } + result = await functions.async_step_ui_options(flow, preferences) + self.assertEqual(result["data"], {"scan_interval": 30} | preferences) async def test_form_uses_saved_preference(self): self.namespace.update( @@ -94,8 +101,14 @@ async def test_form_uses_saved_preference(self): functions = load_functions("config_flow.py", {"async_step_ui_options"}, self.namespace) for enabled in (False, True): flow = SimpleNamespace( - config_entry=SimpleNamespace(options={"legacy_naming": enabled}), + config_entry=SimpleNamespace(options={ + "legacy_naming": enabled, + "show_schedules_sidebar": enabled, + "show_zigbee_sidebar": not enabled, + }), async_show_form=lambda **kwargs: kwargs, ) result = await functions.async_step_ui_options(flow) self.assertIn(("legacy_naming", enabled), result["data_schema"]) + self.assertIn(("show_schedules_sidebar", enabled), result["data_schema"]) + self.assertIn(("show_zigbee_sidebar", not enabled), result["data_schema"]) From 61a8fc044eaedbd8bf62d3a38dfb43cd884221ff Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Sat, 19 Sep 2026 11:33:48 +0100 Subject: [PATCH 019/154] Support evolving sidebar card settings and update Zigbee bundle --- custom_components/wiser/frontend/panel.py | 40 ++-- .../wiser/frontend/schedules_sidebar.py | 7 +- .../wiser/frontend/wiser-zigbee-card.js | 185 +++++++++++------- .../wiser/frontend/zigbee_sidebar.py | 34 +--- tests/test_schedules_sidebar.py | 44 ++++- tests/test_zigbee_sidebar.py | 49 ++++- 6 files changed, 233 insertions(+), 126 deletions(-) diff --git a/custom_components/wiser/frontend/panel.py b/custom_components/wiser/frontend/panel.py index d9bb7872..2fe395f9 100644 --- a/custom_components/wiser/frontend/panel.py +++ b/custom_components/wiser/frontend/panel.py @@ -2,9 +2,9 @@ from __future__ import annotations +import math from dataclasses import dataclass from pathlib import Path -from typing import Callable from homeassistant.components import frontend, panel_custom @@ -26,8 +26,6 @@ class SidebarPanel: config_option: str hub_error: str setting_error: str - field_types: dict - validate_setting: Callable | None = None def _enabled_entries(hass, panel): @@ -99,25 +97,43 @@ async def async_update_panel(hass, panel): hass.data[panel.state_key] = state +def _is_json_value(value, depth=0): + """Accept finite JSON data, including future card options.""" + if depth > 64: + return False + if type(value) in (str, bool, int, type(None)): + return True + if type(value) is float: + return math.isfinite(value) + if type(value) is list: + return all(_is_json_value(item, depth + 1) for item in value) + if type(value) is dict: + return all( + type(key) is str and _is_json_value(item, depth + 1) + for key, item in value.items() + ) + return False + + def save_panel_config(hass, panel, configs): - """Validate every hub's settings before persisting any options.""" + """Validate every hub's settings before persisting any options. + + Cards own their display options. Only validate JSON structure here so new + card settings do not require an integration release. + """ + if type(configs) is not dict: + raise ValueError(panel.setting_error) entries = dict(_enabled_entries(hass, panel)) updates = [] for hub, config in configs.items(): if hub not in entries: raise ValueError(panel.hub_error) + if type(config) is not dict or not _is_json_value(config): + raise ValueError(panel.setting_error) settings = {} for key, value in config.items(): if key in {"type", "hub"}: continue - allowed_types = panel.field_types.get(key, ()) - if not isinstance(allowed_types, tuple): - allowed_types = (allowed_types,) - # Exact types prevent booleans from being accepted as integers. - if type(value) not in allowed_types: - raise ValueError(f"{panel.setting_error}: {key}") - if panel.validate_setting is not None: - panel.validate_setting(key, value) settings[key] = value updates.append((entries[hub], settings)) for entry, settings in updates: diff --git a/custom_components/wiser/frontend/schedules_sidebar.py b/custom_components/wiser/frontend/schedules_sidebar.py index 51e4c5fc..7ca17f4a 100644 --- a/custom_components/wiser/frontend/schedules_sidebar.py +++ b/custom_components/wiser/frontend/schedules_sidebar.py @@ -19,12 +19,7 @@ config_option=CONF_SCHEDULES_PANEL_CONFIG, hub_error="Hub is not enabled in the schedules panel", setting_error="Invalid schedule card setting", - field_types={ - "name": str, "selected_schedule": str, "view_type": str, "home_screen": str, - "theme_colors": bool, "show_badges": bool, "show_schedule_id": bool, - "display_only": bool, "hide_hw_schedule": bool, "admin_only": bool, - "hide_card_borders": bool, "hide_card_background": bool, "overview_details": bool, - }, + ) diff --git a/custom_components/wiser/frontend/wiser-zigbee-card.js b/custom_components/wiser/frontend/wiser-zigbee-card.js index 321f341e..1983f24a 100644 --- a/custom_components/wiser/frontend/wiser-zigbee-card.js +++ b/custom_components/wiser/frontend/wiser-zigbee-card.js @@ -1,53 +1,54 @@ -/*! WISER-CARD-VERSION wiser-zigbee-card 3.0.0-dev.67 */ -var wiserzigbeecard=function(t){"use strict";function e(t,e,i,o){var n,r=arguments.length,s=r<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 a=t.length-1;a>=0;a--)(n=t[a])&&(s=(r<3?n(s):r>3?n(e,i,s):n(e,i))||s);return r>3&&s&&Object.defineProperty(e,i,s),s}"function"==typeof SuppressedError&&SuppressedError;const i="wiser-zigbee-magnifier-size",o="wiser-zigbee-magnifier-zoom";class n{constructor(){this.zoom=2,this.size=180;try{const t=Number(localStorage.getItem(o));[2,3,4].includes(t)&&(this.zoom=t);const e=Number(localStorage.getItem(i));e>=100&&e<=360&&(this.size=10*Math.round(e/10))}catch(t){}}setSize(t){if(Number.isFinite(t)){this.size=Math.max(100,Math.min(360,10*Math.round(t/10)));try{localStorage.setItem(i,String(this.size))}catch(t){}this.refresh()}}setZoom(t){if([2,3,4].includes(t)){this.zoom=t;try{localStorage.setItem(o,String(t))}catch(t){}this.refresh()}}show(t,e){if("touch"===e.pointerType||e.buttons)return void this.hide();const i=t.getBoundingClientRect();this.map=t,this.point={x:(e.clientX-i.left)*t.clientWidth/(i.width||t.clientWidth),y:(e.clientY-i.top)*t.clientHeight/(i.height||t.clientHeight)},this.refresh()}refresh(){this.point&&void 0===this.frame&&(this.frame=requestAnimationFrame((()=>{this.frame=void 0,this.draw()})))}hide(){var t;void 0!==this.frame&&cancelAnimationFrame(this.frame),this.frame=void 0,this.point=void 0,null===(t=this.lens)||void 0===t||t.remove(),this.lens=void 0}draw(){var t;const e=this.map,i=this.point,o=null==e?void 0:e.querySelector("canvas");if(!((null==e?void 0:e.isConnected)&&i&&o&&e.clientWidth&&e.clientHeight))return void this.hide();this.lens||(this.lens=e.ownerDocument.createElement("div"),this.lens.className="map-magnifier",this.lens.setAttribute("aria-hidden","true"),this.lens.append(e.ownerDocument.createElement("canvas"),e.ownerDocument.createElement("div")),e.parentElement.append(this.lens));const n=function(t,e,i,o,n=2,r=180){const s=Math.min(r,i,o);return{size:s,left:Math.max(0,Math.min(i-s,t-s/2)),top:Math.max(0,Math.min(o-s,e-s/2)),imageX:s/2-t*n,imageY:s/2-e*n}}(i.x,i.y,e.clientWidth,e.clientHeight,this.zoom,this.size);this.lens.style.cssText=`left:${n.left}px;top:${n.top}px;width:${n.size}px;height:${n.size}px`;const r=this.lens.firstElementChild,s=(null===(t=e.ownerDocument.defaultView)||void 0===t?void 0:t.devicePixelRatio)||1;r.width=Math.round(n.size*s),r.height=Math.round(n.size*s),r.style.width=r.style.height=`${n.size}px`;const a=r.getContext("2d");if(!a)return;a.scale(s,s),a.drawImage(o,n.imageX,n.imageY,e.clientWidth*this.zoom,e.clientHeight*this.zoom);const l=this.lens.lastElementChild;l.className="magnifier-area-icons",l.style.transform=`translate(${n.imageX}px, ${n.imageY}px) scale(${this.zoom})`,l.replaceChildren(),e.parentElement.querySelectorAll(".area-icons ha-icon").forEach((t=>{const e=t.cloneNode(!1);e.icon=t.icon,l.append(e)}))}}function r(t){var e,i;const o=Object.assign({},t);return(void 0!==o.layout_orientation&&o.layout_orientation!==(null!==(e=o.orientation)&&void 0!==e?e:"vertical")||void 0!==o.layout_group_by&&o.layout_group_by!==(null!==(i=o.group_by)&&void 0!==i?i:"none"))&&delete o.layout_data,delete o.show_layout_export,delete o.layout_orientation,delete o.layout_group_by,o}const s=t=>JSON.stringify(t,((t,e)=>e&&"object"==typeof e&&!Array.isArray(e)?Object.keys(e).sort().reduce(((t,i)=>(t[i]=e[i],t)),{}):e));async function a(t,e,i){var o,n,a,l,h,c;let d,u=t;for(;u;){if("wiser-zigbee-panel"===u.localName&&u.saveZigbeeCardConfig)return u.saveZigbeeCardConfig(t,r(Object.assign(Object.assign({},e),i)));if(null===(o=u.lovelace)||void 0===o?void 0:o.saveConfig){d=u.lovelace;break}u=null!==(n=u.parentElement)&&void 0!==n?n:null===(a=u.getRootNode)||void 0===a?void 0:a.call(u).host}const f=null!==(l=null==d?void 0:d.rawConfig)&&void 0!==l?l:null==d?void 0:d.config;if(!d||"storage"!==d.mode||!f||f.strategy)throw new Error("Dashboard configuration is not editable");const p=[],v=(t,i)=>{if(t&&"object"==typeof t){t.type===e.type&&s(t)===s(e)&&p.push({value:t,path:i});for(const[e,o]of Object.entries(t))v(o,[...i,e])}};v(f,[]);const g=p.filter((t=>t.value===e)),y=g.length?g:p;if(1!==y.length)throw new Error("Cannot uniquely identify this card");const m=JSON.parse(JSON.stringify(f)),b=y[0].path;let w=m;for(const t of b.slice(0,-1))w=w[t];const A=r(Object.assign(Object.assign({},y[0].value),i));w[b[b.length-1]]=A;const E=function(t){if(!t)return()=>{};const{scrollX:e,scrollY:i}=t,o=t.location.href;let n=!1,r=0,s=Date.now()+2500;const a=["wheel","touchstart","pointerdown","keydown","popstate","hashchange"],l=()=>{n=!0,t.cancelAnimationFrame(r),a.forEach((e=>t.removeEventListener(e,l,!0)))},h=()=>{n||Date.now()>=s||t.location.href!==o?l():(t.scrollX===e&&t.scrollY===i||t.scrollTo({left:e,top:i,behavior:"instant"}),r=t.requestAnimationFrame(h))};return a.forEach((e=>t.addEventListener(e,l,{capture:!0,passive:!0}))),r=t.requestAnimationFrame(h),()=>{s=Math.min(s,Date.now()+500)}}(null!==(c=null===(h=t.ownerDocument)||void 0===h?void 0:h.defaultView)&&void 0!==c?c:null);try{await d.saveConfig(m)}finally{E()}return A}const l=new Map,h=t=>t.replace(/&/g,"&").replace(/"/g,""").replace(/`:"";n="data:image/svg+xml,"+encodeURIComponent(`${r}`),l.set(o,n)}return n}function d(t){const e=t.match(/^([\s\S]*?)\n\s*\(([\s\S]*)\)\s*$/);if(!e)return t.replace(/\n/g," ").trim();const i=e[1].trim(),o=e[2].trim();return!o||/^no room$/i.test(o)?i:o}function u(t,e,i){var o,n;const r=new Map;for(const e of t.filter((t=>"Controller"!==t.group))){const t=null!==(o=e.area_id)&&void 0!==o?o:"";r.set(t,[...null!==(n=r.get(t))&&void 0!==n?n:[],e])}const s=t=>{var e;return null!==(e=null==i?void 0:i(t))&&void 0!==e?e:{left:Math.min(...t.map((t=>t.x-Math.max(40,4.5*t.label.length))))-18,right:Math.max(...t.map((t=>t.x+Math.max(40,4.5*t.label.length))))+18,top:Math.min(...t.map((t=>t.y-32)))-18,bottom:Math.max(...t.map((t=>t.y+60)))+18}},a=(t,e)=>Math.max(0,Math.min(t.right,e.right)-Math.max(t.left,e.left))*Math.max(0,Math.min(t.bottom,e.bottom)-Math.max(t.top,e.top)),l=new Map(t.map((t=>[t.id,{x:t.x,y:t.y}]))),h=[...r.values()];if(!t.length)return;const c=h.map(s);if(!c.length)return;const d=c.some(((t,e)=>c.slice(e+1).some((e=>a(t,e)>0)))),u=Math.min(...c.map((t=>t.left))),f=Math.max(...c.map((t=>t.right))),p=Math.min(...c.map((t=>t.top))),v=Math.max(...c.map((t=>t.bottom))),g=Math.max(480,Math.min(1200,Math.hypot(f-u,v-p)));for(let i=0;i<12;i++){let i=!1;for(const o of h){if(o.some((t=>e.has(t.id))))continue;const n=h.filter((t=>t!==o)).map(s),r=s(o),c=t=>n.reduce(((e,i)=>e+a(t,i)),0),u=t=>{const e=[...n,t];return(Math.max(...e.map((t=>t.right)))-Math.min(...e.map((t=>t.left))))*(Math.max(...e.map((t=>t.bottom)))-Math.min(...e.map((t=>t.top))))};let f=c(r),p=u(r),v={x:0,y:0};for(const e of n.filter((t=>d||a(r,t)>0))){const i=[{x:e.left-r.right-16,y:0},{x:e.right-r.left+16,y:0},{x:0,y:e.top-r.bottom-16},{x:0,y:e.bottom-r.top+16},{x:e.right-r.left+16,y:e.top-r.bottom-16},{x:e.left-r.right-16,y:e.top-r.bottom-16},{x:e.right-r.left+16,y:e.bottom-r.top+16},{x:e.left-r.right-16,y:e.bottom-r.top+16}].sort(((t,e)=>Math.hypot(t.x,t.y)-Math.hypot(e.x,e.y)));for(const e of i){if(o.some((t=>Math.hypot(t.x+e.x-l.get(t.id).x,t.y+e.y-l.get(t.id).y)>g)))continue;const i={left:r.left+e.x,right:r.right+e.x,top:r.top+e.y,bottom:r.bottom+e.y};if(t.some((t=>"Controller"===t.group&&a(i,s([t]))>0)))continue;const n=c(i),h=u(i);(nf(e,!0,t))).join("|")} +/*! WISER-CARD-VERSION wiser-zigbee-card 3.0.0-dev.84 */ +var wiserzigbeecard=function(t){"use strict";function e(t,e,i,n){var o,r=arguments.length,s=r<3?e:null===n?n=Object.getOwnPropertyDescriptor(e,i):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,i,n);else for(var a=t.length-1;a>=0;a--)(o=t[a])&&(s=(r<3?o(s):r>3?o(e,i,s):o(e,i))||s);return r>3&&s&&Object.defineProperty(e,i,s),s}let i;"function"==typeof SuppressedError&&SuppressedError;const n="wiser-zigbee:copied-settings";function o(t){i=t;try{void 0===t?sessionStorage.removeItem(n):sessionStorage.setItem(n,t)}catch(t){}} +/*! js-yaml 4.1.0 https://github.com/nodeca/js-yaml @license MIT */ +function r(t){return null==t}var s=function(t,e){var i,n="";for(i=0;ia&&(e=n-a+(r=" ... ").length),i-n>a&&(i=n+a-(s=" ...").length),{str:r+t.slice(e,i).replace(/\t/g,"→")+s,pos:n-e+r.length}}function p(t,e){return h.repeat(" ",e-t.length)+t}var v=function(t,e){if(e=Object.create(e||null),!t.buffer)return null;e.maxLength||(e.maxLength=79),"number"!=typeof e.indent&&(e.indent=1),"number"!=typeof e.linesBefore&&(e.linesBefore=3),"number"!=typeof e.linesAfter&&(e.linesAfter=2);for(var i,n=/\r?\n|\r|\0/g,o=[0],r=[],s=-1;i=n.exec(t.buffer);)r.push(i.index),o.push(i.index+i[0].length),t.position<=i.index&&s<0&&(s=o.length-2);s<0&&(s=o.length-1);var a,l,c="",d=Math.min(t.line+e.linesAfter,r.length).toString().length,u=e.maxLength-(e.indent+d+3);for(a=1;a<=e.linesBefore&&!(s-a<0);a++)l=f(t.buffer,o[s-a],r[s-a],t.position-(o[s]-o[s-a]),u),c=h.repeat(" ",e.indent)+p((t.line-a+1).toString(),d)+" | "+l.str+"\n"+c;for(l=f(t.buffer,o[s],r[s],t.position,u),c+=h.repeat(" ",e.indent)+p((t.line+1).toString(),d)+" | "+l.str+"\n",c+=h.repeat("-",e.indent+d+3+l.pos)+"^\n",a=1;a<=e.linesAfter&&!(s+a>=r.length);a++)l=f(t.buffer,o[s+a],r[s+a],t.position-(o[s]-o[s+a]),u),c+=h.repeat(" ",e.indent)+p((t.line+a+1).toString(),d)+" | "+l.str+"\n";return c.replace(/\n$/,"")},g=["kind","multi","resolve","construct","instanceOf","predicate","represent","representName","defaultStyle","styleAliases"],y=["scalar","sequence","mapping"];var m=function(t,e){if(e=e||{},Object.keys(e).forEach((function(e){if(-1===g.indexOf(e))throw new u('Unknown option "'+e+'" is met in definition of "'+t+'" YAML type.')})),this.options=e,this.tag=t,this.kind=e.kind||null,this.resolve=e.resolve||function(){return!0},this.construct=e.construct||function(t){return t},this.instanceOf=e.instanceOf||null,this.predicate=e.predicate||null,this.represent=e.represent||null,this.representName=e.representName||null,this.defaultStyle=e.defaultStyle||null,this.multi=e.multi||!1,this.styleAliases=function(t){var e={};return null!==t&&Object.keys(t).forEach((function(i){t[i].forEach((function(t){e[String(t)]=i}))})),e}(e.styleAliases||null),-1===y.indexOf(this.kind))throw new u('Unknown kind "'+this.kind+'" is specified for "'+t+'" YAML type.')};function b(t,e){var i=[];return t[e].forEach((function(t){var e=i.length;i.forEach((function(i,n){i.tag===t.tag&&i.kind===t.kind&&i.multi===t.multi&&(e=n)})),i[e]=t})),i}function w(t){return this.extend(t)}w.prototype.extend=function(t){var e=[],i=[];if(t instanceof m)i.push(t);else if(Array.isArray(t))i=i.concat(t);else{if(!t||!Array.isArray(t.implicit)&&!Array.isArray(t.explicit))throw new u("Schema.extend argument should be a Type, [ Type ], or a schema definition ({ implicit: [...], explicit: [...] })");t.implicit&&(e=e.concat(t.implicit)),t.explicit&&(i=i.concat(t.explicit))}e.forEach((function(t){if(!(t instanceof m))throw new u("Specified list of YAML types (or a single Type object) contains a non-Type object.");if(t.loadKind&&"scalar"!==t.loadKind)throw new u("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.");if(t.multi)throw new u("There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.")})),i.forEach((function(t){if(!(t instanceof m))throw new u("Specified list of YAML types (or a single Type object) contains a non-Type object.")}));var n=Object.create(w.prototype);return n.implicit=(this.implicit||[]).concat(e),n.explicit=(this.explicit||[]).concat(i),n.compiledImplicit=b(n,"implicit"),n.compiledExplicit=b(n,"explicit"),n.compiledTypeMap=function(){var t,e,i={scalar:{},sequence:{},mapping:{},fallback:{},multi:{scalar:[],sequence:[],mapping:[],fallback:[]}};function n(t){t.multi?(i.multi[t.kind].push(t),i.multi.fallback.push(t)):i[t.kind][t.tag]=i.fallback[t.tag]=t}for(t=0,e=arguments.length;t=0?"0b"+t.toString(2):"-0b"+t.toString(2).slice(1)},octal:function(t){return t>=0?"0o"+t.toString(8):"-0o"+t.toString(8).slice(1)},decimal:function(t){return t.toString(10)},hexadecimal:function(t){return t>=0?"0x"+t.toString(16).toUpperCase():"-0x"+t.toString(16).toUpperCase().slice(1)}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}}),B=new RegExp("^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");var z=/^[-+]?[0-9]+e/;var P=new m("tag:yaml.org,2002:float",{kind:"scalar",resolve:function(t){return null!==t&&!(!B.test(t)||"_"===t[t.length-1])},construct:function(t){var e,i;return i="-"===(e=t.replace(/_/g,"").toLowerCase())[0]?-1:1,"+-".indexOf(e[0])>=0&&(e=e.slice(1)),".inf"===e?1===i?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:".nan"===e?NaN:i*parseFloat(e,10)},predicate:function(t){return"[object Number]"===Object.prototype.toString.call(t)&&(t%1!=0||h.isNegativeZero(t))},represent:function(t,e){var i;if(isNaN(t))switch(e){case"lowercase":return".nan";case"uppercase":return".NAN";case"camelcase":return".NaN"}else if(Number.POSITIVE_INFINITY===t)switch(e){case"lowercase":return".inf";case"uppercase":return".INF";case"camelcase":return".Inf"}else if(Number.NEGATIVE_INFINITY===t)switch(e){case"lowercase":return"-.inf";case"uppercase":return"-.INF";case"camelcase":return"-.Inf"}else if(h.isNegativeZero(t))return"-0.0";return i=t.toString(10),z.test(i)?i.replace("e",".e"):i},defaultStyle:"lowercase"}),F=x.extend({implicit:[I,S,R,P]}),T=F,N=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),j=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$");var L=new m("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:function(t){return null!==t&&(null!==N.exec(t)||null!==j.exec(t))},construct:function(t){var e,i,n,o,r,s,a,l,h=0,c=null;if(null===(e=N.exec(t))&&(e=j.exec(t)),null===e)throw new Error("Date resolve error");if(i=+e[1],n=+e[2]-1,o=+e[3],!e[4])return new Date(Date.UTC(i,n,o));if(r=+e[4],s=+e[5],a=+e[6],e[7]){for(h=e[7].slice(0,3);h.length<3;)h+="0";h=+h}return e[9]&&(c=6e4*(60*+e[10]+ +(e[11]||0)),"-"===e[9]&&(c=-c)),l=new Date(Date.UTC(i,n,o,r,s,a,h)),c&&l.setTime(l.getTime()-c),l},instanceOf:Date,represent:function(t){return t.toISOString()}});var U=new m("tag:yaml.org,2002:merge",{kind:"scalar",resolve:function(t){return"<<"===t||null===t}}),Q="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r";var H=new m("tag:yaml.org,2002:binary",{kind:"scalar",resolve:function(t){if(null===t)return!1;var e,i,n=0,o=t.length,r=Q;for(i=0;i64)){if(e<0)return!1;n+=6}return n%8==0},construct:function(t){var e,i,n=t.replace(/[\r\n=]/g,""),o=n.length,r=Q,s=0,a=[];for(e=0;e>16&255),a.push(s>>8&255),a.push(255&s)),s=s<<6|r.indexOf(n.charAt(e));return 0===(i=o%4*6)?(a.push(s>>16&255),a.push(s>>8&255),a.push(255&s)):18===i?(a.push(s>>10&255),a.push(s>>2&255)):12===i&&a.push(s>>4&255),new Uint8Array(a)},predicate:function(t){return"[object Uint8Array]"===Object.prototype.toString.call(t)},represent:function(t){var e,i,n="",o=0,r=t.length,s=Q;for(e=0;e>18&63],n+=s[o>>12&63],n+=s[o>>6&63],n+=s[63&o]),o=(o<<8)+t[e];return 0===(i=r%3)?(n+=s[o>>18&63],n+=s[o>>12&63],n+=s[o>>6&63],n+=s[63&o]):2===i?(n+=s[o>>10&63],n+=s[o>>4&63],n+=s[o<<2&63],n+=s[64]):1===i&&(n+=s[o>>2&63],n+=s[o<<4&63],n+=s[64],n+=s[64]),n}}),V=Object.prototype.hasOwnProperty,W=Object.prototype.toString;var G=new m("tag:yaml.org,2002:omap",{kind:"sequence",resolve:function(t){if(null===t)return!0;var e,i,n,o,r,s=[],a=t;for(e=0,i=a.length;e>10),56320+(t-65536&1023))}for(var wt=new Array(256),At=new Array(256),kt=0;kt<256;kt++)wt[kt]=mt(kt)?1:0,At[kt]=mt(kt);function Et(t,e){this.input=t,this.filename=e.filename||null,this.schema=e.schema||J,this.onWarning=e.onWarning||null,this.legacy=e.legacy||!1,this.json=e.json||!1,this.listener=e.listener||null,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=t.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.firstTabInLine=-1,this.documents=[]}function Ct(t,e){var i={name:t.filename,buffer:t.input.slice(0,-1),position:t.position,line:t.line,column:t.position-t.lineStart};return i.snippet=v(i),new u(e,i)}function xt(t,e){throw Ct(t,e)}function It(t,e){t.onWarning&&t.onWarning.call(null,Ct(t,e))}var St={YAML:function(t,e,i){var n,o,r;null!==t.version&&xt(t,"duplication of %YAML directive"),1!==i.length&&xt(t,"YAML directive accepts exactly one argument"),null===(n=/^([0-9]+)\.([0-9]+)$/.exec(i[0]))&&xt(t,"ill-formed argument of the YAML directive"),o=parseInt(n[1],10),r=parseInt(n[2],10),1!==o&&xt(t,"unacceptable YAML version of the document"),t.version=i[0],t.checkLineBreaks=r<2,1!==r&&2!==r&&It(t,"unsupported YAML version of the document")},TAG:function(t,e,i){var n,o;2!==i.length&&xt(t,"TAG directive accepts exactly two arguments"),n=i[0],o=i[1],lt.test(n)||xt(t,"ill-formed tag handle (first argument) of the TAG directive"),X.call(t.tagMap,n)&&xt(t,'there is a previously declared suffix for "'+n+'" tag handle'),ht.test(o)||xt(t,"ill-formed tag prefix (second argument) of the TAG directive");try{o=decodeURIComponent(o)}catch(e){xt(t,"tag prefix is malformed: "+o)}t.tagMap[n]=o}};function Mt(t,e,i,n){var o,r,s,a;if(e1&&(t.result+=h.repeat("\n",e-1))}function Ft(t,e){var i,n,o=t.tag,r=t.anchor,s=[],a=!1;if(-1!==t.firstTabInLine)return!1;for(null!==t.anchor&&(t.anchorMap[t.anchor]=s),n=t.input.charCodeAt(t.position);0!==n&&(-1!==t.firstTabInLine&&(t.position=t.firstTabInLine,xt(t,"tab characters must not be used in indentation")),45===n)&&ft(t.input.charCodeAt(t.position+1));)if(a=!0,t.position++,Bt(t,!0,-1)&&t.lineIndent<=e)s.push(null),n=t.input.charCodeAt(t.position);else if(i=t.line,jt(t,e,tt,!1,!0),s.push(t.result),Bt(t,!0,-1),n=t.input.charCodeAt(t.position),(t.line===i||t.lineIndent>e)&&0!==n)xt(t,"bad indentation of a sequence entry");else if(t.lineIndente?v=1:t.lineIndent===e?v=0:t.lineIndente?v=1:t.lineIndent===e?v=0:t.lineIndente)&&(y&&(s=t.line,a=t.lineStart,l=t.position),jt(t,e,et,!0,o)&&(y?v=t.result:g=t.result),y||(Dt(t,u,f,p,v,g,s,a,l),p=v=g=null),Bt(t,!0,-1),h=t.input.charCodeAt(t.position)),(t.line===r||t.lineIndent>e)&&0!==h)xt(t,"bad indentation of a mapping entry");else if(t.lineIndent=0))break;0===o?xt(t,"bad explicit indentation width of a block scalar; it cannot be less than one"):l?xt(t,"repeat of an indentation width identifier"):(c=e+o-1,l=!0)}if(ut(r)){do{r=t.input.charCodeAt(++t.position)}while(ut(r));if(35===r)do{r=t.input.charCodeAt(++t.position)}while(!dt(r)&&0!==r)}for(;0!==r;){for(Rt(t),t.lineIndent=0,r=t.input.charCodeAt(t.position);(!l||t.lineIndentc&&(c=t.lineIndent),dt(r))d++;else{if(t.lineIndent0){for(o=s,r=0;o>0;o--)(s=vt(a=t.input.charCodeAt(++t.position)))>=0?r=(r<<4)+s:xt(t,"expected hexadecimal character");t.result+=bt(r),t.position++}else xt(t,"unknown escape sequence");i=n=t.position}else dt(a)?(Mt(t,i,n,!0),Pt(t,Bt(t,!1,e)),i=n=t.position):t.position===t.lineStart&&zt(t)?xt(t,"unexpected end of the document within a double quoted scalar"):(t.position++,n=t.position)}xt(t,"unexpected end of the stream within a double quoted scalar")}(t,f)?y=!0:!function(t){var e,i,n;if(42!==(n=t.input.charCodeAt(t.position)))return!1;for(n=t.input.charCodeAt(++t.position),e=t.position;0!==n&&!ft(n)&&!pt(n);)n=t.input.charCodeAt(++t.position);return t.position===e&&xt(t,"name of an alias node must contain at least one character"),i=t.input.slice(e,t.position),X.call(t.anchorMap,i)||xt(t,'unidentified alias "'+i+'"'),t.result=t.anchorMap[i],Bt(t,!0,-1),!0}(t)?function(t,e,i){var n,o,r,s,a,l,h,c,d=t.kind,u=t.result;if(ft(c=t.input.charCodeAt(t.position))||pt(c)||35===c||38===c||42===c||33===c||124===c||62===c||39===c||34===c||37===c||64===c||96===c)return!1;if((63===c||45===c)&&(ft(n=t.input.charCodeAt(t.position+1))||i&&pt(n)))return!1;for(t.kind="scalar",t.result="",o=r=t.position,s=!1;0!==c;){if(58===c){if(ft(n=t.input.charCodeAt(t.position+1))||i&&pt(n))break}else if(35===c){if(ft(t.input.charCodeAt(t.position-1)))break}else{if(t.position===t.lineStart&&zt(t)||i&&pt(c))break;if(dt(c)){if(a=t.line,l=t.lineStart,h=t.lineIndent,Bt(t,!1,-1),t.lineIndent>=e){s=!0,c=t.input.charCodeAt(t.position);continue}t.position=r,t.line=a,t.lineStart=l,t.lineIndent=h;break}}s&&(Mt(t,o,r,!1),Pt(t,t.line-a),o=r=t.position,s=!1),ut(c)||(r=t.position+1),c=t.input.charCodeAt(++t.position)}return Mt(t,o,r,!1),!!t.result||(t.kind=d,t.result=u,!1)}(t,f,_===i)&&(y=!0,null===t.tag&&(t.tag="?")):(y=!0,null===t.tag&&null===t.anchor||xt(t,"alias node should not have any properties")),null!==t.anchor&&(t.anchorMap[t.anchor]=t.result)):0===v&&(y=a&&Ft(t,p))),null===t.tag)null!==t.anchor&&(t.anchorMap[t.anchor]=t.result);else if("?"===t.tag){for(null!==t.result&&"scalar"!==t.kind&&xt(t,'unacceptable node kind for ! tag; it should be "scalar", not "'+t.kind+'"'),l=0,c=t.implicitTypes.length;l"),null!==t.result&&u.kind!==t.kind&&xt(t,"unacceptable node kind for !<"+t.tag+'> tag; it should be "'+u.kind+'", not "'+t.kind+'"'),u.resolve(t.result,t.tag)?(t.result=u.construct(t.result,t.tag),null!==t.anchor&&(t.anchorMap[t.anchor]=t.result)):xt(t,"cannot resolve a node with !<"+t.tag+"> explicit tag")}return null!==t.listener&&t.listener("close",t),null!==t.tag||null!==t.anchor||y}function Lt(t){var e,i,n,o,r=t.position,s=!1;for(t.version=null,t.checkLineBreaks=t.legacy,t.tagMap=Object.create(null),t.anchorMap=Object.create(null);0!==(o=t.input.charCodeAt(t.position))&&(Bt(t,!0,-1),o=t.input.charCodeAt(t.position),!(t.lineIndent>0||37!==o));){for(s=!0,o=t.input.charCodeAt(++t.position),e=t.position;0!==o&&!ft(o);)o=t.input.charCodeAt(++t.position);for(n=[],(i=t.input.slice(e,t.position)).length<1&&xt(t,"directive name must not be less than one character in length");0!==o;){for(;ut(o);)o=t.input.charCodeAt(++t.position);if(35===o){do{o=t.input.charCodeAt(++t.position)}while(0!==o&&!dt(o));break}if(dt(o))break;for(e=t.position;0!==o&&!ft(o);)o=t.input.charCodeAt(++t.position);n.push(t.input.slice(e,t.position))}0!==o&&Rt(t),X.call(St,i)?St[i](t,i,n):It(t,'unknown document directive "'+i+'"')}Bt(t,!0,-1),0===t.lineIndent&&45===t.input.charCodeAt(t.position)&&45===t.input.charCodeAt(t.position+1)&&45===t.input.charCodeAt(t.position+2)?(t.position+=3,Bt(t,!0,-1)):s&&xt(t,"directives end mark is expected"),jt(t,t.lineIndent-1,et,!1,!0),Bt(t,!0,-1),t.checkLineBreaks&&st.test(t.input.slice(r,t.position))&&It(t,"non-ASCII line breaks are interpreted as content"),t.documents.push(t.result),t.position===t.lineStart&&zt(t)?46===t.input.charCodeAt(t.position)&&(t.position+=3,Bt(t,!0,-1)):t.position=55296&&n<=56319&&e+1=56320&&i<=57343?1024*(n-55296)+i-56320+65536:n}function De(t){return/^\n* /.test(t)}var Re=1,Be=2,ze=3,Pe=4,Fe=5;function Te(t,e,i,n,o,r,s,a){var l,h=0,c=null,d=!1,u=!1,f=-1!==n,p=-1,v=function(t){return Ie(t)&&t!==Gt&&!xe(t)&&t!==oe&&t!==le&&t!==re&&t!==ne&&t!==ce&&t!==de&&t!==fe&&t!==ve&&t!==_t&&t!==te&&t!==ie&&t!==Jt&&t!==pe&&t!==se&&t!==ae&&t!==ee&&t!==Xt&&t!==$t&&t!==he&&t!==ue}(Oe(t,0))&&function(t){return!xe(t)&&t!==re}(Oe(t,t.length-1));if(e||s)for(l=0;l=65536?l+=2:l++){if(!Ie(h=Oe(t,l)))return Fe;v=v&&Me(h,c,a),c=h}else{for(l=0;l=65536?l+=2:l++){if((h=Oe(t,l))===qt)d=!0,f&&(u=u||l-p-1>n&&" "!==t[p+1],p=l);else if(!Ie(h))return Fe;v=v&&Me(h,c,a),c=h}u=u||f&&l-p-1>n&&" "!==t[p+1]}return d||u?i>9&&De(t)?Fe:s?r===Ae?Fe:Be:u?Pe:ze:!v||s||o(t)?r===Ae?Fe:Be:Re}function Ne(t,e,i,n,o){t.dump=function(){if(0===e.length)return t.quotingType===Ae?'""':"''";if(!t.noCompatMode&&(-1!==ye.indexOf(e)||me.test(e)))return t.quotingType===Ae?'"'+e+'"':"'"+e+"'";var r=t.indent*Math.max(1,i),s=-1===t.lineWidth?-1:Math.max(Math.min(t.lineWidth,40),t.lineWidth-r),a=n||t.flowLevel>-1&&i>=t.flowLevel;switch(Te(e,a,t.indent,s,(function(e){return function(t,e){var i,n;for(i=0,n=t.implicitTypes.length;i"+je(e,t.indent)+Le(Ee(function(t,e){var i,n,o=/(\n+)([^\n]*)/g,r=(a=t.indexOf("\n"),a=-1!==a?a:t.length,o.lastIndex=a,Ue(t.slice(0,a),e)),s="\n"===t[0]||" "===t[0];var a;for(;n=o.exec(t);){var l=n[1],h=n[2];i=" "===h[0],r+=l+(s||i||""===h?"":"\n")+Ue(h,e),s=i}return r}(e,s),r));case Fe:return'"'+function(t){for(var e,i="",n=0,o=0;o=65536?o+=2:o++)n=Oe(t,o),!(e=ge[n])&&Ie(n)?(i+=t[o],n>=65536&&(i+=t[o+1])):i+=e||be(n);return i}(e)+'"';default:throw new u("impossible error: invalid scalar style")}}()}function je(t,e){var i=De(t)?String(e):"",n="\n"===t[t.length-1];return i+(n&&("\n"===t[t.length-2]||"\n"===t)?"+":n?"":"-")+"\n"}function Le(t){return"\n"===t[t.length-1]?t.slice(0,-1):t}function Ue(t,e){if(""===t||" "===t[0])return t;for(var i,n,o=/ [^ ]/g,r=0,s=0,a=0,l="";i=o.exec(t);)(a=i.index)-r>e&&(n=s>r?s:a,l+="\n"+t.slice(r,n),r=n+1),s=a;return l+="\n",t.length-r>e&&s>r?l+=t.slice(r,s)+"\n"+t.slice(s+1):l+=t.slice(r),l.slice(1)}function Qe(t,e,i,n){var o,r,s,a="",l=t.tag;for(o=0,r=i.length;o tag resolver accepts not "'+l+'" style');n=a.represent[l](e,l)}t.dump=n}return!0}return!1}function Ve(t,e,i,n,o,r,s){t.tag=null,t.dump=i,He(t,i,!1)||He(t,i,!0);var a,l=Vt.call(t.dump),h=n;n&&(n=t.flowLevel<0||t.flowLevel>e);var c,d,f="[object Object]"===l||"[object Array]"===l;if(f&&(d=-1!==(c=t.duplicates.indexOf(i))),(null!==t.tag&&"?"!==t.tag||d||2!==t.indent&&e>0)&&(o=!1),d&&t.usedDuplicates[c])t.dump="*ref_"+c;else{if(f&&d&&!t.usedDuplicates[c]&&(t.usedDuplicates[c]=!0),"[object Object]"===l)n&&0!==Object.keys(t.dump).length?(!function(t,e,i,n){var o,r,s,a,l,h,c="",d=t.tag,f=Object.keys(i);if(!0===t.sortKeys)f.sort();else if("function"==typeof t.sortKeys)f.sort(t.sortKeys);else if(t.sortKeys)throw new u("sortKeys must be a boolean or a function");for(o=0,r=f.length;o1024)&&(t.dump&&qt===t.dump.charCodeAt(0)?h+="?":h+="? "),h+=t.dump,l&&(h+=Ce(t,e)),Ve(t,e+1,a,!0,l)&&(t.dump&&qt===t.dump.charCodeAt(0)?h+=":":h+=": ",c+=h+=t.dump));t.tag=d,t.dump=c||"{}"}(t,e,t.dump,o),d&&(t.dump="&ref_"+c+t.dump)):(!function(t,e,i){var n,o,r,s,a,l="",h=t.tag,c=Object.keys(i);for(n=0,o=c.length;n1024&&(a+="? "),a+=t.dump+(t.condenseFlow?'"':"")+":"+(t.condenseFlow?"":" "),Ve(t,e,s,!1,!1)&&(l+=a+=t.dump));t.tag=h,t.dump="{"+l+"}"}(t,e,t.dump),d&&(t.dump="&ref_"+c+" "+t.dump));else if("[object Array]"===l)n&&0!==t.dump.length?(t.noArrayIndent&&!s&&e>0?Qe(t,e-1,t.dump,o):Qe(t,e,t.dump,o),d&&(t.dump="&ref_"+c+t.dump)):(!function(t,e,i){var n,o,r,s="",a=t.tag;for(n=0,o=i.length;n",t.dump=a+" "+t.dump)}return!0}function We(t,e){var i,n,o=[],r=[];for(Ge(t,o,r),i=0,n=r.length;inull!==t&&"object"==typeof t&&!Array.isArray(t);function Xe(t){if(!Je(t))throw new Error("Invalid layout");const e={};for(const i of["auto_update","map_only","show_device_list","show_labels","magnifier"])if(i in t){if("boolean"!=typeof t[i])throw new Error(`Invalid ${i}`);e[i]=t[i]}if("name"in t){if("string"!=typeof t.name)throw new Error("Invalid name");e.name=t.name}if("map_height"in t){if(null!==t.map_height&&!(Number.isFinite(t.map_height)&&t.map_height>=100&&t.map_height<=2e3))throw new Error("Invalid map height");e.map_height=t.map_height}for(const[i,n]of Object.entries(Ze))if(i in t){if(!n.includes(t[i]))throw new Error(`Invalid ${i}`);e[i]=t[i]}if(!Je(t.layout_data))throw new Error("Missing layout");e.layout_data={};for(const[i,n]of Object.entries(t.layout_data)){if(!(/^-?\d+$/.test(i)&&Je(n)&&Number.isFinite(n.x)&&Number.isFinite(n.y)))throw new Error("Invalid position");e.layout_data[i]={x:n.x,y:n.y}}return e}const _e="wiser-zigbee-magnifier-size",$e="wiser-zigbee-magnifier-zoom";class ti{constructor(){this.zoom=2,this.size=180;try{const t=Number(localStorage.getItem($e));[2,3,4].includes(t)&&(this.zoom=t);const e=Number(localStorage.getItem(_e));e>=100&&e<=360&&(this.size=10*Math.round(e/10))}catch(t){}}setSize(t){if(Number.isFinite(t)){this.size=Math.max(100,Math.min(360,10*Math.round(t/10)));try{localStorage.setItem(_e,String(this.size))}catch(t){}this.refresh()}}setZoom(t){if([2,3,4].includes(t)){this.zoom=t;try{localStorage.setItem($e,String(t))}catch(t){}this.refresh()}}show(t,e){if("touch"===e.pointerType||e.buttons)return void this.hide();const i=t.getBoundingClientRect();this.map=t,this.point={x:(e.clientX-i.left)*t.clientWidth/(i.width||t.clientWidth),y:(e.clientY-i.top)*t.clientHeight/(i.height||t.clientHeight)},this.refresh()}refresh(){this.point&&void 0===this.frame&&(this.frame=requestAnimationFrame((()=>{this.frame=void 0,this.draw()})))}hide(){var t;void 0!==this.frame&&cancelAnimationFrame(this.frame),this.frame=void 0,this.point=void 0,null===(t=this.lens)||void 0===t||t.remove(),this.lens=void 0}draw(){var t;const e=this.map,i=this.point,n=null==e?void 0:e.querySelector("canvas");if(!((null==e?void 0:e.isConnected)&&i&&n&&e.clientWidth&&e.clientHeight))return void this.hide();this.lens||(this.lens=e.ownerDocument.createElement("div"),this.lens.className="map-magnifier",this.lens.setAttribute("aria-hidden","true"),this.lens.append(e.ownerDocument.createElement("canvas"),e.ownerDocument.createElement("div")),e.parentElement.append(this.lens));const o=function(t,e,i,n,o=2,r=180){const s=Math.min(r,i,n);return{size:s,left:Math.max(0,Math.min(i-s,t-s/2)),top:Math.max(0,Math.min(n-s,e-s/2)),imageX:s/2-t*o,imageY:s/2-e*o}}(i.x,i.y,e.clientWidth,e.clientHeight,this.zoom,this.size);this.lens.style.cssText=`left:${o.left}px;top:${o.top}px;width:${o.size}px;height:${o.size}px`;const r=this.lens.firstElementChild,s=(null===(t=e.ownerDocument.defaultView)||void 0===t?void 0:t.devicePixelRatio)||1;r.width=Math.round(o.size*s),r.height=Math.round(o.size*s),r.style.width=r.style.height=`${o.size}px`;const a=r.getContext("2d");if(!a)return;a.scale(s,s),a.drawImage(n,o.imageX,o.imageY,e.clientWidth*this.zoom,e.clientHeight*this.zoom);const l=this.lens.lastElementChild;l.className="magnifier-area-icons",l.style.transform=`translate(${o.imageX}px, ${o.imageY}px) scale(${this.zoom})`,l.replaceChildren(),e.parentElement.querySelectorAll(".area-icons ha-icon").forEach((t=>{const e=t.cloneNode(!1);e.icon=t.icon,l.append(e)}))}}function ei(t){var e,i;const n=Object.assign({},t);return(void 0!==n.layout_orientation&&n.layout_orientation!==(null!==(e=n.orientation)&&void 0!==e?e:"vertical")||void 0!==n.layout_group_by&&n.layout_group_by!==(null!==(i=n.group_by)&&void 0!==i?i:"none"))&&delete n.layout_data,delete n.show_layout_export,delete n.layout_orientation,delete n.layout_group_by,n}const ii=t=>JSON.stringify(t,((t,e)=>e&&"object"==typeof e&&!Array.isArray(e)?Object.keys(e).sort().reduce(((t,i)=>(t[i]=e[i],t)),{}):e));async function ni(t,e,i){var n,o,r,s,a,l;let h,c=t;for(;c;){if("wiser-zigbee-panel"===c.localName&&c.saveZigbeeCardConfig)return c.saveZigbeeCardConfig(t,ei(Object.assign(Object.assign({},e),i)));if(null===(n=c.lovelace)||void 0===n?void 0:n.saveConfig){h=c.lovelace;break}c=null!==(o=c.parentElement)&&void 0!==o?o:null===(r=c.getRootNode)||void 0===r?void 0:r.call(c).host}const d=null!==(s=null==h?void 0:h.rawConfig)&&void 0!==s?s:null==h?void 0:h.config;if(!h||"storage"!==h.mode||!d||d.strategy)throw new Error("Dashboard configuration is not editable");const u=[],f=(t,i)=>{if(t&&"object"==typeof t){t.type===e.type&&ii(t)===ii(e)&&u.push({value:t,path:i});for(const[e,n]of Object.entries(t))f(n,[...i,e])}};f(d,[]);const p=u.filter((t=>t.value===e)),v=p.length?p:u;if(1!==v.length)throw new Error("Cannot uniquely identify this card");const g=JSON.parse(JSON.stringify(d)),y=v[0].path;let m=g;for(const t of y.slice(0,-1))m=m[t];const b=ei(Object.assign(Object.assign({},v[0].value),i));m[y[y.length-1]]=b;const w=function(t){if(!t)return()=>{};const{scrollX:e,scrollY:i}=t,n=t.location.href;let o=!1,r=0,s=Date.now()+2500;const a=["wheel","touchstart","pointerdown","keydown","popstate","hashchange"],l=()=>{o=!0,t.cancelAnimationFrame(r),a.forEach((e=>t.removeEventListener(e,l,!0)))},h=()=>{o||Date.now()>=s||t.location.href!==n?l():(t.scrollX===e&&t.scrollY===i||t.scrollTo({left:e,top:i,behavior:"instant"}),r=t.requestAnimationFrame(h))};return a.forEach((e=>t.addEventListener(e,l,{capture:!0,passive:!0}))),r=t.requestAnimationFrame(h),()=>{s=Math.min(s,Date.now()+500)}}(null!==(l=null===(a=t.ownerDocument)||void 0===a?void 0:a.defaultView)&&void 0!==l?l:null);try{await h.saveConfig(g)}finally{w()}return b}const oi=new Map,ri=t=>t.replace(/&/g,"&").replace(/"/g,""").replace(/`:"";o="data:image/svg+xml,"+encodeURIComponent(`${r}`),oi.set(n,o)}return o}function ai(t){const e=t.match(/^([\s\S]*?)\n\s*\(([\s\S]*)\)\s*$/);if(!e)return t.replace(/\n/g," ").trim();const i=e[1].trim(),n=e[2].trim();return!n||/^no room$/i.test(n)?i:n}function li(t,e,i){var n,o;const r=new Map;for(const e of t.filter((t=>"Controller"!==t.group))){const t=null!==(n=e.area_id)&&void 0!==n?n:"";r.set(t,[...null!==(o=r.get(t))&&void 0!==o?o:[],e])}const s=t=>{var e;return null!==(e=null==i?void 0:i(t))&&void 0!==e?e:{left:Math.min(...t.map((t=>t.x-Math.max(40,4.5*t.label.length))))-18,right:Math.max(...t.map((t=>t.x+Math.max(40,4.5*t.label.length))))+18,top:Math.min(...t.map((t=>t.y-32)))-18,bottom:Math.max(...t.map((t=>t.y+60)))+18}},a=(t,e)=>Math.max(0,Math.min(t.right,e.right)-Math.max(t.left,e.left))*Math.max(0,Math.min(t.bottom,e.bottom)-Math.max(t.top,e.top)),l=new Map(t.map((t=>[t.id,{x:t.x,y:t.y}]))),h=[...r.values()];if(!t.length)return;const c=h.map(s);if(!c.length)return;const d=c.some(((t,e)=>c.slice(e+1).some((e=>a(t,e)>0)))),u=Math.min(...c.map((t=>t.left))),f=Math.max(...c.map((t=>t.right))),p=Math.min(...c.map((t=>t.top))),v=Math.max(...c.map((t=>t.bottom))),g=Math.max(480,Math.min(1200,Math.hypot(f-u,v-p)));for(let i=0;i<12;i++){let i=!1;for(const n of h){if(n.some((t=>e.has(t.id))))continue;const o=h.filter((t=>t!==n)).map(s),r=s(n),c=t=>o.reduce(((e,i)=>e+a(t,i)),0),u=t=>{const e=[...o,t];return(Math.max(...e.map((t=>t.right)))-Math.min(...e.map((t=>t.left))))*(Math.max(...e.map((t=>t.bottom)))-Math.min(...e.map((t=>t.top))))};let f=c(r),p=u(r),v={x:0,y:0};for(const e of o.filter((t=>d||a(r,t)>0))){const i=[{x:e.left-r.right-16,y:0},{x:e.right-r.left+16,y:0},{x:0,y:e.top-r.bottom-16},{x:0,y:e.bottom-r.top+16},{x:e.right-r.left+16,y:e.top-r.bottom-16},{x:e.left-r.right-16,y:e.top-r.bottom-16},{x:e.right-r.left+16,y:e.bottom-r.top+16},{x:e.left-r.right-16,y:e.bottom-r.top+16}].sort(((t,e)=>Math.hypot(t.x,t.y)-Math.hypot(e.x,e.y)));for(const e of i){if(n.some((t=>Math.hypot(t.x+e.x-l.get(t.id).x,t.y+e.y-l.get(t.id).y)>g)))continue;const i={left:r.left+e.x,right:r.right+e.x,top:r.top+e.y,bottom:r.bottom+e.y};if(t.some((t=>"Controller"===t.group&&a(i,s([t]))>0)))continue;const o=c(i),h=u(i);(ohi(e,!0,t))).join("|")} /** * @license * Copyright 2019 Google LLC * SPDX-License-Identifier: BSD-3-Clause - */const v=window,g=v.ShadowRoot&&(void 0===v.ShadyCSS||v.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,y=Symbol(),m=new WeakMap;let b=class{constructor(t,e,i){if(this._$cssResult$=!0,i!==y)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(g&&void 0===t){const i=void 0!==e&&1===e.length;i&&(t=m.get(e)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&m.set(e,t))}return t}toString(){return this.cssText}};const w=g?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new b("string"==typeof t?t:t+"",void 0,y))(e)})(t):t + */const di=window,ui=di.ShadowRoot&&(void 0===di.ShadyCSS||di.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,fi=Symbol(),pi=new WeakMap;let vi=class{constructor(t,e,i){if(this._$cssResult$=!0,i!==fi)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(ui&&void 0===t){const i=void 0!==e&&1===e.length;i&&(t=pi.get(e)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&pi.set(e,t))}return t}toString(){return this.cssText}};const gi=ui?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new vi("string"==typeof t?t:t+"",void 0,fi))(e)})(t):t /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause - */;var A;const E=window,k=E.trustedTypes,C=k?k.emptyScript:"",x=E.reactiveElementPolyfillSupport,S={toAttribute(t,e){switch(e){case Boolean:t=t?C: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}},I=(t,e)=>e!==t&&(e==e||t==t),M={attribute:!0,type:String,converter:S,reflect:!1,hasChanged:I},O="finalized";let D=class extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(t){var e;this.finalize(),(null!==(e=this.h)&&void 0!==e?e:this.h=[]).push(t)}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach(((e,i)=>{const o=this._$Ep(i,e);void 0!==o&&(this._$Ev.set(o,i),t.push(o))})),t}static createProperty(t,e=M){if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){const i="symbol"==typeof t?Symbol():"__"+t,o=this.getPropertyDescriptor(t,i,e);void 0!==o&&Object.defineProperty(this.prototype,t,o)}}static getPropertyDescriptor(t,e,i){return{get(){return this[e]},set(o){const n=this[t];this[e]=o,this.requestUpdate(t,n,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||M}static finalize(){if(this.hasOwnProperty(O))return!1;this[O]=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),void 0!==t.h&&(this.h=[...t.h]),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,e=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const i of e)this.createProperty(i,t[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}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(w(t))}else void 0!==t&&e.push(w(t));return e}static _$Ep(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}_$Eu(){var t;this._$E_=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach((t=>t(this)))}addController(t){var e,i;(null!==(e=this._$ES)&&void 0!==e?e:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(i=t.hostConnected)||void 0===i||i.call(t))}removeController(t){var e;null===(e=this._$ES)||void 0===e||e.splice(this._$ES.indexOf(t)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach(((t,e)=>{this.hasOwnProperty(e)&&(this._$Ei.set(e,this[e]),delete this[e])}))}createRenderRoot(){var t;const e=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return((t,e)=>{g?t.adoptedStyleSheets=e.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet)):e.forEach((e=>{const i=document.createElement("style"),o=v.litNonce;void 0!==o&&i.setAttribute("nonce",o),i.textContent=e.cssText,t.appendChild(i)}))})(e,this.constructor.elementStyles),e}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)}))}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)}))}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$EO(t,e,i=M){var o;const n=this.constructor._$Ep(t,i);if(void 0!==n&&!0===i.reflect){const r=(void 0!==(null===(o=i.converter)||void 0===o?void 0:o.toAttribute)?i.converter:S).toAttribute(e,i.type);this._$El=t,null==r?this.removeAttribute(n):this.setAttribute(n,r),this._$El=null}}_$AK(t,e){var i;const o=this.constructor,n=o._$Ev.get(t);if(void 0!==n&&this._$El!==n){const t=o.getPropertyOptions(n),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(i=t.converter)||void 0===i?void 0:i.fromAttribute)?t.converter:S;this._$El=n,this[n]=r.fromAttribute(e,t.type),this._$El=null}}requestUpdate(t,e,i){let o=!0;void 0!==t&&(((i=i||this.constructor.getPropertyOptions(t)).hasChanged||I)(this[t],e)?(this._$AL.has(t)||this._$AL.set(t,e),!0===i.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,i))):o=!1),!this.isUpdatePending&&o&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach(((t,e)=>this[e]=t)),this._$Ei=void 0);let e=!1;const i=this._$AL;try{e=this.shouldUpdate(i),e?(this.willUpdate(i),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)})),this.update(i)):this._$Ek()}catch(t){throw e=!1,this._$Ek(),t}e&&this._$AE(i)}willUpdate(t){}_$AE(t){var e;null===(e=this._$ES)||void 0===e||e.forEach((t=>{var e;return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)})),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return!0}update(t){void 0!==this._$EC&&(this._$EC.forEach(((t,e)=>this._$EO(e,this[e],t))),this._$EC=void 0),this._$Ek()}updated(t){}firstUpdated(t){}}; + */;var yi;const mi=window,bi=mi.trustedTypes,wi=bi?bi.emptyScript:"",Ai=mi.reactiveElementPolyfillSupport,ki={toAttribute(t,e){switch(e){case Boolean:t=t?wi: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}},Ei=(t,e)=>e!==t&&(e==e||t==t),Ci={attribute:!0,type:String,converter:ki,reflect:!1,hasChanged:Ei},xi="finalized";let Ii=class extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(t){var e;this.finalize(),(null!==(e=this.h)&&void 0!==e?e:this.h=[]).push(t)}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach(((e,i)=>{const n=this._$Ep(i,e);void 0!==n&&(this._$Ev.set(n,i),t.push(n))})),t}static createProperty(t,e=Ci){if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){const i="symbol"==typeof t?Symbol():"__"+t,n=this.getPropertyDescriptor(t,i,e);void 0!==n&&Object.defineProperty(this.prototype,t,n)}}static getPropertyDescriptor(t,e,i){return{get(){return this[e]},set(n){const o=this[t];this[e]=n,this.requestUpdate(t,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||Ci}static finalize(){if(this.hasOwnProperty(xi))return!1;this[xi]=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),void 0!==t.h&&(this.h=[...t.h]),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,e=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const i of e)this.createProperty(i,t[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}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(gi(t))}else void 0!==t&&e.push(gi(t));return e}static _$Ep(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}_$Eu(){var t;this._$E_=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach((t=>t(this)))}addController(t){var e,i;(null!==(e=this._$ES)&&void 0!==e?e:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(i=t.hostConnected)||void 0===i||i.call(t))}removeController(t){var e;null===(e=this._$ES)||void 0===e||e.splice(this._$ES.indexOf(t)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach(((t,e)=>{this.hasOwnProperty(e)&&(this._$Ei.set(e,this[e]),delete this[e])}))}createRenderRoot(){var t;const e=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return((t,e)=>{ui?t.adoptedStyleSheets=e.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet)):e.forEach((e=>{const i=document.createElement("style"),n=di.litNonce;void 0!==n&&i.setAttribute("nonce",n),i.textContent=e.cssText,t.appendChild(i)}))})(e,this.constructor.elementStyles),e}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)}))}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)}))}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$EO(t,e,i=Ci){var n;const o=this.constructor._$Ep(t,i);if(void 0!==o&&!0===i.reflect){const r=(void 0!==(null===(n=i.converter)||void 0===n?void 0:n.toAttribute)?i.converter:ki).toAttribute(e,i.type);this._$El=t,null==r?this.removeAttribute(o):this.setAttribute(o,r),this._$El=null}}_$AK(t,e){var i;const n=this.constructor,o=n._$Ev.get(t);if(void 0!==o&&this._$El!==o){const t=n.getPropertyOptions(o),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(i=t.converter)||void 0===i?void 0:i.fromAttribute)?t.converter:ki;this._$El=o,this[o]=r.fromAttribute(e,t.type),this._$El=null}}requestUpdate(t,e,i){let n=!0;void 0!==t&&(((i=i||this.constructor.getPropertyOptions(t)).hasChanged||Ei)(this[t],e)?(this._$AL.has(t)||this._$AL.set(t,e),!0===i.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,i))):n=!1),!this.isUpdatePending&&n&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach(((t,e)=>this[e]=t)),this._$Ei=void 0);let e=!1;const i=this._$AL;try{e=this.shouldUpdate(i),e?(this.willUpdate(i),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)})),this.update(i)):this._$Ek()}catch(t){throw e=!1,this._$Ek(),t}e&&this._$AE(i)}willUpdate(t){}_$AE(t){var e;null===(e=this._$ES)||void 0===e||e.forEach((t=>{var e;return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)})),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return!0}update(t){void 0!==this._$EC&&(this._$EC.forEach(((t,e)=>this._$EO(e,this[e],t))),this._$EC=void 0),this._$Ek()}updated(t){}firstUpdated(t){}}; /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause */ -var R;D[O]=!0,D.elementProperties=new Map,D.elementStyles=[],D.shadowRootOptions={mode:"open"},null==x||x({ReactiveElement:D}),(null!==(A=E.reactiveElementVersions)&&void 0!==A?A:E.reactiveElementVersions=[]).push("1.6.3");const B=window,z=B.trustedTypes,P=z?z.createPolicy("lit-html",{createHTML:t=>t}):void 0,F="$lit$",T=`lit$${(Math.random()+"").slice(9)}$`,N="?"+T,j=`<${N}>`,U=document,L=()=>U.createComment(""),Q=t=>null===t||"object"!=typeof t&&"function"!=typeof t,H=Array.isArray,V="[ \t\n\f\r]",W=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,G=/-->/g,K=/>/g,q=RegExp(`>|${V}(?:([^\\s"'>=/]+)(${V}*=${V}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),Y=/'/g,Z=/"/g,J=/^(?:script|style|textarea|title)$/i,X=(t=>(e,...i)=>({_$litType$:t,strings:e,values:i}))(1),_=Symbol.for("lit-noChange"),$=Symbol.for("lit-nothing"),tt=new WeakMap,et=U.createTreeWalker(U,129,null,!1);function it(t,e){if(!Array.isArray(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==P?P.createHTML(e):e}const ot=(t,e)=>{const i=t.length-1,o=[];let n,r=2===e?"":"",s=W;for(let e=0;e"===l[0]?(s=null!=n?n:W,h=-1):void 0===l[1]?h=-2:(h=s.lastIndex-l[2].length,a=l[1],s=void 0===l[3]?q:'"'===l[3]?Z:Y):s===Z||s===Y?s=q:s===G||s===K?s=W:(s=q,n=void 0);const d=s===q&&t[e+1].startsWith("/>")?" ":"";r+=s===W?i+j:h>=0?(o.push(a),i.slice(0,h)+F+i.slice(h)+T+d):i+T+(-2===h?(o.push(void 0),e):d)}return[it(t,r+(t[i]||"")+(2===e?"":"")),o]};class nt{constructor({strings:t,_$litType$:e},i){let o;this.parts=[];let n=0,r=0;const s=t.length-1,a=this.parts,[l,h]=ot(t,e);if(this.el=nt.createElement(l,i),et.currentNode=this.el.content,2===e){const t=this.el.content,e=t.firstChild;e.remove(),t.append(...e.childNodes)}for(;null!==(o=et.nextNode())&&a.length0){o.textContent=z?z.emptyScript:"";for(let i=0;iH(t)||"function"==typeof(null==t?void 0: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!==$&&Q(this._$AH)?this._$AA.nextSibling.data=t:this.$(U.createTextNode(t)),this._$AH=t}g(t){var e;const{values:i,_$litType$:o}=t,n="number"==typeof o?this._$AC(t):(void 0===o.el&&(o.el=nt.createElement(it(o.h,o.h[0]),this.options)),o);if((null===(e=this._$AH)||void 0===e?void 0:e._$AD)===n)this._$AH.v(i);else{const t=new st(n,this),e=t.u(this.options);t.v(i),this.$(e),this._$AH=t}}_$AC(t){let e=tt.get(t.strings);return void 0===e&&tt.set(t.strings,e=new nt(t)),e}T(t){H(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 at(this.k(L()),this.k(L()),this,this.options)):i=e[o],i._$AI(n),o++;o2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=$}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(t,e=this,i,o){const n=this.strings;let r=!1;if(void 0===n)t=rt(this,t,e,0),r=!Q(t)||t!==this._$AH&&t!==_,r&&(this._$AH=t);else{const o=t;let s,a;for(t=n[0],s=0;st}):void 0,Ri="$lit$",Bi=`lit$${(Math.random()+"").slice(9)}$`,zi="?"+Bi,Pi=`<${zi}>`,Fi=document,Ti=()=>Fi.createComment(""),Ni=t=>null===t||"object"!=typeof t&&"function"!=typeof t,ji=Array.isArray,Li="[ \t\n\f\r]",Ui=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Qi=/-->/g,Hi=/>/g,Vi=RegExp(`>|${Li}(?:([^\\s"'>=/]+)(${Li}*=${Li}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),Wi=/'/g,Gi=/"/g,Ki=/^(?:script|style|textarea|title)$/i,qi=(t=>(e,...i)=>({_$litType$:t,strings:e,values:i}))(1),Yi=Symbol.for("lit-noChange"),Zi=Symbol.for("lit-nothing"),Ji=new WeakMap,Xi=Fi.createTreeWalker(Fi,129,null,!1);function _i(t,e){if(!Array.isArray(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==Di?Di.createHTML(e):e}const $i=(t,e)=>{const i=t.length-1,n=[];let o,r=2===e?"":"",s=Ui;for(let e=0;e"===l[0]?(s=null!=o?o:Ui,h=-1):void 0===l[1]?h=-2:(h=s.lastIndex-l[2].length,a=l[1],s=void 0===l[3]?Vi:'"'===l[3]?Gi:Wi):s===Gi||s===Wi?s=Vi:s===Qi||s===Hi?s=Ui:(s=Vi,o=void 0);const d=s===Vi&&t[e+1].startsWith("/>")?" ":"";r+=s===Ui?i+Pi:h>=0?(n.push(a),i.slice(0,h)+Ri+i.slice(h)+Bi+d):i+Bi+(-2===h?(n.push(void 0),e):d)}return[_i(t,r+(t[i]||"")+(2===e?"":"")),n]};class tn{constructor({strings:t,_$litType$:e},i){let n;this.parts=[];let o=0,r=0;const s=t.length-1,a=this.parts,[l,h]=$i(t,e);if(this.el=tn.createElement(l,i),Xi.currentNode=this.el.content,2===e){const t=this.el.content,e=t.firstChild;e.remove(),t.append(...e.childNodes)}for(;null!==(n=Xi.nextNode())&&a.length0){n.textContent=Oi?Oi.emptyScript:"";for(let i=0;iji(t)||"function"==typeof(null==t?void 0: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!==Zi&&Ni(this._$AH)?this._$AA.nextSibling.data=t:this.$(Fi.createTextNode(t)),this._$AH=t}g(t){var e;const{values:i,_$litType$:n}=t,o="number"==typeof n?this._$AC(t):(void 0===n.el&&(n.el=tn.createElement(_i(n.h,n.h[0]),this.options)),n);if((null===(e=this._$AH)||void 0===e?void 0:e._$AD)===o)this._$AH.v(i);else{const t=new nn(o,this),e=t.u(this.options);t.v(i),this.$(e),this._$AH=t}}_$AC(t){let e=Ji.get(t.strings);return void 0===e&&Ji.set(t.strings,e=new tn(t)),e}T(t){ji(this._$AH)||(this._$AH=[],this._$AR());const e=this._$AH;let i,n=0;for(const o of t)n===e.length?e.push(i=new on(this.k(Ti()),this.k(Ti()),this,this.options)):i=e[n],i._$AI(o),n++;n2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=Zi}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(t,e=this,i,n){const o=this.strings;let r=!1;if(void 0===o)t=en(this,t,e,0),r=!Ni(t)||t!==this._$AH&&t!==Yi,r&&(this._$AH=t);else{const n=t;let s,a;for(t=o[0],s=0;s{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 bt(i,t,yt)},At=gt?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new bt("string"==typeof t?t:t+"",void 0,yt))(e)})(t):t + */let gn=class{constructor(t,e,i){if(this._$cssResult$=!0,i!==pn)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(fn&&void 0===t){const i=void 0!==e&&1===e.length;i&&(t=vn.get(e)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&vn.set(e,t))}return t}toString(){return this.cssText}};const yn=t=>new gn("string"==typeof t?t:t+"",void 0,pn),mn=(t,...e)=>{const i=1===t.length?t[0]:e.reduce(((e,i,n)=>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[n+1]),t[0]);return new gn(i,t,pn)},bn=fn?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return yn(e)})(t):t /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause - */;var Et;const kt=window,Ct=kt.trustedTypes,xt=Ct?Ct.emptyScript:"",St=kt.reactiveElementPolyfillSupport,It={toAttribute(t,e){switch(e){case Boolean:t=t?xt: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}},Mt=(t,e)=>e!==t&&(e==e||t==t),Ot={attribute:!0,type:String,converter:It,reflect:!1,hasChanged:Mt},Dt="finalized";class Rt extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(t){var e;this.finalize(),(null!==(e=this.h)&&void 0!==e?e:this.h=[]).push(t)}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach(((e,i)=>{const o=this._$Ep(i,e);void 0!==o&&(this._$Ev.set(o,i),t.push(o))})),t}static createProperty(t,e=Ot){if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){const i="symbol"==typeof t?Symbol():"__"+t,o=this.getPropertyDescriptor(t,i,e);void 0!==o&&Object.defineProperty(this.prototype,t,o)}}static getPropertyDescriptor(t,e,i){return{get(){return this[e]},set(o){const n=this[t];this[e]=o,this.requestUpdate(t,n,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||Ot}static finalize(){if(this.hasOwnProperty(Dt))return!1;this[Dt]=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),void 0!==t.h&&(this.h=[...t.h]),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,e=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const i of e)this.createProperty(i,t[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}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(At(t))}else void 0!==t&&e.push(At(t));return e}static _$Ep(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}_$Eu(){var t;this._$E_=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach((t=>t(this)))}addController(t){var e,i;(null!==(e=this._$ES)&&void 0!==e?e:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(i=t.hostConnected)||void 0===i||i.call(t))}removeController(t){var e;null===(e=this._$ES)||void 0===e||e.splice(this._$ES.indexOf(t)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach(((t,e)=>{this.hasOwnProperty(e)&&(this._$Ei.set(e,this[e]),delete this[e])}))}createRenderRoot(){var t;const e=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return((t,e)=>{gt?t.adoptedStyleSheets=e.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet)):e.forEach((e=>{const i=document.createElement("style"),o=vt.litNonce;void 0!==o&&i.setAttribute("nonce",o),i.textContent=e.cssText,t.appendChild(i)}))})(e,this.constructor.elementStyles),e}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)}))}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)}))}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$EO(t,e,i=Ot){var o;const n=this.constructor._$Ep(t,i);if(void 0!==n&&!0===i.reflect){const r=(void 0!==(null===(o=i.converter)||void 0===o?void 0:o.toAttribute)?i.converter:It).toAttribute(e,i.type);this._$El=t,null==r?this.removeAttribute(n):this.setAttribute(n,r),this._$El=null}}_$AK(t,e){var i;const o=this.constructor,n=o._$Ev.get(t);if(void 0!==n&&this._$El!==n){const t=o.getPropertyOptions(n),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(i=t.converter)||void 0===i?void 0:i.fromAttribute)?t.converter:It;this._$El=n,this[n]=r.fromAttribute(e,t.type),this._$El=null}}requestUpdate(t,e,i){let o=!0;void 0!==t&&(((i=i||this.constructor.getPropertyOptions(t)).hasChanged||Mt)(this[t],e)?(this._$AL.has(t)||this._$AL.set(t,e),!0===i.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,i))):o=!1),!this.isUpdatePending&&o&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach(((t,e)=>this[e]=t)),this._$Ei=void 0);let e=!1;const i=this._$AL;try{e=this.shouldUpdate(i),e?(this.willUpdate(i),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)})),this.update(i)):this._$Ek()}catch(t){throw e=!1,this._$Ek(),t}e&&this._$AE(i)}willUpdate(t){}_$AE(t){var e;null===(e=this._$ES)||void 0===e||e.forEach((t=>{var e;return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)})),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return!0}update(t){void 0!==this._$EC&&(this._$EC.forEach(((t,e)=>this._$EO(e,this[e],t))),this._$EC=void 0),this._$Ek()}updated(t){}firstUpdated(t){}} + */;var wn;const An=window,kn=An.trustedTypes,En=kn?kn.emptyScript:"",Cn=An.reactiveElementPolyfillSupport,xn={toAttribute(t,e){switch(e){case Boolean:t=t?En: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}},In=(t,e)=>e!==t&&(e==e||t==t),Sn={attribute:!0,type:String,converter:xn,reflect:!1,hasChanged:In},Mn="finalized";class On extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(t){var e;this.finalize(),(null!==(e=this.h)&&void 0!==e?e:this.h=[]).push(t)}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach(((e,i)=>{const n=this._$Ep(i,e);void 0!==n&&(this._$Ev.set(n,i),t.push(n))})),t}static createProperty(t,e=Sn){if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){const i="symbol"==typeof t?Symbol():"__"+t,n=this.getPropertyDescriptor(t,i,e);void 0!==n&&Object.defineProperty(this.prototype,t,n)}}static getPropertyDescriptor(t,e,i){return{get(){return this[e]},set(n){const o=this[t];this[e]=n,this.requestUpdate(t,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||Sn}static finalize(){if(this.hasOwnProperty(Mn))return!1;this[Mn]=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),void 0!==t.h&&(this.h=[...t.h]),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,e=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const i of e)this.createProperty(i,t[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}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(bn(t))}else void 0!==t&&e.push(bn(t));return e}static _$Ep(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}_$Eu(){var t;this._$E_=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach((t=>t(this)))}addController(t){var e,i;(null!==(e=this._$ES)&&void 0!==e?e:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(i=t.hostConnected)||void 0===i||i.call(t))}removeController(t){var e;null===(e=this._$ES)||void 0===e||e.splice(this._$ES.indexOf(t)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach(((t,e)=>{this.hasOwnProperty(e)&&(this._$Ei.set(e,this[e]),delete this[e])}))}createRenderRoot(){var t;const e=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return((t,e)=>{fn?t.adoptedStyleSheets=e.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet)):e.forEach((e=>{const i=document.createElement("style"),n=un.litNonce;void 0!==n&&i.setAttribute("nonce",n),i.textContent=e.cssText,t.appendChild(i)}))})(e,this.constructor.elementStyles),e}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)}))}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)}))}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$EO(t,e,i=Sn){var n;const o=this.constructor._$Ep(t,i);if(void 0!==o&&!0===i.reflect){const r=(void 0!==(null===(n=i.converter)||void 0===n?void 0:n.toAttribute)?i.converter:xn).toAttribute(e,i.type);this._$El=t,null==r?this.removeAttribute(o):this.setAttribute(o,r),this._$El=null}}_$AK(t,e){var i;const n=this.constructor,o=n._$Ev.get(t);if(void 0!==o&&this._$El!==o){const t=n.getPropertyOptions(o),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(i=t.converter)||void 0===i?void 0:i.fromAttribute)?t.converter:xn;this._$El=o,this[o]=r.fromAttribute(e,t.type),this._$El=null}}requestUpdate(t,e,i){let n=!0;void 0!==t&&(((i=i||this.constructor.getPropertyOptions(t)).hasChanged||In)(this[t],e)?(this._$AL.has(t)||this._$AL.set(t,e),!0===i.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,i))):n=!1),!this.isUpdatePending&&n&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach(((t,e)=>this[e]=t)),this._$Ei=void 0);let e=!1;const i=this._$AL;try{e=this.shouldUpdate(i),e?(this.willUpdate(i),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)})),this.update(i)):this._$Ek()}catch(t){throw e=!1,this._$Ek(),t}e&&this._$AE(i)}willUpdate(t){}_$AE(t){var e;null===(e=this._$ES)||void 0===e||e.forEach((t=>{var e;return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)})),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return!0}update(t){void 0!==this._$EC&&(this._$EC.forEach(((t,e)=>this._$EO(e,this[e],t))),this._$EC=void 0),this._$Ek()}updated(t){}firstUpdated(t){}} /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause */ -var Bt,zt;Rt[Dt]=!0,Rt.elementProperties=new Map,Rt.elementStyles=[],Rt.shadowRootOptions={mode:"open"},null==St||St({ReactiveElement:Rt}),(null!==(Et=kt.reactiveElementVersions)&&void 0!==Et?Et:kt.reactiveElementVersions=[]).push("1.6.3");class Pt extends Rt{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){var t,e;const i=super.createRenderRoot();return null!==(t=(e=this.renderOptions).renderBefore)&&void 0!==t||(e.renderBefore=i.firstChild),i}update(t){const e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=((t,e,i)=>{var o,n;const r=null!==(o=null==i?void 0:i.renderBefore)&&void 0!==o?o:e;let s=r._$litPart$;if(void 0===s){const t=null!==(n=null==i?void 0:i.renderBefore)&&void 0!==n?n:null;r._$litPart$=s=new at(e.insertBefore(L(),t),t,void 0,null!=i?i:{})}return s._$AI(t),s})(e,this.renderRoot,this.renderOptions)}connectedCallback(){var t;super.connectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!0)}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!1)}render(){return _}}Pt.finalized=!0,Pt._$litElement$=!0,null===(Bt=globalThis.litElementHydrateSupport)||void 0===Bt||Bt.call(globalThis,{LitElement:Pt});const Ft=globalThis.litElementPolyfillSupport;null==Ft||Ft({LitElement:Pt}),(null!==(zt=globalThis.litElementVersions)&&void 0!==zt?zt:globalThis.litElementVersions=[]).push("3.3.3"); +var Dn,Rn;On[Mn]=!0,On.elementProperties=new Map,On.elementStyles=[],On.shadowRootOptions={mode:"open"},null==Cn||Cn({ReactiveElement:On}),(null!==(wn=An.reactiveElementVersions)&&void 0!==wn?wn:An.reactiveElementVersions=[]).push("1.6.3");class Bn extends On{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){var t,e;const i=super.createRenderRoot();return null!==(t=(e=this.renderOptions).renderBefore)&&void 0!==t||(e.renderBefore=i.firstChild),i}update(t){const e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=((t,e,i)=>{var n,o;const r=null!==(n=null==i?void 0:i.renderBefore)&&void 0!==n?n:e;let s=r._$litPart$;if(void 0===s){const t=null!==(o=null==i?void 0:i.renderBefore)&&void 0!==o?o:null;r._$litPart$=s=new on(e.insertBefore(Ti(),t),t,void 0,null!=i?i:{})}return s._$AI(t),s})(e,this.renderRoot,this.renderOptions)}connectedCallback(){var t;super.connectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!0)}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!1)}render(){return Yi}}Bn.finalized=!0,Bn._$litElement$=!0,null===(Dn=globalThis.litElementHydrateSupport)||void 0===Dn||Dn.call(globalThis,{LitElement:Bn});const zn=globalThis.litElementPolyfillSupport;function Pn(t){return"dark"===t||"light"===t?t:"auto"}null==zn||zn({LitElement:Bn}),(null!==(Rn=globalThis.litElementVersions)&&void 0!==Rn?Rn:globalThis.litElementVersions=[]).push("3.3.3");const Fn='\n :host([theme-mode="dark"]) {\n color-scheme: dark;\n --primary-text-color: #e1e1e1;\n --secondary-text-color: #9b9b9b;\n --disabled-text-color: #6f6f6f;\n --primary-background-color: #111111;\n --secondary-background-color: #202020;\n --card-background-color: #1c1c1c;\n --divider-color: rgba(225, 225, 225, 0.12);\n --app-header-background-color: #1c1c1c;\n --app-header-text-color: #e1e1e1;\n }\n :host([theme-mode="light"]) {\n color-scheme: light;\n --primary-text-color: #212121;\n --secondary-text-color: #727272;\n --disabled-text-color: #bdbdbd;\n --primary-background-color: #fafafa;\n --secondary-background-color: #e5e5e5;\n --card-background-color: #ffffff;\n --divider-color: rgba(0, 0, 0, 0.12);\n --app-header-background-color: #ffffff;\n --app-header-text-color: #212121;\n }\n :host([theme-mode="dark"]), :host([theme-mode="light"]) {\n --ha-card-background: var(--card-background-color);\n --ha-dialog-surface-background: var(--card-background-color);\n --ha-color-surface-default: var(--card-background-color);\n --ha-color-surface-raised: var(--card-background-color);\n --ha-color-text-primary: var(--primary-text-color);\n --ha-color-text-secondary: var(--secondary-text-color);\n --ha-color-text-disabled: var(--disabled-text-color);\n --ha-color-border-neutral-normal: var(--divider-color);\n --mdc-theme-surface: var(--card-background-color);\n --mdc-theme-on-surface: var(--primary-text-color);\n }\n',Tn=t=>null!=t?t:Zi /** * @license - * Copyright 2018 Google LLC + * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause - */ -const Tt=t=>null!=t?t:$ + */,Nn=(t,e)=>"method"===e.kind&&e.descriptor&&!("value"in e.descriptor)?{...e,finisher(i){i.createProperty(e.key,t)}}:{kind:"field",key:Symbol(),placement:"own",descriptor:{},originalKey:e.key,initializer(){"function"==typeof e.initializer&&(this[e.key]=e.initializer.call(this))},finisher(i){i.createProperty(e.key,t)}},jn=(t,e,i)=>{e.constructor.createProperty(i,t)}; /** * @license - * Copyright 2017 Google LLC + * Copyright 2018 Google LLC * SPDX-License-Identifier: BSD-3-Clause - */,Nt=(t,e)=>"method"===e.kind&&e.descriptor&&!("value"in e.descriptor)?{...e,finisher(i){i.createProperty(e.key,t)}}:{kind:"field",key:Symbol(),placement:"own",descriptor:{},originalKey:e.key,initializer(){"function"==typeof e.initializer&&(this[e.key]=e.initializer.call(this))},finisher(i){i.createProperty(e.key,t)}},jt=(t,e,i)=>{e.constructor.createProperty(i,t)};function Ut(t){return(e,i)=>void 0!==i?jt(t,e,i):Nt(t,e) + */function Ln(t){return(e,i)=>void 0!==i?jn(t,e,i):Nn(t,e) /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause - */}function Lt(t){return Ut({...t,state:!0})} + */}function Un(t){return Ln({...t,state:!0})} /** * @license * Copyright 2017 Google LLC @@ -58,12 +59,12 @@ const Tt=t=>null!=t?t:$ * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause */ -function Qt(t){return(({finisher:t,descriptor:e})=>(i,o)=>{var n;if(void 0===o){const o=null!==(n=i.originalKey)&&void 0!==n?n:i.key,r=null!=e?{kind:"method",placement:"prototype",key:o,descriptor:e(i.key)}:{...i,key:o};return null!=t&&(r.finisher=function(e){t(e,o)}),r}{const n=i.constructor;void 0!==e&&Object.defineProperty(i,o,e(o)),null==t||t(n,o)}})({finisher:(e,i)=>{Object.assign(e.prototype[i],t)}})} +function Qn(t){return(({finisher:t,descriptor:e})=>(i,n)=>{var o;if(void 0===n){const n=null!==(o=i.originalKey)&&void 0!==o?o:i.key,r=null!=e?{kind:"method",placement:"prototype",key:n,descriptor:e(i.key)}:{...i,key:n};return null!=t&&(r.finisher=function(e){t(e,n)}),r}{const o=i.constructor;void 0!==e&&Object.defineProperty(i,n,e(n)),null==t||t(o,n)}})({finisher:(e,i)=>{Object.assign(e.prototype[i],t)}})} /** * @license * Copyright 2021 Google LLC * SPDX-License-Identifier: BSD-3-Clause - */var Ht,Vt,Wt;null===(Ht=window.HTMLSlotElement)||void 0===Ht||Ht.prototype.assignedElements,function(t){t.language="language",t.system="system",t.comma_decimal="comma_decimal",t.decimal_comma="decimal_comma",t.space_comma="space_comma",t.none="none"}(Vt||(Vt={})),function(t){t.language="language",t.system="system",t.am_pm="12",t.twenty_four="24"}(Wt||(Wt={}));var Gt=function(t,e,i,o){o=o||{},i=null==i?{}:i;var n=new Event(e,{bubbles:void 0===o.bubbles||o.bubbles,cancelable:Boolean(o.cancelable),composed:void 0===o.composed||o.composed});return n.detail=i,t.dispatchEvent(n),n + */var Hn,Vn,Wn;null===(Hn=window.HTMLSlotElement)||void 0===Hn||Hn.prototype.assignedElements,function(t){t.language="language",t.system="system",t.comma_decimal="comma_decimal",t.decimal_comma="decimal_comma",t.space_comma="space_comma",t.none="none"}(Vn||(Vn={})),function(t){t.language="language",t.system="system",t.am_pm="12",t.twenty_four="24"}(Wn||(Wn={}));var Gn=function(t,e,i,n){n=n||{},i=null==i?{}:i;var o=new Event(e,{bubbles:void 0===n.bubbles||n.bubbles,cancelable:Boolean(n.cancelable),composed:void 0===n.composed||n.composed});return o.detail=i,t.dispatchEvent(o),o /** * vis-data * http://visjs.org/ @@ -88,14 +89,14 @@ function Qt(t){return(({finisher:t,descriptor:e})=>(i,o)=>{var n;if(void 0===o){ * http://opensource.org/licenses/MIT * * vis.js may be distributed under either license. - */};function Kt(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var qt="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function Yt(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var Zt={exports:{}},Jt=function(t){return t&&t.Math===Math&&t},Xt=Jt("object"==typeof globalThis&&globalThis)||Jt("object"==typeof window&&window)||Jt("object"==typeof self&&self)||Jt("object"==typeof qt&&qt)||function(){return this}()||qt||Function("return this")(),_t=function(t){try{return!!t()}catch(t){return!0}},$t=!_t((function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")})),te=$t,ee=Function.prototype,ie=ee.apply,oe=ee.call,ne="object"==typeof Reflect&&Reflect.apply||(te?oe.bind(ie):function(){return oe.apply(ie,arguments)}),re=$t,se=Function.prototype,ae=se.call,le=re&&se.bind.bind(ae,ae),he=re?le:function(t){return function(){return ae.apply(t,arguments)}},ce=he,de=ce({}.toString),ue=ce("".slice),fe=function(t){return ue(de(t),8,-1)},pe=fe,ve=he,ge=function(t){if("Function"===pe(t))return ve(t)},ye="object"==typeof document&&document.all,me={all:ye,IS_HTMLDDA:void 0===ye&&void 0!==ye},be=me.all,we=me.IS_HTMLDDA?function(t){return"function"==typeof t||t===be}:function(t){return"function"==typeof t},Ae={},Ee=!_t((function(){return 7!==Object.defineProperty({},1,{get:function(){return 7}})[1]})),ke=$t,Ce=Function.prototype.call,xe=ke?Ce.bind(Ce):function(){return Ce.apply(Ce,arguments)},Se={},Ie={}.propertyIsEnumerable,Me=Object.getOwnPropertyDescriptor,Oe=Me&&!Ie.call({1:2},1);Se.f=Oe?function(t){var e=Me(this,t);return!!e&&e.enumerable}:Ie;var De,Re,Be=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}},ze=_t,Pe=fe,Fe=Object,Te=he("".split),Ne=ze((function(){return!Fe("z").propertyIsEnumerable(0)}))?function(t){return"String"===Pe(t)?Te(t,""):Fe(t)}:Fe,je=function(t){return null==t},Ue=je,Le=TypeError,Qe=function(t){if(Ue(t))throw new Le("Can't call method on "+t);return t},He=Ne,Ve=Qe,We=function(t){return He(Ve(t))},Ge=we,Ke=me.all,qe=me.IS_HTMLDDA?function(t){return"object"==typeof t?null!==t:Ge(t)||t===Ke}:function(t){return"object"==typeof t?null!==t:Ge(t)},Ye={},Ze=Ye,Je=Xt,Xe=we,_e=function(t){return Xe(t)?t:void 0},$e=function(t,e){return arguments.length<2?_e(Ze[t])||_e(Je[t]):Ze[t]&&Ze[t][e]||Je[t]&&Je[t][e]},ti=he({}.isPrototypeOf),ei="undefined"!=typeof navigator&&String(navigator.userAgent)||"",ii=Xt,oi=ei,ni=ii.process,ri=ii.Deno,si=ni&&ni.versions||ri&&ri.version,ai=si&&si.v8;ai&&(Re=(De=ai.split("."))[0]>0&&De[0]<4?1:+(De[0]+De[1])),!Re&&oi&&(!(De=oi.match(/Edge\/(\d+)/))||De[1]>=74)&&(De=oi.match(/Chrome\/(\d+)/))&&(Re=+De[1]);var li=Re,hi=li,ci=_t,di=Xt.String,ui=!!Object.getOwnPropertySymbols&&!ci((function(){var t=Symbol("symbol detection");return!di(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&hi&&hi<41})),fi=ui&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,pi=$e,vi=we,gi=ti,yi=Object,mi=fi?function(t){return"symbol"==typeof t}:function(t){var e=pi("Symbol");return vi(e)&&gi(e.prototype,yi(t))},bi=String,wi=function(t){try{return bi(t)}catch(t){return"Object"}},Ai=we,Ei=wi,ki=TypeError,Ci=function(t){if(Ai(t))return t;throw new ki(Ei(t)+" is not a function")},xi=Ci,Si=je,Ii=function(t,e){var i=t[e];return Si(i)?void 0:xi(i)},Mi=xe,Oi=we,Di=qe,Ri=TypeError,Bi={exports:{}},zi=Xt,Pi=Object.defineProperty,Fi=function(t,e){try{Pi(zi,t,{value:e,configurable:!0,writable:!0})}catch(i){zi[t]=e}return e},Ti="__core-js_shared__",Ni=Xt[Ti]||Fi(Ti,{}),ji=Ni;(Bi.exports=function(t,e){return ji[t]||(ji[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.33.2",mode:"pure",copyright:"© 2014-2023 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.33.2/LICENSE",source:"https://github.com/zloirock/core-js"});var Ui=Bi.exports,Li=Qe,Qi=Object,Hi=function(t){return Qi(Li(t))},Vi=Hi,Wi=he({}.hasOwnProperty),Gi=Object.hasOwn||function(t,e){return Wi(Vi(t),e)},Ki=he,qi=0,Yi=Math.random(),Zi=Ki(1..toString),Ji=function(t){return"Symbol("+(void 0===t?"":t)+")_"+Zi(++qi+Yi,36)},Xi=Ui,_i=Gi,$i=Ji,to=ui,eo=fi,io=Xt.Symbol,oo=Xi("wks"),no=eo?io.for||io:io&&io.withoutSetter||$i,ro=function(t){return _i(oo,t)||(oo[t]=to&&_i(io,t)?io[t]:no("Symbol."+t)),oo[t]},so=xe,ao=qe,lo=mi,ho=Ii,co=function(t,e){var i,o;if("string"===e&&Oi(i=t.toString)&&!Di(o=Mi(i,t)))return o;if(Oi(i=t.valueOf)&&!Di(o=Mi(i,t)))return o;if("string"!==e&&Oi(i=t.toString)&&!Di(o=Mi(i,t)))return o;throw new Ri("Can't convert object to primitive value")},uo=TypeError,fo=ro("toPrimitive"),po=function(t,e){if(!ao(t)||lo(t))return t;var i,o=ho(t,fo);if(o){if(void 0===e&&(e="default"),i=so(o,t,e),!ao(i)||lo(i))return i;throw new uo("Can't convert object to primitive value")}return void 0===e&&(e="number"),co(t,e)},vo=mi,go=function(t){var e=po(t,"string");return vo(e)?e:e+""},yo=qe,mo=Xt.document,bo=yo(mo)&&yo(mo.createElement),wo=function(t){return bo?mo.createElement(t):{}},Ao=wo,Eo=!Ee&&!_t((function(){return 7!==Object.defineProperty(Ao("div"),"a",{get:function(){return 7}}).a})),ko=Ee,Co=xe,xo=Se,So=Be,Io=We,Mo=go,Oo=Gi,Do=Eo,Ro=Object.getOwnPropertyDescriptor;Ae.f=ko?Ro:function(t,e){if(t=Io(t),e=Mo(e),Do)try{return Ro(t,e)}catch(t){}if(Oo(t,e))return So(!Co(xo.f,t,e),t[e])};var Bo=_t,zo=we,Po=/#|\.prototype\./,Fo=function(t,e){var i=No[To(t)];return i===Uo||i!==jo&&(zo(e)?Bo(e):!!e)},To=Fo.normalize=function(t){return String(t).replace(Po,".").toLowerCase()},No=Fo.data={},jo=Fo.NATIVE="N",Uo=Fo.POLYFILL="P",Lo=Fo,Qo=Ci,Ho=$t,Vo=ge(ge.bind),Wo=function(t,e){return Qo(t),void 0===e?t:Ho?Vo(t,e):function(){return t.apply(e,arguments)}},Go={},Ko=Ee&&_t((function(){return 42!==Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype})),qo=qe,Yo=String,Zo=TypeError,Jo=function(t){if(qo(t))return t;throw new Zo(Yo(t)+" is not an object")},Xo=Ee,_o=Eo,$o=Ko,tn=Jo,en=go,on=TypeError,nn=Object.defineProperty,rn=Object.getOwnPropertyDescriptor,sn="enumerable",an="configurable",ln="writable";Go.f=Xo?$o?function(t,e,i){if(tn(t),e=en(e),tn(i),"function"==typeof t&&"prototype"===e&&"value"in i&&ln in i&&!i[ln]){var o=rn(t,e);o&&o[ln]&&(t[e]=i.value,i={configurable:an in i?i[an]:o[an],enumerable:sn in i?i[sn]:o[sn],writable:!1})}return nn(t,e,i)}:nn:function(t,e,i){if(tn(t),e=en(e),tn(i),_o)try{return nn(t,e,i)}catch(t){}if("get"in i||"set"in i)throw new on("Accessors not supported");return"value"in i&&(t[e]=i.value),t};var hn=Go,cn=Be,dn=Ee?function(t,e,i){return hn.f(t,e,cn(1,i))}:function(t,e,i){return t[e]=i,t},un=Xt,fn=ne,pn=ge,vn=we,gn=Ae.f,yn=Lo,mn=Ye,bn=Wo,wn=dn,An=Gi,En=function(t){var e=function(i,o,n){if(this instanceof e){switch(arguments.length){case 0:return new t;case 1:return new t(i);case 2:return new t(i,o)}return new t(i,o,n)}return fn(t,this,arguments)};return e.prototype=t.prototype,e},kn=function(t,e){var i,o,n,r,s,a,l,h,c,d=t.target,u=t.global,f=t.stat,p=t.proto,v=u?un:f?un[d]:(un[d]||{}).prototype,g=u?mn:mn[d]||wn(mn,d,{})[d],y=g.prototype;for(r in e)o=!(i=yn(u?r:d+(f?".":"#")+r,t.forced))&&v&&An(v,r),a=g[r],o&&(l=t.dontCallGetSet?(c=gn(v,r))&&c.value:v[r]),s=o&&l?l:e[r],o&&typeof a==typeof s||(h=t.bind&&o?bn(s,un):t.wrap&&o?En(s):p&&vn(s)?pn(s):s,(t.sham||s&&s.sham||a&&a.sham)&&wn(h,"sham",!0),wn(g,r,h),p&&(An(mn,n=d+"Prototype")||wn(mn,n,{}),wn(mn[n],r,s),t.real&&y&&(i||!y[r])&&wn(y,r,s)))},Cn=kn,xn=Ee,Sn=Go.f;Cn({target:"Object",stat:!0,forced:Object.defineProperty!==Sn,sham:!xn},{defineProperty:Sn});var In=Ye.Object,Mn=Zt.exports=function(t,e,i){return In.defineProperty(t,e,i)};In.defineProperty.sham&&(Mn.sham=!0);var On=Zt.exports,Dn=On,Rn=Yt(Dn),Bn=fe,zn=Array.isArray||function(t){return"Array"===Bn(t)},Pn=Math.ceil,Fn=Math.floor,Tn=Math.trunc||function(t){var e=+t;return(e>0?Fn:Pn)(e)},Nn=Tn,jn=function(t){var e=+t;return e!=e||0===e?0:Nn(e)},Un=jn,Ln=Math.min,Qn=function(t){return t>0?Ln(Un(t),9007199254740991):0},Hn=function(t){return Qn(t.length)},Vn=TypeError,Wn=function(t){if(t>9007199254740991)throw Vn("Maximum allowed index exceeded");return t},Gn=go,Kn=Go,qn=Be,Yn=function(t,e,i){var o=Gn(e);o in t?Kn.f(t,o,qn(0,i)):t[o]=i},Zn={};Zn[ro("toStringTag")]="z";var Jn="[object z]"===String(Zn),Xn=Jn,_n=we,$n=fe,tr=ro("toStringTag"),er=Object,ir="Arguments"===$n(function(){return arguments}()),or=Xn?$n:function(t){var e,i,o;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(i=function(t,e){try{return t[e]}catch(t){}}(e=er(t),tr))?i:ir?$n(e):"Object"===(o=$n(e))&&_n(e.callee)?"Arguments":o},nr=we,rr=Ni,sr=he(Function.toString);nr(rr.inspectSource)||(rr.inspectSource=function(t){return sr(t)});var ar=rr.inspectSource,lr=he,hr=_t,cr=we,dr=or,ur=ar,fr=function(){},pr=[],vr=$e("Reflect","construct"),gr=/^\s*(?:class|function)\b/,yr=lr(gr.exec),mr=!gr.test(fr),br=function(t){if(!cr(t))return!1;try{return vr(fr,pr,t),!0}catch(t){return!1}},wr=function(t){if(!cr(t))return!1;switch(dr(t)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}try{return mr||!!yr(gr,ur(t))}catch(t){return!0}};wr.sham=!0;var Ar=!vr||hr((function(){var t;return br(br.call)||!br(Object)||!br((function(){t=!0}))||t}))?wr:br,Er=zn,kr=Ar,Cr=qe,xr=ro("species"),Sr=Array,Ir=function(t){var e;return Er(t)&&(e=t.constructor,(kr(e)&&(e===Sr||Er(e.prototype))||Cr(e)&&null===(e=e[xr]))&&(e=void 0)),void 0===e?Sr:e},Mr=function(t,e){return new(Ir(t))(0===e?0:e)},Or=_t,Dr=li,Rr=ro("species"),Br=function(t){return Dr>=51||!Or((function(){var e=[];return(e.constructor={})[Rr]=function(){return{foo:1}},1!==e[t](Boolean).foo}))},zr=kn,Pr=_t,Fr=zn,Tr=qe,Nr=Hi,jr=Hn,Ur=Wn,Lr=Yn,Qr=Mr,Hr=Br,Vr=li,Wr=ro("isConcatSpreadable"),Gr=Vr>=51||!Pr((function(){var t=[];return t[Wr]=!1,t.concat()[0]!==t})),Kr=function(t){if(!Tr(t))return!1;var e=t[Wr];return void 0!==e?!!e:Fr(t)};zr({target:"Array",proto:!0,arity:1,forced:!Gr||!Hr("concat")},{concat:function(t){var e,i,o,n,r,s=Nr(this),a=Qr(s,0),l=0;for(e=-1,o=arguments.length;ea;)if((n=r[a++])!=n)return!0}else for(;s>a;a++)if((t||a in r)&&r[a]===i)return t||a||0;return!t&&-1}},rs={includes:ns(!0),indexOf:ns(!1)},ss={},as=Gi,ls=We,hs=rs.indexOf,cs=ss,ds=he([].push),us=function(t,e){var i,o=ls(t),n=0,r=[];for(i in o)!as(cs,i)&&as(o,i)&&ds(r,i);for(;e.length>n;)as(o,i=e[n++])&&(~hs(r,i)||ds(r,i));return r},fs=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],ps=us,vs=fs,gs=Object.keys||function(t){return ps(t,vs)},ys=Ee,ms=Ko,bs=Go,ws=Jo,As=We,Es=gs;Jr.f=ys&&!ms?Object.defineProperties:function(t,e){ws(t);for(var i,o=As(e),n=Es(e),r=n.length,s=0;r>s;)bs.f(t,i=n[s++],o[i]);return t};var ks,Cs=$e("document","documentElement"),xs=Ji,Ss=Ui("keys"),Is=function(t){return Ss[t]||(Ss[t]=xs(t))},Ms=Jo,Os=Jr,Ds=fs,Rs=ss,Bs=Cs,zs=wo,Ps="prototype",Fs="script",Ts=Is("IE_PROTO"),Ns=function(){},js=function(t){return"<"+Fs+">"+t+""},Us=function(t){t.write(js("")),t.close();var e=t.parentWindow.Object;return t=null,e},Ls=function(){try{ks=new ActiveXObject("htmlfile")}catch(t){}var t,e,i;Ls="undefined"!=typeof document?document.domain&&ks?Us(ks):(e=zs("iframe"),i="java"+Fs+":",e.style.display="none",Bs.appendChild(e),e.src=String(i),(t=e.contentWindow.document).open(),t.write(js("document.F=Object")),t.close(),t.F):Us(ks);for(var o=Ds.length;o--;)delete Ls[Ps][Ds[o]];return Ls()};Rs[Ts]=!0;var Qs=Object.create||function(t,e){var i;return null!==t?(Ns[Ps]=Ms(t),i=new Ns,Ns[Ps]=null,i[Ts]=t):i=Ls(),void 0===e?i:Os.f(i,e)},Hs={},Vs=us,Ws=fs.concat("length","prototype");Hs.f=Object.getOwnPropertyNames||function(t){return Vs(t,Ws)};var Gs={},Ks=ts,qs=Hn,Ys=Yn,Zs=Array,Js=Math.max,Xs=function(t,e,i){for(var o=qs(t),n=Ks(e,o),r=Ks(void 0===i?o:i,o),s=Zs(Js(r-n,0)),a=0;nm;m++)if((a||m in v)&&(f=g(u=v[m],m,p),t))if(e)w[m]=f;else if(f)switch(t){case 3:return!0;case 5:return u;case 6:return m;case 2:$a(w,u)}else switch(t){case 4:return!1;case 7:$a(w,u)}return r?-1:o||n?n:w}},el={forEach:tl(0),map:tl(1),filter:tl(2),some:tl(3),every:tl(4),find:tl(5),findIndex:tl(6),filterReject:tl(7)},il=kn,ol=Xt,nl=xe,rl=he,sl=Ee,al=ui,ll=_t,hl=Gi,cl=ti,dl=Jo,ul=We,fl=go,pl=Zr,vl=Be,gl=Qs,yl=gs,ml=Hs,bl=Gs,wl=oa,Al=Ae,El=Go,kl=Jr,Cl=Se,xl=ra,Sl=aa,Il=Ui,Ml=ss,Ol=Ji,Dl=ro,Rl=la,Bl=ya,zl=Ea,Pl=Ra,Fl=qa,Tl=el.forEach,Nl=Is("hidden"),jl="Symbol",Ul="prototype",Ll=Fl.set,Ql=Fl.getterFor(jl),Hl=Object[Ul],Vl=ol.Symbol,Wl=Vl&&Vl[Ul],Gl=ol.RangeError,Kl=ol.TypeError,ql=ol.QObject,Yl=Al.f,Zl=El.f,Jl=bl.f,Xl=Cl.f,_l=rl([].push),$l=Il("symbols"),th=Il("op-symbols"),eh=Il("wks"),ih=!ql||!ql[Ul]||!ql[Ul].findChild,oh=function(t,e,i){var o=Yl(Hl,e);o&&delete Hl[e],Zl(t,e,i),o&&t!==Hl&&Zl(Hl,e,o)},nh=sl&&ll((function(){return 7!==gl(Zl({},"a",{get:function(){return Zl(this,"a",{value:7}).a}})).a}))?oh:Zl,rh=function(t,e){var i=$l[t]=gl(Wl);return Ll(i,{type:jl,tag:t,description:e}),sl||(i.description=e),i},sh=function(t,e,i){t===Hl&&sh(th,e,i),dl(t);var o=fl(e);return dl(i),hl($l,o)?(i.enumerable?(hl(t,Nl)&&t[Nl][o]&&(t[Nl][o]=!1),i=gl(i,{enumerable:vl(0,!1)})):(hl(t,Nl)||Zl(t,Nl,vl(1,{})),t[Nl][o]=!0),nh(t,o,i)):Zl(t,o,i)},ah=function(t,e){dl(t);var i=ul(e),o=yl(i).concat(dh(i));return Tl(o,(function(e){sl&&!nl(lh,i,e)||sh(t,e,i[e])})),t},lh=function(t){var e=fl(t),i=nl(Xl,this,e);return!(this===Hl&&hl($l,e)&&!hl(th,e))&&(!(i||!hl(this,e)||!hl($l,e)||hl(this,Nl)&&this[Nl][e])||i)},hh=function(t,e){var i=ul(t),o=fl(e);if(i!==Hl||!hl($l,o)||hl(th,o)){var n=Yl(i,o);return!n||!hl($l,o)||hl(i,Nl)&&i[Nl][o]||(n.enumerable=!0),n}},ch=function(t){var e=Jl(ul(t)),i=[];return Tl(e,(function(t){hl($l,t)||hl(Ml,t)||_l(i,t)})),i},dh=function(t){var e=t===Hl,i=Jl(e?th:ul(t)),o=[];return Tl(i,(function(t){!hl($l,t)||e&&!hl(Hl,t)||_l(o,$l[t])})),o};al||(Vl=function(){if(cl(Wl,this))throw new Kl("Symbol is not a constructor");var t=arguments.length&&void 0!==arguments[0]?pl(arguments[0]):void 0,e=Ol(t),i=function(t){var o=void 0===this?ol:this;o===Hl&&nl(i,th,t),hl(o,Nl)&&hl(o[Nl],e)&&(o[Nl][e]=!1);var n=vl(1,t);try{nh(o,e,n)}catch(t){if(!(t instanceof Gl))throw t;oh(o,e,n)}};return sl&&ih&&nh(Hl,e,{configurable:!0,set:i}),rh(e,t)},xl(Wl=Vl[Ul],"toString",(function(){return Ql(this).tag})),xl(Vl,"withoutSetter",(function(t){return rh(Ol(t),t)})),Cl.f=lh,El.f=sh,kl.f=ah,Al.f=hh,ml.f=bl.f=ch,wl.f=dh,Rl.f=function(t){return rh(Dl(t),t)},sl&&Sl(Wl,"description",{configurable:!0,get:function(){return Ql(this).description}})),il({global:!0,constructor:!0,wrap:!0,forced:!al,sham:!al},{Symbol:Vl}),Tl(yl(eh),(function(t){Bl(t)})),il({target:jl,stat:!0,forced:!al},{useSetter:function(){ih=!0},useSimple:function(){ih=!1}}),il({target:"Object",stat:!0,forced:!al,sham:!sl},{create:function(t,e){return void 0===e?gl(t):ah(gl(t),e)},defineProperty:sh,defineProperties:ah,getOwnPropertyDescriptor:hh}),il({target:"Object",stat:!0,forced:!al},{getOwnPropertyNames:ch}),zl(),Pl(Vl,jl),Ml[Nl]=!0;var uh=ui&&!!Symbol.for&&!!Symbol.keyFor,fh=kn,ph=$e,vh=Gi,gh=Zr,yh=Ui,mh=uh,bh=yh("string-to-symbol-registry"),wh=yh("symbol-to-string-registry");fh({target:"Symbol",stat:!0,forced:!mh},{for:function(t){var e=gh(t);if(vh(bh,e))return bh[e];var i=ph("Symbol")(e);return bh[e]=i,wh[i]=e,i}});var Ah=kn,Eh=Gi,kh=mi,Ch=wi,xh=uh,Sh=Ui("symbol-to-string-registry");Ah({target:"Symbol",stat:!0,forced:!xh},{keyFor:function(t){if(!kh(t))throw new TypeError(Ch(t)+" is not a symbol");if(Eh(Sh,t))return Sh[t]}});var Ih=he([].slice),Mh=zn,Oh=we,Dh=fe,Rh=Zr,Bh=he([].push),zh=kn,Ph=$e,Fh=ne,Th=xe,Nh=he,jh=_t,Uh=we,Lh=mi,Qh=Ih,Hh=function(t){if(Oh(t))return t;if(Mh(t)){for(var e=t.length,i=[],o=0;o=e.length)return t.target=void 0,wd(void 0,!0);switch(t.kind){case"keys":return wd(i,!1);case"values":return wd(e[i],!1)}return wd([i,e[i]],!1)}),"values"),yd.Arguments=yd.Array;var Cd={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0},xd=Xt,Sd=or,Id=dn,Md=fc,Od=ro("toStringTag");for(var Dd in Cd){var Rd=xd[Dd],Bd=Rd&&Rd.prototype;Bd&&Sd(Bd)!==Od&&Id(Bd,Od,Dd),Md[Dd]=Md.Array}var zd=uc,Pd=ro,Fd=Go.f,Td=Pd("metadata"),Nd=Function.prototype;void 0===Nd[Td]&&Fd(Nd,Td,{value:null}),ya("asyncDispose"),ya("dispose"),ya("metadata");var jd=zd,Ud=he,Ld=$e("Symbol"),Qd=Ld.keyFor,Hd=Ud(Ld.prototype.valueOf),Vd=Ld.isRegisteredSymbol||function(t){try{return void 0!==Qd(Hd(t))}catch(t){return!1}};kn({target:"Symbol",stat:!0},{isRegisteredSymbol:Vd});for(var Wd=Ui,Gd=$e,Kd=he,qd=mi,Yd=ro,Zd=Gd("Symbol"),Jd=Zd.isWellKnownSymbol,Xd=Gd("Object","getOwnPropertyNames"),_d=Kd(Zd.prototype.valueOf),$d=Wd("wks"),tu=0,eu=Xd(Zd),iu=eu.length;tu=a?t?"":void 0:(o=uu(r,s))<55296||o>56319||s+1===a||(n=uu(r,s+1))<56320||n>57343?t?du(r,s):o:t?fu(r,s,s+2):n-56320+(o-55296<<10)+65536}},vu={codeAt:pu(!1),charAt:pu(!0)}.charAt,gu=Zr,yu=qa,mu=pd,bu=vd,wu="String Iterator",Au=yu.set,Eu=yu.getterFor(wu);mu(String,"String",(function(t){Au(this,{type:wu,string:gu(t),index:0})}),(function(){var t,e=Eu(this),i=e.string,o=e.index;return o>=i.length?bu(void 0,!0):(t=vu(i,o),e.index+=t.length,bu(t,!1))}));var ku=la.f("iterator"),Cu=ku,xu=Yt(Cu);function Su(t){return Su="function"==typeof su&&"symbol"==typeof xu?function(t){return typeof t}:function(t){return t&&"function"==typeof su&&t.constructor===su&&t!==su.prototype?"symbol":typeof t},Su(t)}var Iu=Yt(la.f("toPrimitive"));function Mu(t){var e=function(t,e){if("object"!==Su(t)||null===t)return t;var i=t[Iu];if(void 0!==i){var o=i.call(t,e||"default");if("object"!==Su(o))return o;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(t,"string");return"symbol"===Su(e)?e:String(e)}function Ou(t,e){for(var i=0;i=0:a>l;l+=h)l in s&&(n=i(n,s[l],l,r));return n}},af={left:sf(!1),right:sf(!0)},lf=_t,hf=function(t,e){var i=[][t];return!!i&&lf((function(){i.call(null,e||function(){return 1},1)}))},cf="process"===fe(Xt.process),df=af.left;kn({target:"Array",proto:!0,forced:!cf&&li>79&&li<83||!hf("reduce")},{reduce:function(t){var e=arguments.length;return df(this,t,e,e>1?arguments[1]:void 0)}});var uf=Ku("Array","reduce"),ff=ti,pf=uf,vf=Array.prototype,gf=function(t){var e=t.reduce;return t===vf||ff(vf,t)&&e===vf.reduce?pf:e},yf=Yt(gf),mf=el.filter;kn({target:"Array",proto:!0,forced:!Br("filter")},{filter:function(t){return mf(this,t,arguments.length>1?arguments[1]:void 0)}});var bf=Ku("Array","filter"),wf=ti,Af=bf,Ef=Array.prototype,kf=function(t){var e=t.filter;return t===Ef||wf(Ef,t)&&e===Ef.filter?Af:e},Cf=Yt(kf),xf=el.map;kn({target:"Array",proto:!0,forced:!Br("map")},{map:function(t){return xf(this,t,arguments.length>1?arguments[1]:void 0)}});var Sf=Ku("Array","map"),If=ti,Mf=Sf,Of=Array.prototype,Df=function(t){var e=t.map;return t===Of||If(Of,t)&&e===Of.map?Mf:e},Rf=Yt(Df),Bf=zn,zf=Hn,Pf=Wn,Ff=Wo,Tf=function(t,e,i,o,n,r,s,a){for(var l,h,c=n,d=0,u=!!s&&Ff(s,a);d0&&Bf(l)?(h=zf(l),c=Tf(t,e,l,h,c,r-1)-1):(Pf(c+1),t[c]=l),c++),d++;return c},Nf=Tf,jf=Ci,Uf=Hi,Lf=Hn,Qf=Mr;kn({target:"Array",proto:!0},{flatMap:function(t){var e,i=Uf(this),o=Lf(i);return jf(t),(e=Qf(i,0)).length=Nf(e,i,i,o,0,1,t,arguments.length>1?arguments[1]:void 0),e}}),Ku("Array","flatMap");var Hf=xe,Vf=Jo,Wf=Ii,Gf=function(t,e,i){var o,n;Vf(t);try{if(!(o=Wf(t,"return"))){if("throw"===e)throw i;return i}o=Hf(o,t)}catch(t){n=!0,o=t}if("throw"===e)throw i;if(n)throw o;return Vf(o),i},Kf=Jo,qf=Gf,Yf=fc,Zf=ro("iterator"),Jf=Array.prototype,Xf=function(t){return void 0!==t&&(Yf.Array===t||Jf[Zf]===t)},_f=or,$f=Ii,tp=je,ep=fc,ip=ro("iterator"),op=function(t){if(!tp(t))return $f(t,ip)||$f(t,"@@iterator")||ep[_f(t)]},np=xe,rp=Ci,sp=Jo,ap=wi,lp=op,hp=TypeError,cp=function(t,e){var i=arguments.length<2?lp(t):e;if(rp(i))return sp(np(i,t));throw new hp(ap(t)+" is not iterable")},dp=Wo,up=xe,fp=Hi,pp=function(t,e,i,o){try{return o?e(Kf(i)[0],i[1]):e(i)}catch(e){qf(t,"throw",e)}},vp=Xf,gp=Ar,yp=Hn,mp=Yn,bp=cp,wp=op,Ap=Array,Ep=ro("iterator"),kp=!1;try{var Cp=0,xp={next:function(){return{done:!!Cp++}},return:function(){kp=!0}};xp[Ep]=function(){return this},Array.from(xp,(function(){throw 2}))}catch(t){}var Sp=function(t,e){try{if(!e&&!kp)return!1}catch(t){return!1}var i=!1;try{var o={};o[Ep]=function(){return{next:function(){return{done:i=!0}}}},t(o)}catch(t){}return i},Ip=function(t){var e=fp(t),i=gp(this),o=arguments.length,n=o>1?arguments[1]:void 0,r=void 0!==n;r&&(n=dp(n,o>2?arguments[2]:void 0));var s,a,l,h,c,d,u=wp(e),f=0;if(!u||this===Ap&&vp(u))for(s=yp(e),a=i?new this(s):Ap(s);s>f;f++)d=r?n(e[f],f):e[f],mp(a,f,d);else for(c=(h=bp(e,u)).next,a=i?new this:[];!(l=up(c,h)).done;f++)d=r?pp(h,n,[l.value,f],!0):l.value,mp(a,f,d);return a.length=f,a};kn({target:"Array",stat:!0,forced:!Sp((function(t){Array.from(t)}))},{from:Ip});var Mp=Ye.Array.from,Op=Yt(Mp),Dp=op,Rp=Yt(Dp),Bp=Yt(Dp);kn({target:"Array",stat:!0},{isArray:zn});var zp=Ye.Array.isArray,Pp=Yt(zp);var Fp=Ee,Tp=zn,Np=TypeError,jp=Object.getOwnPropertyDescriptor,Up=Fp&&!function(){if(void 0!==this)return!0;try{Object.defineProperty([],"length",{writable:!1}).length=1}catch(t){return t instanceof TypeError}}()?function(t,e){if(Tp(t)&&!jp(t,"length").writable)throw new Np("Cannot set read only .length");return t.length=e}:function(t,e){return t.length=e},Lp=Hi,Qp=Hn,Hp=Up,Vp=Wn;kn({target:"Array",proto:!0,arity:1,forced:_t((function(){return 4294967297!==[].push.call({length:4294967296},1)}))||!function(){try{Object.defineProperty([],"length",{writable:!1}).push()}catch(t){return t instanceof TypeError}}()},{push:function(t){var e=Lp(this),i=Qp(e),o=arguments.length;Vp(i+o);for(var n=0;nt.length)&&(e=t.length);for(var i=0,o=new Array(e);i1?arguments[1]:void 0)};kn({target:"Array",proto:!0,forced:[].forEach!==Wv},{forEach:Wv});var Gv=Ku("Array","forEach"),Kv=or,qv=Gi,Yv=ti,Zv=Gv,Jv=Array.prototype,Xv={DOMTokenList:!0,NodeList:!0},_v=function(t){var e=t.forEach;return t===Jv||Yv(Jv,t)&&e===Jv.forEach||qv(Xv,Kv(t))?Zv:e},$v=Yt(_v),tg=kn,eg=zn,ig=he([].reverse),og=[1,2];tg({target:"Array",proto:!0,forced:String(og)===String(og.reverse())},{reverse:function(){return eg(this)&&(this.length=this.length),ig(this)}});var ng=Ku("Array","reverse"),rg=ti,sg=ng,ag=Array.prototype,lg=function(t){var e=t.reverse;return t===ag||rg(ag,t)&&e===ag.reverse?sg:e},hg=lg,cg=Yt(hg),dg=wi,ug=TypeError,fg=function(t,e){if(!delete t[e])throw new ug("Cannot delete property "+dg(e)+" of "+dg(t))},pg=kn,vg=Hi,gg=ts,yg=jn,mg=Hn,bg=Up,wg=Wn,Ag=Mr,Eg=Yn,kg=fg,Cg=Br("splice"),xg=Math.max,Sg=Math.min;pg({target:"Array",proto:!0,forced:!Cg},{splice:function(t,e){var i,o,n,r,s,a,l=vg(this),h=mg(l),c=gg(t,h),d=arguments.length;for(0===d?i=o=0:1===d?(i=0,o=h-c):(i=d-2,o=Sg(xg(yg(e),0),h-c)),wg(h+i-o),n=Ag(l,o),r=0;rh-o+i;r--)kg(l,r-1)}else if(i>o)for(r=h-o;r>c;r--)a=r+i-1,(s=r+o-1)in l?l[a]=l[s]:kg(l,a);for(r=0;rn;)for(var a,l=Qg(arguments[n++]),h=r?Wg(Ng(l),r(l)):Ng(l),c=h.length,d=0;c>d;)a=h[d++],zg&&!Fg(s,l,a)||(i[a]=l[a]);return i}:Hg,Kg=Gg;kn({target:"Object",stat:!0,arity:2,forced:Object.assign!==Kg},{assign:Kg});var qg=Yt(Ye.Object.assign),Yg=Hi,Zg=Mc,Jg=wc;kn({target:"Object",stat:!0,forced:_t((function(){Zg(1)})),sham:!Jg},{getPrototypeOf:function(t){return Zg(Yg(t))}});var Xg=Ye.Object.getPrototypeOf;kn({target:"Object",stat:!0,sham:!Ee},{create:Qs});var _g=Ye.Object,$g=function(t,e){return _g.create(t,e)},ty=$g,ey=Yt(ty),iy=Ye,oy=ne;iy.JSON||(iy.JSON={stringify:JSON.stringify});var ny=function(t,e,i){return oy(iy.JSON.stringify,null,arguments)},ry=Yt(ny),sy="function"==typeof Bun&&Bun&&"string"==typeof Bun.version,ay=TypeError,ly=function(t,e){if(ti,s=dy(o)?o:gy(o),a=r?py(arguments,i):[],l=r?function(){cy(s,this,a)}:s;return e?t(l,n):t(l)}:t},by=kn,wy=Xt,Ay=my(wy.setInterval,!0);by({global:!0,bind:!0,forced:wy.setInterval!==Ay},{setInterval:Ay});var Ey=kn,ky=Xt,Cy=my(ky.setTimeout,!0);Ey({global:!0,bind:!0,forced:ky.setTimeout!==Cy},{setTimeout:Cy});var xy=Yt(Ye.setTimeout),Sy={exports:{}};!function(t){function e(t){if(t)return function(t){return Object.assign(t,e.prototype),t._callbacks=new Map,t}(t);this._callbacks=new Map}e.prototype.on=function(t,e){const i=this._callbacks.get(t)??[];return i.push(e),this._callbacks.set(t,i),this},e.prototype.once=function(t,e){const i=(...o)=>{this.off(t,i),e.apply(this,o)};return i.fn=e,this.on(t,i),this},e.prototype.off=function(t,e){if(void 0===t&&void 0===e)return this._callbacks.clear(),this;if(void 0===e)return this._callbacks.delete(t),this;const i=this._callbacks.get(t);if(i){for(const[t,o]of i.entries())if(o===e||o.fn===e){i.splice(t,1);break}0===i.length?this._callbacks.delete(t):this._callbacks.set(t,i)}return this},e.prototype.emit=function(t,...e){const i=this._callbacks.get(t);if(i){const t=[...i];for(const i of t)i.apply(this,e)}return this},e.prototype.listeners=function(t){return this._callbacks.get(t)??[]},e.prototype.listenerCount=function(t){if(t)return this.listeners(t).length;let e=0;for(const t of this._callbacks.values())e+=t.length;return e},e.prototype.hasListeners=function(t){return this.listenerCount(t)>0},e.prototype.addEventListener=e.prototype.on,e.prototype.removeListener=e.prototype.off,e.prototype.removeEventListener=e.prototype.off,e.prototype.removeAllListeners=e.prototype.off,t.exports=e}(Sy);var Iy,My=Yt(Sy.exports); + */};function Kn(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var qn="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function Yn(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var Zn={exports:{}},Jn=function(t){return t&&t.Math===Math&&t},Xn=Jn("object"==typeof globalThis&&globalThis)||Jn("object"==typeof window&&window)||Jn("object"==typeof self&&self)||Jn("object"==typeof qn&&qn)||function(){return this}()||qn||Function("return this")(),_n=function(t){try{return!!t()}catch(t){return!0}},$n=!_n((function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")})),to=$n,eo=Function.prototype,io=eo.apply,no=eo.call,oo="object"==typeof Reflect&&Reflect.apply||(to?no.bind(io):function(){return no.apply(io,arguments)}),ro=$n,so=Function.prototype,ao=so.call,lo=ro&&so.bind.bind(ao,ao),ho=ro?lo:function(t){return function(){return ao.apply(t,arguments)}},co=ho,uo=co({}.toString),fo=co("".slice),po=function(t){return fo(uo(t),8,-1)},vo=po,go=ho,yo=function(t){if("Function"===vo(t))return go(t)},mo="object"==typeof document&&document.all,bo={all:mo,IS_HTMLDDA:void 0===mo&&void 0!==mo},wo=bo.all,Ao=bo.IS_HTMLDDA?function(t){return"function"==typeof t||t===wo}:function(t){return"function"==typeof t},ko={},Eo=!_n((function(){return 7!==Object.defineProperty({},1,{get:function(){return 7}})[1]})),Co=$n,xo=Function.prototype.call,Io=Co?xo.bind(xo):function(){return xo.apply(xo,arguments)},So={},Mo={}.propertyIsEnumerable,Oo=Object.getOwnPropertyDescriptor,Do=Oo&&!Mo.call({1:2},1);So.f=Do?function(t){var e=Oo(this,t);return!!e&&e.enumerable}:Mo;var Ro,Bo,zo=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}},Po=_n,Fo=po,To=Object,No=ho("".split),jo=Po((function(){return!To("z").propertyIsEnumerable(0)}))?function(t){return"String"===Fo(t)?No(t,""):To(t)}:To,Lo=function(t){return null==t},Uo=Lo,Qo=TypeError,Ho=function(t){if(Uo(t))throw new Qo("Can't call method on "+t);return t},Vo=jo,Wo=Ho,Go=function(t){return Vo(Wo(t))},Ko=Ao,qo=bo.all,Yo=bo.IS_HTMLDDA?function(t){return"object"==typeof t?null!==t:Ko(t)||t===qo}:function(t){return"object"==typeof t?null!==t:Ko(t)},Zo={},Jo=Zo,Xo=Xn,_o=Ao,$o=function(t){return _o(t)?t:void 0},tr=function(t,e){return arguments.length<2?$o(Jo[t])||$o(Xo[t]):Jo[t]&&Jo[t][e]||Xo[t]&&Xo[t][e]},er=ho({}.isPrototypeOf),ir="undefined"!=typeof navigator&&String(navigator.userAgent)||"",nr=Xn,or=ir,rr=nr.process,sr=nr.Deno,ar=rr&&rr.versions||sr&&sr.version,lr=ar&&ar.v8;lr&&(Bo=(Ro=lr.split("."))[0]>0&&Ro[0]<4?1:+(Ro[0]+Ro[1])),!Bo&&or&&(!(Ro=or.match(/Edge\/(\d+)/))||Ro[1]>=74)&&(Ro=or.match(/Chrome\/(\d+)/))&&(Bo=+Ro[1]);var hr=Bo,cr=hr,dr=_n,ur=Xn.String,fr=!!Object.getOwnPropertySymbols&&!dr((function(){var t=Symbol("symbol detection");return!ur(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&cr&&cr<41})),pr=fr&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,vr=tr,gr=Ao,yr=er,mr=Object,br=pr?function(t){return"symbol"==typeof t}:function(t){var e=vr("Symbol");return gr(e)&&yr(e.prototype,mr(t))},wr=String,Ar=function(t){try{return wr(t)}catch(t){return"Object"}},kr=Ao,Er=Ar,Cr=TypeError,xr=function(t){if(kr(t))return t;throw new Cr(Er(t)+" is not a function")},Ir=xr,Sr=Lo,Mr=function(t,e){var i=t[e];return Sr(i)?void 0:Ir(i)},Or=Io,Dr=Ao,Rr=Yo,Br=TypeError,zr={exports:{}},Pr=Xn,Fr=Object.defineProperty,Tr=function(t,e){try{Fr(Pr,t,{value:e,configurable:!0,writable:!0})}catch(i){Pr[t]=e}return e},Nr="__core-js_shared__",jr=Xn[Nr]||Tr(Nr,{}),Lr=jr;(zr.exports=function(t,e){return Lr[t]||(Lr[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.33.2",mode:"pure",copyright:"© 2014-2023 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.33.2/LICENSE",source:"https://github.com/zloirock/core-js"});var Ur=zr.exports,Qr=Ho,Hr=Object,Vr=function(t){return Hr(Qr(t))},Wr=Vr,Gr=ho({}.hasOwnProperty),Kr=Object.hasOwn||function(t,e){return Gr(Wr(t),e)},qr=ho,Yr=0,Zr=Math.random(),Jr=qr(1..toString),Xr=function(t){return"Symbol("+(void 0===t?"":t)+")_"+Jr(++Yr+Zr,36)},_r=Ur,$r=Kr,ts=Xr,es=fr,is=pr,ns=Xn.Symbol,os=_r("wks"),rs=is?ns.for||ns:ns&&ns.withoutSetter||ts,ss=function(t){return $r(os,t)||(os[t]=es&&$r(ns,t)?ns[t]:rs("Symbol."+t)),os[t]},as=Io,ls=Yo,hs=br,cs=Mr,ds=function(t,e){var i,n;if("string"===e&&Dr(i=t.toString)&&!Rr(n=Or(i,t)))return n;if(Dr(i=t.valueOf)&&!Rr(n=Or(i,t)))return n;if("string"!==e&&Dr(i=t.toString)&&!Rr(n=Or(i,t)))return n;throw new Br("Can't convert object to primitive value")},us=TypeError,fs=ss("toPrimitive"),ps=function(t,e){if(!ls(t)||hs(t))return t;var i,n=cs(t,fs);if(n){if(void 0===e&&(e="default"),i=as(n,t,e),!ls(i)||hs(i))return i;throw new us("Can't convert object to primitive value")}return void 0===e&&(e="number"),ds(t,e)},vs=br,gs=function(t){var e=ps(t,"string");return vs(e)?e:e+""},ys=Yo,ms=Xn.document,bs=ys(ms)&&ys(ms.createElement),ws=function(t){return bs?ms.createElement(t):{}},As=ws,ks=!Eo&&!_n((function(){return 7!==Object.defineProperty(As("div"),"a",{get:function(){return 7}}).a})),Es=Eo,Cs=Io,xs=So,Is=zo,Ss=Go,Ms=gs,Os=Kr,Ds=ks,Rs=Object.getOwnPropertyDescriptor;ko.f=Es?Rs:function(t,e){if(t=Ss(t),e=Ms(e),Ds)try{return Rs(t,e)}catch(t){}if(Os(t,e))return Is(!Cs(xs.f,t,e),t[e])};var Bs=_n,zs=Ao,Ps=/#|\.prototype\./,Fs=function(t,e){var i=Ns[Ts(t)];return i===Ls||i!==js&&(zs(e)?Bs(e):!!e)},Ts=Fs.normalize=function(t){return String(t).replace(Ps,".").toLowerCase()},Ns=Fs.data={},js=Fs.NATIVE="N",Ls=Fs.POLYFILL="P",Us=Fs,Qs=xr,Hs=$n,Vs=yo(yo.bind),Ws=function(t,e){return Qs(t),void 0===e?t:Hs?Vs(t,e):function(){return t.apply(e,arguments)}},Gs={},Ks=Eo&&_n((function(){return 42!==Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype})),qs=Yo,Ys=String,Zs=TypeError,Js=function(t){if(qs(t))return t;throw new Zs(Ys(t)+" is not an object")},Xs=Eo,_s=ks,$s=Ks,ta=Js,ea=gs,ia=TypeError,na=Object.defineProperty,oa=Object.getOwnPropertyDescriptor,ra="enumerable",sa="configurable",aa="writable";Gs.f=Xs?$s?function(t,e,i){if(ta(t),e=ea(e),ta(i),"function"==typeof t&&"prototype"===e&&"value"in i&&aa in i&&!i[aa]){var n=oa(t,e);n&&n[aa]&&(t[e]=i.value,i={configurable:sa in i?i[sa]:n[sa],enumerable:ra in i?i[ra]:n[ra],writable:!1})}return na(t,e,i)}:na:function(t,e,i){if(ta(t),e=ea(e),ta(i),_s)try{return na(t,e,i)}catch(t){}if("get"in i||"set"in i)throw new ia("Accessors not supported");return"value"in i&&(t[e]=i.value),t};var la=Gs,ha=zo,ca=Eo?function(t,e,i){return la.f(t,e,ha(1,i))}:function(t,e,i){return t[e]=i,t},da=Xn,ua=oo,fa=yo,pa=Ao,va=ko.f,ga=Us,ya=Zo,ma=Ws,ba=ca,wa=Kr,Aa=function(t){var e=function(i,n,o){if(this instanceof e){switch(arguments.length){case 0:return new t;case 1:return new t(i);case 2:return new t(i,n)}return new t(i,n,o)}return ua(t,this,arguments)};return e.prototype=t.prototype,e},ka=function(t,e){var i,n,o,r,s,a,l,h,c,d=t.target,u=t.global,f=t.stat,p=t.proto,v=u?da:f?da[d]:(da[d]||{}).prototype,g=u?ya:ya[d]||ba(ya,d,{})[d],y=g.prototype;for(r in e)n=!(i=ga(u?r:d+(f?".":"#")+r,t.forced))&&v&&wa(v,r),a=g[r],n&&(l=t.dontCallGetSet?(c=va(v,r))&&c.value:v[r]),s=n&&l?l:e[r],n&&typeof a==typeof s||(h=t.bind&&n?ma(s,da):t.wrap&&n?Aa(s):p&&pa(s)?fa(s):s,(t.sham||s&&s.sham||a&&a.sham)&&ba(h,"sham",!0),ba(g,r,h),p&&(wa(ya,o=d+"Prototype")||ba(ya,o,{}),ba(ya[o],r,s),t.real&&y&&(i||!y[r])&&ba(y,r,s)))},Ea=ka,Ca=Eo,xa=Gs.f;Ea({target:"Object",stat:!0,forced:Object.defineProperty!==xa,sham:!Ca},{defineProperty:xa});var Ia=Zo.Object,Sa=Zn.exports=function(t,e,i){return Ia.defineProperty(t,e,i)};Ia.defineProperty.sham&&(Sa.sham=!0);var Ma=Zn.exports,Oa=Ma,Da=Yn(Oa),Ra=po,Ba=Array.isArray||function(t){return"Array"===Ra(t)},za=Math.ceil,Pa=Math.floor,Fa=Math.trunc||function(t){var e=+t;return(e>0?Pa:za)(e)},Ta=Fa,Na=function(t){var e=+t;return e!=e||0===e?0:Ta(e)},ja=Na,La=Math.min,Ua=function(t){return t>0?La(ja(t),9007199254740991):0},Qa=function(t){return Ua(t.length)},Ha=TypeError,Va=function(t){if(t>9007199254740991)throw Ha("Maximum allowed index exceeded");return t},Wa=gs,Ga=Gs,Ka=zo,qa=function(t,e,i){var n=Wa(e);n in t?Ga.f(t,n,Ka(0,i)):t[n]=i},Ya={};Ya[ss("toStringTag")]="z";var Za="[object z]"===String(Ya),Ja=Za,Xa=Ao,_a=po,$a=ss("toStringTag"),tl=Object,el="Arguments"===_a(function(){return arguments}()),il=Ja?_a:function(t){var e,i,n;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(i=function(t,e){try{return t[e]}catch(t){}}(e=tl(t),$a))?i:el?_a(e):"Object"===(n=_a(e))&&Xa(e.callee)?"Arguments":n},nl=Ao,ol=jr,rl=ho(Function.toString);nl(ol.inspectSource)||(ol.inspectSource=function(t){return rl(t)});var sl=ol.inspectSource,al=ho,ll=_n,hl=Ao,cl=il,dl=sl,ul=function(){},fl=[],pl=tr("Reflect","construct"),vl=/^\s*(?:class|function)\b/,gl=al(vl.exec),yl=!vl.test(ul),ml=function(t){if(!hl(t))return!1;try{return pl(ul,fl,t),!0}catch(t){return!1}},bl=function(t){if(!hl(t))return!1;switch(cl(t)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}try{return yl||!!gl(vl,dl(t))}catch(t){return!0}};bl.sham=!0;var wl=!pl||ll((function(){var t;return ml(ml.call)||!ml(Object)||!ml((function(){t=!0}))||t}))?bl:ml,Al=Ba,kl=wl,El=Yo,Cl=ss("species"),xl=Array,Il=function(t){var e;return Al(t)&&(e=t.constructor,(kl(e)&&(e===xl||Al(e.prototype))||El(e)&&null===(e=e[Cl]))&&(e=void 0)),void 0===e?xl:e},Sl=function(t,e){return new(Il(t))(0===e?0:e)},Ml=_n,Ol=hr,Dl=ss("species"),Rl=function(t){return Ol>=51||!Ml((function(){var e=[];return(e.constructor={})[Dl]=function(){return{foo:1}},1!==e[t](Boolean).foo}))},Bl=ka,zl=_n,Pl=Ba,Fl=Yo,Tl=Vr,Nl=Qa,jl=Va,Ll=qa,Ul=Sl,Ql=Rl,Hl=hr,Vl=ss("isConcatSpreadable"),Wl=Hl>=51||!zl((function(){var t=[];return t[Vl]=!1,t.concat()[0]!==t})),Gl=function(t){if(!Fl(t))return!1;var e=t[Vl];return void 0!==e?!!e:Pl(t)};Bl({target:"Array",proto:!0,arity:1,forced:!Wl||!Ql("concat")},{concat:function(t){var e,i,n,o,r,s=Tl(this),a=Ul(s,0),l=0;for(e=-1,n=arguments.length;ea;)if((o=r[a++])!=o)return!0}else for(;s>a;a++)if((t||a in r)&&r[a]===i)return t||a||0;return!t&&-1}},oh={includes:nh(!0),indexOf:nh(!1)},rh={},sh=Kr,ah=Go,lh=oh.indexOf,hh=rh,ch=ho([].push),dh=function(t,e){var i,n=ah(t),o=0,r=[];for(i in n)!sh(hh,i)&&sh(n,i)&&ch(r,i);for(;e.length>o;)sh(n,i=e[o++])&&(~lh(r,i)||ch(r,i));return r},uh=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],fh=dh,ph=uh,vh=Object.keys||function(t){return fh(t,ph)},gh=Eo,yh=Ks,mh=Gs,bh=Js,wh=Go,Ah=vh;Zl.f=gh&&!yh?Object.defineProperties:function(t,e){bh(t);for(var i,n=wh(e),o=Ah(e),r=o.length,s=0;r>s;)mh.f(t,i=o[s++],n[i]);return t};var kh,Eh=tr("document","documentElement"),Ch=Xr,xh=Ur("keys"),Ih=function(t){return xh[t]||(xh[t]=Ch(t))},Sh=Js,Mh=Zl,Oh=uh,Dh=rh,Rh=Eh,Bh=ws,zh="prototype",Ph="script",Fh=Ih("IE_PROTO"),Th=function(){},Nh=function(t){return"<"+Ph+">"+t+""},jh=function(t){t.write(Nh("")),t.close();var e=t.parentWindow.Object;return t=null,e},Lh=function(){try{kh=new ActiveXObject("htmlfile")}catch(t){}var t,e,i;Lh="undefined"!=typeof document?document.domain&&kh?jh(kh):(e=Bh("iframe"),i="java"+Ph+":",e.style.display="none",Rh.appendChild(e),e.src=String(i),(t=e.contentWindow.document).open(),t.write(Nh("document.F=Object")),t.close(),t.F):jh(kh);for(var n=Oh.length;n--;)delete Lh[zh][Oh[n]];return Lh()};Dh[Fh]=!0;var Uh=Object.create||function(t,e){var i;return null!==t?(Th[zh]=Sh(t),i=new Th,Th[zh]=null,i[Fh]=t):i=Lh(),void 0===e?i:Mh.f(i,e)},Qh={},Hh=dh,Vh=uh.concat("length","prototype");Qh.f=Object.getOwnPropertyNames||function(t){return Hh(t,Vh)};var Wh={},Gh=$l,Kh=Qa,qh=qa,Yh=Array,Zh=Math.max,Jh=function(t,e,i){for(var n=Kh(t),o=Gh(e,n),r=Gh(void 0===i?n:i,n),s=Yh(Zh(r-o,0)),a=0;om;m++)if((a||m in v)&&(f=g(u=v[m],m,p),t))if(e)w[m]=f;else if(f)switch(t){case 3:return!0;case 5:return u;case 6:return m;case 2:_c(w,u)}else switch(t){case 4:return!1;case 7:_c(w,u)}return r?-1:n||o?o:w}},td={forEach:$c(0),map:$c(1),filter:$c(2),some:$c(3),every:$c(4),find:$c(5),findIndex:$c(6),filterReject:$c(7)},ed=ka,id=Xn,nd=Io,od=ho,rd=Eo,sd=fr,ad=_n,ld=Kr,hd=er,cd=Js,dd=Go,ud=gs,fd=Yl,pd=zo,vd=Uh,gd=vh,yd=Qh,md=Wh,bd=ic,wd=ko,Ad=Gs,kd=Zl,Ed=So,Cd=oc,xd=sc,Id=Ur,Sd=rh,Md=Xr,Od=ss,Dd=ac,Rd=gc,Bd=Ac,zd=Dc,Pd=Kc,Fd=td.forEach,Td=Ih("hidden"),Nd="Symbol",jd="prototype",Ld=Pd.set,Ud=Pd.getterFor(Nd),Qd=Object[jd],Hd=id.Symbol,Vd=Hd&&Hd[jd],Wd=id.RangeError,Gd=id.TypeError,Kd=id.QObject,qd=wd.f,Yd=Ad.f,Zd=md.f,Jd=Ed.f,Xd=od([].push),_d=Id("symbols"),$d=Id("op-symbols"),tu=Id("wks"),eu=!Kd||!Kd[jd]||!Kd[jd].findChild,iu=function(t,e,i){var n=qd(Qd,e);n&&delete Qd[e],Yd(t,e,i),n&&t!==Qd&&Yd(Qd,e,n)},nu=rd&&ad((function(){return 7!==vd(Yd({},"a",{get:function(){return Yd(this,"a",{value:7}).a}})).a}))?iu:Yd,ou=function(t,e){var i=_d[t]=vd(Vd);return Ld(i,{type:Nd,tag:t,description:e}),rd||(i.description=e),i},ru=function(t,e,i){t===Qd&&ru($d,e,i),cd(t);var n=ud(e);return cd(i),ld(_d,n)?(i.enumerable?(ld(t,Td)&&t[Td][n]&&(t[Td][n]=!1),i=vd(i,{enumerable:pd(0,!1)})):(ld(t,Td)||Yd(t,Td,pd(1,{})),t[Td][n]=!0),nu(t,n,i)):Yd(t,n,i)},su=function(t,e){cd(t);var i=dd(e),n=gd(i).concat(cu(i));return Fd(n,(function(e){rd&&!nd(au,i,e)||ru(t,e,i[e])})),t},au=function(t){var e=ud(t),i=nd(Jd,this,e);return!(this===Qd&&ld(_d,e)&&!ld($d,e))&&(!(i||!ld(this,e)||!ld(_d,e)||ld(this,Td)&&this[Td][e])||i)},lu=function(t,e){var i=dd(t),n=ud(e);if(i!==Qd||!ld(_d,n)||ld($d,n)){var o=qd(i,n);return!o||!ld(_d,n)||ld(i,Td)&&i[Td][n]||(o.enumerable=!0),o}},hu=function(t){var e=Zd(dd(t)),i=[];return Fd(e,(function(t){ld(_d,t)||ld(Sd,t)||Xd(i,t)})),i},cu=function(t){var e=t===Qd,i=Zd(e?$d:dd(t)),n=[];return Fd(i,(function(t){!ld(_d,t)||e&&!ld(Qd,t)||Xd(n,_d[t])})),n};sd||(Hd=function(){if(hd(Vd,this))throw new Gd("Symbol is not a constructor");var t=arguments.length&&void 0!==arguments[0]?fd(arguments[0]):void 0,e=Md(t),i=function(t){var n=void 0===this?id:this;n===Qd&&nd(i,$d,t),ld(n,Td)&&ld(n[Td],e)&&(n[Td][e]=!1);var o=pd(1,t);try{nu(n,e,o)}catch(t){if(!(t instanceof Wd))throw t;iu(n,e,o)}};return rd&&eu&&nu(Qd,e,{configurable:!0,set:i}),ou(e,t)},Cd(Vd=Hd[jd],"toString",(function(){return Ud(this).tag})),Cd(Hd,"withoutSetter",(function(t){return ou(Md(t),t)})),Ed.f=au,Ad.f=ru,kd.f=su,wd.f=lu,yd.f=md.f=hu,bd.f=cu,Dd.f=function(t){return ou(Od(t),t)},rd&&xd(Vd,"description",{configurable:!0,get:function(){return Ud(this).description}})),ed({global:!0,constructor:!0,wrap:!0,forced:!sd,sham:!sd},{Symbol:Hd}),Fd(gd(tu),(function(t){Rd(t)})),ed({target:Nd,stat:!0,forced:!sd},{useSetter:function(){eu=!0},useSimple:function(){eu=!1}}),ed({target:"Object",stat:!0,forced:!sd,sham:!rd},{create:function(t,e){return void 0===e?vd(t):su(vd(t),e)},defineProperty:ru,defineProperties:su,getOwnPropertyDescriptor:lu}),ed({target:"Object",stat:!0,forced:!sd},{getOwnPropertyNames:hu}),Bd(),zd(Hd,Nd),Sd[Td]=!0;var du=fr&&!!Symbol.for&&!!Symbol.keyFor,uu=ka,fu=tr,pu=Kr,vu=Yl,gu=Ur,yu=du,mu=gu("string-to-symbol-registry"),bu=gu("symbol-to-string-registry");uu({target:"Symbol",stat:!0,forced:!yu},{for:function(t){var e=vu(t);if(pu(mu,e))return mu[e];var i=fu("Symbol")(e);return mu[e]=i,bu[i]=e,i}});var wu=ka,Au=Kr,ku=br,Eu=Ar,Cu=du,xu=Ur("symbol-to-string-registry");wu({target:"Symbol",stat:!0,forced:!Cu},{keyFor:function(t){if(!ku(t))throw new TypeError(Eu(t)+" is not a symbol");if(Au(xu,t))return xu[t]}});var Iu=ho([].slice),Su=Ba,Mu=Ao,Ou=po,Du=Yl,Ru=ho([].push),Bu=ka,zu=tr,Pu=oo,Fu=Io,Tu=ho,Nu=_n,ju=Ao,Lu=br,Uu=Iu,Qu=function(t){if(Mu(t))return t;if(Su(t)){for(var e=t.length,i=[],n=0;n=e.length)return t.target=void 0,wp(void 0,!0);switch(t.kind){case"keys":return wp(i,!1);case"values":return wp(e[i],!1)}return wp([i,e[i]],!1)}),"values"),yp.Arguments=yp.Array;var Cp={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0},xp=Xn,Ip=il,Sp=ca,Mp=ff,Op=ss("toStringTag");for(var Dp in Cp){var Rp=xp[Dp],Bp=Rp&&Rp.prototype;Bp&&Ip(Bp)!==Op&&Sp(Bp,Op,Dp),Mp[Dp]=Mp.Array}var zp=uf,Pp=ss,Fp=Gs.f,Tp=Pp("metadata"),Np=Function.prototype;void 0===Np[Tp]&&Fp(Np,Tp,{value:null}),gc("asyncDispose"),gc("dispose"),gc("metadata");var jp=zp,Lp=ho,Up=tr("Symbol"),Qp=Up.keyFor,Hp=Lp(Up.prototype.valueOf),Vp=Up.isRegisteredSymbol||function(t){try{return void 0!==Qp(Hp(t))}catch(t){return!1}};ka({target:"Symbol",stat:!0},{isRegisteredSymbol:Vp});for(var Wp=Ur,Gp=tr,Kp=ho,qp=br,Yp=ss,Zp=Gp("Symbol"),Jp=Zp.isWellKnownSymbol,Xp=Gp("Object","getOwnPropertyNames"),_p=Kp(Zp.prototype.valueOf),$p=Wp("wks"),tv=0,ev=Xp(Zp),iv=ev.length;tv=a?t?"":void 0:(n=uv(r,s))<55296||n>56319||s+1===a||(o=uv(r,s+1))<56320||o>57343?t?dv(r,s):n:t?fv(r,s,s+2):o-56320+(n-55296<<10)+65536}},vv={codeAt:pv(!1),charAt:pv(!0)}.charAt,gv=Yl,yv=Kc,mv=pp,bv=vp,wv="String Iterator",Av=yv.set,kv=yv.getterFor(wv);mv(String,"String",(function(t){Av(this,{type:wv,string:gv(t),index:0})}),(function(){var t,e=kv(this),i=e.string,n=e.index;return n>=i.length?bv(void 0,!0):(t=vv(i,n),e.index+=t.length,bv(t,!1))}));var Ev=ac.f("iterator"),Cv=Ev,xv=Yn(Cv);function Iv(t){return Iv="function"==typeof sv&&"symbol"==typeof xv?function(t){return typeof t}:function(t){return t&&"function"==typeof sv&&t.constructor===sv&&t!==sv.prototype?"symbol":typeof t},Iv(t)}var Sv=Yn(ac.f("toPrimitive"));function Mv(t){var e=function(t,e){if("object"!==Iv(t)||null===t)return t;var i=t[Sv];if(void 0!==i){var n=i.call(t,e||"default");if("object"!==Iv(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(t,"string");return"symbol"===Iv(e)?e:String(e)}function Ov(t,e){for(var i=0;i=0:a>l;l+=h)l in s&&(o=i(o,s[l],l,r));return o}},sg={left:rg(!1),right:rg(!0)},ag=_n,lg=function(t,e){var i=[][t];return!!i&&ag((function(){i.call(null,e||function(){return 1},1)}))},hg="process"===po(Xn.process),cg=sg.left;ka({target:"Array",proto:!0,forced:!hg&&hr>79&&hr<83||!lg("reduce")},{reduce:function(t){var e=arguments.length;return cg(this,t,e,e>1?arguments[1]:void 0)}});var dg=Kv("Array","reduce"),ug=er,fg=dg,pg=Array.prototype,vg=function(t){var e=t.reduce;return t===pg||ug(pg,t)&&e===pg.reduce?fg:e},gg=Yn(vg),yg=td.filter;ka({target:"Array",proto:!0,forced:!Rl("filter")},{filter:function(t){return yg(this,t,arguments.length>1?arguments[1]:void 0)}});var mg=Kv("Array","filter"),bg=er,wg=mg,Ag=Array.prototype,kg=function(t){var e=t.filter;return t===Ag||bg(Ag,t)&&e===Ag.filter?wg:e},Eg=Yn(kg),Cg=td.map;ka({target:"Array",proto:!0,forced:!Rl("map")},{map:function(t){return Cg(this,t,arguments.length>1?arguments[1]:void 0)}});var xg=Kv("Array","map"),Ig=er,Sg=xg,Mg=Array.prototype,Og=function(t){var e=t.map;return t===Mg||Ig(Mg,t)&&e===Mg.map?Sg:e},Dg=Yn(Og),Rg=Ba,Bg=Qa,zg=Va,Pg=Ws,Fg=function(t,e,i,n,o,r,s,a){for(var l,h,c=o,d=0,u=!!s&&Pg(s,a);d0&&Rg(l)?(h=Bg(l),c=Fg(t,e,l,h,c,r-1)-1):(zg(c+1),t[c]=l),c++),d++;return c},Tg=Fg,Ng=xr,jg=Vr,Lg=Qa,Ug=Sl;ka({target:"Array",proto:!0},{flatMap:function(t){var e,i=jg(this),n=Lg(i);return Ng(t),(e=Ug(i,0)).length=Tg(e,i,i,n,0,1,t,arguments.length>1?arguments[1]:void 0),e}}),Kv("Array","flatMap");var Qg=Io,Hg=Js,Vg=Mr,Wg=function(t,e,i){var n,o;Hg(t);try{if(!(n=Vg(t,"return"))){if("throw"===e)throw i;return i}n=Qg(n,t)}catch(t){o=!0,n=t}if("throw"===e)throw i;if(o)throw n;return Hg(n),i},Gg=Js,Kg=Wg,qg=ff,Yg=ss("iterator"),Zg=Array.prototype,Jg=function(t){return void 0!==t&&(qg.Array===t||Zg[Yg]===t)},Xg=il,_g=Mr,$g=Lo,ty=ff,ey=ss("iterator"),iy=function(t){if(!$g(t))return _g(t,ey)||_g(t,"@@iterator")||ty[Xg(t)]},ny=Io,oy=xr,ry=Js,sy=Ar,ay=iy,ly=TypeError,hy=function(t,e){var i=arguments.length<2?ay(t):e;if(oy(i))return ry(ny(i,t));throw new ly(sy(t)+" is not iterable")},cy=Ws,dy=Io,uy=Vr,fy=function(t,e,i,n){try{return n?e(Gg(i)[0],i[1]):e(i)}catch(e){Kg(t,"throw",e)}},py=Jg,vy=wl,gy=Qa,yy=qa,my=hy,by=iy,wy=Array,Ay=ss("iterator"),ky=!1;try{var Ey=0,Cy={next:function(){return{done:!!Ey++}},return:function(){ky=!0}};Cy[Ay]=function(){return this},Array.from(Cy,(function(){throw 2}))}catch(t){}var xy=function(t,e){try{if(!e&&!ky)return!1}catch(t){return!1}var i=!1;try{var n={};n[Ay]=function(){return{next:function(){return{done:i=!0}}}},t(n)}catch(t){}return i},Iy=function(t){var e=uy(t),i=vy(this),n=arguments.length,o=n>1?arguments[1]:void 0,r=void 0!==o;r&&(o=cy(o,n>2?arguments[2]:void 0));var s,a,l,h,c,d,u=by(e),f=0;if(!u||this===wy&&py(u))for(s=gy(e),a=i?new this(s):wy(s);s>f;f++)d=r?o(e[f],f):e[f],yy(a,f,d);else for(c=(h=my(e,u)).next,a=i?new this:[];!(l=dy(c,h)).done;f++)d=r?fy(h,o,[l.value,f],!0):l.value,yy(a,f,d);return a.length=f,a};ka({target:"Array",stat:!0,forced:!xy((function(t){Array.from(t)}))},{from:Iy});var Sy=Zo.Array.from,My=Yn(Sy),Oy=iy,Dy=Yn(Oy),Ry=Yn(Oy);ka({target:"Array",stat:!0},{isArray:Ba});var By=Zo.Array.isArray,zy=Yn(By);var Py=Eo,Fy=Ba,Ty=TypeError,Ny=Object.getOwnPropertyDescriptor,jy=Py&&!function(){if(void 0!==this)return!0;try{Object.defineProperty([],"length",{writable:!1}).length=1}catch(t){return t instanceof TypeError}}()?function(t,e){if(Fy(t)&&!Ny(t,"length").writable)throw new Ty("Cannot set read only .length");return t.length=e}:function(t,e){return t.length=e},Ly=Vr,Uy=Qa,Qy=jy,Hy=Va;ka({target:"Array",proto:!0,arity:1,forced:_n((function(){return 4294967297!==[].push.call({length:4294967296},1)}))||!function(){try{Object.defineProperty([],"length",{writable:!1}).push()}catch(t){return t instanceof TypeError}}()},{push:function(t){var e=Ly(this),i=Uy(e),n=arguments.length;Hy(i+n);for(var o=0;ot.length)&&(e=t.length);for(var i=0,n=new Array(e);i1?arguments[1]:void 0)};ka({target:"Array",proto:!0,forced:[].forEach!==Vm},{forEach:Vm});var Wm=Kv("Array","forEach"),Gm=il,Km=Kr,qm=er,Ym=Wm,Zm=Array.prototype,Jm={DOMTokenList:!0,NodeList:!0},Xm=function(t){var e=t.forEach;return t===Zm||qm(Zm,t)&&e===Zm.forEach||Km(Jm,Gm(t))?Ym:e},_m=Yn(Xm),$m=ka,tb=Ba,eb=ho([].reverse),ib=[1,2];$m({target:"Array",proto:!0,forced:String(ib)===String(ib.reverse())},{reverse:function(){return tb(this)&&(this.length=this.length),eb(this)}});var nb=Kv("Array","reverse"),ob=er,rb=nb,sb=Array.prototype,ab=function(t){var e=t.reverse;return t===sb||ob(sb,t)&&e===sb.reverse?rb:e},lb=ab,hb=Yn(lb),cb=Ar,db=TypeError,ub=function(t,e){if(!delete t[e])throw new db("Cannot delete property "+cb(e)+" of "+cb(t))},fb=ka,pb=Vr,vb=$l,gb=Na,yb=Qa,mb=jy,bb=Va,wb=Sl,Ab=qa,kb=ub,Eb=Rl("splice"),Cb=Math.max,xb=Math.min;fb({target:"Array",proto:!0,forced:!Eb},{splice:function(t,e){var i,n,o,r,s,a,l=pb(this),h=yb(l),c=vb(t,h),d=arguments.length;for(0===d?i=n=0:1===d?(i=0,n=h-c):(i=d-2,n=xb(Cb(gb(e),0),h-c)),bb(h+i-n),o=wb(l,n),r=0;rh-n+i;r--)kb(l,r-1)}else if(i>n)for(r=h-n;r>c;r--)a=r+i-1,(s=r+n-1)in l?l[a]=l[s]:kb(l,a);for(r=0;ro;)for(var a,l=Ub(arguments[o++]),h=r?Vb(Tb(l),r(l)):Tb(l),c=h.length,d=0;c>d;)a=h[d++],Bb&&!Pb(s,l,a)||(i[a]=l[a]);return i}:Qb,Gb=Wb;ka({target:"Object",stat:!0,arity:2,forced:Object.assign!==Gb},{assign:Gb});var Kb=Yn(Zo.Object.assign),qb=Vr,Yb=Mf,Zb=wf;ka({target:"Object",stat:!0,forced:_n((function(){Yb(1)})),sham:!Zb},{getPrototypeOf:function(t){return Yb(qb(t))}});var Jb=Zo.Object.getPrototypeOf;ka({target:"Object",stat:!0,sham:!Eo},{create:Uh});var Xb=Zo.Object,_b=function(t,e){return Xb.create(t,e)},$b=_b,tw=Yn($b),ew=Zo,iw=oo;ew.JSON||(ew.JSON={stringify:JSON.stringify});var nw=function(t,e,i){return iw(ew.JSON.stringify,null,arguments)},ow=Yn(nw),rw="function"==typeof Bun&&Bun&&"string"==typeof Bun.version,sw=TypeError,aw=function(t,e){if(ti,s=cw(n)?n:vw(n),a=r?fw(arguments,i):[],l=r?function(){hw(s,this,a)}:s;return e?t(l,o):t(l)}:t},mw=ka,bw=Xn,ww=yw(bw.setInterval,!0);mw({global:!0,bind:!0,forced:bw.setInterval!==ww},{setInterval:ww});var Aw=ka,kw=Xn,Ew=yw(kw.setTimeout,!0);Aw({global:!0,bind:!0,forced:kw.setTimeout!==Ew},{setTimeout:Ew});var Cw=Yn(Zo.setTimeout),xw={exports:{}};!function(t){function e(t){if(t)return function(t){return Object.assign(t,e.prototype),t._callbacks=new Map,t}(t);this._callbacks=new Map}e.prototype.on=function(t,e){const i=this._callbacks.get(t)??[];return i.push(e),this._callbacks.set(t,i),this},e.prototype.once=function(t,e){const i=(...n)=>{this.off(t,i),e.apply(this,n)};return i.fn=e,this.on(t,i),this},e.prototype.off=function(t,e){if(void 0===t&&void 0===e)return this._callbacks.clear(),this;if(void 0===e)return this._callbacks.delete(t),this;const i=this._callbacks.get(t);if(i){for(const[t,n]of i.entries())if(n===e||n.fn===e){i.splice(t,1);break}0===i.length?this._callbacks.delete(t):this._callbacks.set(t,i)}return this},e.prototype.emit=function(t,...e){const i=this._callbacks.get(t);if(i){const t=[...i];for(const i of t)i.apply(this,e)}return this},e.prototype.listeners=function(t){return this._callbacks.get(t)??[]},e.prototype.listenerCount=function(t){if(t)return this.listeners(t).length;let e=0;for(const t of this._callbacks.values())e+=t.length;return e},e.prototype.hasListeners=function(t){return this.listenerCount(t)>0},e.prototype.addEventListener=e.prototype.on,e.prototype.removeListener=e.prototype.off,e.prototype.removeEventListener=e.prototype.off,e.prototype.removeAllListeners=e.prototype.off,t.exports=e}(xw);var Iw,Sw=Yn(xw.exports); /*! Hammer.JS - v2.0.17-rc - 2019-12-16 * http://naver.github.io/egjs * * Forked By Naver egjs * Copyright (c) hammerjs * Licensed under the MIT license */ -function Oy(){return Oy=Object.assign||function(t){for(var e=1;e-1}var ym=function(){function t(t,e){this.manager=t,this.set(e)}var e=t.prototype;return e.set=function(t){t===Hy&&(t=this.compute()),Qy&&this.manager.element.style&&Yy[t]&&(this.manager.element.style[Ly]=t),this.actions=t.toLowerCase().trim()},e.update=function(){this.set(this.manager.options.touchAction)},e.compute=function(){var t=[];return pm(this.manager.recognizers,(function(e){vm(e.options.enable,[e])&&(t=t.concat(e.getTouchAction()))})),function(t){if(gm(t,Gy))return Gy;var e=gm(t,Ky),i=gm(t,qy);return e&&i?Gy:e||i?e?Ky:qy:gm(t,Wy)?Wy:Vy}(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=gm(o,Gy)&&!Yy[Gy],r=gm(o,qy)&&!Yy[qy],s=gm(o,Ky)&&!Yy[Ky];if(n){var a=1===t.pointers.length,l=t.distance<2,h=t.deltaTime<250;if(a&&l&&h)return}if(!s||!r)return n||r&&i&hm||s&&i&cm?this.preventSrc(e):void 0}},e.preventSrc=function(t){this.manager.session.prevented=!0,t.preventDefault()},t}();function mm(t,e){for(;t;){if(t===e)return!0;t=t.parentNode}return!1}function bm(t){var e=t.length;if(1===e)return{x:Ty(t[0].clientX),y:Ty(t[0].clientY)};for(var i=0,o=0,n=0;n=Ny(e)?t<0?rm:sm:e<0?am:lm}function Cm(t,e,i){return{x:e/t||0,y:i/t||0}}function xm(t,e){var i=t.session,o=e.pointers,n=o.length;i.firstInput||(i.firstInput=wm(e)),n>1&&!i.firstMultiple?i.firstMultiple=wm(e):1===n&&(i.firstMultiple=!1);var r=i.firstInput,s=i.firstMultiple,a=s?s.center:r.center,l=e.center=bm(o);e.timeStamp=jy(),e.deltaTime=e.timeStamp-r.timeStamp,e.angle=Em(a,l),e.distance=Am(a,l),function(t,e){var i=e.center,o=t.offsetDelta||{},n=t.prevDelta||{},r=t.prevInput||{};e.eventType!==em&&r.eventType!==im||(n=t.prevDelta={x:r.deltaX||0,y:r.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=km(e.deltaX,e.deltaY);var h,c,d=Cm(e.deltaTime,e.deltaX,e.deltaY);e.overallVelocityX=d.x,e.overallVelocityY=d.y,e.overallVelocity=Ny(d.x)>Ny(d.y)?d.x:d.y,e.scale=s?(h=s.pointers,Am((c=o)[0],c[1],fm)/Am(h[0],h[1],fm)):1,e.rotation=s?function(t,e){return Em(e[1],e[0],fm)+Em(t[1],t[0],fm)}(s.pointers,o):0,e.maxPointers=i.prevInput?e.pointers.length>i.prevInput.maxPointers?e.pointers.length:i.prevInput.maxPointers:e.pointers.length,function(t,e){var i,o,n,r,s=t.lastInterval||e,a=e.timeStamp-s.timeStamp;if(e.eventType!==om&&(a>tm||void 0===s.velocity)){var l=e.deltaX-s.deltaX,h=e.deltaY-s.deltaY,c=Cm(a,l,h);o=c.x,n=c.y,i=Ny(c.x)>Ny(c.y)?c.x:c.y,r=km(l,h),t.lastInterval=e}else i=s.velocity,o=s.velocityX,n=s.velocityY,r=s.direction;e.velocity=i,e.velocityX=o,e.velocityY=n,e.direction=r}(i,e);var u,f=t.element,p=e.srcEvent;mm(u=p.composedPath?p.composedPath()[0]:p.path?p.path[0]:p.target,f)&&(f=u),e.target=f}function Sm(t,e,i){var o=i.pointers.length,n=i.changedPointers.length,r=e&em&&o-n==0,s=e&(im|om)&&o-n==0;i.isFirst=!!r,i.isFinal=!!s,r&&(t.session={}),i.eventType=e,xm(t,i),t.emit("hammer.input",i),t.recognize(i),t.session.prevInput=i}function Im(t){return t.trim().split(/\s+/g)}function Mm(t,e,i){pm(Im(e),(function(e){t.addEventListener(e,i,!1)}))}function Om(t,e,i){pm(Im(e),(function(e){t.removeEventListener(e,i,!1)}))}function Dm(t){var e=t.ownerDocument||t;return e.defaultView||e.parentWindow||window}var Rm=function(){function t(t,e){var i=this;this.manager=t,this.callback=e,this.element=t.element,this.target=t.options.inputTarget,this.domHandler=function(e){vm(t.options.enable,[t])&&i.handler(e)},this.init()}var e=t.prototype;return e.handler=function(){},e.init=function(){this.evEl&&Mm(this.element,this.evEl,this.domHandler),this.evTarget&&Mm(this.target,this.evTarget,this.domHandler),this.evWin&&Mm(Dm(this.element),this.evWin,this.domHandler)},e.destroy=function(){this.evEl&&Om(this.element,this.evEl,this.domHandler),this.evTarget&&Om(this.target,this.evTarget,this.domHandler),this.evWin&&Om(Dm(this.element),this.evWin,this.domHandler)},t}();function Bm(t,e,i){if(t.indexOf&&!i)return t.indexOf(e);for(var o=0;oi[e]})):o.sort()),o}var Lm={touchstart:em,touchmove:2,touchend:im,touchcancel:om},Qm=function(t){function e(){var i;return e.prototype.evTarget="touchstart touchmove touchend touchcancel",(i=t.apply(this,arguments)||this).targetIds={},i}return Dy(e,t),e.prototype.handler=function(t){var e=Lm[t.type],i=Hm.call(this,t,e);i&&this.callback(this.manager,e,{pointers:i[0],changedPointers:i[1],pointerType:_y,srcEvent:t})},e}(Rm);function Hm(t,e){var i,o,n=jm(t.touches),r=this.targetIds;if(e&(2|em)&&1===n.length)return r[n[0].identifier]=!0,[n,n];var s=jm(t.changedTouches),a=[],l=this.target;if(o=n.filter((function(t){return mm(t.target,l)})),e===em)for(i=0;i-1&&o.splice(t,1)}),Gm)}}function qm(t,e){t&em?(this.primaryTouch=e.changedPointers[0].identifier,Km.call(this,e)):t&(im|om)&&Km.call(this,e)}function Ym(t){for(var e=t.srcEvent.clientX,i=t.srcEvent.clientY,o=0;o-1&&this.requireFail.splice(e,1),this},e.hasRequireFailures=function(){return this.requireFail.length>0},e.canRecognizeWith=function(t){return!!this.simultaneous[t.id]},e.emit=function(t){var e=this,i=this.state;function o(i){e.manager.emit(i,t)}i<8&&o(e.options.event+tb(i)),o(e.options.event),t.additionalEvent&&o(t.additionalEvent),i>=8&&o(e.options.event+tb(i))},e.tryEmit=function(t){if(this.canEmit())return this.emit(t);this.state=Xm},e.canEmit=function(){for(var t=0;te.threshold&&n&e.direction},i.attrTest=function(t){return ob.prototype.attrTest.call(this,t)&&(2&this.state||!(2&this.state)&&this.directionTest(t))},i.emit=function(e){this.pX=e.deltaX,this.pY=e.deltaY;var i=nb(e.direction);i&&(e.additionalEvent=this.options.event+i),t.prototype.emit.call(this,e)},e}(ob),sb=function(t){function e(e){return void 0===e&&(e={}),t.call(this,Oy({event:"swipe",threshold:10,velocity:.3,direction:hm|cm,pointers:1},e))||this}Dy(e,t);var i=e.prototype;return i.getTouchAction=function(){return rb.prototype.getTouchAction.call(this)},i.attrTest=function(e){var i,o=this.options.direction;return o&(hm|cm)?i=e.overallVelocity:o&hm?i=e.overallVelocityX:o&cm&&(i=e.overallVelocityY),t.prototype.attrTest.call(this,e)&&o&e.offsetDirection&&e.distance>this.options.threshold&&e.maxPointers===this.options.pointers&&Ny(i)>this.options.velocity&&e.eventType&im},i.emit=function(t){var e=nb(t.offsetDirection);e&&this.manager.emit(this.options.event+e,t),this.manager.emit(this.options.event,t)},e}(ob),ab=function(t){function e(e){return void 0===e&&(e={}),t.call(this,Oy({event:"pinch",threshold:0,pointers:2},e))||this}Dy(e,t);var i=e.prototype;return i.getTouchAction=function(){return[Gy]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.scale-1)>this.options.threshold||2&this.state)},i.emit=function(e){if(1!==e.scale){var i=e.scale<1?"in":"out";e.additionalEvent=this.options.event+i}t.prototype.emit.call(this,e)},e}(ob),lb=function(t){function e(e){return void 0===e&&(e={}),t.call(this,Oy({event:"rotate",threshold:0,pointers:2},e))||this}Dy(e,t);var i=e.prototype;return i.getTouchAction=function(){return[Gy]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.rotation)>this.options.threshold||2&this.state)},e}(ob),hb=function(t){function e(e){var i;return void 0===e&&(e={}),(i=t.call(this,Oy({event:"press",pointers:1,time:251,threshold:9},e))||this)._timer=null,i._input=null,i}Dy(e,t);var i=e.prototype;return i.getTouchAction=function(){return[Vy]},i.process=function(t){var e=this,i=this.options,o=t.pointers.length===i.pointers,n=t.distancei.time;if(this._input=t,!n||!o||t.eventType&(im|om)&&!r)this.reset();else if(t.eventType&em)this.reset(),this._timer=setTimeout((function(){e.state=8,e.tryEmit()}),i.time);else if(t.eventType&im)return 8;return Xm},i.reset=function(){clearTimeout(this._timer)},i.emit=function(t){8===this.state&&(t&&t.eventType&im?this.manager.emit(this.options.event+"up",t):(this._input.timeStamp=jy(),this.manager.emit(this.options.event,this._input)))},e}(eb),cb={domEvents:!1,touchAction:Hy,enable:!0,inputTarget:null,inputClass:null,cssProps:{userSelect:"none",touchSelect:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}},db=[[lb,{enable:!1}],[ab,{enable:!1},["rotate"]],[sb,{direction:hm}],[rb,{direction:hm},["swipe"]],[ib],[ib,{event:"doubletap",taps:2},["tap"]],[hb]];function ub(t,e){var i,o=t.element;o.style&&(pm(t.options.cssProps,(function(n,r){i=Uy(o.style,r),e?(t.oldCssProps[i]=o.style[i],o.style[i]=n):o.style[i]=t.oldCssProps[i]||""})),e||(t.oldCssProps={}))}var fb=function(){function t(t,e){var i,o=this;this.options=zy({},cb,e||{}),this.options.inputTarget=this.options.inputTarget||t,this.handlers={},this.session={},this.recognizers=[],this.oldCssProps={},this.element=t,this.input=new((i=this).options.inputClass||(Jy?Nm:Xy?Qm:Zy?Zm:Wm))(i,Sm),this.touchAction=new ym(this,this.options.touchAction),ub(this,!0),pm(this.options.recognizers,(function(t){var e=o.add(new t[0](t[1]));t[2]&&e.recognizeWith(t[2]),t[3]&&e.requireFailure(t[3])}),this)}var e=t.prototype;return e.set=function(t){return zy(this.options,t),t.touchAction&&this.touchAction.update(),t.inputTarget&&(this.input.destroy(),this.input.target=t.inputTarget,this.input.init()),this},e.stop=function(t){this.session.stopped=t?2:1},e.recognize=function(t){var e=this.session;if(!e.stopped){var i;this.touchAction.preventDefaults(t);var o=this.recognizers,n=e.curRecognizer;(!n||n&&8&n.state)&&(e.curRecognizer=null,n=null);for(var r=0;r\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",n=window.console&&(window.console.warn||window.console.log);return n&&n.call(window.console,o,i),t.apply(this,arguments)}}var mb=yb((function(t,e,i){for(var o=Object.keys(e),n=0;n=t.length?{done:!0}:{done:!1,value:t[o++]}},e:function(t){throw t},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function xb(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,o=new Array(e);i2)return Mb.apply(void 0,Dv(o=[Ib(e[0],e[1])]).call(o,kv(Rv(e).call(e,2))));var n=e[0],r=e[1];if(n instanceof Date&&r instanceof Date)return n.setTime(r.getTime()),n;var s,a=Cb(jv(r));try{for(a.s();!(s=a.n()).done;){var l=s.value;Object.prototype.propertyIsEnumerable.call(r,l)&&(r[l]===Sb?delete n[l]:null===n[l]||null===r[l]||"object"!=typeof n[l]||"object"!=typeof r[l]||Uv(n[l])||Uv(r[l])?n[l]=Ob(r[l]):n[l]=Mb(n[l],r[l]))}}catch(t){a.e(t)}finally{a.f()}return n}function Ob(t){return Uv(t)?Rf(t).call(t,(function(t){return Ob(t)})):"object"==typeof t&&null!==t?t instanceof Date?new Date(t.getTime()):Mb({},t):t}function Db(t){for(var e=0,i=Hv(t);e({set:t})}}()};function Bb(t){var e,i=this;this._cleanupQueue=[],this.active=!1,this._dom={container:t,overlay:document.createElement("div")},this._dom.overlay.classList.add("vis-overlay"),this._dom.container.appendChild(this._dom.overlay),this._cleanupQueue.push((function(){i._dom.overlay.parentNode.removeChild(i._dom.overlay)}));var o=Rb(this._dom.overlay);o.on("tap",$u(e=this._onTapOverlay).call(e,this)),this._cleanupQueue.push((function(){o.destroy()}));var n=["tap","doubletap","press","pinch","pan","panstart","panmove","panend"];$v(n).call(n,(function(t){o.on(t,(function(t){t.srcEvent.stopPropagation()}))})),document&&document.body&&(this._onClick=function(e){(function(t,e){for(;t;){if(t===e)return!0;t=t.parentNode}return!1})(e.target,t)||i.deactivate()},document.body.addEventListener("click",this._onClick),this._cleanupQueue.push((function(){document.body.removeEventListener("click",i._onClick)}))),this._escListener=function(t){("key"in t?"Escape"===t.key:27===t.keyCode)&&i.deactivate()}}My(Bb.prototype),Bb.current=null,Bb.prototype.destroy=function(){var t,e;this.deactivate();var i,o=Cb(cg(t=Bg(e=this._cleanupQueue).call(e,0)).call(t));try{for(o.s();!(i=o.n()).done;){(0,i.value)()}}catch(t){o.e(t)}finally{o.f()}},Bb.prototype.activate=function(){Bb.current&&Bb.current.deactivate(),Bb.current=this,this.active=!0,this._dom.overlay.style.display="none",this._dom.container.classList.add("vis-active"),this.emit("change"),this.emit("activate"),document.body.addEventListener("keydown",this._escListener)},Bb.prototype.deactivate=function(){this.active=!1,this._dom.overlay.style.display="block",this._dom.container.classList.remove("vis-active"),document.body.removeEventListener("keydown",this._escListener),this.emit("change"),this.emit("deactivate")},Bb.prototype._onTapOverlay=function(t){this.activate(),t.srcEvent.stopPropagation()};var zb=Ar,Pb=wi,Fb=TypeError,Tb=function(t){if(zb(t))return t;throw new Fb(Pb(t)+" is not a constructor")},Nb=kn,jb=ne,Ub=Hu,Lb=Tb,Qb=Jo,Hb=qe,Vb=Qs,Wb=_t,Gb=$e("Reflect","construct"),Kb=Object.prototype,qb=[].push,Yb=Wb((function(){function t(){}return!(Gb((function(){}),[],t)instanceof t)})),Zb=!Wb((function(){Gb((function(){}))})),Jb=Yb||Zb;Nb({target:"Reflect",stat:!0,forced:Jb,sham:Jb},{construct:function(t,e){Lb(t),Qb(e);var i=arguments.length<3?t:Lb(arguments[2]);if(Zb&&!Yb)return Gb(t,e,i);if(t===i){switch(e.length){case 0:return new t;case 1:return new t(e[0]);case 2:return new t(e[0],e[1]);case 3:return new t(e[0],e[1],e[2]);case 4:return new t(e[0],e[1],e[2],e[3])}var o=[null];return jb(qb,o,e),new(jb(Ub,t,o))}var n=i.prototype,r=Vb(Hb(n)?n:Kb),s=jb(t,r,e);return Hb(s)?s:r}});var Xb=Yt(Ye.Reflect.construct),_b=Yt(Ye.Object.getOwnPropertySymbols),$b={exports:{}},tw=kn,ew=_t,iw=We,ow=Ae.f,nw=Ee;tw({target:"Object",stat:!0,forced:!nw||ew((function(){ow(1)})),sham:!nw},{getOwnPropertyDescriptor:function(t,e){return ow(iw(t),e)}});var rw=Ye.Object,sw=$b.exports=function(t,e){return rw.getOwnPropertyDescriptor(t,e)};rw.getOwnPropertyDescriptor.sham&&(sw.sham=!0);var aw=Yt($b.exports),lw=Nv,hw=We,cw=Ae,dw=Yn;kn({target:"Object",stat:!0,sham:!Ee},{getOwnPropertyDescriptors:function(t){for(var e,i,o=hw(t),n=cw.f,r=lw(o),s={},a=0;r.length>a;)void 0!==(i=n(o,e=r[a++]))&&dw(s,e,i);return s}});var uw=Yt(Ye.Object.getOwnPropertyDescriptors),fw={exports:{}},pw=kn,vw=Ee,gw=Jr.f;pw({target:"Object",stat:!0,forced:Object.defineProperties!==gw,sham:!vw},{defineProperties:gw});var yw=Ye.Object,mw=fw.exports=function(t,e){return yw.defineProperties(t,e)};yw.defineProperties.sham&&(mw.sham=!0);var bw=Yt(fw.exports),ww=Yt(On);function Aw(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}var Ew=ty,kw=Yt(Ew);kn({target:"Object",stat:!0},{setPrototypeOf:$c});var Cw=Ye.Object.setPrototypeOf,xw=Yt(Cw),Sw=Yt(_u);function Iw(t,e){var i;return Iw=xw?Sw(i=xw).call(i):function(t,e){return t.__proto__=e,t},Iw(t,e)}var Mw=Xg,Ow=Yt(Mw);function Dw(t){var e;return Dw=xw?Sw(e=Ow).call(e):function(t){return t.__proto__||Ow(t)},Dw(t)}var Rw={exports:{}},Bw={exports:{}};!function(t){var e=ru,i=Cu;function o(n){return t.exports=o="function"==typeof e&&"symbol"==typeof i?function(t){return typeof t}:function(t){return t&&"function"==typeof e&&t.constructor===e&&t!==e.prototype?"symbol":typeof t},t.exports.__esModule=!0,t.exports.default=t.exports,o(n)}t.exports=o,t.exports.__esModule=!0,t.exports.default=t.exports}(Bw);var zw=Bw.exports,Pw=_v,Fw=Gi,Tw=Nv,Nw=Ae,jw=Go,Uw=qe,Lw=dn,Qw=Error,Hw=he("".replace),Vw=String(new Qw("zxcasd").stack),Ww=/\n\s*at [^:]*:[^\n]*/,Gw=Ww.test(Vw),Kw=Be,qw=!_t((function(){var t=new Error("a");return!("stack"in t)||(Object.defineProperty(t,"stack",Kw(1,7)),7!==t.stack)})),Yw=dn,Zw=function(t,e){if(Gw&&"string"==typeof t&&!Qw.prepareStackTrace)for(;e--;)t=Hw(t,Ww,"");return t},Jw=qw,Xw=Error.captureStackTrace,_w=Wo,$w=xe,tA=Jo,eA=wi,iA=Xf,oA=Hn,nA=ti,rA=cp,sA=op,aA=Gf,lA=TypeError,hA=function(t,e){this.stopped=t,this.result=e},cA=hA.prototype,dA=function(t,e,i){var o,n,r,s,a,l,h,c=i&&i.that,d=!(!i||!i.AS_ENTRIES),u=!(!i||!i.IS_RECORD),f=!(!i||!i.IS_ITERATOR),p=!(!i||!i.INTERRUPTED),v=_w(e,c),g=function(t){return o&&aA(o,"normal",t),new hA(!0,t)},y=function(t){return d?(tA(t),p?v(t[0],t[1],g):v(t[0],t[1])):p?v(t,g):v(t)};if(u)o=t.iterator;else if(f)o=t;else{if(!(n=sA(t)))throw new lA(eA(t)+" is not iterable");if(iA(n)){for(r=0,s=oA(t);s>r;r++)if((a=y(t[r]))&&nA(cA,a))return a;return new hA(!1)}o=rA(t,n)}for(l=u?t.next:o.next;!(h=$w(l,o)).done;){try{a=y(h.value)}catch(t){aA(o,"throw",t)}if("object"==typeof a&&a&&nA(cA,a))return a}return new hA(!1)},uA=Zr,fA=kn,pA=ti,vA=Mc,gA=$c,yA=function(t,e,i){for(var o=Tw(e),n=jw.f,r=Nw.f,s=0;s2&&AA(i,arguments[2]);var n=[];return kA(t,IA,{that:n}),bA(i,"errors",n),i};gA?gA(MA,SA):yA(MA,SA,{name:!0});var OA=MA.prototype=mA(SA.prototype,{constructor:wA(1,MA),message:wA(1,""),name:wA(1,"AggregateError")});fA({global:!0,constructor:!0,arity:2},{AggregateError:MA});var DA,RA,BA,zA,PA=$e,FA=aa,TA=Ee,NA=ro("species"),jA=function(t){var e=PA(t);TA&&e&&!e[NA]&&FA(e,NA,{configurable:!0,get:function(){return this}})},UA=ti,LA=TypeError,QA=function(t,e){if(UA(e,t))return t;throw new LA("Incorrect invocation")},HA=Jo,VA=Tb,WA=je,GA=ro("species"),KA=function(t,e){var i,o=HA(t).constructor;return void 0===o||WA(i=HA(o)[GA])?e:VA(i)},qA=/(?:ipad|iphone|ipod).*applewebkit/i.test(ei),YA=Xt,ZA=ne,JA=Wo,XA=we,_A=Gi,$A=_t,tE=Cs,eE=Ih,iE=wo,oE=ly,nE=qA,rE=cf,sE=YA.setImmediate,aE=YA.clearImmediate,lE=YA.process,hE=YA.Dispatch,cE=YA.Function,dE=YA.MessageChannel,uE=YA.String,fE=0,pE={},vE="onreadystatechange";$A((function(){DA=YA.location}));var gE=function(t){if(_A(pE,t)){var e=pE[t];delete pE[t],e()}},yE=function(t){return function(){gE(t)}},mE=function(t){gE(t.data)},bE=function(t){YA.postMessage(uE(t),DA.protocol+"//"+DA.host)};sE&&aE||(sE=function(t){oE(arguments.length,1);var e=XA(t)?t:cE(t),i=eE(arguments,1);return pE[++fE]=function(){ZA(e,void 0,i)},RA(fE),fE},aE=function(t){delete pE[t]},rE?RA=function(t){lE.nextTick(yE(t))}:hE&&hE.now?RA=function(t){hE.now(yE(t))}:dE&&!nE?(zA=(BA=new dE).port2,BA.port1.onmessage=mE,RA=JA(zA.postMessage,zA)):YA.addEventListener&&XA(YA.postMessage)&&!YA.importScripts&&DA&&"file:"!==DA.protocol&&!$A(bE)?(RA=bE,YA.addEventListener("message",mE,!1)):RA=vE in iE("script")?function(t){tE.appendChild(iE("script"))[vE]=function(){tE.removeChild(this),gE(t)}}:function(t){setTimeout(yE(t),0)});var wE={set:sE,clear:aE},AE=function(){this.head=null,this.tail=null};AE.prototype={add:function(t){var e={item:t,next:null},i=this.tail;i?i.next=e:this.head=e,this.tail=e},get:function(){var t=this.head;if(t)return null===(this.head=t.next)&&(this.tail=null),t.item}};var EE,kE,CE,xE,SE,IE=AE,ME=/ipad|iphone|ipod/i.test(ei)&&"undefined"!=typeof Pebble,OE=/web0s(?!.*chrome)/i.test(ei),DE=Xt,RE=Wo,BE=Ae.f,zE=wE.set,PE=IE,FE=qA,TE=ME,NE=OE,jE=cf,UE=DE.MutationObserver||DE.WebKitMutationObserver,LE=DE.document,QE=DE.process,HE=DE.Promise,VE=BE(DE,"queueMicrotask"),WE=VE&&VE.value;if(!WE){var GE=new PE,KE=function(){var t,e;for(jE&&(t=QE.domain)&&t.exit();e=GE.get();)try{e()}catch(t){throw GE.head&&EE(),t}t&&t.enter()};FE||jE||NE||!UE||!LE?!TE&&HE&&HE.resolve?((xE=HE.resolve(void 0)).constructor=HE,SE=RE(xE.then,xE),EE=function(){SE(KE)}):jE?EE=function(){QE.nextTick(KE)}:(zE=RE(zE,DE),EE=function(){zE(KE)}):(kE=!0,CE=LE.createTextNode(""),new UE(KE).observe(CE,{characterData:!0}),EE=function(){CE.data=kE=!kE}),WE=function(t){GE.head||EE(),GE.add(t)}}var qE=WE,YE=function(t){try{return{error:!1,value:t()}}catch(t){return{error:!0,value:t}}},ZE=Xt.Promise,JE="object"==typeof Deno&&Deno&&"object"==typeof Deno.version,XE=!JE&&!cf&&"object"==typeof window&&"object"==typeof document,_E=Xt,$E=ZE,tk=we,ek=Lo,ik=ar,ok=ro,nk=XE,rk=JE,sk=li,ak=$E&&$E.prototype,lk=ok("species"),hk=!1,ck=tk(_E.PromiseRejectionEvent),dk=ek("Promise",(function(){var t=ik($E),e=t!==String($E);if(!e&&66===sk)return!0;if(!ak.catch||!ak.finally)return!0;if(!sk||sk<51||!/native code/.test(t)){var i=new $E((function(t){t(1)})),o=function(t){t((function(){}),(function(){}))};if((i.constructor={})[lk]=o,!(hk=i.then((function(){}))instanceof o))return!0}return!e&&(nk||rk)&&!ck})),uk={CONSTRUCTOR:dk,REJECTION_EVENT:ck,SUBCLASSING:hk},fk={},pk=Ci,vk=TypeError,gk=function(t){var e,i;this.promise=new t((function(t,o){if(void 0!==e||void 0!==i)throw new vk("Bad Promise constructor");e=t,i=o})),this.resolve=pk(e),this.reject=pk(i)};fk.f=function(t){return new gk(t)};var yk,mk,bk=kn,wk=cf,Ak=Xt,Ek=xe,kk=ra,Ck=Ra,xk=jA,Sk=Ci,Ik=we,Mk=qe,Ok=QA,Dk=KA,Rk=wE.set,Bk=qE,zk=function(t,e){try{1===arguments.length?console.error(t):console.error(t,e)}catch(t){}},Pk=YE,Fk=IE,Tk=qa,Nk=ZE,jk=fk,Uk="Promise",Lk=uk.CONSTRUCTOR,Qk=uk.REJECTION_EVENT,Hk=Tk.getterFor(Uk),Vk=Tk.set,Wk=Nk&&Nk.prototype,Gk=Nk,Kk=Wk,qk=Ak.TypeError,Yk=Ak.document,Zk=Ak.process,Jk=jk.f,Xk=Jk,_k=!!(Yk&&Yk.createEvent&&Ak.dispatchEvent),$k="unhandledrejection",tC=function(t){var e;return!(!Mk(t)||!Ik(e=t.then))&&e},eC=function(t,e){var i,o,n,r=e.value,s=1===e.state,a=s?t.ok:t.fail,l=t.resolve,h=t.reject,c=t.domain;try{a?(s||(2===e.rejection&&sC(e),e.rejection=1),!0===a?i=r:(c&&c.enter(),i=a(r),c&&(c.exit(),n=!0)),i===t.promise?h(new qk("Promise-chain cycle")):(o=tC(i))?Ek(o,i,l,h):l(i)):h(r)}catch(t){c&&!n&&c.exit(),h(t)}},iC=function(t,e){t.notified||(t.notified=!0,Bk((function(){for(var i,o=t.reactions;i=o.get();)eC(i,t);t.notified=!1,e&&!t.rejection&&nC(t)})))},oC=function(t,e,i){var o,n;_k?((o=Yk.createEvent("Event")).promise=e,o.reason=i,o.initEvent(t,!1,!0),Ak.dispatchEvent(o)):o={promise:e,reason:i},!Qk&&(n=Ak["on"+t])?n(o):t===$k&&zk("Unhandled promise rejection",i)},nC=function(t){Ek(Rk,Ak,(function(){var e,i=t.facade,o=t.value;if(rC(t)&&(e=Pk((function(){wk?Zk.emit("unhandledRejection",o,i):oC($k,i,o)})),t.rejection=wk||rC(t)?2:1,e.error))throw e.value}))},rC=function(t){return 1!==t.rejection&&!t.parent},sC=function(t){Ek(Rk,Ak,(function(){var e=t.facade;wk?Zk.emit("rejectionHandled",e):oC("rejectionhandled",e,t.value)}))},aC=function(t,e,i){return function(o){t(e,o,i)}},lC=function(t,e,i){t.done||(t.done=!0,i&&(t=i),t.value=e,t.state=2,iC(t,!0))},hC=function(t,e,i){if(!t.done){t.done=!0,i&&(t=i);try{if(t.facade===e)throw new qk("Promise can't be resolved itself");var o=tC(e);o?Bk((function(){var i={done:!1};try{Ek(o,e,aC(hC,i,t),aC(lC,i,t))}catch(e){lC(i,e,t)}})):(t.value=e,t.state=1,iC(t,!1))}catch(e){lC({done:!1},e,t)}}};Lk&&(Kk=(Gk=function(t){Ok(this,Kk),Sk(t),Ek(yk,this);var e=Hk(this);try{t(aC(hC,e),aC(lC,e))}catch(t){lC(e,t)}}).prototype,(yk=function(t){Vk(this,{type:Uk,done:!1,notified:!1,parent:!1,reactions:new Fk,rejection:!1,state:0,value:void 0})}).prototype=kk(Kk,"then",(function(t,e){var i=Hk(this),o=Jk(Dk(this,Gk));return i.parent=!0,o.ok=!Ik(t)||t,o.fail=Ik(e)&&e,o.domain=wk?Zk.domain:void 0,0===i.state?i.reactions.add(o):Bk((function(){eC(o,i)})),o.promise})),mk=function(){var t=new yk,e=Hk(t);this.promise=t,this.resolve=aC(hC,e),this.reject=aC(lC,e)},jk.f=Jk=function(t){return t===Gk||undefined===t?new mk(t):Xk(t)}),bk({global:!0,constructor:!0,wrap:!0,forced:Lk},{Promise:Gk}),Ck(Gk,Uk,!1,!0),xk(Uk);var cC=ZE,dC=uk.CONSTRUCTOR||!Sp((function(t){cC.all(t).then(void 0,(function(){}))})),uC=xe,fC=Ci,pC=fk,vC=YE,gC=dA;kn({target:"Promise",stat:!0,forced:dC},{all:function(t){var e=this,i=pC.f(e),o=i.resolve,n=i.reject,r=vC((function(){var i=fC(e.resolve),r=[],s=0,a=1;gC(t,(function(t){var l=s++,h=!1;a++,uC(i,e,t).then((function(t){h||(h=!0,r[l]=t,--a||o(r))}),n)})),--a||o(r)}));return r.error&&n(r.value),i.promise}});var yC=kn,mC=uk.CONSTRUCTOR;ZE&&ZE.prototype,yC({target:"Promise",proto:!0,forced:mC,real:!0},{catch:function(t){return this.then(void 0,t)}});var bC=xe,wC=Ci,AC=fk,EC=YE,kC=dA;kn({target:"Promise",stat:!0,forced:dC},{race:function(t){var e=this,i=AC.f(e),o=i.reject,n=EC((function(){var n=wC(e.resolve);kC(t,(function(t){bC(n,e,t).then(i.resolve,o)}))}));return n.error&&o(n.value),i.promise}});var CC=xe,xC=fk;kn({target:"Promise",stat:!0,forced:uk.CONSTRUCTOR},{reject:function(t){var e=xC.f(this);return CC(e.reject,void 0,t),e.promise}});var SC=Jo,IC=qe,MC=fk,OC=function(t,e){if(SC(t),IC(e)&&e.constructor===t)return e;var i=MC.f(t);return(0,i.resolve)(e),i.promise},DC=kn,RC=ZE,BC=uk.CONSTRUCTOR,zC=OC,PC=$e("Promise"),FC=!BC;DC({target:"Promise",stat:!0,forced:true},{resolve:function(t){return zC(FC&&this===PC?RC:this,t)}});var TC=xe,NC=Ci,jC=fk,UC=YE,LC=dA;kn({target:"Promise",stat:!0,forced:dC},{allSettled:function(t){var e=this,i=jC.f(e),o=i.resolve,n=i.reject,r=UC((function(){var i=NC(e.resolve),n=[],r=0,s=1;LC(t,(function(t){var a=r++,l=!1;s++,TC(i,e,t).then((function(t){l||(l=!0,n[a]={status:"fulfilled",value:t},--s||o(n))}),(function(t){l||(l=!0,n[a]={status:"rejected",reason:t},--s||o(n))}))})),--s||o(n)}));return r.error&&n(r.value),i.promise}});var QC=xe,HC=Ci,VC=$e,WC=fk,GC=YE,KC=dA,qC="No one promise resolved";kn({target:"Promise",stat:!0,forced:dC},{any:function(t){var e=this,i=VC("AggregateError"),o=WC.f(e),n=o.resolve,r=o.reject,s=GC((function(){var o=HC(e.resolve),s=[],a=0,l=1,h=!1;KC(t,(function(t){var c=a++,d=!1;l++,QC(o,e,t).then((function(t){d||h||(h=!0,n(t))}),(function(t){d||h||(d=!0,s[c]=t,--l||r(new i(s,qC)))}))})),--l||r(new i(s,qC))}));return s.error&&r(s.value),o.promise}});var YC=kn,ZC=ZE,JC=_t,XC=$e,_C=we,$C=KA,tx=OC,ex=ZC&&ZC.prototype;YC({target:"Promise",proto:!0,real:!0,forced:!!ZC&&JC((function(){ex.finally.call({then:function(){}},(function(){}))}))},{finally:function(t){var e=$C(this,XC("Promise")),i=_C(t);return this.then(i?function(i){return tx(e,t()).then((function(){return i}))}:t,i?function(i){return tx(e,t()).then((function(){throw i}))}:t)}});var ix=Ye.Promise,ox=fk;kn({target:"Promise",stat:!0},{withResolvers:function(){var t=ox.f(this);return{promise:t.promise,resolve:t.resolve,reject:t.reject}}});var nx=ix,rx=fk,sx=YE;kn({target:"Promise",stat:!0,forced:!0},{try:function(t){var e=rx.f(this),i=sx(t);return(i.error?e.reject:e.resolve)(i.value),e.promise}});var ax=nx,lx=hg;!function(t){var e=zw.default,i=Dn,o=ru,n=Ew,r=Mw,s=Pw,a=Zp,l=Cw,h=ax,c=lx,d=yv;function u(){t.exports=u=function(){return p},t.exports.__esModule=!0,t.exports.default=t.exports;var f,p={},v=Object.prototype,g=v.hasOwnProperty,y=i||function(t,e,i){t[e]=i.value},m="function"==typeof o?o:{},b=m.iterator||"@@iterator",w=m.asyncIterator||"@@asyncIterator",A=m.toStringTag||"@@toStringTag";function E(t,e,o){return i(t,e,{value:o,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{E({},"")}catch(f){E=function(t,e,i){return t[e]=i}}function k(t,e,i,o){var r=e&&e.prototype instanceof D?e:D,s=n(r.prototype),a=new H(o||[]);return y(s,"_invoke",{value:j(t,i,a)}),s}function C(t,e,i){try{return{type:"normal",arg:t.call(e,i)}}catch(t){return{type:"throw",arg:t}}}p.wrap=k;var x="suspendedStart",S="suspendedYield",I="executing",M="completed",O={};function D(){}function R(){}function B(){}var z={};E(z,b,(function(){return this}));var P=r&&r(r(V([])));P&&P!==v&&g.call(P,b)&&(z=P);var F=B.prototype=D.prototype=n(z);function T(t){var e;s(e=["next","throw","return"]).call(e,(function(e){E(t,e,(function(t){return this._invoke(e,t)}))}))}function N(t,i){function o(n,r,s,a){var l=C(t[n],t,r);if("throw"!==l.type){var h=l.arg,c=h.value;return c&&"object"==e(c)&&g.call(c,"__await")?i.resolve(c.__await).then((function(t){o("next",t,s,a)}),(function(t){o("throw",t,s,a)})):i.resolve(c).then((function(t){h.value=t,s(h)}),(function(t){return o("throw",t,s,a)}))}a(l.arg)}var n;y(this,"_invoke",{value:function(t,e){function r(){return new i((function(i,n){o(t,e,i,n)}))}return n=n?n.then(r,r):r()}})}function j(t,e,i){var o=x;return function(n,r){if(o===I)throw new Error("Generator is already running");if(o===M){if("throw"===n)throw r;return{value:f,done:!0}}for(i.method=n,i.arg=r;;){var s=i.delegate;if(s){var a=U(s,i);if(a){if(a===O)continue;return a}}if("next"===i.method)i.sent=i._sent=i.arg;else if("throw"===i.method){if(o===x)throw o=M,i.arg;i.dispatchException(i.arg)}else"return"===i.method&&i.abrupt("return",i.arg);o=I;var l=C(t,e,i);if("normal"===l.type){if(o=i.done?M:S,l.arg===O)continue;return{value:l.arg,done:i.done}}"throw"===l.type&&(o=M,i.method="throw",i.arg=l.arg)}}}function U(t,e){var i=e.method,o=t.iterator[i];if(o===f)return e.delegate=null,"throw"===i&&t.iterator.return&&(e.method="return",e.arg=f,U(t,e),"throw"===e.method)||"return"!==i&&(e.method="throw",e.arg=new TypeError("The iterator does not provide a '"+i+"' method")),O;var n=C(o,t.iterator,e.arg);if("throw"===n.type)return e.method="throw",e.arg=n.arg,e.delegate=null,O;var r=n.arg;return r?r.done?(e[t.resultName]=r.value,e.next=t.nextLoc,"return"!==e.method&&(e.method="next",e.arg=f),e.delegate=null,O):r:(e.method="throw",e.arg=new TypeError("iterator result is not an object"),e.delegate=null,O)}function L(t){var e,i={tryLoc:t[0]};1 in t&&(i.catchLoc=t[1]),2 in t&&(i.finallyLoc=t[2],i.afterLoc=t[3]),a(e=this.tryEntries).call(e,i)}function Q(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function H(t){this.tryEntries=[{tryLoc:"root"}],s(t).call(t,L,this),this.reset(!0)}function V(t){if(t||""===t){var i=t[b];if(i)return i.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var o=-1,n=function e(){for(;++o=0;--o){var n=this.tryEntries[o],r=n.completion;if("root"===n.tryLoc)return i("end");if(n.tryLoc<=this.prev){var s=g.call(n,"catchLoc"),a=g.call(n,"finallyLoc");if(s&&a){if(this.prev=0;--i){var o=this.tryEntries[i];if(o.tryLoc<=this.prev&&g.call(o,"finallyLoc")&&this.prev=0;--e){var i=this.tryEntries[e];if(i.finallyLoc===t)return this.complete(i.completion,i.afterLoc),Q(i),O}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var i=this.tryEntries[e];if(i.tryLoc===t){var o=i.completion;if("throw"===o.type){var n=o.arg;Q(i)}return n}}throw new Error("illegal catch attempt")},delegateYield:function(t,e,i){return this.delegate={iterator:V(t),resultName:e,nextLoc:i},"next"===this.method&&(this.arg=f),O}},p}t.exports=u,t.exports.__esModule=!0,t.exports.default=t.exports}(Rw);var hx=(0,Rw.exports)(),cx=hx;try{regeneratorRuntime=hx}catch(t){"object"==typeof globalThis?globalThis.regeneratorRuntime=hx:Function("r","regeneratorRuntime = r")(hx)}var dx=Yt(cx),ux={exports:{}},fx=_t((function(){if("function"==typeof ArrayBuffer){var t=new ArrayBuffer(8);Object.isExtensible(t)&&Object.defineProperty(t,"a",{value:8})}})),px=_t,vx=qe,gx=fe,yx=fx,mx=Object.isExtensible,bx=px((function(){mx(1)}))||yx?function(t){return!!vx(t)&&((!yx||"ArrayBuffer"!==gx(t))&&(!mx||mx(t)))}:mx,wx=!_t((function(){return Object.isExtensible(Object.preventExtensions({}))})),Ax=kn,Ex=he,kx=ss,Cx=qe,xx=Gi,Sx=Go.f,Ix=Hs,Mx=Gs,Ox=bx,Dx=wx,Rx=!1,Bx=Ji("meta"),zx=0,Px=function(t){Sx(t,Bx,{value:{objectID:"O"+zx++,weakData:{}}})},Fx=ux.exports={enable:function(){Fx.enable=function(){},Rx=!0;var t=Ix.f,e=Ex([].splice),i={};i[Bx]=1,t(i).length&&(Ix.f=function(i){for(var o=t(i),n=0,r=o.length;n1?arguments[1]:void 0);e=e?e.next:i.first;)for(o(e.value,e.key,this);e&&e.removed;)e=e.previous},has:function(t){return!!l(this,t)}}),oS(r,i?{get:function(t){var e=l(this,t);return e&&e.value},set:function(t,e){return a(this,0===t?0:t,e)}}:{add:function(t){return a(this,t=0===t?0:t,t)}}),dS&&iS(r,"size",{configurable:!0,get:function(){return s(this).size}}),n},setStrong:function(t,e,i){var o=e+" Iterator",n=pS(e),r=pS(o);lS(t,e,(function(t,e){fS(this,{type:o,target:t,state:n(t),kind:e,last:void 0})}),(function(){for(var t=r(this),e=t.kind,i=t.last;i&&i.removed;)i=i.previous;return t.target&&(t.last=i=i?i.next:t.state.first)?hS("keys"===e?i.key:"values"===e?i.value:[i.key,i.value],!1):(t.target=void 0,hS(void 0,!0))}),i?"entries":"values",!i,!0),cS(e)}};$x("Map",(function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}}),vS);var gS=Yt(Ye.Map),yS=el.some;kn({target:"Array",proto:!0,forced:!hf("some")},{some:function(t){return yS(this,t,arguments.length>1?arguments[1]:void 0)}});var mS=Ku("Array","some"),bS=ti,wS=mS,AS=Array.prototype,ES=function(t){var e=t.some;return t===AS||bS(AS,t)&&e===AS.some?wS:e},kS=Yt(ES),CS=Ku("Array","keys"),xS=or,SS=Gi,IS=ti,MS=CS,OS=Array.prototype,DS={DOMTokenList:!0,NodeList:!0},RS=function(t){var e=t.keys;return t===OS||IS(OS,t)&&e===OS.keys||SS(DS,xS(t))?MS:e},BS=Yt(RS),zS=Xs,PS=Math.floor,FS=function(t,e){var i=t.length,o=PS(i/2);return i<8?TS(t,e):NS(t,FS(zS(t,0,o),e),FS(zS(t,o),e),e)},TS=function(t,e){for(var i,o,n=t.length,r=1;r0;)t[o]=t[--o];o!==r++&&(t[o]=i)}return t},NS=function(t,e,i,o){for(var n=e.length,r=i.length,s=0,a=0;s3)){if(eI)return!0;if(oI)return oI<603;var t,e,i,o,n="";for(t=65;t<76;t++){switch(e=String.fromCharCode(t),t){case 66:case 69:case 70:case 72:i=3;break;case 68:case 71:i=4;break;default:i=2}for(o=0;o<47;o++)nI.push({k:e+o,v:i})}for(nI.sort((function(t,e){return e.v-t.v})),o=0;oJS(i)?1:-1}}(t)),i=YS(n),o=0;othis.max&&this.flush(),null!=this._timeout&&(clearTimeout(this._timeout),this._timeout=null),this.queue.length>0&&"number"==typeof this.delay&&(this._timeout=xy((function(){t.flush()}),this.delay))}},{key:"flush",value:function(){var t,e;$v(t=Bg(e=this._queue).call(e,0)).call(t,(function(t){t.fn.apply(t.context||t.fn,t.args||[])}))}}],[{key:"extend",value:function(e,i){var o=new t(i);if(void 0!==e.flush)throw new Error("Target object already has a property flush");e.flush=function(){o.flush()};var n=[{name:"flush",original:void 0}];if(i&&i.replace)for(var r=0;r=t.length?{done:!0}:{done:!1,value:t[o++]}},e:function(t){throw t},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function YI(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,o=new Array(e);idx.mark((function e(){var o,n,r,s,a;return dx.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:o=qI(i),e.prev=1,o.s();case 3:if((n=o.n()).done){e.next=10;break}if(r=Ev(n.value,2),s=r[0],a=r[1],!t(a,s)){e.next=8;break}return e.next=8,[s,a];case 8:e.next=3;break;case 10:e.next=15;break;case 12:e.prev=12,e.t0=e.catch(1),o.e(e.t0);case 15:return e.prev=15,o.f(),e.finish(15);case 18:case"end":return e.stop()}}),e,null,[[1,12,15,18]])}))()})}},{key:"forEach",value:function(t){var e,i=qI(this._pairs);try{for(i.s();!(e=i.n()).done;){var o=Ev(e.value,2),n=o[0];t(o[1],n)}}catch(t){i.e(t)}finally{i.f()}}},{key:"map",value:function(t){var i=this._pairs;return new e({[SI]:()=>dx.mark((function e(){var o,n,r,s,a;return dx.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:o=qI(i),e.prev=1,o.s();case 3:if((n=o.n()).done){e.next=9;break}return r=Ev(n.value,2),s=r[0],a=r[1],e.next=7,[s,t(a,s)];case 7:e.next=3;break;case 9:e.next=14;break;case 11:e.prev=11,e.t0=e.catch(1),o.e(e.t0);case 14:return e.prev=14,o.f(),e.finish(14);case 17:case"end":return e.stop()}}),e,null,[[1,11,14,17]])}))()})}},{key:"max",value:function(t){var e=KI(this._pairs),i=e.next();if(i.done)return null;for(var o=i.value[1],n=t(i.value[1],i.value[0]);!(i=e.next()).done;){var r=Ev(i.value,2),s=r[0],a=r[1],l=t(a,s);l>n&&(n=l,o=a)}return o}},{key:"min",value:function(t){var e=KI(this._pairs),i=e.next();if(i.done)return null;for(var o=i.value[1],n=t(i.value[1],i.value[0]);!(i=e.next()).done;){var r=Ev(i.value,2),s=r[0],a=r[1],l=t(a,s);l=t.length?{done:!0}:{done:!1,value:t[o++]}},e:function(t){throw t},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function $I(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,o=new Array(e);i1?i-1:0),n=1;nn?1:on)&&(o=s,n=a)}}catch(t){r.e(t)}finally{r.f()}return o||null}},{key:"min",value:function(t){var e,i,o=null,n=null,r=_I(xI(e=this._data).call(e));try{for(r.s();!(i=r.n()).done;){var s=i.value,a=s[t];"number"==typeof a&&(null==n||adx.mark((function i(){var o,n,r,s;return dx.wrap((function(i){for(;;)switch(i.prev=i.next){case 0:o=_I(t),i.prev=1,o.s();case 3:if((n=o.n()).done){i.next=11;break}if(r=n.value,null==(s=e.get(r))){i.next=9;break}return i.next=9,[r,s];case 9:i.next=3;break;case 11:i.next=16;break;case 13:i.prev=13,i.t0=i.catch(1),o.e(i.t0);case 16:return i.prev=16,o.f(),i.finish(16);case 19:case"end":return i.stop()}}),i,null,[[1,13,16,19]])}))()})}var i;return new ZI({[SI]:$u(i=FI(this._data)).call(i,this._data)})}}]),i}(WI);function iM(t,e){return"object"==typeof e&&null!==e&&t===e.idProp&&"function"==typeof $v(e)&&"function"==typeof e.get&&"function"==typeof e.getDataSet&&"function"==typeof e.getIds&&"number"==typeof e.length&&"function"==typeof Rf(e)&&"function"==typeof e.off&&"function"==typeof e.on&&"function"==typeof e.stream&&function(t,e){return"object"==typeof e&&null!==e&&t===e.idProp&&"function"==typeof e.add&&"function"==typeof e.clear&&"function"==typeof e.distinct&&"function"==typeof $v(e)&&"function"==typeof e.get&&"function"==typeof e.getDataSet&&"function"==typeof e.getIds&&"number"==typeof e.length&&"function"==typeof Rf(e)&&"function"==typeof e.max&&"function"==typeof e.min&&"function"==typeof e.off&&"function"==typeof e.on&&"function"==typeof e.remove&&"function"==typeof e.setOptions&&"function"==typeof e.stream&&"function"==typeof e.update&&"function"==typeof e.updateOnly}(t,e.getDataSet())} +function Mw(){return Mw=Object.assign||function(t){for(var e=1;e-1}var gA=function(){function t(t,e){this.manager=t,this.set(e)}var e=t.prototype;return e.set=function(t){t===Qw&&(t=this.compute()),Uw&&this.manager.element.style&&qw[t]&&(this.manager.element.style[Lw]=t),this.actions=t.toLowerCase().trim()},e.update=function(){this.set(this.manager.options.touchAction)},e.compute=function(){var t=[];return fA(this.manager.recognizers,(function(e){pA(e.options.enable,[e])&&(t=t.concat(e.getTouchAction()))})),function(t){if(vA(t,Ww))return Ww;var e=vA(t,Gw),i=vA(t,Kw);return e&&i?Ww:e||i?e?Gw:Kw:vA(t,Vw)?Vw:Hw}(t.join(" "))},e.preventDefaults=function(t){var e=t.srcEvent,i=t.offsetDirection;if(this.manager.session.prevented)e.preventDefault();else{var n=this.actions,o=vA(n,Ww)&&!qw[Ww],r=vA(n,Kw)&&!qw[Kw],s=vA(n,Gw)&&!qw[Gw];if(o){var a=1===t.pointers.length,l=t.distance<2,h=t.deltaTime<250;if(a&&l&&h)return}if(!s||!r)return o||r&&i&lA||s&&i&hA?this.preventSrc(e):void 0}},e.preventSrc=function(t){this.manager.session.prevented=!0,t.preventDefault()},t}();function yA(t,e){for(;t;){if(t===e)return!0;t=t.parentNode}return!1}function mA(t){var e=t.length;if(1===e)return{x:Fw(t[0].clientX),y:Fw(t[0].clientY)};for(var i=0,n=0,o=0;o=Tw(e)?t<0?oA:rA:e<0?sA:aA}function EA(t,e,i){return{x:e/t||0,y:i/t||0}}function CA(t,e){var i=t.session,n=e.pointers,o=n.length;i.firstInput||(i.firstInput=bA(e)),o>1&&!i.firstMultiple?i.firstMultiple=bA(e):1===o&&(i.firstMultiple=!1);var r=i.firstInput,s=i.firstMultiple,a=s?s.center:r.center,l=e.center=mA(n);e.timeStamp=Nw(),e.deltaTime=e.timeStamp-r.timeStamp,e.angle=AA(a,l),e.distance=wA(a,l),function(t,e){var i=e.center,n=t.offsetDelta||{},o=t.prevDelta||{},r=t.prevInput||{};e.eventType!==tA&&r.eventType!==eA||(o=t.prevDelta={x:r.deltaX||0,y:r.deltaY||0},n=t.offsetDelta={x:i.x,y:i.y}),e.deltaX=o.x+(i.x-n.x),e.deltaY=o.y+(i.y-n.y)}(i,e),e.offsetDirection=kA(e.deltaX,e.deltaY);var h,c,d=EA(e.deltaTime,e.deltaX,e.deltaY);e.overallVelocityX=d.x,e.overallVelocityY=d.y,e.overallVelocity=Tw(d.x)>Tw(d.y)?d.x:d.y,e.scale=s?(h=s.pointers,wA((c=n)[0],c[1],uA)/wA(h[0],h[1],uA)):1,e.rotation=s?function(t,e){return AA(e[1],e[0],uA)+AA(t[1],t[0],uA)}(s.pointers,n):0,e.maxPointers=i.prevInput?e.pointers.length>i.prevInput.maxPointers?e.pointers.length:i.prevInput.maxPointers:e.pointers.length,function(t,e){var i,n,o,r,s=t.lastInterval||e,a=e.timeStamp-s.timeStamp;if(e.eventType!==iA&&(a>$w||void 0===s.velocity)){var l=e.deltaX-s.deltaX,h=e.deltaY-s.deltaY,c=EA(a,l,h);n=c.x,o=c.y,i=Tw(c.x)>Tw(c.y)?c.x:c.y,r=kA(l,h),t.lastInterval=e}else i=s.velocity,n=s.velocityX,o=s.velocityY,r=s.direction;e.velocity=i,e.velocityX=n,e.velocityY=o,e.direction=r}(i,e);var u,f=t.element,p=e.srcEvent;yA(u=p.composedPath?p.composedPath()[0]:p.path?p.path[0]:p.target,f)&&(f=u),e.target=f}function xA(t,e,i){var n=i.pointers.length,o=i.changedPointers.length,r=e&tA&&n-o==0,s=e&(eA|iA)&&n-o==0;i.isFirst=!!r,i.isFinal=!!s,r&&(t.session={}),i.eventType=e,CA(t,i),t.emit("hammer.input",i),t.recognize(i),t.session.prevInput=i}function IA(t){return t.trim().split(/\s+/g)}function SA(t,e,i){fA(IA(e),(function(e){t.addEventListener(e,i,!1)}))}function MA(t,e,i){fA(IA(e),(function(e){t.removeEventListener(e,i,!1)}))}function OA(t){var e=t.ownerDocument||t;return e.defaultView||e.parentWindow||window}var DA=function(){function t(t,e){var i=this;this.manager=t,this.callback=e,this.element=t.element,this.target=t.options.inputTarget,this.domHandler=function(e){pA(t.options.enable,[t])&&i.handler(e)},this.init()}var e=t.prototype;return e.handler=function(){},e.init=function(){this.evEl&&SA(this.element,this.evEl,this.domHandler),this.evTarget&&SA(this.target,this.evTarget,this.domHandler),this.evWin&&SA(OA(this.element),this.evWin,this.domHandler)},e.destroy=function(){this.evEl&&MA(this.element,this.evEl,this.domHandler),this.evTarget&&MA(this.target,this.evTarget,this.domHandler),this.evWin&&MA(OA(this.element),this.evWin,this.domHandler)},t}();function RA(t,e,i){if(t.indexOf&&!i)return t.indexOf(e);for(var n=0;ni[e]})):n.sort()),n}var LA={touchstart:tA,touchmove:2,touchend:eA,touchcancel:iA},UA=function(t){function e(){var i;return e.prototype.evTarget="touchstart touchmove touchend touchcancel",(i=t.apply(this,arguments)||this).targetIds={},i}return Ow(e,t),e.prototype.handler=function(t){var e=LA[t.type],i=QA.call(this,t,e);i&&this.callback(this.manager,e,{pointers:i[0],changedPointers:i[1],pointerType:Xw,srcEvent:t})},e}(DA);function QA(t,e){var i,n,o=NA(t.touches),r=this.targetIds;if(e&(2|tA)&&1===o.length)return r[o[0].identifier]=!0,[o,o];var s=NA(t.changedTouches),a=[],l=this.target;if(n=o.filter((function(t){return yA(t.target,l)})),e===tA)for(i=0;i-1&&n.splice(t,1)}),WA)}}function KA(t,e){t&tA?(this.primaryTouch=e.changedPointers[0].identifier,GA.call(this,e)):t&(eA|iA)&&GA.call(this,e)}function qA(t){for(var e=t.srcEvent.clientX,i=t.srcEvent.clientY,n=0;n-1&&this.requireFail.splice(e,1),this},e.hasRequireFailures=function(){return this.requireFail.length>0},e.canRecognizeWith=function(t){return!!this.simultaneous[t.id]},e.emit=function(t){var e=this,i=this.state;function n(i){e.manager.emit(i,t)}i<8&&n(e.options.event+$A(i)),n(e.options.event),t.additionalEvent&&n(t.additionalEvent),i>=8&&n(e.options.event+$A(i))},e.tryEmit=function(t){if(this.canEmit())return this.emit(t);this.state=JA},e.canEmit=function(){for(var t=0;te.threshold&&o&e.direction},i.attrTest=function(t){return ik.prototype.attrTest.call(this,t)&&(2&this.state||!(2&this.state)&&this.directionTest(t))},i.emit=function(e){this.pX=e.deltaX,this.pY=e.deltaY;var i=nk(e.direction);i&&(e.additionalEvent=this.options.event+i),t.prototype.emit.call(this,e)},e}(ik),rk=function(t){function e(e){return void 0===e&&(e={}),t.call(this,Mw({event:"swipe",threshold:10,velocity:.3,direction:lA|hA,pointers:1},e))||this}Ow(e,t);var i=e.prototype;return i.getTouchAction=function(){return ok.prototype.getTouchAction.call(this)},i.attrTest=function(e){var i,n=this.options.direction;return n&(lA|hA)?i=e.overallVelocity:n&lA?i=e.overallVelocityX:n&hA&&(i=e.overallVelocityY),t.prototype.attrTest.call(this,e)&&n&e.offsetDirection&&e.distance>this.options.threshold&&e.maxPointers===this.options.pointers&&Tw(i)>this.options.velocity&&e.eventType&eA},i.emit=function(t){var e=nk(t.offsetDirection);e&&this.manager.emit(this.options.event+e,t),this.manager.emit(this.options.event,t)},e}(ik),sk=function(t){function e(e){return void 0===e&&(e={}),t.call(this,Mw({event:"pinch",threshold:0,pointers:2},e))||this}Ow(e,t);var i=e.prototype;return i.getTouchAction=function(){return[Ww]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.scale-1)>this.options.threshold||2&this.state)},i.emit=function(e){if(1!==e.scale){var i=e.scale<1?"in":"out";e.additionalEvent=this.options.event+i}t.prototype.emit.call(this,e)},e}(ik),ak=function(t){function e(e){return void 0===e&&(e={}),t.call(this,Mw({event:"rotate",threshold:0,pointers:2},e))||this}Ow(e,t);var i=e.prototype;return i.getTouchAction=function(){return[Ww]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.rotation)>this.options.threshold||2&this.state)},e}(ik),lk=function(t){function e(e){var i;return void 0===e&&(e={}),(i=t.call(this,Mw({event:"press",pointers:1,time:251,threshold:9},e))||this)._timer=null,i._input=null,i}Ow(e,t);var i=e.prototype;return i.getTouchAction=function(){return[Hw]},i.process=function(t){var e=this,i=this.options,n=t.pointers.length===i.pointers,o=t.distancei.time;if(this._input=t,!o||!n||t.eventType&(eA|iA)&&!r)this.reset();else if(t.eventType&tA)this.reset(),this._timer=setTimeout((function(){e.state=8,e.tryEmit()}),i.time);else if(t.eventType&eA)return 8;return JA},i.reset=function(){clearTimeout(this._timer)},i.emit=function(t){8===this.state&&(t&&t.eventType&eA?this.manager.emit(this.options.event+"up",t):(this._input.timeStamp=Nw(),this.manager.emit(this.options.event,this._input)))},e}(tk),hk={domEvents:!1,touchAction:Qw,enable:!0,inputTarget:null,inputClass:null,cssProps:{userSelect:"none",touchSelect:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}},ck=[[ak,{enable:!1}],[sk,{enable:!1},["rotate"]],[rk,{direction:lA}],[ok,{direction:lA},["swipe"]],[ek],[ek,{event:"doubletap",taps:2},["tap"]],[lk]];function dk(t,e){var i,n=t.element;n.style&&(fA(t.options.cssProps,(function(o,r){i=jw(n.style,r),e?(t.oldCssProps[i]=n.style[i],n.style[i]=o):n.style[i]=t.oldCssProps[i]||""})),e||(t.oldCssProps={}))}var uk=function(){function t(t,e){var i,n=this;this.options=Bw({},hk,e||{}),this.options.inputTarget=this.options.inputTarget||t,this.handlers={},this.session={},this.recognizers=[],this.oldCssProps={},this.element=t,this.input=new((i=this).options.inputClass||(Zw?TA:Jw?UA:Yw?YA:VA))(i,xA),this.touchAction=new gA(this,this.options.touchAction),dk(this,!0),fA(this.options.recognizers,(function(t){var e=n.add(new t[0](t[1]));t[2]&&e.recognizeWith(t[2]),t[3]&&e.requireFailure(t[3])}),this)}var e=t.prototype;return e.set=function(t){return Bw(this.options,t),t.touchAction&&this.touchAction.update(),t.inputTarget&&(this.input.destroy(),this.input.target=t.inputTarget,this.input.init()),this},e.stop=function(t){this.session.stopped=t?2:1},e.recognize=function(t){var e=this.session;if(!e.stopped){var i;this.touchAction.preventDefaults(t);var n=this.recognizers,o=e.curRecognizer;(!o||o&&8&o.state)&&(e.curRecognizer=null,o=null);for(var r=0;r\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",o=window.console&&(window.console.warn||window.console.log);return o&&o.call(window.console,n,i),t.apply(this,arguments)}}var yk=gk((function(t,e,i){for(var n=Object.keys(e),o=0;o=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function Ck(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i2)return Sk.apply(void 0,Om(n=[Ik(e[0],e[1])]).call(n,km(Dm(e).call(e,2))));var o=e[0],r=e[1];if(o instanceof Date&&r instanceof Date)return o.setTime(r.getTime()),o;var s,a=Ek(Nm(r));try{for(a.s();!(s=a.n()).done;){var l=s.value;Object.prototype.propertyIsEnumerable.call(r,l)&&(r[l]===xk?delete o[l]:null===o[l]||null===r[l]||"object"!=typeof o[l]||"object"!=typeof r[l]||jm(o[l])||jm(r[l])?o[l]=Mk(r[l]):o[l]=Sk(o[l],r[l]))}}catch(t){a.e(t)}finally{a.f()}return o}function Mk(t){return jm(t)?Dg(t).call(t,(function(t){return Mk(t)})):"object"==typeof t&&null!==t?t instanceof Date?new Date(t.getTime()):Sk({},t):t}function Ok(t){for(var e=0,i=Qm(t);e({set:t})}}()};function Rk(t){var e,i=this;this._cleanupQueue=[],this.active=!1,this._dom={container:t,overlay:document.createElement("div")},this._dom.overlay.classList.add("vis-overlay"),this._dom.container.appendChild(this._dom.overlay),this._cleanupQueue.push((function(){i._dom.overlay.parentNode.removeChild(i._dom.overlay)}));var n=Dk(this._dom.overlay);n.on("tap",$v(e=this._onTapOverlay).call(e,this)),this._cleanupQueue.push((function(){n.destroy()}));var o=["tap","doubletap","press","pinch","pan","panstart","panmove","panend"];_m(o).call(o,(function(t){n.on(t,(function(t){t.srcEvent.stopPropagation()}))})),document&&document.body&&(this._onClick=function(e){(function(t,e){for(;t;){if(t===e)return!0;t=t.parentNode}return!1})(e.target,t)||i.deactivate()},document.body.addEventListener("click",this._onClick),this._cleanupQueue.push((function(){document.body.removeEventListener("click",i._onClick)}))),this._escListener=function(t){("key"in t?"Escape"===t.key:27===t.keyCode)&&i.deactivate()}}Sw(Rk.prototype),Rk.current=null,Rk.prototype.destroy=function(){var t,e;this.deactivate();var i,n=Ek(hb(t=Rb(e=this._cleanupQueue).call(e,0)).call(t));try{for(n.s();!(i=n.n()).done;){(0,i.value)()}}catch(t){n.e(t)}finally{n.f()}},Rk.prototype.activate=function(){Rk.current&&Rk.current.deactivate(),Rk.current=this,this.active=!0,this._dom.overlay.style.display="none",this._dom.container.classList.add("vis-active"),this.emit("change"),this.emit("activate"),document.body.addEventListener("keydown",this._escListener)},Rk.prototype.deactivate=function(){this.active=!1,this._dom.overlay.style.display="block",this._dom.container.classList.remove("vis-active"),document.body.removeEventListener("keydown",this._escListener),this.emit("change"),this.emit("deactivate")},Rk.prototype._onTapOverlay=function(t){this.activate(),t.srcEvent.stopPropagation()};var Bk=wl,zk=Ar,Pk=TypeError,Fk=function(t){if(Bk(t))return t;throw new Pk(zk(t)+" is not a constructor")},Tk=ka,Nk=oo,jk=Hv,Lk=Fk,Uk=Js,Qk=Yo,Hk=Uh,Vk=_n,Wk=tr("Reflect","construct"),Gk=Object.prototype,Kk=[].push,qk=Vk((function(){function t(){}return!(Wk((function(){}),[],t)instanceof t)})),Yk=!Vk((function(){Wk((function(){}))})),Zk=qk||Yk;Tk({target:"Reflect",stat:!0,forced:Zk,sham:Zk},{construct:function(t,e){Lk(t),Uk(e);var i=arguments.length<3?t:Lk(arguments[2]);if(Yk&&!qk)return Wk(t,e,i);if(t===i){switch(e.length){case 0:return new t;case 1:return new t(e[0]);case 2:return new t(e[0],e[1]);case 3:return new t(e[0],e[1],e[2]);case 4:return new t(e[0],e[1],e[2],e[3])}var n=[null];return Nk(Kk,n,e),new(Nk(jk,t,n))}var o=i.prototype,r=Hk(Qk(o)?o:Gk),s=Nk(t,r,e);return Qk(s)?s:r}});var Jk=Yn(Zo.Reflect.construct),Xk=Yn(Zo.Object.getOwnPropertySymbols),_k={exports:{}},$k=ka,tE=_n,eE=Go,iE=ko.f,nE=Eo;$k({target:"Object",stat:!0,forced:!nE||tE((function(){iE(1)})),sham:!nE},{getOwnPropertyDescriptor:function(t,e){return iE(eE(t),e)}});var oE=Zo.Object,rE=_k.exports=function(t,e){return oE.getOwnPropertyDescriptor(t,e)};oE.getOwnPropertyDescriptor.sham&&(rE.sham=!0);var sE=Yn(_k.exports),aE=Tm,lE=Go,hE=ko,cE=qa;ka({target:"Object",stat:!0,sham:!Eo},{getOwnPropertyDescriptors:function(t){for(var e,i,n=lE(t),o=hE.f,r=aE(n),s={},a=0;r.length>a;)void 0!==(i=o(n,e=r[a++]))&&cE(s,e,i);return s}});var dE=Yn(Zo.Object.getOwnPropertyDescriptors),uE={exports:{}},fE=ka,pE=Eo,vE=Zl.f;fE({target:"Object",stat:!0,forced:Object.defineProperties!==vE,sham:!pE},{defineProperties:vE});var gE=Zo.Object,yE=uE.exports=function(t,e){return gE.defineProperties(t,e)};gE.defineProperties.sham&&(yE.sham=!0);var mE=Yn(uE.exports),bE=Yn(Ma);function wE(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}var AE=$b,kE=Yn(AE);ka({target:"Object",stat:!0},{setPrototypeOf:$f});var EE=Zo.Object.setPrototypeOf,CE=Yn(EE),xE=Yn(_v);function IE(t,e){var i;return IE=CE?xE(i=CE).call(i):function(t,e){return t.__proto__=e,t},IE(t,e)}var SE=Jb,ME=Yn(SE);function OE(t){var e;return OE=CE?xE(e=ME).call(e):function(t){return t.__proto__||ME(t)},OE(t)}var DE={exports:{}},RE={exports:{}};!function(t){var e=rv,i=Cv;function n(o){return t.exports=n="function"==typeof e&&"symbol"==typeof i?function(t){return typeof t}:function(t){return t&&"function"==typeof e&&t.constructor===e&&t!==e.prototype?"symbol":typeof t},t.exports.__esModule=!0,t.exports.default=t.exports,n(o)}t.exports=n,t.exports.__esModule=!0,t.exports.default=t.exports}(RE);var BE=RE.exports,zE=Xm,PE=Kr,FE=Tm,TE=ko,NE=Gs,jE=Yo,LE=ca,UE=Error,QE=ho("".replace),HE=String(new UE("zxcasd").stack),VE=/\n\s*at [^:]*:[^\n]*/,WE=VE.test(HE),GE=zo,KE=!_n((function(){var t=new Error("a");return!("stack"in t)||(Object.defineProperty(t,"stack",GE(1,7)),7!==t.stack)})),qE=ca,YE=function(t,e){if(WE&&"string"==typeof t&&!UE.prepareStackTrace)for(;e--;)t=QE(t,VE,"");return t},ZE=KE,JE=Error.captureStackTrace,XE=Ws,_E=Io,$E=Js,tC=Ar,eC=Jg,iC=Qa,nC=er,oC=hy,rC=iy,sC=Wg,aC=TypeError,lC=function(t,e){this.stopped=t,this.result=e},hC=lC.prototype,cC=function(t,e,i){var n,o,r,s,a,l,h,c=i&&i.that,d=!(!i||!i.AS_ENTRIES),u=!(!i||!i.IS_RECORD),f=!(!i||!i.IS_ITERATOR),p=!(!i||!i.INTERRUPTED),v=XE(e,c),g=function(t){return n&&sC(n,"normal",t),new lC(!0,t)},y=function(t){return d?($E(t),p?v(t[0],t[1],g):v(t[0],t[1])):p?v(t,g):v(t)};if(u)n=t.iterator;else if(f)n=t;else{if(!(o=rC(t)))throw new aC(tC(t)+" is not iterable");if(eC(o)){for(r=0,s=iC(t);s>r;r++)if((a=y(t[r]))&&nC(hC,a))return a;return new lC(!1)}n=oC(t,o)}for(l=u?t.next:n.next;!(h=_E(l,n)).done;){try{a=y(h.value)}catch(t){sC(n,"throw",t)}if("object"==typeof a&&a&&nC(hC,a))return a}return new lC(!1)},dC=Yl,uC=ka,fC=er,pC=Mf,vC=$f,gC=function(t,e,i){for(var n=FE(e),o=NE.f,r=TE.f,s=0;s2&&wC(i,arguments[2]);var o=[];return kC(t,IC,{that:o}),mC(i,"errors",o),i};vC?vC(SC,xC):gC(SC,xC,{name:!0});var MC=SC.prototype=yC(xC.prototype,{constructor:bC(1,SC),message:bC(1,""),name:bC(1,"AggregateError")});uC({global:!0,constructor:!0,arity:2},{AggregateError:SC});var OC,DC,RC,BC,zC=tr,PC=sc,FC=Eo,TC=ss("species"),NC=function(t){var e=zC(t);FC&&e&&!e[TC]&&PC(e,TC,{configurable:!0,get:function(){return this}})},jC=er,LC=TypeError,UC=function(t,e){if(jC(e,t))return t;throw new LC("Incorrect invocation")},QC=Js,HC=Fk,VC=Lo,WC=ss("species"),GC=function(t,e){var i,n=QC(t).constructor;return void 0===n||VC(i=QC(n)[WC])?e:HC(i)},KC=/(?:ipad|iphone|ipod).*applewebkit/i.test(ir),qC=Xn,YC=oo,ZC=Ws,JC=Ao,XC=Kr,_C=_n,$C=Eh,tx=Iu,ex=ws,ix=aw,nx=KC,ox=hg,rx=qC.setImmediate,sx=qC.clearImmediate,ax=qC.process,lx=qC.Dispatch,hx=qC.Function,cx=qC.MessageChannel,dx=qC.String,ux=0,fx={},px="onreadystatechange";_C((function(){OC=qC.location}));var vx=function(t){if(XC(fx,t)){var e=fx[t];delete fx[t],e()}},gx=function(t){return function(){vx(t)}},yx=function(t){vx(t.data)},mx=function(t){qC.postMessage(dx(t),OC.protocol+"//"+OC.host)};rx&&sx||(rx=function(t){ix(arguments.length,1);var e=JC(t)?t:hx(t),i=tx(arguments,1);return fx[++ux]=function(){YC(e,void 0,i)},DC(ux),ux},sx=function(t){delete fx[t]},ox?DC=function(t){ax.nextTick(gx(t))}:lx&&lx.now?DC=function(t){lx.now(gx(t))}:cx&&!nx?(BC=(RC=new cx).port2,RC.port1.onmessage=yx,DC=ZC(BC.postMessage,BC)):qC.addEventListener&&JC(qC.postMessage)&&!qC.importScripts&&OC&&"file:"!==OC.protocol&&!_C(mx)?(DC=mx,qC.addEventListener("message",yx,!1)):DC=px in ex("script")?function(t){$C.appendChild(ex("script"))[px]=function(){$C.removeChild(this),vx(t)}}:function(t){setTimeout(gx(t),0)});var bx={set:rx,clear:sx},wx=function(){this.head=null,this.tail=null};wx.prototype={add:function(t){var e={item:t,next:null},i=this.tail;i?i.next=e:this.head=e,this.tail=e},get:function(){var t=this.head;if(t)return null===(this.head=t.next)&&(this.tail=null),t.item}};var Ax,kx,Ex,Cx,xx,Ix=wx,Sx=/ipad|iphone|ipod/i.test(ir)&&"undefined"!=typeof Pebble,Mx=/web0s(?!.*chrome)/i.test(ir),Ox=Xn,Dx=Ws,Rx=ko.f,Bx=bx.set,zx=Ix,Px=KC,Fx=Sx,Tx=Mx,Nx=hg,jx=Ox.MutationObserver||Ox.WebKitMutationObserver,Lx=Ox.document,Ux=Ox.process,Qx=Ox.Promise,Hx=Rx(Ox,"queueMicrotask"),Vx=Hx&&Hx.value;if(!Vx){var Wx=new zx,Gx=function(){var t,e;for(Nx&&(t=Ux.domain)&&t.exit();e=Wx.get();)try{e()}catch(t){throw Wx.head&&Ax(),t}t&&t.enter()};Px||Nx||Tx||!jx||!Lx?!Fx&&Qx&&Qx.resolve?((Cx=Qx.resolve(void 0)).constructor=Qx,xx=Dx(Cx.then,Cx),Ax=function(){xx(Gx)}):Nx?Ax=function(){Ux.nextTick(Gx)}:(Bx=Dx(Bx,Ox),Ax=function(){Bx(Gx)}):(kx=!0,Ex=Lx.createTextNode(""),new jx(Gx).observe(Ex,{characterData:!0}),Ax=function(){Ex.data=kx=!kx}),Vx=function(t){Wx.head||Ax(),Wx.add(t)}}var Kx=Vx,qx=function(t){try{return{error:!1,value:t()}}catch(t){return{error:!0,value:t}}},Yx=Xn.Promise,Zx="object"==typeof Deno&&Deno&&"object"==typeof Deno.version,Jx=!Zx&&!hg&&"object"==typeof window&&"object"==typeof document,Xx=Xn,_x=Yx,$x=Ao,tI=Us,eI=sl,iI=ss,nI=Jx,oI=Zx,rI=hr,sI=_x&&_x.prototype,aI=iI("species"),lI=!1,hI=$x(Xx.PromiseRejectionEvent),cI=tI("Promise",(function(){var t=eI(_x),e=t!==String(_x);if(!e&&66===rI)return!0;if(!sI.catch||!sI.finally)return!0;if(!rI||rI<51||!/native code/.test(t)){var i=new _x((function(t){t(1)})),n=function(t){t((function(){}),(function(){}))};if((i.constructor={})[aI]=n,!(lI=i.then((function(){}))instanceof n))return!0}return!e&&(nI||oI)&&!hI})),dI={CONSTRUCTOR:cI,REJECTION_EVENT:hI,SUBCLASSING:lI},uI={},fI=xr,pI=TypeError,vI=function(t){var e,i;this.promise=new t((function(t,n){if(void 0!==e||void 0!==i)throw new pI("Bad Promise constructor");e=t,i=n})),this.resolve=fI(e),this.reject=fI(i)};uI.f=function(t){return new vI(t)};var gI,yI,mI=ka,bI=hg,wI=Xn,AI=Io,kI=oc,EI=Dc,CI=NC,xI=xr,II=Ao,SI=Yo,MI=UC,OI=GC,DI=bx.set,RI=Kx,BI=function(t,e){try{1===arguments.length?console.error(t):console.error(t,e)}catch(t){}},zI=qx,PI=Ix,FI=Kc,TI=Yx,NI=uI,jI="Promise",LI=dI.CONSTRUCTOR,UI=dI.REJECTION_EVENT,QI=FI.getterFor(jI),HI=FI.set,VI=TI&&TI.prototype,WI=TI,GI=VI,KI=wI.TypeError,qI=wI.document,YI=wI.process,ZI=NI.f,JI=ZI,XI=!!(qI&&qI.createEvent&&wI.dispatchEvent),_I="unhandledrejection",$I=function(t){var e;return!(!SI(t)||!II(e=t.then))&&e},tS=function(t,e){var i,n,o,r=e.value,s=1===e.state,a=s?t.ok:t.fail,l=t.resolve,h=t.reject,c=t.domain;try{a?(s||(2===e.rejection&&rS(e),e.rejection=1),!0===a?i=r:(c&&c.enter(),i=a(r),c&&(c.exit(),o=!0)),i===t.promise?h(new KI("Promise-chain cycle")):(n=$I(i))?AI(n,i,l,h):l(i)):h(r)}catch(t){c&&!o&&c.exit(),h(t)}},eS=function(t,e){t.notified||(t.notified=!0,RI((function(){for(var i,n=t.reactions;i=n.get();)tS(i,t);t.notified=!1,e&&!t.rejection&&nS(t)})))},iS=function(t,e,i){var n,o;XI?((n=qI.createEvent("Event")).promise=e,n.reason=i,n.initEvent(t,!1,!0),wI.dispatchEvent(n)):n={promise:e,reason:i},!UI&&(o=wI["on"+t])?o(n):t===_I&&BI("Unhandled promise rejection",i)},nS=function(t){AI(DI,wI,(function(){var e,i=t.facade,n=t.value;if(oS(t)&&(e=zI((function(){bI?YI.emit("unhandledRejection",n,i):iS(_I,i,n)})),t.rejection=bI||oS(t)?2:1,e.error))throw e.value}))},oS=function(t){return 1!==t.rejection&&!t.parent},rS=function(t){AI(DI,wI,(function(){var e=t.facade;bI?YI.emit("rejectionHandled",e):iS("rejectionhandled",e,t.value)}))},sS=function(t,e,i){return function(n){t(e,n,i)}},aS=function(t,e,i){t.done||(t.done=!0,i&&(t=i),t.value=e,t.state=2,eS(t,!0))},lS=function(t,e,i){if(!t.done){t.done=!0,i&&(t=i);try{if(t.facade===e)throw new KI("Promise can't be resolved itself");var n=$I(e);n?RI((function(){var i={done:!1};try{AI(n,e,sS(lS,i,t),sS(aS,i,t))}catch(e){aS(i,e,t)}})):(t.value=e,t.state=1,eS(t,!1))}catch(e){aS({done:!1},e,t)}}};LI&&(GI=(WI=function(t){MI(this,GI),xI(t),AI(gI,this);var e=QI(this);try{t(sS(lS,e),sS(aS,e))}catch(t){aS(e,t)}}).prototype,(gI=function(t){HI(this,{type:jI,done:!1,notified:!1,parent:!1,reactions:new PI,rejection:!1,state:0,value:void 0})}).prototype=kI(GI,"then",(function(t,e){var i=QI(this),n=ZI(OI(this,WI));return i.parent=!0,n.ok=!II(t)||t,n.fail=II(e)&&e,n.domain=bI?YI.domain:void 0,0===i.state?i.reactions.add(n):RI((function(){tS(n,i)})),n.promise})),yI=function(){var t=new gI,e=QI(t);this.promise=t,this.resolve=sS(lS,e),this.reject=sS(aS,e)},NI.f=ZI=function(t){return t===WI||undefined===t?new yI(t):JI(t)}),mI({global:!0,constructor:!0,wrap:!0,forced:LI},{Promise:WI}),EI(WI,jI,!1,!0),CI(jI);var hS=Yx,cS=dI.CONSTRUCTOR||!xy((function(t){hS.all(t).then(void 0,(function(){}))})),dS=Io,uS=xr,fS=uI,pS=qx,vS=cC;ka({target:"Promise",stat:!0,forced:cS},{all:function(t){var e=this,i=fS.f(e),n=i.resolve,o=i.reject,r=pS((function(){var i=uS(e.resolve),r=[],s=0,a=1;vS(t,(function(t){var l=s++,h=!1;a++,dS(i,e,t).then((function(t){h||(h=!0,r[l]=t,--a||n(r))}),o)})),--a||n(r)}));return r.error&&o(r.value),i.promise}});var gS=ka,yS=dI.CONSTRUCTOR;Yx&&Yx.prototype,gS({target:"Promise",proto:!0,forced:yS,real:!0},{catch:function(t){return this.then(void 0,t)}});var mS=Io,bS=xr,wS=uI,AS=qx,kS=cC;ka({target:"Promise",stat:!0,forced:cS},{race:function(t){var e=this,i=wS.f(e),n=i.reject,o=AS((function(){var o=bS(e.resolve);kS(t,(function(t){mS(o,e,t).then(i.resolve,n)}))}));return o.error&&n(o.value),i.promise}});var ES=Io,CS=uI;ka({target:"Promise",stat:!0,forced:dI.CONSTRUCTOR},{reject:function(t){var e=CS.f(this);return ES(e.reject,void 0,t),e.promise}});var xS=Js,IS=Yo,SS=uI,MS=function(t,e){if(xS(t),IS(e)&&e.constructor===t)return e;var i=SS.f(t);return(0,i.resolve)(e),i.promise},OS=ka,DS=Yx,RS=dI.CONSTRUCTOR,BS=MS,zS=tr("Promise"),PS=!RS;OS({target:"Promise",stat:!0,forced:true},{resolve:function(t){return BS(PS&&this===zS?DS:this,t)}});var FS=Io,TS=xr,NS=uI,jS=qx,LS=cC;ka({target:"Promise",stat:!0,forced:cS},{allSettled:function(t){var e=this,i=NS.f(e),n=i.resolve,o=i.reject,r=jS((function(){var i=TS(e.resolve),o=[],r=0,s=1;LS(t,(function(t){var a=r++,l=!1;s++,FS(i,e,t).then((function(t){l||(l=!0,o[a]={status:"fulfilled",value:t},--s||n(o))}),(function(t){l||(l=!0,o[a]={status:"rejected",reason:t},--s||n(o))}))})),--s||n(o)}));return r.error&&o(r.value),i.promise}});var US=Io,QS=xr,HS=tr,VS=uI,WS=qx,GS=cC,KS="No one promise resolved";ka({target:"Promise",stat:!0,forced:cS},{any:function(t){var e=this,i=HS("AggregateError"),n=VS.f(e),o=n.resolve,r=n.reject,s=WS((function(){var n=QS(e.resolve),s=[],a=0,l=1,h=!1;GS(t,(function(t){var c=a++,d=!1;l++,US(n,e,t).then((function(t){d||h||(h=!0,o(t))}),(function(t){d||h||(d=!0,s[c]=t,--l||r(new i(s,KS)))}))})),--l||r(new i(s,KS))}));return s.error&&r(s.value),n.promise}});var qS=ka,YS=Yx,ZS=_n,JS=tr,XS=Ao,_S=GC,$S=MS,tM=YS&&YS.prototype;qS({target:"Promise",proto:!0,real:!0,forced:!!YS&&ZS((function(){tM.finally.call({then:function(){}},(function(){}))}))},{finally:function(t){var e=_S(this,JS("Promise")),i=XS(t);return this.then(i?function(i){return $S(e,t()).then((function(){return i}))}:t,i?function(i){return $S(e,t()).then((function(){throw i}))}:t)}});var eM=Zo.Promise,iM=uI;ka({target:"Promise",stat:!0},{withResolvers:function(){var t=iM.f(this);return{promise:t.promise,resolve:t.resolve,reject:t.reject}}});var nM=eM,oM=uI,rM=qx;ka({target:"Promise",stat:!0,forced:!0},{try:function(t){var e=oM.f(this),i=rM(t);return(i.error?e.reject:e.resolve)(i.value),e.promise}});var sM=nM,aM=lb;!function(t){var e=BE.default,i=Oa,n=rv,o=AE,r=SE,s=zE,a=Yy,l=EE,h=sM,c=aM,d=gm;function u(){t.exports=u=function(){return p},t.exports.__esModule=!0,t.exports.default=t.exports;var f,p={},v=Object.prototype,g=v.hasOwnProperty,y=i||function(t,e,i){t[e]=i.value},m="function"==typeof n?n:{},b=m.iterator||"@@iterator",w=m.asyncIterator||"@@asyncIterator",A=m.toStringTag||"@@toStringTag";function k(t,e,n){return i(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{k({},"")}catch(f){k=function(t,e,i){return t[e]=i}}function E(t,e,i,n){var r=e&&e.prototype instanceof D?e:D,s=o(r.prototype),a=new H(n||[]);return y(s,"_invoke",{value:j(t,i,a)}),s}function C(t,e,i){try{return{type:"normal",arg:t.call(e,i)}}catch(t){return{type:"throw",arg:t}}}p.wrap=E;var x="suspendedStart",I="suspendedYield",S="executing",M="completed",O={};function D(){}function R(){}function B(){}var z={};k(z,b,(function(){return this}));var P=r&&r(r(V([])));P&&P!==v&&g.call(P,b)&&(z=P);var F=B.prototype=D.prototype=o(z);function T(t){var e;s(e=["next","throw","return"]).call(e,(function(e){k(t,e,(function(t){return this._invoke(e,t)}))}))}function N(t,i){function n(o,r,s,a){var l=C(t[o],t,r);if("throw"!==l.type){var h=l.arg,c=h.value;return c&&"object"==e(c)&&g.call(c,"__await")?i.resolve(c.__await).then((function(t){n("next",t,s,a)}),(function(t){n("throw",t,s,a)})):i.resolve(c).then((function(t){h.value=t,s(h)}),(function(t){return n("throw",t,s,a)}))}a(l.arg)}var o;y(this,"_invoke",{value:function(t,e){function r(){return new i((function(i,o){n(t,e,i,o)}))}return o=o?o.then(r,r):r()}})}function j(t,e,i){var n=x;return function(o,r){if(n===S)throw new Error("Generator is already running");if(n===M){if("throw"===o)throw r;return{value:f,done:!0}}for(i.method=o,i.arg=r;;){var s=i.delegate;if(s){var a=L(s,i);if(a){if(a===O)continue;return a}}if("next"===i.method)i.sent=i._sent=i.arg;else if("throw"===i.method){if(n===x)throw n=M,i.arg;i.dispatchException(i.arg)}else"return"===i.method&&i.abrupt("return",i.arg);n=S;var l=C(t,e,i);if("normal"===l.type){if(n=i.done?M:I,l.arg===O)continue;return{value:l.arg,done:i.done}}"throw"===l.type&&(n=M,i.method="throw",i.arg=l.arg)}}}function L(t,e){var i=e.method,n=t.iterator[i];if(n===f)return e.delegate=null,"throw"===i&&t.iterator.return&&(e.method="return",e.arg=f,L(t,e),"throw"===e.method)||"return"!==i&&(e.method="throw",e.arg=new TypeError("The iterator does not provide a '"+i+"' method")),O;var o=C(n,t.iterator,e.arg);if("throw"===o.type)return e.method="throw",e.arg=o.arg,e.delegate=null,O;var r=o.arg;return r?r.done?(e[t.resultName]=r.value,e.next=t.nextLoc,"return"!==e.method&&(e.method="next",e.arg=f),e.delegate=null,O):r:(e.method="throw",e.arg=new TypeError("iterator result is not an object"),e.delegate=null,O)}function U(t){var e,i={tryLoc:t[0]};1 in t&&(i.catchLoc=t[1]),2 in t&&(i.finallyLoc=t[2],i.afterLoc=t[3]),a(e=this.tryEntries).call(e,i)}function Q(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function H(t){this.tryEntries=[{tryLoc:"root"}],s(t).call(t,U,this),this.reset(!0)}function V(t){if(t||""===t){var i=t[b];if(i)return i.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var n=-1,o=function e(){for(;++n=0;--n){var o=this.tryEntries[n],r=o.completion;if("root"===o.tryLoc)return i("end");if(o.tryLoc<=this.prev){var s=g.call(o,"catchLoc"),a=g.call(o,"finallyLoc");if(s&&a){if(this.prev=0;--i){var n=this.tryEntries[i];if(n.tryLoc<=this.prev&&g.call(n,"finallyLoc")&&this.prev=0;--e){var i=this.tryEntries[e];if(i.finallyLoc===t)return this.complete(i.completion,i.afterLoc),Q(i),O}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var i=this.tryEntries[e];if(i.tryLoc===t){var n=i.completion;if("throw"===n.type){var o=n.arg;Q(i)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,e,i){return this.delegate={iterator:V(t),resultName:e,nextLoc:i},"next"===this.method&&(this.arg=f),O}},p}t.exports=u,t.exports.__esModule=!0,t.exports.default=t.exports}(DE);var lM=(0,DE.exports)(),hM=lM;try{regeneratorRuntime=lM}catch(t){"object"==typeof globalThis?globalThis.regeneratorRuntime=lM:Function("r","regeneratorRuntime = r")(lM)}var cM=Yn(hM),dM={exports:{}},uM=_n((function(){if("function"==typeof ArrayBuffer){var t=new ArrayBuffer(8);Object.isExtensible(t)&&Object.defineProperty(t,"a",{value:8})}})),fM=_n,pM=Yo,vM=po,gM=uM,yM=Object.isExtensible,mM=fM((function(){yM(1)}))||gM?function(t){return!!pM(t)&&((!gM||"ArrayBuffer"!==vM(t))&&(!yM||yM(t)))}:yM,bM=!_n((function(){return Object.isExtensible(Object.preventExtensions({}))})),wM=ka,AM=ho,kM=rh,EM=Yo,CM=Kr,xM=Gs.f,IM=Qh,SM=Wh,MM=mM,OM=bM,DM=!1,RM=Xr("meta"),BM=0,zM=function(t){xM(t,RM,{value:{objectID:"O"+BM++,weakData:{}}})},PM=dM.exports={enable:function(){PM.enable=function(){},DM=!0;var t=IM.f,e=AM([].splice),i={};i[RM]=1,t(i).length&&(IM.f=function(i){for(var n=t(i),o=0,r=n.length;o1?arguments[1]:void 0);e=e?e.next:i.first;)for(n(e.value,e.key,this);e&&e.removed;)e=e.previous},has:function(t){return!!l(this,t)}}),iO(r,i?{get:function(t){var e=l(this,t);return e&&e.value},set:function(t,e){return a(this,0===t?0:t,e)}}:{add:function(t){return a(this,t=0===t?0:t,t)}}),cO&&eO(r,"size",{configurable:!0,get:function(){return s(this).size}}),o},setStrong:function(t,e,i){var n=e+" Iterator",o=fO(e),r=fO(n);aO(t,e,(function(t,e){uO(this,{type:n,target:t,state:o(t),kind:e,last:void 0})}),(function(){for(var t=r(this),e=t.kind,i=t.last;i&&i.removed;)i=i.previous;return t.target&&(t.last=i=i?i.next:t.state.first)?lO("keys"===e?i.key:"values"===e?i.value:[i.key,i.value],!1):(t.target=void 0,lO(void 0,!0))}),i?"entries":"values",!i,!0),hO(e)}};_M("Map",(function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}}),pO);var vO=Yn(Zo.Map),gO=td.some;ka({target:"Array",proto:!0,forced:!lg("some")},{some:function(t){return gO(this,t,arguments.length>1?arguments[1]:void 0)}});var yO=Kv("Array","some"),mO=er,bO=yO,wO=Array.prototype,AO=function(t){var e=t.some;return t===wO||mO(wO,t)&&e===wO.some?bO:e},kO=Yn(AO),EO=Kv("Array","keys"),CO=il,xO=Kr,IO=er,SO=EO,MO=Array.prototype,OO={DOMTokenList:!0,NodeList:!0},DO=function(t){var e=t.keys;return t===MO||IO(MO,t)&&e===MO.keys||xO(OO,CO(t))?SO:e},RO=Yn(DO),BO=Jh,zO=Math.floor,PO=function(t,e){var i=t.length,n=zO(i/2);return i<8?FO(t,e):TO(t,PO(BO(t,0,n),e),PO(BO(t,n),e),e)},FO=function(t,e){for(var i,n,o=t.length,r=1;r0;)t[n]=t[--n];n!==r++&&(t[n]=i)}return t},TO=function(t,e,i,n){for(var o=e.length,r=i.length,s=0,a=0;s3)){if(tD)return!0;if(iD)return iD<603;var t,e,i,n,o="";for(t=65;t<76;t++){switch(e=String.fromCharCode(t),t){case 66:case 69:case 70:case 72:i=3;break;case 68:case 71:i=4;break;default:i=2}for(n=0;n<47;n++)nD.push({k:e+n,v:i})}for(nD.sort((function(t,e){return e.v-t.v})),n=0;nZO(i)?1:-1}}(t)),i=qO(o),n=0;nthis.max&&this.flush(),null!=this._timeout&&(clearTimeout(this._timeout),this._timeout=null),this.queue.length>0&&"number"==typeof this.delay&&(this._timeout=Cw((function(){t.flush()}),this.delay))}},{key:"flush",value:function(){var t,e;_m(t=Rb(e=this._queue).call(e,0)).call(t,(function(t){t.fn.apply(t.context||t.fn,t.args||[])}))}}],[{key:"extend",value:function(e,i){var n=new t(i);if(void 0!==e.flush)throw new Error("Target object already has a property flush");e.flush=function(){n.flush()};var o=[{name:"flush",original:void 0}];if(i&&i.replace)for(var r=0;r=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function qD(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);icM.mark((function e(){var n,o,r,s,a;return cM.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:n=KD(i),e.prev=1,n.s();case 3:if((o=n.n()).done){e.next=10;break}if(r=Am(o.value,2),s=r[0],a=r[1],!t(a,s)){e.next=8;break}return e.next=8,[s,a];case 8:e.next=3;break;case 10:e.next=15;break;case 12:e.prev=12,e.t0=e.catch(1),n.e(e.t0);case 15:return e.prev=15,n.f(),e.finish(15);case 18:case"end":return e.stop()}}),e,null,[[1,12,15,18]])}))()})}},{key:"forEach",value:function(t){var e,i=KD(this._pairs);try{for(i.s();!(e=i.n()).done;){var n=Am(e.value,2),o=n[0];t(n[1],o)}}catch(t){i.e(t)}finally{i.f()}}},{key:"map",value:function(t){var i=this._pairs;return new e({[xD]:()=>cM.mark((function e(){var n,o,r,s,a;return cM.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:n=KD(i),e.prev=1,n.s();case 3:if((o=n.n()).done){e.next=9;break}return r=Am(o.value,2),s=r[0],a=r[1],e.next=7,[s,t(a,s)];case 7:e.next=3;break;case 9:e.next=14;break;case 11:e.prev=11,e.t0=e.catch(1),n.e(e.t0);case 14:return e.prev=14,n.f(),e.finish(14);case 17:case"end":return e.stop()}}),e,null,[[1,11,14,17]])}))()})}},{key:"max",value:function(t){var e=GD(this._pairs),i=e.next();if(i.done)return null;for(var n=i.value[1],o=t(i.value[1],i.value[0]);!(i=e.next()).done;){var r=Am(i.value,2),s=r[0],a=r[1],l=t(a,s);l>o&&(o=l,n=a)}return n}},{key:"min",value:function(t){var e=GD(this._pairs),i=e.next();if(i.done)return null;for(var n=i.value[1],o=t(i.value[1],i.value[0]);!(i=e.next()).done;){var r=Am(i.value,2),s=r[0],a=r[1],l=t(a,s);l=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function _D(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i1?i-1:0),o=1;oo?1:no)&&(n=s,o=a)}}catch(t){r.e(t)}finally{r.f()}return n||null}},{key:"min",value:function(t){var e,i,n=null,o=null,r=XD(CD(e=this._data).call(e));try{for(r.s();!(i=r.n()).done;){var s=i.value,a=s[t];"number"==typeof a&&(null==o||acM.mark((function i(){var n,o,r,s;return cM.wrap((function(i){for(;;)switch(i.prev=i.next){case 0:n=XD(t),i.prev=1,n.s();case 3:if((o=n.n()).done){i.next=11;break}if(r=o.value,null==(s=e.get(r))){i.next=9;break}return i.next=9,[r,s];case 9:i.next=3;break;case 11:i.next=16;break;case 13:i.prev=13,i.t0=i.catch(1),n.e(i.t0);case 16:return i.prev=16,n.f(),i.finish(16);case 19:case"end":return i.stop()}}),i,null,[[1,13,16,19]])}))()})}var i;return new YD({[xD]:$v(i=PD(this._data)).call(i,this._data)})}}]),i}(VD);function eR(t,e){return"object"==typeof e&&null!==e&&t===e.idProp&&"function"==typeof _m(e)&&"function"==typeof e.get&&"function"==typeof e.getDataSet&&"function"==typeof e.getIds&&"number"==typeof e.length&&"function"==typeof Dg(e)&&"function"==typeof e.off&&"function"==typeof e.on&&"function"==typeof e.stream&&function(t,e){return"object"==typeof e&&null!==e&&t===e.idProp&&"function"==typeof e.add&&"function"==typeof e.clear&&"function"==typeof e.distinct&&"function"==typeof _m(e)&&"function"==typeof e.get&&"function"==typeof e.getDataSet&&"function"==typeof e.getIds&&"number"==typeof e.length&&"function"==typeof Dg(e)&&"function"==typeof e.max&&"function"==typeof e.min&&"function"==typeof e.off&&"function"==typeof e.on&&"function"==typeof e.remove&&"function"==typeof e.setOptions&&"function"==typeof e.stream&&"function"==typeof e.update&&"function"==typeof e.updateOnly}(t,e.getDataSet())} /** * vis-network * https://visjs.github.io/vis-network/ @@ -120,24 +121,24 @@ function Oy(){return Oy=Object.assign||function(t){for(var e=1;e0&&UM[0]<4?1:+(UM[0]+UM[1])),!LM&&uO&&(!(UM=uO.match(/Edge\/(\d+)/))||UM[1]>=74)&&(UM=uO.match(/Chrome\/(\d+)/))&&(LM=+UM[1]);var yO=LM,mO=yO,bO=aM,wO=sM.String,AO=!!Object.getOwnPropertySymbols&&!bO((function(){var t=Symbol("symbol detection");return!wO(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&mO&&mO<41})),EO=AO&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,kO=lO,CO=OM,xO=hO,SO=Object,IO=EO?function(t){return"symbol"==typeof t}:function(t){var e=kO("Symbol");return CO(e)&&xO(e.prototype,SO(t))},MO=String,OO=function(t){try{return MO(t)}catch(t){return"Object"}},DO=OM,RO=OO,BO=TypeError,zO=function(t){if(DO(t))return t;throw new BO(RO(t)+" is not a function")},PO=zO,FO=qM,TO=function(t,e){var i=t[e];return FO(i)?void 0:PO(i)},NO=PM,jO=OM,UO=iO,LO=TypeError,QO={exports:{}},HO=sM,VO=Object.defineProperty,WO=function(t,e){try{VO(HO,t,{value:e,configurable:!0,writable:!0})}catch(i){HO[t]=e}return e},GO="__core-js_shared__",KO=sM[GO]||WO(GO,{}),qO=KO;(QO.exports=function(t,e){return qO[t]||(qO[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.33.0",mode:"pure",copyright:"© 2014-2023 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.33.0/LICENSE",source:"https://github.com/zloirock/core-js"});var YO=QO.exports,ZO=JM,JO=Object,XO=function(t){return JO(ZO(t))},_O=XO,$O=mM({}.hasOwnProperty),tD=Object.hasOwn||function(t,e){return $O(_O(t),e)},eD=mM,iD=0,oD=Math.random(),nD=eD(1..toString),rD=function(t){return"Symbol("+(void 0===t?"":t)+")_"+nD(++iD+oD,36)},sD=YO,aD=tD,lD=rD,hD=AO,cD=EO,dD=sM.Symbol,uD=sD("wks"),fD=cD?dD.for||dD:dD&&dD.withoutSetter||lD,pD=function(t){return aD(uD,t)||(uD[t]=hD&&aD(dD,t)?dD[t]:fD("Symbol."+t)),uD[t]},vD=PM,gD=iO,yD=IO,mD=TO,bD=function(t,e){var i,o;if("string"===e&&jO(i=t.toString)&&!UO(o=NO(i,t)))return o;if(jO(i=t.valueOf)&&!UO(o=NO(i,t)))return o;if("string"!==e&&jO(i=t.toString)&&!UO(o=NO(i,t)))return o;throw new LO("Can't convert object to primitive value")},wD=TypeError,AD=pD("toPrimitive"),ED=function(t,e){if(!gD(t)||yD(t))return t;var i,o=mD(t,AD);if(o){if(void 0===e&&(e="default"),i=vD(o,t,e),!gD(i)||yD(i))return i;throw new wD("Can't convert object to primitive value")}return void 0===e&&(e="number"),bD(t,e)},kD=IO,CD=function(t){var e=ED(t,"string");return kD(e)?e:e+""},xD=iO,SD=sM.document,ID=xD(SD)&&xD(SD.createElement),MD=function(t){return ID?SD.createElement(t):{}},OD=MD,DD=!RM&&!aM((function(){return 7!==Object.defineProperty(OD("div"),"a",{get:function(){return 7}}).a})),RD=RM,BD=PM,zD=FM,PD=QM,FD=$M,TD=CD,ND=tD,jD=DD,UD=Object.getOwnPropertyDescriptor;DM.f=RD?UD:function(t,e){if(t=FD(t),e=TD(e),jD)try{return UD(t,e)}catch(t){}if(ND(t,e))return PD(!BD(zD.f,t,e),t[e])};var LD=aM,QD=OM,HD=/#|\.prototype\./,VD=function(t,e){var i=GD[WD(t)];return i===qD||i!==KD&&(QD(e)?LD(e):!!e)},WD=VD.normalize=function(t){return String(t).replace(HD,".").toLowerCase()},GD=VD.data={},KD=VD.NATIVE="N",qD=VD.POLYFILL="P",YD=VD,ZD=zO,JD=lM,XD=xM(xM.bind),_D=function(t,e){return ZD(t),void 0===e?t:JD?XD(t,e):function(){return t.apply(e,arguments)}},$D={},tR=RM&&aM((function(){return 42!==Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype})),eR=iO,iR=String,oR=TypeError,nR=function(t){if(eR(t))return t;throw new oR(iR(t)+" is not an object")},rR=RM,sR=DD,aR=tR,lR=nR,hR=CD,cR=TypeError,dR=Object.defineProperty,uR=Object.getOwnPropertyDescriptor,fR="enumerable",pR="configurable",vR="writable";$D.f=rR?aR?function(t,e,i){if(lR(t),e=hR(e),lR(i),"function"==typeof t&&"prototype"===e&&"value"in i&&vR in i&&!i[vR]){var o=uR(t,e);o&&o[vR]&&(t[e]=i.value,i={configurable:pR in i?i[pR]:o[pR],enumerable:fR in i?i[fR]:o[fR],writable:!1})}return dR(t,e,i)}:dR:function(t,e,i){if(lR(t),e=hR(e),lR(i),sR)try{return dR(t,e,i)}catch(t){}if("get"in i||"set"in i)throw new cR("Accessors not supported");return"value"in i&&(t[e]=i.value),t};var gR=$D,yR=QM,mR=RM?function(t,e,i){return gR.f(t,e,yR(1,i))}:function(t,e,i){return t[e]=i,t},bR=sM,wR=fM,AR=xM,ER=OM,kR=DM.f,CR=YD,xR=oO,SR=_D,IR=mR,MR=tD,OR=function(t){var e=function(i,o,n){if(this instanceof e){switch(arguments.length){case 0:return new t;case 1:return new t(i);case 2:return new t(i,o)}return new t(i,o,n)}return wR(t,this,arguments)};return e.prototype=t.prototype,e},DR=function(t,e){var i,o,n,r,s,a,l,h,c,d=t.target,u=t.global,f=t.stat,p=t.proto,v=u?bR:f?bR[d]:(bR[d]||{}).prototype,g=u?xR:xR[d]||IR(xR,d,{})[d],y=g.prototype;for(r in e)o=!(i=CR(u?r:d+(f?".":"#")+r,t.forced))&&v&&MR(v,r),a=g[r],o&&(l=t.dontCallGetSet?(c=kR(v,r))&&c.value:v[r]),s=o&&l?l:e[r],o&&typeof a==typeof s||(h=t.bind&&o?SR(s,bR):t.wrap&&o?OR(s):p&&ER(s)?AR(s):s,(t.sham||s&&s.sham||a&&a.sham)&&IR(h,"sham",!0),IR(g,r,h),p&&(MR(xR,n=d+"Prototype")||IR(xR,n,{}),IR(xR[n],r,s),t.real&&y&&(i||!y[r])&&IR(y,r,s)))},RR=Math.ceil,BR=Math.floor,zR=Math.trunc||function(t){var e=+t;return(e>0?BR:RR)(e)},PR=zR,FR=function(t){var e=+t;return e!=e||0===e?0:PR(e)},TR=FR,NR=Math.max,jR=Math.min,UR=function(t,e){var i=TR(t);return i<0?NR(i+e,0):jR(i,e)},LR=FR,QR=Math.min,HR=function(t){return t>0?QR(LR(t),9007199254740991):0},VR=function(t){return HR(t.length)},WR=$M,GR=UR,KR=VR,qR=function(t){return function(e,i,o){var n,r=WR(e),s=KR(r),a=GR(o,s);if(t&&i!=i){for(;s>a;)if((n=r[a++])!=n)return!0}else for(;s>a;a++)if((t||a in r)&&r[a]===i)return t||a||0;return!t&&-1}},YR={includes:qR(!0),indexOf:qR(!1)},ZR={},JR=tD,XR=$M,_R=YR.indexOf,$R=ZR,tB=mM([].push),eB=function(t,e){var i,o=XR(t),n=0,r=[];for(i in o)!JR($R,i)&&JR(o,i)&&tB(r,i);for(;e.length>n;)JR(o,i=e[n++])&&(~_R(r,i)||tB(r,i));return r},iB=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],oB=eB,nB=iB,rB=Object.keys||function(t){return oB(t,nB)},sB={};sB.f=Object.getOwnPropertySymbols;var aB=RM,lB=mM,hB=PM,cB=aM,dB=rB,uB=sB,fB=FM,pB=XO,vB=KM,gB=Object.assign,yB=Object.defineProperty,mB=lB([].concat),bB=!gB||cB((function(){if(aB&&1!==gB({b:1},gB(yB({},"a",{enumerable:!0,get:function(){yB(this,"b",{value:3,enumerable:!1})}}),{b:2})).b)return!0;var t={},e={},i=Symbol("assign detection"),o="abcdefghijklmnopqrst";return t[i]=7,o.split("").forEach((function(t){e[t]=t})),7!==gB({},t)[i]||dB(gB({},e)).join("")!==o}))?function(t,e){for(var i=pB(t),o=arguments.length,n=1,r=uB.f,s=fB.f;o>n;)for(var a,l=vB(arguments[n++]),h=r?mB(dB(l),r(l)):dB(l),c=h.length,d=0;c>d;)a=h[d++],aB&&!hB(s,l,a)||(i[a]=l[a]);return i}:gB,wB=bB;DR({target:"Object",stat:!0,arity:2,forced:Object.assign!==wB},{assign:wB});var AB=nM(oO.Object.assign),EB=mM([].slice),kB=mM,CB=zO,xB=iO,SB=tD,IB=EB,MB=lM,OB=Function,DB=kB([].concat),RB=kB([].join),BB={},zB=MB?OB.bind:function(t){var e=CB(this),i=e.prototype,o=IB(arguments,1),n=function(){var i=DB(o,IB(arguments));return this instanceof n?function(t,e,i){if(!SB(BB,e)){for(var o=[],n=0;n=.1;)(p=+r[d++%s])>c&&(p=c),f=Math.sqrt(p*p/(1+h*h)),e+=f=a<0?-f:f,i+=h*f,!0===u?t.lineTo(e,i):t.moveTo(e,i),c-=p,u=!u}var ZB={circle:WB,dashedLine:YB,database:qB,diamond:function(t,e,i,o){t.beginPath(),t.lineTo(e,i+o),t.lineTo(e+o,i),t.lineTo(e,i-o),t.lineTo(e-o,i),t.closePath()},ellipse:KB,ellipse_vis:KB,hexagon:function(t,e,i,o){t.beginPath();var n=2*Math.PI/6;t.moveTo(e+o,i);for(var r=1;r<6;r++)t.lineTo(e+o*Math.cos(n*r),i+o*Math.sin(n*r));t.closePath()},roundRect:GB,square:function(t,e,i,o){t.beginPath(),t.rect(e-o,i-o,2*o,2*o),t.closePath()},star:function(t,e,i,o){t.beginPath(),i+=.1*(o*=.82);for(var n=0;n<10;n++){var r=n%2==0?1.3*o:.5*o;t.lineTo(e+r*Math.sin(2*n*Math.PI/10),i-r*Math.cos(2*n*Math.PI/10))}t.closePath()},triangle:function(t,e,i,o){t.beginPath(),i+=.275*(o*=1.15);var n=2*o,r=n/2,s=Math.sqrt(3)/6*n,a=Math.sqrt(n*n-r*r);t.moveTo(e,i-(a-s)),t.lineTo(e+r,i+s),t.lineTo(e-r,i+s),t.lineTo(e,i-(a-s)),t.closePath()},triangleDown:function(t,e,i,o){t.beginPath(),i-=.275*(o*=1.15);var n=2*o,r=n/2,s=Math.sqrt(3)/6*n,a=Math.sqrt(n*n-r*r);t.moveTo(e,i+(a-s)),t.lineTo(e+r,i-s),t.lineTo(e-r,i-s),t.lineTo(e,i+(a-s)),t.closePath()}};var JB={exports:{}};!function(t){function e(t){if(t)return function(t){for(var i in e.prototype)t[i]=e.prototype[i];return t}(t)}t.exports=e,e.prototype.on=e.prototype.addEventListener=function(t,e){return this._callbacks=this._callbacks||{},(this._callbacks["$"+t]=this._callbacks["$"+t]||[]).push(e),this},e.prototype.once=function(t,e){function i(){this.off(t,i),e.apply(this,arguments)}return i.fn=e,this.on(t,i),this},e.prototype.off=e.prototype.removeListener=e.prototype.removeAllListeners=e.prototype.removeEventListener=function(t,e){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var i,o=this._callbacks["$"+t];if(!o)return this;if(1==arguments.length)return delete this._callbacks["$"+t],this;for(var n=0;n=a?t?"":void 0:(o=mz(r,s))<55296||o>56319||s+1===a||(n=mz(r,s+1))<56320||n>57343?t?yz(r,s):o:t?bz(r,s,s+2):n-56320+(o-55296<<10)+65536}},Az={codeAt:wz(!1),charAt:wz(!0)},Ez=OM,kz=sM.WeakMap,Cz=Ez(kz)&&/native code/.test(String(kz)),xz=rD,Sz=YO("keys"),Iz=function(t){return Sz[t]||(Sz[t]=xz(t))},Mz=Cz,Oz=sM,Dz=iO,Rz=mR,Bz=tD,zz=KO,Pz=Iz,Fz=ZR,Tz="Object already initialized",Nz=Oz.TypeError,jz=Oz.WeakMap;if(Mz||zz.state){var Uz=zz.state||(zz.state=new jz);Uz.get=Uz.get,Uz.has=Uz.has,Uz.set=Uz.set,$B=function(t,e){if(Uz.has(t))throw new Nz(Tz);return e.facade=t,Uz.set(t,e),e},tz=function(t){return Uz.get(t)||{}},ez=function(t){return Uz.has(t)}}else{var Lz=Pz("state");Fz[Lz]=!0,$B=function(t,e){if(Bz(t,Lz))throw new Nz(Tz);return e.facade=t,Rz(t,Lz,e),e},tz=function(t){return Bz(t,Lz)?t[Lz]:{}},ez=function(t){return Bz(t,Lz)}}var Qz={set:$B,get:tz,has:ez,enforce:function(t){return ez(t)?tz(t):$B(t,{})},getterFor:function(t){return function(e){var i;if(!Dz(e)||(i=tz(e)).type!==t)throw new Nz("Incompatible receiver, "+t+" required");return i}}},Hz=RM,Vz=tD,Wz=Function.prototype,Gz=Hz&&Object.getOwnPropertyDescriptor,Kz=Vz(Wz,"name"),qz={EXISTS:Kz,PROPER:Kz&&"something"===function(){}.name,CONFIGURABLE:Kz&&(!Hz||Hz&&Gz(Wz,"name").configurable)},Yz={},Zz=RM,Jz=tR,Xz=$D,_z=nR,$z=$M,tP=rB;Yz.f=Zz&&!Jz?Object.defineProperties:function(t,e){_z(t);for(var i,o=$z(e),n=tP(e),r=n.length,s=0;r>s;)Xz.f(t,i=n[s++],o[i]);return t};var eP,iP=lO("document","documentElement"),oP=nR,nP=Yz,rP=iB,sP=ZR,aP=iP,lP=MD,hP="prototype",cP="script",dP=Iz("IE_PROTO"),uP=function(){},fP=function(t){return"<"+cP+">"+t+""},pP=function(t){t.write(fP("")),t.close();var e=t.parentWindow.Object;return t=null,e},vP=function(){try{eP=new ActiveXObject("htmlfile")}catch(t){}var t,e,i;vP="undefined"!=typeof document?document.domain&&eP?pP(eP):(e=lP("iframe"),i="java"+cP+":",e.style.display="none",aP.appendChild(e),e.src=String(i),(t=e.contentWindow.document).open(),t.write(fP("document.F=Object")),t.close(),t.F):pP(eP);for(var o=rP.length;o--;)delete vP[hP][rP[o]];return vP()};sP[dP]=!0;var gP,yP,mP,bP=Object.create||function(t,e){var i;return null!==t?(uP[hP]=oP(t),i=new uP,uP[hP]=null,i[dP]=t):i=vP(),void 0===e?i:nP.f(i,e)},wP=!aM((function(){function t(){}return t.prototype.constructor=null,Object.getPrototypeOf(new t)!==t.prototype})),AP=tD,EP=OM,kP=XO,CP=wP,xP=Iz("IE_PROTO"),SP=Object,IP=SP.prototype,MP=CP?SP.getPrototypeOf:function(t){var e=kP(t);if(AP(e,xP))return e[xP];var i=e.constructor;return EP(i)&&e instanceof i?i.prototype:e instanceof SP?IP:null},OP=mR,DP=function(t,e,i,o){return o&&o.enumerable?t[e]=i:OP(t,e,i),t},RP=aM,BP=OM,zP=iO,PP=bP,FP=MP,TP=DP,NP=pD("iterator"),jP=!1;[].keys&&("next"in(mP=[].keys())?(yP=FP(FP(mP)))!==Object.prototype&&(gP=yP):jP=!0);var UP=!zP(gP)||RP((function(){var t={};return gP[NP].call(t)!==t}));BP((gP=UP?{}:PP(gP))[NP])||TP(gP,NP,(function(){return this}));var LP={IteratorPrototype:gP,BUGGY_SAFARI_ITERATORS:jP},QP=hz,HP=iz?{}.toString:function(){return"[object "+QP(this)+"]"},VP=iz,WP=$D.f,GP=mR,KP=tD,qP=HP,YP=pD("toStringTag"),ZP=function(t,e,i,o){if(t){var n=i?t:t.prototype;KP(n,YP)||WP(n,YP,{configurable:!0,value:e}),o&&!VP&&GP(n,"toString",qP)}},JP={},XP=LP.IteratorPrototype,_P=bP,$P=QM,tF=ZP,eF=JP,iF=function(){return this},oF=mM,nF=zO,rF=OM,sF=String,aF=TypeError,lF=function(t,e,i){try{return oF(nF(Object.getOwnPropertyDescriptor(t,e)[i]))}catch(t){}},hF=nR,cF=function(t){if("object"==typeof t||rF(t))return t;throw new aF("Can't set "+sF(t)+" as a prototype")},dF=Object.setPrototypeOf||("__proto__"in{}?function(){var t,e=!1,i={};try{(t=lF(Object.prototype,"__proto__","set"))(i,[]),e=i instanceof Array}catch(t){}return function(i,o){return hF(i),cF(o),e?t(i,o):i.__proto__=o,i}}():void 0),uF=DR,fF=PM,pF=function(t,e,i,o){var n=e+" Iterator";return t.prototype=_P(XP,{next:$P(+!o,i)}),tF(t,n,!1,!0),eF[n]=iF,t},vF=MP,gF=ZP,yF=DP,mF=JP,bF=qz.PROPER,wF=LP.BUGGY_SAFARI_ITERATORS,AF=pD("iterator"),EF="keys",kF="values",CF="entries",xF=function(){return this},SF=function(t,e,i,o,n,r,s){pF(i,e,o);var a,l,h,c=function(t){if(t===n&&v)return v;if(!wF&&t&&t in f)return f[t];switch(t){case EF:case kF:case CF:return function(){return new i(this,t)}}return function(){return new i(this)}},d=e+" Iterator",u=!1,f=t.prototype,p=f[AF]||f["@@iterator"]||n&&f[n],v=!wF&&p||c(n),g="Array"===e&&f.entries||p;if(g&&(a=vF(g.call(new t)))!==Object.prototype&&a.next&&(gF(a,d,!0,!0),mF[d]=xF),bF&&n===kF&&p&&p.name!==kF&&(u=!0,v=function(){return fF(p,this)}),n)if(l={values:c(kF),keys:r?v:c(EF),entries:c(CF)},s)for(h in l)(wF||u||!(h in f))&&yF(f,h,l[h]);else uF({target:e,proto:!0,forced:wF||u},l);return s&&f[AF]!==v&&yF(f,AF,v,{name:n}),mF[e]=v,l},IF=function(t,e){return{value:t,done:e}},MF=Az.charAt,OF=uz,DF=Qz,RF=SF,BF=IF,zF="String Iterator",PF=DF.set,FF=DF.getterFor(zF);RF(String,"String",(function(t){PF(this,{type:zF,string:OF(t),index:0})}),(function(){var t,e=FF(this),i=e.string,o=e.index;return o>=i.length?BF(void 0,!0):(t=MF(i,o),e.index+=t.length,BF(t,!1))}));var TF=PM,NF=nR,jF=TO,UF=function(t,e,i){var o,n;NF(t);try{if(!(o=jF(t,"return"))){if("throw"===e)throw i;return i}o=TF(o,t)}catch(t){n=!0,o=t}if("throw"===e)throw i;if(n)throw o;return NF(o),i},LF=nR,QF=UF,HF=JP,VF=pD("iterator"),WF=Array.prototype,GF=function(t){return void 0!==t&&(HF.Array===t||WF[VF]===t)},KF=OM,qF=KO,YF=mM(Function.toString);KF(qF.inspectSource)||(qF.inspectSource=function(t){return YF(t)});var ZF=qF.inspectSource,JF=mM,XF=aM,_F=OM,$F=hz,tT=ZF,eT=function(){},iT=[],oT=lO("Reflect","construct"),nT=/^\s*(?:class|function)\b/,rT=JF(nT.exec),sT=!nT.test(eT),aT=function(t){if(!_F(t))return!1;try{return oT(eT,iT,t),!0}catch(t){return!1}},lT=function(t){if(!_F(t))return!1;switch($F(t)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}try{return sT||!!rT(nT,tT(t))}catch(t){return!0}};lT.sham=!0;var hT=!oT||XF((function(){var t;return aT(aT.call)||!aT(Object)||!aT((function(){t=!0}))||t}))?lT:aT,cT=CD,dT=$D,uT=QM,fT=function(t,e,i){var o=cT(e);o in t?dT.f(t,o,uT(0,i)):t[o]=i},pT=hz,vT=TO,gT=qM,yT=JP,mT=pD("iterator"),bT=function(t){if(!gT(t))return vT(t,mT)||vT(t,"@@iterator")||yT[pT(t)]},wT=PM,AT=zO,ET=nR,kT=OO,CT=bT,xT=TypeError,ST=function(t,e){var i=arguments.length<2?CT(t):e;if(AT(i))return ET(wT(i,t));throw new xT(kT(t)+" is not iterable")},IT=_D,MT=PM,OT=XO,DT=function(t,e,i,o){try{return o?e(LF(i)[0],i[1]):e(i)}catch(e){QF(t,"throw",e)}},RT=GF,BT=hT,zT=VR,PT=fT,FT=ST,TT=bT,NT=Array,jT=pD("iterator"),UT=!1;try{var LT=0,QT={next:function(){return{done:!!LT++}},return:function(){UT=!0}};QT[jT]=function(){return this},Array.from(QT,(function(){throw 2}))}catch(t){}var HT=function(t){var e=OT(t),i=BT(this),o=arguments.length,n=o>1?arguments[1]:void 0,r=void 0!==n;r&&(n=IT(n,o>2?arguments[2]:void 0));var s,a,l,h,c,d,u=TT(e),f=0;if(!u||this===NT&&RT(u))for(s=zT(e),a=i?new this(s):NT(s);s>f;f++)d=r?n(e[f],f):e[f],PT(a,f,d);else for(c=(h=FT(e,u)).next,a=i?new this:[];!(l=MT(c,h)).done;f++)d=r?DT(h,n,[l.value,f],!0):l.value,PT(a,f,d);return a.length=f,a},VT=function(t,e){try{if(!e&&!UT)return!1}catch(t){return!1}var i=!1;try{var o={};o[jT]=function(){return{next:function(){return{done:i=!0}}}},t(o)}catch(t){}return i};DR({target:"Array",stat:!0,forced:!VT((function(t){Array.from(t)}))},{from:HT});var WT=oO.Array.from,GT=nM(WT),KT=$M,qT=JP,YT=Qz;$D.f;var ZT=SF,JT=IF,XT="Array Iterator",_T=YT.set,$T=YT.getterFor(XT);ZT(Array,"Array",(function(t,e){_T(this,{type:XT,target:KT(t),index:0,kind:e})}),(function(){var t=$T(this),e=t.target,i=t.kind,o=t.index++;if(!e||o>=e.length)return t.target=void 0,JT(void 0,!0);switch(i){case"keys":return JT(o,!1);case"values":return JT(e[o],!1)}return JT([o,e[o]],!1)}),"values"),qT.Arguments=qT.Array;var tN=bT,eN={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0},iN=sM,oN=hz,nN=mR,rN=JP,sN=pD("toStringTag");for(var aN in eN){var lN=iN[aN],hN=lN&&lN.prototype;hN&&oN(hN)!==sN&&nN(hN,sN,aN),rN[aN]=rN.Array}var cN=tN,dN=nM(cN),uN=nM(cN);function fN(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var pN={exports:{}},vN=DR,gN=RM,yN=$D.f;vN({target:"Object",stat:!0,forced:Object.defineProperty!==yN,sham:!gN},{defineProperty:yN});var mN=oO.Object,bN=pN.exports=function(t,e,i){return mN.defineProperty(t,e,i)};mN.defineProperty.sham&&(bN.sham=!0);var wN=pN.exports,AN=nM(wN),EN=EM,kN=Array.isArray||function(t){return"Array"===EN(t)},CN=TypeError,xN=function(t){if(t>9007199254740991)throw CN("Maximum allowed index exceeded");return t},SN=kN,IN=hT,MN=iO,ON=pD("species"),DN=Array,RN=function(t){var e;return SN(t)&&(e=t.constructor,(IN(e)&&(e===DN||SN(e.prototype))||MN(e)&&null===(e=e[ON]))&&(e=void 0)),void 0===e?DN:e},BN=function(t,e){return new(RN(t))(0===e?0:e)},zN=aM,PN=yO,FN=pD("species"),TN=function(t){return PN>=51||!zN((function(){var e=[];return(e.constructor={})[FN]=function(){return{foo:1}},1!==e[t](Boolean).foo}))},NN=DR,jN=aM,UN=kN,LN=iO,QN=XO,HN=VR,VN=xN,WN=fT,GN=BN,KN=TN,qN=yO,YN=pD("isConcatSpreadable"),ZN=qN>=51||!jN((function(){var t=[];return t[YN]=!1,t.concat()[0]!==t})),JN=function(t){if(!LN(t))return!1;var e=t[YN];return void 0!==e?!!e:UN(t)};NN({target:"Array",proto:!0,arity:1,forced:!ZN||!KN("concat")},{concat:function(t){var e,i,o,n,r,s=QN(this),a=GN(s,0),l=0;for(e=-1,o=arguments.length;em;m++)if((a||m in v)&&(f=g(u=v[m],m,p),t))if(e)w[m]=f;else if(f)switch(t){case 3:return!0;case 5:return u;case 6:return m;case 2:Rj(w,u)}else switch(t){case 4:return!1;case 7:Rj(w,u)}return r?-1:o||n?n:w}},zj={forEach:Bj(0),map:Bj(1),filter:Bj(2),some:Bj(3),every:Bj(4),find:Bj(5),findIndex:Bj(6),filterReject:Bj(7)},Pj=DR,Fj=sM,Tj=PM,Nj=mM,jj=RM,Uj=AO,Lj=aM,Qj=tD,Hj=hO,Vj=nR,Wj=$M,Gj=CD,Kj=uz,qj=QM,Yj=bP,Zj=rB,Jj=XN,Xj=tj,_j=sB,$j=DM,tU=$D,eU=Yz,iU=FM,oU=DP,nU=fj,rU=YO,sU=ZR,aU=rD,lU=pD,hU=pj,cU=wj,dU=xj,uU=ZP,fU=Qz,pU=zj.forEach,vU=Iz("hidden"),gU="Symbol",yU="prototype",mU=fU.set,bU=fU.getterFor(gU),wU=Object[yU],AU=Fj.Symbol,EU=AU&&AU[yU],kU=Fj.RangeError,CU=Fj.TypeError,xU=Fj.QObject,SU=$j.f,IU=tU.f,MU=Xj.f,OU=iU.f,DU=Nj([].push),RU=rU("symbols"),BU=rU("op-symbols"),zU=rU("wks"),PU=!xU||!xU[yU]||!xU[yU].findChild,FU=function(t,e,i){var o=SU(wU,e);o&&delete wU[e],IU(t,e,i),o&&t!==wU&&IU(wU,e,o)},TU=jj&&Lj((function(){return 7!==Yj(IU({},"a",{get:function(){return IU(this,"a",{value:7}).a}})).a}))?FU:IU,NU=function(t,e){var i=RU[t]=Yj(EU);return mU(i,{type:gU,tag:t,description:e}),jj||(i.description=e),i},jU=function(t,e,i){t===wU&&jU(BU,e,i),Vj(t);var o=Gj(e);return Vj(i),Qj(RU,o)?(i.enumerable?(Qj(t,vU)&&t[vU][o]&&(t[vU][o]=!1),i=Yj(i,{enumerable:qj(0,!1)})):(Qj(t,vU)||IU(t,vU,qj(1,{})),t[vU][o]=!0),TU(t,o,i)):IU(t,o,i)},UU=function(t,e){Vj(t);var i=Wj(e),o=Zj(i).concat(VU(i));return pU(o,(function(e){jj&&!Tj(LU,i,e)||jU(t,e,i[e])})),t},LU=function(t){var e=Gj(t),i=Tj(OU,this,e);return!(this===wU&&Qj(RU,e)&&!Qj(BU,e))&&(!(i||!Qj(this,e)||!Qj(RU,e)||Qj(this,vU)&&this[vU][e])||i)},QU=function(t,e){var i=Wj(t),o=Gj(e);if(i!==wU||!Qj(RU,o)||Qj(BU,o)){var n=SU(i,o);return!n||!Qj(RU,o)||Qj(i,vU)&&i[vU][o]||(n.enumerable=!0),n}},HU=function(t){var e=MU(Wj(t)),i=[];return pU(e,(function(t){Qj(RU,t)||Qj(sU,t)||DU(i,t)})),i},VU=function(t){var e=t===wU,i=MU(e?BU:Wj(t)),o=[];return pU(i,(function(t){!Qj(RU,t)||e&&!Qj(wU,t)||DU(o,RU[t])})),o};Uj||(AU=function(){if(Hj(EU,this))throw new CU("Symbol is not a constructor");var t=arguments.length&&void 0!==arguments[0]?Kj(arguments[0]):void 0,e=aU(t),i=function(t){this===wU&&Tj(i,BU,t),Qj(this,vU)&&Qj(this[vU],e)&&(this[vU][e]=!1);var o=qj(1,t);try{TU(this,e,o)}catch(t){if(!(t instanceof kU))throw t;FU(this,e,o)}};return jj&&PU&&TU(wU,e,{configurable:!0,set:i}),NU(e,t)},oU(EU=AU[yU],"toString",(function(){return bU(this).tag})),oU(AU,"withoutSetter",(function(t){return NU(aU(t),t)})),iU.f=LU,tU.f=jU,eU.f=UU,$j.f=QU,Jj.f=Xj.f=HU,_j.f=VU,hU.f=function(t){return NU(lU(t),t)},jj&&nU(EU,"description",{configurable:!0,get:function(){return bU(this).description}})),Pj({global:!0,constructor:!0,wrap:!0,forced:!Uj,sham:!Uj},{Symbol:AU}),pU(Zj(zU),(function(t){cU(t)})),Pj({target:gU,stat:!0,forced:!Uj},{useSetter:function(){PU=!0},useSimple:function(){PU=!1}}),Pj({target:"Object",stat:!0,forced:!Uj,sham:!jj},{create:function(t,e){return void 0===e?Yj(t):UU(Yj(t),e)},defineProperty:jU,defineProperties:UU,getOwnPropertyDescriptor:QU}),Pj({target:"Object",stat:!0,forced:!Uj},{getOwnPropertyNames:HU}),dU(),uU(AU,gU),sU[vU]=!0;var WU=AO&&!!Symbol.for&&!!Symbol.keyFor,GU=DR,KU=lO,qU=tD,YU=uz,ZU=YO,JU=WU,XU=ZU("string-to-symbol-registry"),_U=ZU("symbol-to-string-registry");GU({target:"Symbol",stat:!0,forced:!JU},{for:function(t){var e=YU(t);if(qU(XU,e))return XU[e];var i=KU("Symbol")(e);return XU[e]=i,_U[i]=e,i}});var $U=DR,tL=tD,eL=IO,iL=OO,oL=WU,nL=YO("symbol-to-string-registry");$U({target:"Symbol",stat:!0,forced:!oL},{keyFor:function(t){if(!eL(t))throw new TypeError(iL(t)+" is not a symbol");if(tL(nL,t))return nL[t]}});var rL=kN,sL=OM,aL=EM,lL=uz,hL=mM([].push),cL=DR,dL=lO,uL=fM,fL=PM,pL=mM,vL=aM,gL=OM,yL=IO,mL=EB,bL=function(t){if(sL(t))return t;if(rL(t)){for(var e=t.length,i=[],o=0;ot.length)&&(e=t.length);for(var i=0,o=new Array(e);i1?arguments[1]:void 0)}});var CH=TB("Array").map,xH=hO,SH=CH,IH=Array.prototype,MH=function(t){var e=t.map;return t===IH||xH(IH,t)&&e===IH.map?SH:e},OH=nM(MH),DH=XO,RH=rB;DR({target:"Object",stat:!0,forced:aM((function(){RH(1)}))},{keys:function(t){return RH(DH(t))}});var BH=nM(oO.Object.keys),zH=DR,PH=Date,FH=mM(PH.prototype.getTime);zH({target:"Date",stat:!0},{now:function(){return FH(new PH)}});var TH=nM(oO.Date.now),NH=aM,jH=function(t,e){var i=[][t];return!!i&&NH((function(){i.call(null,e||function(){return 1},1)}))},UH=zj.forEach,LH=jH("forEach")?[].forEach:function(t){return UH(this,t,arguments.length>1?arguments[1]:void 0)};DR({target:"Array",proto:!0,forced:[].forEach!==LH},{forEach:LH});var QH=TB("Array").forEach,HH=hz,VH=tD,WH=hO,GH=QH,KH=Array.prototype,qH={DOMTokenList:!0,NodeList:!0},YH=function(t){var e=t.forEach;return t===KH||WH(KH,t)&&e===KH.forEach||VH(qH,HH(t))?GH:e},ZH=nM(YH),JH=DR,XH=kN,_H=mM([].reverse),$H=[1,2];JH({target:"Array",proto:!0,forced:String($H)===String($H.reverse())},{reverse:function(){return XH(this)&&(this.length=this.length),_H(this)}});var tV=TB("Array").reverse,eV=hO,iV=tV,oV=Array.prototype,nV=function(t){var e=t.reverse;return t===oV||eV(oV,t)&&e===oV.reverse?iV:e},rV=nM(nV),sV=OO,aV=TypeError,lV=function(t,e){if(!delete t[e])throw new aV("Cannot delete property "+sV(e)+" of "+sV(t))},hV=DR,cV=XO,dV=UR,uV=FR,fV=VR,pV=xQ,vV=xN,gV=BN,yV=fT,mV=lV,bV=TN("splice"),wV=Math.max,AV=Math.min;hV({target:"Array",proto:!0,forced:!bV},{splice:function(t,e){var i,o,n,r,s,a,l=cV(this),h=fV(l),c=dV(t,h),d=arguments.length;for(0===d?i=o=0:1===d?(i=0,o=h-c):(i=d-2,o=AV(wV(uV(e),0),h-c)),vV(h+i-o),n=gV(l,o),r=0;rh-o+i;r--)mV(l,r-1)}else if(i>o)for(r=h-o;r>c;r--)a=r+i-1,(s=r+o-1)in l?l[a]=l[s]:mV(l,a);for(r=0;r1?arguments[1]:void 0)}});var OV=TB("Array").includes,DV=iO,RV=EM,BV=pD("match"),zV=function(t){var e;return DV(t)&&(void 0!==(e=t[BV])?!!e:"RegExp"===RV(t))},PV=TypeError,FV=pD("match"),TV=DR,NV=function(t){if(zV(t))throw new PV("The method doesn't accept regular expressions");return t},jV=JM,UV=uz,LV=function(t){var e=/./;try{"/./"[t](e)}catch(i){try{return e[FV]=!1,"/./"[t](e)}catch(t){}}return!1},QV=mM("".indexOf);TV({target:"String",proto:!0,forced:!LV("includes")},{includes:function(t){return!!~QV(UV(jV(this)),UV(NV(t)),arguments.length>1?arguments[1]:void 0)}});var HV=TB("String").includes,VV=hO,WV=OV,GV=HV,KV=Array.prototype,qV=String.prototype,YV=function(t){var e=t.includes;return t===KV||VV(KV,t)&&e===KV.includes?WV:"string"==typeof t||t===qV||VV(qV,t)&&e===qV.includes?GV:e},ZV=nM(YV),JV=XO,XV=MP,_V=wP;DR({target:"Object",stat:!0,forced:aM((function(){XV(1)})),sham:!_V},{getPrototypeOf:function(t){return XV(JV(t))}});var $V=oO.Object.getPrototypeOf,tW=nM($V),eW=zj.filter;DR({target:"Array",proto:!0,forced:!TN("filter")},{filter:function(t){return eW(this,t,arguments.length>1?arguments[1]:void 0)}});var iW=TB("Array").filter,oW=hO,nW=iW,rW=Array.prototype,sW=function(t){var e=t.filter;return t===rW||oW(rW,t)&&e===rW.filter?nW:e},aW=nM(sW),lW="\t\n\v\f\r                 \u2028\u2029\ufeff",hW=JM,cW=uz,dW=lW,uW=mM("".replace),fW=RegExp("^["+dW+"]+"),pW=RegExp("(^|[^"+dW+"])["+dW+"]+$"),vW=function(t){return function(e){var i=cW(hW(e));return 1&t&&(i=uW(i,fW,"")),2&t&&(i=uW(i,pW,"$1")),i}},gW={start:vW(1),end:vW(2),trim:vW(3)},yW=sM,mW=aM,bW=mM,wW=uz,AW=gW.trim,EW=lW,kW=yW.parseInt,CW=yW.Symbol,xW=CW&&CW.iterator,SW=/^[+-]?0x/i,IW=bW(SW.exec),MW=8!==kW(EW+"08")||22!==kW(EW+"0x16")||xW&&!mW((function(){kW(Object(xW))}))?function(t,e){var i=AW(wW(t));return kW(i,e>>>0||(IW(SW,i)?16:10))}:kW;DR({global:!0,forced:parseInt!==MW},{parseInt:MW});var OW=nM(oO.parseInt),DW=DR,RW=YR.indexOf,BW=jH,zW=xM([].indexOf),PW=!!zW&&1/zW([1],1,-0)<0;DW({target:"Array",proto:!0,forced:PW||!BW("indexOf")},{indexOf:function(t){var e=arguments.length>1?arguments[1]:void 0;return PW?zW(this,t,e)||0:RW(this,t,e)}});var FW=TB("Array").indexOf,TW=hO,NW=FW,jW=Array.prototype,UW=function(t){var e=t.indexOf;return t===jW||TW(jW,t)&&e===jW.indexOf?NW:e},LW=nM(UW);DR({target:"Object",stat:!0,sham:!RM},{create:bP});var QW=oO.Object,HW=function(t,e){return QW.create(t,e)},VW=HW,WW=nM(VW),GW=oO,KW=fM;GW.JSON||(GW.JSON={stringify:JSON.stringify});var qW=function(t,e,i){return KW(GW.JSON.stringify,null,arguments)},YW=nM(qW),ZW="function"==typeof Bun&&Bun&&"string"==typeof Bun.version,JW=TypeError,XW=sM,_W=fM,$W=OM,tG=ZW,eG=cO,iG=EB,oG=function(t,e){if(ti,s=$W(o)?o:nG(o),a=r?iG(arguments,i):[],l=r?function(){_W(s,this,a)}:s;return e?t(l,n):t(l)}:t},aG=DR,lG=sM,hG=sG(lG.setInterval,!0);aG({global:!0,bind:!0,forced:lG.setInterval!==hG},{setInterval:hG});var cG=DR,dG=sM,uG=sG(dG.setTimeout,!0);cG({global:!0,bind:!0,forced:dG.setTimeout!==uG},{setTimeout:uG});var fG=nM(oO.setTimeout),pG=XO,vG=UR,gG=VR,yG=function(t){for(var e=pG(this),i=gG(e),o=arguments.length,n=vG(o>1?arguments[1]:void 0,i),r=o>2?arguments[2]:void 0,s=void 0===r?i:vG(r,i);s>n;)e[n++]=t;return e};DR({target:"Array",proto:!0},{fill:yG});var mG,bG=TB("Array").fill,wG=hO,AG=bG,EG=Array.prototype,kG=function(t){var e=t.fill;return t===EG||wG(EG,t)&&e===EG.fill?AG:e},CG=nM(kG); + */var iR="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function nR(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var oR=function(t){return t&&t.Math===Math&&t},rR=oR("object"==typeof globalThis&&globalThis)||oR("object"==typeof window&&window)||oR("object"==typeof self&&self)||oR("object"==typeof iR&&iR)||function(){return this}()||iR||Function("return this")(),sR=function(t){try{return!!t()}catch(t){return!0}},aR=!sR((function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")})),lR=aR,hR=Function.prototype,cR=hR.apply,dR=hR.call,uR="object"==typeof Reflect&&Reflect.apply||(lR?dR.bind(cR):function(){return dR.apply(cR,arguments)}),fR=aR,pR=Function.prototype,vR=pR.call,gR=fR&&pR.bind.bind(vR,vR),yR=fR?gR:function(t){return function(){return vR.apply(t,arguments)}},mR=yR,bR=mR({}.toString),wR=mR("".slice),AR=function(t){return wR(bR(t),8,-1)},kR=AR,ER=yR,CR=function(t){if("Function"===kR(t))return ER(t)},xR="object"==typeof document&&document.all,IR={all:xR,IS_HTMLDDA:void 0===xR&&void 0!==xR},SR=IR.all,MR=IR.IS_HTMLDDA?function(t){return"function"==typeof t||t===SR}:function(t){return"function"==typeof t},OR={},DR=!sR((function(){return 7!==Object.defineProperty({},1,{get:function(){return 7}})[1]})),RR=aR,BR=Function.prototype.call,zR=RR?BR.bind(BR):function(){return BR.apply(BR,arguments)},PR={},FR={}.propertyIsEnumerable,TR=Object.getOwnPropertyDescriptor,NR=TR&&!FR.call({1:2},1);PR.f=NR?function(t){var e=TR(this,t);return!!e&&e.enumerable}:FR;var jR,LR,UR=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}},QR=sR,HR=AR,VR=Object,WR=yR("".split),GR=QR((function(){return!VR("z").propertyIsEnumerable(0)}))?function(t){return"String"===HR(t)?WR(t,""):VR(t)}:VR,KR=function(t){return null==t},qR=KR,YR=TypeError,ZR=function(t){if(qR(t))throw new YR("Can't call method on "+t);return t},JR=GR,XR=ZR,_R=function(t){return JR(XR(t))},$R=MR,tB=IR.all,eB=IR.IS_HTMLDDA?function(t){return"object"==typeof t?null!==t:$R(t)||t===tB}:function(t){return"object"==typeof t?null!==t:$R(t)},iB={},nB=iB,oB=rR,rB=MR,sB=function(t){return rB(t)?t:void 0},aB=function(t,e){return arguments.length<2?sB(nB[t])||sB(oB[t]):nB[t]&&nB[t][e]||oB[t]&&oB[t][e]},lB=yR({}.isPrototypeOf),hB="undefined"!=typeof navigator&&String(navigator.userAgent)||"",cB=rR,dB=hB,uB=cB.process,fB=cB.Deno,pB=uB&&uB.versions||fB&&fB.version,vB=pB&&pB.v8;vB&&(LR=(jR=vB.split("."))[0]>0&&jR[0]<4?1:+(jR[0]+jR[1])),!LR&&dB&&(!(jR=dB.match(/Edge\/(\d+)/))||jR[1]>=74)&&(jR=dB.match(/Chrome\/(\d+)/))&&(LR=+jR[1]);var gB=LR,yB=gB,mB=sR,bB=rR.String,wB=!!Object.getOwnPropertySymbols&&!mB((function(){var t=Symbol("symbol detection");return!bB(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&yB&&yB<41})),AB=wB&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,kB=aB,EB=MR,CB=lB,xB=Object,IB=AB?function(t){return"symbol"==typeof t}:function(t){var e=kB("Symbol");return EB(e)&&CB(e.prototype,xB(t))},SB=String,MB=function(t){try{return SB(t)}catch(t){return"Object"}},OB=MR,DB=MB,RB=TypeError,BB=function(t){if(OB(t))return t;throw new RB(DB(t)+" is not a function")},zB=BB,PB=KR,FB=function(t,e){var i=t[e];return PB(i)?void 0:zB(i)},TB=zR,NB=MR,jB=eB,LB=TypeError,UB={exports:{}},QB=rR,HB=Object.defineProperty,VB=function(t,e){try{HB(QB,t,{value:e,configurable:!0,writable:!0})}catch(i){QB[t]=e}return e},WB="__core-js_shared__",GB=rR[WB]||VB(WB,{}),KB=GB;(UB.exports=function(t,e){return KB[t]||(KB[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.33.0",mode:"pure",copyright:"© 2014-2023 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.33.0/LICENSE",source:"https://github.com/zloirock/core-js"});var qB=UB.exports,YB=ZR,ZB=Object,JB=function(t){return ZB(YB(t))},XB=JB,_B=yR({}.hasOwnProperty),$B=Object.hasOwn||function(t,e){return _B(XB(t),e)},tz=yR,ez=0,iz=Math.random(),nz=tz(1..toString),oz=function(t){return"Symbol("+(void 0===t?"":t)+")_"+nz(++ez+iz,36)},rz=qB,sz=$B,az=oz,lz=wB,hz=AB,cz=rR.Symbol,dz=rz("wks"),uz=hz?cz.for||cz:cz&&cz.withoutSetter||az,fz=function(t){return sz(dz,t)||(dz[t]=lz&&sz(cz,t)?cz[t]:uz("Symbol."+t)),dz[t]},pz=zR,vz=eB,gz=IB,yz=FB,mz=function(t,e){var i,n;if("string"===e&&NB(i=t.toString)&&!jB(n=TB(i,t)))return n;if(NB(i=t.valueOf)&&!jB(n=TB(i,t)))return n;if("string"!==e&&NB(i=t.toString)&&!jB(n=TB(i,t)))return n;throw new LB("Can't convert object to primitive value")},bz=TypeError,wz=fz("toPrimitive"),Az=function(t,e){if(!vz(t)||gz(t))return t;var i,n=yz(t,wz);if(n){if(void 0===e&&(e="default"),i=pz(n,t,e),!vz(i)||gz(i))return i;throw new bz("Can't convert object to primitive value")}return void 0===e&&(e="number"),mz(t,e)},kz=IB,Ez=function(t){var e=Az(t,"string");return kz(e)?e:e+""},Cz=eB,xz=rR.document,Iz=Cz(xz)&&Cz(xz.createElement),Sz=function(t){return Iz?xz.createElement(t):{}},Mz=Sz,Oz=!DR&&!sR((function(){return 7!==Object.defineProperty(Mz("div"),"a",{get:function(){return 7}}).a})),Dz=DR,Rz=zR,Bz=PR,zz=UR,Pz=_R,Fz=Ez,Tz=$B,Nz=Oz,jz=Object.getOwnPropertyDescriptor;OR.f=Dz?jz:function(t,e){if(t=Pz(t),e=Fz(e),Nz)try{return jz(t,e)}catch(t){}if(Tz(t,e))return zz(!Rz(Bz.f,t,e),t[e])};var Lz=sR,Uz=MR,Qz=/#|\.prototype\./,Hz=function(t,e){var i=Wz[Vz(t)];return i===Kz||i!==Gz&&(Uz(e)?Lz(e):!!e)},Vz=Hz.normalize=function(t){return String(t).replace(Qz,".").toLowerCase()},Wz=Hz.data={},Gz=Hz.NATIVE="N",Kz=Hz.POLYFILL="P",qz=Hz,Yz=BB,Zz=aR,Jz=CR(CR.bind),Xz=function(t,e){return Yz(t),void 0===e?t:Zz?Jz(t,e):function(){return t.apply(e,arguments)}},_z={},$z=DR&&sR((function(){return 42!==Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype})),tP=eB,eP=String,iP=TypeError,nP=function(t){if(tP(t))return t;throw new iP(eP(t)+" is not an object")},oP=DR,rP=Oz,sP=$z,aP=nP,lP=Ez,hP=TypeError,cP=Object.defineProperty,dP=Object.getOwnPropertyDescriptor,uP="enumerable",fP="configurable",pP="writable";_z.f=oP?sP?function(t,e,i){if(aP(t),e=lP(e),aP(i),"function"==typeof t&&"prototype"===e&&"value"in i&&pP in i&&!i[pP]){var n=dP(t,e);n&&n[pP]&&(t[e]=i.value,i={configurable:fP in i?i[fP]:n[fP],enumerable:uP in i?i[uP]:n[uP],writable:!1})}return cP(t,e,i)}:cP:function(t,e,i){if(aP(t),e=lP(e),aP(i),rP)try{return cP(t,e,i)}catch(t){}if("get"in i||"set"in i)throw new hP("Accessors not supported");return"value"in i&&(t[e]=i.value),t};var vP=_z,gP=UR,yP=DR?function(t,e,i){return vP.f(t,e,gP(1,i))}:function(t,e,i){return t[e]=i,t},mP=rR,bP=uR,wP=CR,AP=MR,kP=OR.f,EP=qz,CP=iB,xP=Xz,IP=yP,SP=$B,MP=function(t){var e=function(i,n,o){if(this instanceof e){switch(arguments.length){case 0:return new t;case 1:return new t(i);case 2:return new t(i,n)}return new t(i,n,o)}return bP(t,this,arguments)};return e.prototype=t.prototype,e},OP=function(t,e){var i,n,o,r,s,a,l,h,c,d=t.target,u=t.global,f=t.stat,p=t.proto,v=u?mP:f?mP[d]:(mP[d]||{}).prototype,g=u?CP:CP[d]||IP(CP,d,{})[d],y=g.prototype;for(r in e)n=!(i=EP(u?r:d+(f?".":"#")+r,t.forced))&&v&&SP(v,r),a=g[r],n&&(l=t.dontCallGetSet?(c=kP(v,r))&&c.value:v[r]),s=n&&l?l:e[r],n&&typeof a==typeof s||(h=t.bind&&n?xP(s,mP):t.wrap&&n?MP(s):p&&AP(s)?wP(s):s,(t.sham||s&&s.sham||a&&a.sham)&&IP(h,"sham",!0),IP(g,r,h),p&&(SP(CP,o=d+"Prototype")||IP(CP,o,{}),IP(CP[o],r,s),t.real&&y&&(i||!y[r])&&IP(y,r,s)))},DP=Math.ceil,RP=Math.floor,BP=Math.trunc||function(t){var e=+t;return(e>0?RP:DP)(e)},zP=BP,PP=function(t){var e=+t;return e!=e||0===e?0:zP(e)},FP=PP,TP=Math.max,NP=Math.min,jP=function(t,e){var i=FP(t);return i<0?TP(i+e,0):NP(i,e)},LP=PP,UP=Math.min,QP=function(t){return t>0?UP(LP(t),9007199254740991):0},HP=function(t){return QP(t.length)},VP=_R,WP=jP,GP=HP,KP=function(t){return function(e,i,n){var o,r=VP(e),s=GP(r),a=WP(n,s);if(t&&i!=i){for(;s>a;)if((o=r[a++])!=o)return!0}else for(;s>a;a++)if((t||a in r)&&r[a]===i)return t||a||0;return!t&&-1}},qP={includes:KP(!0),indexOf:KP(!1)},YP={},ZP=$B,JP=_R,XP=qP.indexOf,_P=YP,$P=yR([].push),tF=function(t,e){var i,n=JP(t),o=0,r=[];for(i in n)!ZP(_P,i)&&ZP(n,i)&&$P(r,i);for(;e.length>o;)ZP(n,i=e[o++])&&(~XP(r,i)||$P(r,i));return r},eF=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],iF=tF,nF=eF,oF=Object.keys||function(t){return iF(t,nF)},rF={};rF.f=Object.getOwnPropertySymbols;var sF=DR,aF=yR,lF=zR,hF=sR,cF=oF,dF=rF,uF=PR,fF=JB,pF=GR,vF=Object.assign,gF=Object.defineProperty,yF=aF([].concat),mF=!vF||hF((function(){if(sF&&1!==vF({b:1},vF(gF({},"a",{enumerable:!0,get:function(){gF(this,"b",{value:3,enumerable:!1})}}),{b:2})).b)return!0;var t={},e={},i=Symbol("assign detection"),n="abcdefghijklmnopqrst";return t[i]=7,n.split("").forEach((function(t){e[t]=t})),7!==vF({},t)[i]||cF(vF({},e)).join("")!==n}))?function(t,e){for(var i=fF(t),n=arguments.length,o=1,r=dF.f,s=uF.f;n>o;)for(var a,l=pF(arguments[o++]),h=r?yF(cF(l),r(l)):cF(l),c=h.length,d=0;c>d;)a=h[d++],sF&&!lF(s,l,a)||(i[a]=l[a]);return i}:vF,bF=mF;OP({target:"Object",stat:!0,arity:2,forced:Object.assign!==bF},{assign:bF});var wF=nR(iB.Object.assign),AF=yR([].slice),kF=yR,EF=BB,CF=eB,xF=$B,IF=AF,SF=aR,MF=Function,OF=kF([].concat),DF=kF([].join),RF={},BF=SF?MF.bind:function(t){var e=EF(this),i=e.prototype,n=IF(arguments,1),o=function(){var i=OF(n,IF(arguments));return this instanceof o?function(t,e,i){if(!xF(RF,e)){for(var n=[],o=0;o=.1;)(p=+r[d++%s])>c&&(p=c),f=Math.sqrt(p*p/(1+h*h)),e+=f=a<0?-f:f,i+=h*f,!0===u?t.lineTo(e,i):t.moveTo(e,i),c-=p,u=!u}var YF={circle:VF,dashedLine:qF,database:KF,diamond:function(t,e,i,n){t.beginPath(),t.lineTo(e,i+n),t.lineTo(e+n,i),t.lineTo(e,i-n),t.lineTo(e-n,i),t.closePath()},ellipse:GF,ellipse_vis:GF,hexagon:function(t,e,i,n){t.beginPath();var o=2*Math.PI/6;t.moveTo(e+n,i);for(var r=1;r<6;r++)t.lineTo(e+n*Math.cos(o*r),i+n*Math.sin(o*r));t.closePath()},roundRect:WF,square:function(t,e,i,n){t.beginPath(),t.rect(e-n,i-n,2*n,2*n),t.closePath()},star:function(t,e,i,n){t.beginPath(),i+=.1*(n*=.82);for(var o=0;o<10;o++){var r=o%2==0?1.3*n:.5*n;t.lineTo(e+r*Math.sin(2*o*Math.PI/10),i-r*Math.cos(2*o*Math.PI/10))}t.closePath()},triangle:function(t,e,i,n){t.beginPath(),i+=.275*(n*=1.15);var o=2*n,r=o/2,s=Math.sqrt(3)/6*o,a=Math.sqrt(o*o-r*r);t.moveTo(e,i-(a-s)),t.lineTo(e+r,i+s),t.lineTo(e-r,i+s),t.lineTo(e,i-(a-s)),t.closePath()},triangleDown:function(t,e,i,n){t.beginPath(),i-=.275*(n*=1.15);var o=2*n,r=o/2,s=Math.sqrt(3)/6*o,a=Math.sqrt(o*o-r*r);t.moveTo(e,i+(a-s)),t.lineTo(e+r,i-s),t.lineTo(e-r,i-s),t.lineTo(e,i+(a-s)),t.closePath()}};var ZF={exports:{}};!function(t){function e(t){if(t)return function(t){for(var i in e.prototype)t[i]=e.prototype[i];return t}(t)}t.exports=e,e.prototype.on=e.prototype.addEventListener=function(t,e){return this._callbacks=this._callbacks||{},(this._callbacks["$"+t]=this._callbacks["$"+t]||[]).push(e),this},e.prototype.once=function(t,e){function i(){this.off(t,i),e.apply(this,arguments)}return i.fn=e,this.on(t,i),this},e.prototype.off=e.prototype.removeListener=e.prototype.removeAllListeners=e.prototype.removeEventListener=function(t,e){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var i,n=this._callbacks["$"+t];if(!n)return this;if(1==arguments.length)return delete this._callbacks["$"+t],this;for(var o=0;o=a?t?"":void 0:(n=yT(r,s))<55296||n>56319||s+1===a||(o=yT(r,s+1))<56320||o>57343?t?gT(r,s):n:t?mT(r,s,s+2):o-56320+(n-55296<<10)+65536}},wT={codeAt:bT(!1),charAt:bT(!0)},AT=MR,kT=rR.WeakMap,ET=AT(kT)&&/native code/.test(String(kT)),CT=oz,xT=qB("keys"),IT=function(t){return xT[t]||(xT[t]=CT(t))},ST=ET,MT=rR,OT=eB,DT=yP,RT=$B,BT=GB,zT=IT,PT=YP,FT="Object already initialized",TT=MT.TypeError,NT=MT.WeakMap;if(ST||BT.state){var jT=BT.state||(BT.state=new NT);jT.get=jT.get,jT.has=jT.has,jT.set=jT.set,_F=function(t,e){if(jT.has(t))throw new TT(FT);return e.facade=t,jT.set(t,e),e},$F=function(t){return jT.get(t)||{}},tT=function(t){return jT.has(t)}}else{var LT=zT("state");PT[LT]=!0,_F=function(t,e){if(RT(t,LT))throw new TT(FT);return e.facade=t,DT(t,LT,e),e},$F=function(t){return RT(t,LT)?t[LT]:{}},tT=function(t){return RT(t,LT)}}var UT={set:_F,get:$F,has:tT,enforce:function(t){return tT(t)?$F(t):_F(t,{})},getterFor:function(t){return function(e){var i;if(!OT(e)||(i=$F(e)).type!==t)throw new TT("Incompatible receiver, "+t+" required");return i}}},QT=DR,HT=$B,VT=Function.prototype,WT=QT&&Object.getOwnPropertyDescriptor,GT=HT(VT,"name"),KT={EXISTS:GT,PROPER:GT&&"something"===function(){}.name,CONFIGURABLE:GT&&(!QT||QT&&WT(VT,"name").configurable)},qT={},YT=DR,ZT=$z,JT=_z,XT=nP,_T=_R,$T=oF;qT.f=YT&&!ZT?Object.defineProperties:function(t,e){XT(t);for(var i,n=_T(e),o=$T(e),r=o.length,s=0;r>s;)JT.f(t,i=o[s++],n[i]);return t};var tN,eN=aB("document","documentElement"),iN=nP,nN=qT,oN=eF,rN=YP,sN=eN,aN=Sz,lN="prototype",hN="script",cN=IT("IE_PROTO"),dN=function(){},uN=function(t){return"<"+hN+">"+t+""},fN=function(t){t.write(uN("")),t.close();var e=t.parentWindow.Object;return t=null,e},pN=function(){try{tN=new ActiveXObject("htmlfile")}catch(t){}var t,e,i;pN="undefined"!=typeof document?document.domain&&tN?fN(tN):(e=aN("iframe"),i="java"+hN+":",e.style.display="none",sN.appendChild(e),e.src=String(i),(t=e.contentWindow.document).open(),t.write(uN("document.F=Object")),t.close(),t.F):fN(tN);for(var n=oN.length;n--;)delete pN[lN][oN[n]];return pN()};rN[cN]=!0;var vN,gN,yN,mN=Object.create||function(t,e){var i;return null!==t?(dN[lN]=iN(t),i=new dN,dN[lN]=null,i[cN]=t):i=pN(),void 0===e?i:nN.f(i,e)},bN=!sR((function(){function t(){}return t.prototype.constructor=null,Object.getPrototypeOf(new t)!==t.prototype})),wN=$B,AN=MR,kN=JB,EN=bN,CN=IT("IE_PROTO"),xN=Object,IN=xN.prototype,SN=EN?xN.getPrototypeOf:function(t){var e=kN(t);if(wN(e,CN))return e[CN];var i=e.constructor;return AN(i)&&e instanceof i?i.prototype:e instanceof xN?IN:null},MN=yP,ON=function(t,e,i,n){return n&&n.enumerable?t[e]=i:MN(t,e,i),t},DN=sR,RN=MR,BN=eB,zN=mN,PN=SN,FN=ON,TN=fz("iterator"),NN=!1;[].keys&&("next"in(yN=[].keys())?(gN=PN(PN(yN)))!==Object.prototype&&(vN=gN):NN=!0);var jN=!BN(vN)||DN((function(){var t={};return vN[TN].call(t)!==t}));RN((vN=jN?{}:zN(vN))[TN])||FN(vN,TN,(function(){return this}));var LN={IteratorPrototype:vN,BUGGY_SAFARI_ITERATORS:NN},UN=lT,QN=eT?{}.toString:function(){return"[object "+UN(this)+"]"},HN=eT,VN=_z.f,WN=yP,GN=$B,KN=QN,qN=fz("toStringTag"),YN=function(t,e,i,n){if(t){var o=i?t:t.prototype;GN(o,qN)||VN(o,qN,{configurable:!0,value:e}),n&&!HN&&WN(o,"toString",KN)}},ZN={},JN=LN.IteratorPrototype,XN=mN,_N=UR,$N=YN,tj=ZN,ej=function(){return this},ij=yR,nj=BB,oj=MR,rj=String,sj=TypeError,aj=function(t,e,i){try{return ij(nj(Object.getOwnPropertyDescriptor(t,e)[i]))}catch(t){}},lj=nP,hj=function(t){if("object"==typeof t||oj(t))return t;throw new sj("Can't set "+rj(t)+" as a prototype")},cj=Object.setPrototypeOf||("__proto__"in{}?function(){var t,e=!1,i={};try{(t=aj(Object.prototype,"__proto__","set"))(i,[]),e=i instanceof Array}catch(t){}return function(i,n){return lj(i),hj(n),e?t(i,n):i.__proto__=n,i}}():void 0),dj=OP,uj=zR,fj=function(t,e,i,n){var o=e+" Iterator";return t.prototype=XN(JN,{next:_N(+!n,i)}),$N(t,o,!1,!0),tj[o]=ej,t},pj=SN,vj=YN,gj=ON,yj=ZN,mj=KT.PROPER,bj=LN.BUGGY_SAFARI_ITERATORS,wj=fz("iterator"),Aj="keys",kj="values",Ej="entries",Cj=function(){return this},xj=function(t,e,i,n,o,r,s){fj(i,e,n);var a,l,h,c=function(t){if(t===o&&v)return v;if(!bj&&t&&t in f)return f[t];switch(t){case Aj:case kj:case Ej:return function(){return new i(this,t)}}return function(){return new i(this)}},d=e+" Iterator",u=!1,f=t.prototype,p=f[wj]||f["@@iterator"]||o&&f[o],v=!bj&&p||c(o),g="Array"===e&&f.entries||p;if(g&&(a=pj(g.call(new t)))!==Object.prototype&&a.next&&(vj(a,d,!0,!0),yj[d]=Cj),mj&&o===kj&&p&&p.name!==kj&&(u=!0,v=function(){return uj(p,this)}),o)if(l={values:c(kj),keys:r?v:c(Aj),entries:c(Ej)},s)for(h in l)(bj||u||!(h in f))&&gj(f,h,l[h]);else dj({target:e,proto:!0,forced:bj||u},l);return s&&f[wj]!==v&&gj(f,wj,v,{name:o}),yj[e]=v,l},Ij=function(t,e){return{value:t,done:e}},Sj=wT.charAt,Mj=dT,Oj=UT,Dj=xj,Rj=Ij,Bj="String Iterator",zj=Oj.set,Pj=Oj.getterFor(Bj);Dj(String,"String",(function(t){zj(this,{type:Bj,string:Mj(t),index:0})}),(function(){var t,e=Pj(this),i=e.string,n=e.index;return n>=i.length?Rj(void 0,!0):(t=Sj(i,n),e.index+=t.length,Rj(t,!1))}));var Fj=zR,Tj=nP,Nj=FB,jj=function(t,e,i){var n,o;Tj(t);try{if(!(n=Nj(t,"return"))){if("throw"===e)throw i;return i}n=Fj(n,t)}catch(t){o=!0,n=t}if("throw"===e)throw i;if(o)throw n;return Tj(n),i},Lj=nP,Uj=jj,Qj=ZN,Hj=fz("iterator"),Vj=Array.prototype,Wj=function(t){return void 0!==t&&(Qj.Array===t||Vj[Hj]===t)},Gj=MR,Kj=GB,qj=yR(Function.toString);Gj(Kj.inspectSource)||(Kj.inspectSource=function(t){return qj(t)});var Yj=Kj.inspectSource,Zj=yR,Jj=sR,Xj=MR,_j=lT,$j=Yj,tL=function(){},eL=[],iL=aB("Reflect","construct"),nL=/^\s*(?:class|function)\b/,oL=Zj(nL.exec),rL=!nL.test(tL),sL=function(t){if(!Xj(t))return!1;try{return iL(tL,eL,t),!0}catch(t){return!1}},aL=function(t){if(!Xj(t))return!1;switch(_j(t)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}try{return rL||!!oL(nL,$j(t))}catch(t){return!0}};aL.sham=!0;var lL=!iL||Jj((function(){var t;return sL(sL.call)||!sL(Object)||!sL((function(){t=!0}))||t}))?aL:sL,hL=Ez,cL=_z,dL=UR,uL=function(t,e,i){var n=hL(e);n in t?cL.f(t,n,dL(0,i)):t[n]=i},fL=lT,pL=FB,vL=KR,gL=ZN,yL=fz("iterator"),mL=function(t){if(!vL(t))return pL(t,yL)||pL(t,"@@iterator")||gL[fL(t)]},bL=zR,wL=BB,AL=nP,kL=MB,EL=mL,CL=TypeError,xL=function(t,e){var i=arguments.length<2?EL(t):e;if(wL(i))return AL(bL(i,t));throw new CL(kL(t)+" is not iterable")},IL=Xz,SL=zR,ML=JB,OL=function(t,e,i,n){try{return n?e(Lj(i)[0],i[1]):e(i)}catch(e){Uj(t,"throw",e)}},DL=Wj,RL=lL,BL=HP,zL=uL,PL=xL,FL=mL,TL=Array,NL=fz("iterator"),jL=!1;try{var LL=0,UL={next:function(){return{done:!!LL++}},return:function(){jL=!0}};UL[NL]=function(){return this},Array.from(UL,(function(){throw 2}))}catch(t){}var QL=function(t){var e=ML(t),i=RL(this),n=arguments.length,o=n>1?arguments[1]:void 0,r=void 0!==o;r&&(o=IL(o,n>2?arguments[2]:void 0));var s,a,l,h,c,d,u=FL(e),f=0;if(!u||this===TL&&DL(u))for(s=BL(e),a=i?new this(s):TL(s);s>f;f++)d=r?o(e[f],f):e[f],zL(a,f,d);else for(c=(h=PL(e,u)).next,a=i?new this:[];!(l=SL(c,h)).done;f++)d=r?OL(h,o,[l.value,f],!0):l.value,zL(a,f,d);return a.length=f,a},HL=function(t,e){try{if(!e&&!jL)return!1}catch(t){return!1}var i=!1;try{var n={};n[NL]=function(){return{next:function(){return{done:i=!0}}}},t(n)}catch(t){}return i};OP({target:"Array",stat:!0,forced:!HL((function(t){Array.from(t)}))},{from:QL});var VL=iB.Array.from,WL=nR(VL),GL=_R,KL=ZN,qL=UT;_z.f;var YL=xj,ZL=Ij,JL="Array Iterator",XL=qL.set,_L=qL.getterFor(JL);YL(Array,"Array",(function(t,e){XL(this,{type:JL,target:GL(t),index:0,kind:e})}),(function(){var t=_L(this),e=t.target,i=t.kind,n=t.index++;if(!e||n>=e.length)return t.target=void 0,ZL(void 0,!0);switch(i){case"keys":return ZL(n,!1);case"values":return ZL(e[n],!1)}return ZL([n,e[n]],!1)}),"values"),KL.Arguments=KL.Array;var $L=mL,tU={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0},eU=rR,iU=lT,nU=yP,oU=ZN,rU=fz("toStringTag");for(var sU in tU){var aU=eU[sU],lU=aU&&aU.prototype;lU&&iU(lU)!==rU&&nU(lU,rU,sU),oU[sU]=oU.Array}var hU=$L,cU=nR(hU),dU=nR(hU);function uU(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var fU={exports:{}},pU=OP,vU=DR,gU=_z.f;pU({target:"Object",stat:!0,forced:Object.defineProperty!==gU,sham:!vU},{defineProperty:gU});var yU=iB.Object,mU=fU.exports=function(t,e,i){return yU.defineProperty(t,e,i)};yU.defineProperty.sham&&(mU.sham=!0);var bU=fU.exports,wU=nR(bU),AU=AR,kU=Array.isArray||function(t){return"Array"===AU(t)},EU=TypeError,CU=function(t){if(t>9007199254740991)throw EU("Maximum allowed index exceeded");return t},xU=kU,IU=lL,SU=eB,MU=fz("species"),OU=Array,DU=function(t){var e;return xU(t)&&(e=t.constructor,(IU(e)&&(e===OU||xU(e.prototype))||SU(e)&&null===(e=e[MU]))&&(e=void 0)),void 0===e?OU:e},RU=function(t,e){return new(DU(t))(0===e?0:e)},BU=sR,zU=gB,PU=fz("species"),FU=function(t){return zU>=51||!BU((function(){var e=[];return(e.constructor={})[PU]=function(){return{foo:1}},1!==e[t](Boolean).foo}))},TU=OP,NU=sR,jU=kU,LU=eB,UU=JB,QU=HP,HU=CU,VU=uL,WU=RU,GU=FU,KU=gB,qU=fz("isConcatSpreadable"),YU=KU>=51||!NU((function(){var t=[];return t[qU]=!1,t.concat()[0]!==t})),ZU=function(t){if(!LU(t))return!1;var e=t[qU];return void 0!==e?!!e:jU(t)};TU({target:"Array",proto:!0,arity:1,forced:!YU||!GU("concat")},{concat:function(t){var e,i,n,o,r,s=UU(this),a=WU(s,0),l=0;for(e=-1,n=arguments.length;em;m++)if((a||m in v)&&(f=g(u=v[m],m,p),t))if(e)w[m]=f;else if(f)switch(t){case 3:return!0;case 5:return u;case 6:return m;case 2:DQ(w,u)}else switch(t){case 4:return!1;case 7:DQ(w,u)}return r?-1:n||o?o:w}},BQ={forEach:RQ(0),map:RQ(1),filter:RQ(2),some:RQ(3),every:RQ(4),find:RQ(5),findIndex:RQ(6),filterReject:RQ(7)},zQ=OP,PQ=rR,FQ=zR,TQ=yR,NQ=DR,jQ=wB,LQ=sR,UQ=$B,QQ=lB,HQ=nP,VQ=_R,WQ=Ez,GQ=dT,KQ=UR,qQ=mN,YQ=oF,ZQ=JU,JQ=$U,XQ=rF,_Q=OR,$Q=_z,tH=qT,eH=PR,iH=ON,nH=uQ,oH=qB,rH=YP,sH=oz,aH=fz,lH=fQ,hH=bQ,cH=CQ,dH=YN,uH=UT,fH=BQ.forEach,pH=IT("hidden"),vH="Symbol",gH="prototype",yH=uH.set,mH=uH.getterFor(vH),bH=Object[gH],wH=PQ.Symbol,AH=wH&&wH[gH],kH=PQ.RangeError,EH=PQ.TypeError,CH=PQ.QObject,xH=_Q.f,IH=$Q.f,SH=JQ.f,MH=eH.f,OH=TQ([].push),DH=oH("symbols"),RH=oH("op-symbols"),BH=oH("wks"),zH=!CH||!CH[gH]||!CH[gH].findChild,PH=function(t,e,i){var n=xH(bH,e);n&&delete bH[e],IH(t,e,i),n&&t!==bH&&IH(bH,e,n)},FH=NQ&&LQ((function(){return 7!==qQ(IH({},"a",{get:function(){return IH(this,"a",{value:7}).a}})).a}))?PH:IH,TH=function(t,e){var i=DH[t]=qQ(AH);return yH(i,{type:vH,tag:t,description:e}),NQ||(i.description=e),i},NH=function(t,e,i){t===bH&&NH(RH,e,i),HQ(t);var n=WQ(e);return HQ(i),UQ(DH,n)?(i.enumerable?(UQ(t,pH)&&t[pH][n]&&(t[pH][n]=!1),i=qQ(i,{enumerable:KQ(0,!1)})):(UQ(t,pH)||IH(t,pH,KQ(1,{})),t[pH][n]=!0),FH(t,n,i)):IH(t,n,i)},jH=function(t,e){HQ(t);var i=VQ(e),n=YQ(i).concat(HH(i));return fH(n,(function(e){NQ&&!FQ(LH,i,e)||NH(t,e,i[e])})),t},LH=function(t){var e=WQ(t),i=FQ(MH,this,e);return!(this===bH&&UQ(DH,e)&&!UQ(RH,e))&&(!(i||!UQ(this,e)||!UQ(DH,e)||UQ(this,pH)&&this[pH][e])||i)},UH=function(t,e){var i=VQ(t),n=WQ(e);if(i!==bH||!UQ(DH,n)||UQ(RH,n)){var o=xH(i,n);return!o||!UQ(DH,n)||UQ(i,pH)&&i[pH][n]||(o.enumerable=!0),o}},QH=function(t){var e=SH(VQ(t)),i=[];return fH(e,(function(t){UQ(DH,t)||UQ(rH,t)||OH(i,t)})),i},HH=function(t){var e=t===bH,i=SH(e?RH:VQ(t)),n=[];return fH(i,(function(t){!UQ(DH,t)||e&&!UQ(bH,t)||OH(n,DH[t])})),n};jQ||(wH=function(){if(QQ(AH,this))throw new EH("Symbol is not a constructor");var t=arguments.length&&void 0!==arguments[0]?GQ(arguments[0]):void 0,e=sH(t),i=function(t){this===bH&&FQ(i,RH,t),UQ(this,pH)&&UQ(this[pH],e)&&(this[pH][e]=!1);var n=KQ(1,t);try{FH(this,e,n)}catch(t){if(!(t instanceof kH))throw t;PH(this,e,n)}};return NQ&&zH&&FH(bH,e,{configurable:!0,set:i}),TH(e,t)},iH(AH=wH[gH],"toString",(function(){return mH(this).tag})),iH(wH,"withoutSetter",(function(t){return TH(sH(t),t)})),eH.f=LH,$Q.f=NH,tH.f=jH,_Q.f=UH,ZQ.f=JQ.f=QH,XQ.f=HH,lH.f=function(t){return TH(aH(t),t)},NQ&&nH(AH,"description",{configurable:!0,get:function(){return mH(this).description}})),zQ({global:!0,constructor:!0,wrap:!0,forced:!jQ,sham:!jQ},{Symbol:wH}),fH(YQ(BH),(function(t){hH(t)})),zQ({target:vH,stat:!0,forced:!jQ},{useSetter:function(){zH=!0},useSimple:function(){zH=!1}}),zQ({target:"Object",stat:!0,forced:!jQ,sham:!NQ},{create:function(t,e){return void 0===e?qQ(t):jH(qQ(t),e)},defineProperty:NH,defineProperties:jH,getOwnPropertyDescriptor:UH}),zQ({target:"Object",stat:!0,forced:!jQ},{getOwnPropertyNames:QH}),cH(),dH(wH,vH),rH[pH]=!0;var VH=wB&&!!Symbol.for&&!!Symbol.keyFor,WH=OP,GH=aB,KH=$B,qH=dT,YH=qB,ZH=VH,JH=YH("string-to-symbol-registry"),XH=YH("symbol-to-string-registry");WH({target:"Symbol",stat:!0,forced:!ZH},{for:function(t){var e=qH(t);if(KH(JH,e))return JH[e];var i=GH("Symbol")(e);return JH[e]=i,XH[i]=e,i}});var _H=OP,$H=$B,tV=IB,eV=MB,iV=VH,nV=qB("symbol-to-string-registry");_H({target:"Symbol",stat:!0,forced:!iV},{keyFor:function(t){if(!tV(t))throw new TypeError(eV(t)+" is not a symbol");if($H(nV,t))return nV[t]}});var oV=kU,rV=MR,sV=AR,aV=dT,lV=yR([].push),hV=OP,cV=aB,dV=uR,uV=zR,fV=yR,pV=sR,vV=MR,gV=IB,yV=AF,mV=function(t){if(rV(t))return t;if(oV(t)){for(var e=t.length,i=[],n=0;nt.length)&&(e=t.length);for(var i=0,n=new Array(e);i1?arguments[1]:void 0)}});var EG=FF("Array").map,CG=lB,xG=EG,IG=Array.prototype,SG=function(t){var e=t.map;return t===IG||CG(IG,t)&&e===IG.map?xG:e},MG=nR(SG),OG=JB,DG=oF;OP({target:"Object",stat:!0,forced:sR((function(){DG(1)}))},{keys:function(t){return DG(OG(t))}});var RG=nR(iB.Object.keys),BG=OP,zG=Date,PG=yR(zG.prototype.getTime);BG({target:"Date",stat:!0},{now:function(){return PG(new zG)}});var FG=nR(iB.Date.now),TG=sR,NG=function(t,e){var i=[][t];return!!i&&TG((function(){i.call(null,e||function(){return 1},1)}))},jG=BQ.forEach,LG=NG("forEach")?[].forEach:function(t){return jG(this,t,arguments.length>1?arguments[1]:void 0)};OP({target:"Array",proto:!0,forced:[].forEach!==LG},{forEach:LG});var UG=FF("Array").forEach,QG=lT,HG=$B,VG=lB,WG=UG,GG=Array.prototype,KG={DOMTokenList:!0,NodeList:!0},qG=function(t){var e=t.forEach;return t===GG||VG(GG,t)&&e===GG.forEach||HG(KG,QG(t))?WG:e},YG=nR(qG),ZG=OP,JG=kU,XG=yR([].reverse),_G=[1,2];ZG({target:"Array",proto:!0,forced:String(_G)===String(_G.reverse())},{reverse:function(){return JG(this)&&(this.length=this.length),XG(this)}});var $G=FF("Array").reverse,tK=lB,eK=$G,iK=Array.prototype,nK=function(t){var e=t.reverse;return t===iK||tK(iK,t)&&e===iK.reverse?eK:e},oK=nR(nK),rK=MB,sK=TypeError,aK=function(t,e){if(!delete t[e])throw new sK("Cannot delete property "+rK(e)+" of "+rK(t))},lK=OP,hK=JB,cK=jP,dK=PP,uK=HP,fK=CW,pK=CU,vK=RU,gK=uL,yK=aK,mK=FU("splice"),bK=Math.max,wK=Math.min;lK({target:"Array",proto:!0,forced:!mK},{splice:function(t,e){var i,n,o,r,s,a,l=hK(this),h=uK(l),c=cK(t,h),d=arguments.length;for(0===d?i=n=0:1===d?(i=0,n=h-c):(i=d-2,n=wK(bK(dK(e),0),h-c)),pK(h+i-n),o=vK(l,n),r=0;rh-n+i;r--)yK(l,r-1)}else if(i>n)for(r=h-n;r>c;r--)a=r+i-1,(s=r+n-1)in l?l[a]=l[s]:yK(l,a);for(r=0;r1?arguments[1]:void 0)}});var MK=FF("Array").includes,OK=eB,DK=AR,RK=fz("match"),BK=function(t){var e;return OK(t)&&(void 0!==(e=t[RK])?!!e:"RegExp"===DK(t))},zK=TypeError,PK=fz("match"),FK=OP,TK=function(t){if(BK(t))throw new zK("The method doesn't accept regular expressions");return t},NK=ZR,jK=dT,LK=function(t){var e=/./;try{"/./"[t](e)}catch(i){try{return e[PK]=!1,"/./"[t](e)}catch(t){}}return!1},UK=yR("".indexOf);FK({target:"String",proto:!0,forced:!LK("includes")},{includes:function(t){return!!~UK(jK(NK(this)),jK(TK(t)),arguments.length>1?arguments[1]:void 0)}});var QK=FF("String").includes,HK=lB,VK=MK,WK=QK,GK=Array.prototype,KK=String.prototype,qK=function(t){var e=t.includes;return t===GK||HK(GK,t)&&e===GK.includes?VK:"string"==typeof t||t===KK||HK(KK,t)&&e===KK.includes?WK:e},YK=nR(qK),ZK=JB,JK=SN,XK=bN;OP({target:"Object",stat:!0,forced:sR((function(){JK(1)})),sham:!XK},{getPrototypeOf:function(t){return JK(ZK(t))}});var _K=iB.Object.getPrototypeOf,$K=nR(_K),tq=BQ.filter;OP({target:"Array",proto:!0,forced:!FU("filter")},{filter:function(t){return tq(this,t,arguments.length>1?arguments[1]:void 0)}});var eq=FF("Array").filter,iq=lB,nq=eq,oq=Array.prototype,rq=function(t){var e=t.filter;return t===oq||iq(oq,t)&&e===oq.filter?nq:e},sq=nR(rq),aq="\t\n\v\f\r                 \u2028\u2029\ufeff",lq=ZR,hq=dT,cq=aq,dq=yR("".replace),uq=RegExp("^["+cq+"]+"),fq=RegExp("(^|[^"+cq+"])["+cq+"]+$"),pq=function(t){return function(e){var i=hq(lq(e));return 1&t&&(i=dq(i,uq,"")),2&t&&(i=dq(i,fq,"$1")),i}},vq={start:pq(1),end:pq(2),trim:pq(3)},gq=rR,yq=sR,mq=yR,bq=dT,wq=vq.trim,Aq=aq,kq=gq.parseInt,Eq=gq.Symbol,Cq=Eq&&Eq.iterator,xq=/^[+-]?0x/i,Iq=mq(xq.exec),Sq=8!==kq(Aq+"08")||22!==kq(Aq+"0x16")||Cq&&!yq((function(){kq(Object(Cq))}))?function(t,e){var i=wq(bq(t));return kq(i,e>>>0||(Iq(xq,i)?16:10))}:kq;OP({global:!0,forced:parseInt!==Sq},{parseInt:Sq});var Mq=nR(iB.parseInt),Oq=OP,Dq=qP.indexOf,Rq=NG,Bq=CR([].indexOf),zq=!!Bq&&1/Bq([1],1,-0)<0;Oq({target:"Array",proto:!0,forced:zq||!Rq("indexOf")},{indexOf:function(t){var e=arguments.length>1?arguments[1]:void 0;return zq?Bq(this,t,e)||0:Dq(this,t,e)}});var Pq=FF("Array").indexOf,Fq=lB,Tq=Pq,Nq=Array.prototype,jq=function(t){var e=t.indexOf;return t===Nq||Fq(Nq,t)&&e===Nq.indexOf?Tq:e},Lq=nR(jq);OP({target:"Object",stat:!0,sham:!DR},{create:mN});var Uq=iB.Object,Qq=function(t,e){return Uq.create(t,e)},Hq=Qq,Vq=nR(Hq),Wq=iB,Gq=uR;Wq.JSON||(Wq.JSON={stringify:JSON.stringify});var Kq=function(t,e,i){return Gq(Wq.JSON.stringify,null,arguments)},qq=nR(Kq),Yq="function"==typeof Bun&&Bun&&"string"==typeof Bun.version,Zq=TypeError,Jq=rR,Xq=uR,_q=MR,$q=Yq,tY=hB,eY=AF,iY=function(t,e){if(ti,s=_q(n)?n:nY(n),a=r?eY(arguments,i):[],l=r?function(){Xq(s,this,a)}:s;return e?t(l,o):t(l)}:t},sY=OP,aY=rR,lY=rY(aY.setInterval,!0);sY({global:!0,bind:!0,forced:aY.setInterval!==lY},{setInterval:lY});var hY=OP,cY=rR,dY=rY(cY.setTimeout,!0);hY({global:!0,bind:!0,forced:cY.setTimeout!==dY},{setTimeout:dY});var uY=nR(iB.setTimeout),fY=JB,pY=jP,vY=HP,gY=function(t){for(var e=fY(this),i=vY(e),n=arguments.length,o=pY(n>1?arguments[1]:void 0,i),r=n>2?arguments[2]:void 0,s=void 0===r?i:pY(r,i);s>o;)e[o++]=t;return e};OP({target:"Array",proto:!0},{fill:gY});var yY,mY=FF("Array").fill,bY=lB,wY=mY,AY=Array.prototype,kY=function(t){var e=t.fill;return t===AY||bY(AY,t)&&e===AY.fill?wY:e},EY=nR(kY); /*! Hammer.JS - v2.0.17-rc - 2019-12-16 * http://naver.github.io/egjs * * Forked By Naver egjs * Copyright (c) hammerjs * Licensed under the MIT license */ -function xG(){return xG=Object.assign||function(t){for(var e=1;e-1}var fK=function(){function t(t,e){this.manager=t,this.set(e)}var e=t.prototype;return e.set=function(t){t===jG&&(t=this.compute()),NG&&this.manager.element.style&&WG[t]&&(this.manager.element.style[TG]=t),this.actions=t.toLowerCase().trim()},e.update=function(){this.set(this.manager.options.touchAction)},e.compute=function(){var t=[];return cK(this.manager.recognizers,(function(e){dK(e.options.enable,[e])&&(t=t.concat(e.getTouchAction()))})),function(t){if(uK(t,QG))return QG;var e=uK(t,HG),i=uK(t,VG);return e&&i?QG:e||i?e?HG:VG:uK(t,LG)?LG:UG}(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=uK(o,QG)&&!WG[QG],r=uK(o,VG)&&!WG[VG],s=uK(o,HG)&&!WG[HG];if(n){var a=1===t.pointers.length,l=t.distance<2,h=t.deltaTime<250;if(a&&l&&h)return}if(!s||!r)return n||r&&i&rK||s&&i&sK?this.preventSrc(e):void 0}},e.preventSrc=function(t){this.manager.session.prevented=!0,t.preventDefault()},t}();function pK(t,e){for(;t;){if(t===e)return!0;t=t.parentNode}return!1}function vK(t){var e=t.length;if(1===e)return{x:BG(t[0].clientX),y:BG(t[0].clientY)};for(var i=0,o=0,n=0;n=zG(e)?t<0?eK:iK:e<0?oK:nK}function wK(t,e,i){return{x:e/t||0,y:i/t||0}}function AK(t,e){var i=t.session,o=e.pointers,n=o.length;i.firstInput||(i.firstInput=gK(e)),n>1&&!i.firstMultiple?i.firstMultiple=gK(e):1===n&&(i.firstMultiple=!1);var r=i.firstInput,s=i.firstMultiple,a=s?s.center:r.center,l=e.center=vK(o);e.timeStamp=PG(),e.deltaTime=e.timeStamp-r.timeStamp,e.angle=mK(a,l),e.distance=yK(a,l),function(t,e){var i=e.center,o=t.offsetDelta||{},n=t.prevDelta||{},r=t.prevInput||{};e.eventType!==XG&&r.eventType!==_G||(n=t.prevDelta={x:r.deltaX||0,y:r.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=bK(e.deltaX,e.deltaY);var h,c,d=wK(e.deltaTime,e.deltaX,e.deltaY);e.overallVelocityX=d.x,e.overallVelocityY=d.y,e.overallVelocity=zG(d.x)>zG(d.y)?d.x:d.y,e.scale=s?(h=s.pointers,yK((c=o)[0],c[1],hK)/yK(h[0],h[1],hK)):1,e.rotation=s?function(t,e){return mK(e[1],e[0],hK)+mK(t[1],t[0],hK)}(s.pointers,o):0,e.maxPointers=i.prevInput?e.pointers.length>i.prevInput.maxPointers?e.pointers.length:i.prevInput.maxPointers:e.pointers.length,function(t,e){var i,o,n,r,s=t.lastInterval||e,a=e.timeStamp-s.timeStamp;if(e.eventType!==$G&&(a>JG||void 0===s.velocity)){var l=e.deltaX-s.deltaX,h=e.deltaY-s.deltaY,c=wK(a,l,h);o=c.x,n=c.y,i=zG(c.x)>zG(c.y)?c.x:c.y,r=bK(l,h),t.lastInterval=e}else i=s.velocity,o=s.velocityX,n=s.velocityY,r=s.direction;e.velocity=i,e.velocityX=o,e.velocityY=n,e.direction=r}(i,e);var u,f=t.element,p=e.srcEvent;pK(u=p.composedPath?p.composedPath()[0]:p.path?p.path[0]:p.target,f)&&(f=u),e.target=f}function EK(t,e,i){var o=i.pointers.length,n=i.changedPointers.length,r=e&XG&&o-n==0,s=e&(_G|$G)&&o-n==0;i.isFirst=!!r,i.isFinal=!!s,r&&(t.session={}),i.eventType=e,AK(t,i),t.emit("hammer.input",i),t.recognize(i),t.session.prevInput=i}function kK(t){return t.trim().split(/\s+/g)}function CK(t,e,i){cK(kK(e),(function(e){t.addEventListener(e,i,!1)}))}function xK(t,e,i){cK(kK(e),(function(e){t.removeEventListener(e,i,!1)}))}function SK(t){var e=t.ownerDocument||t;return e.defaultView||e.parentWindow||window}var IK=function(){function t(t,e){var i=this;this.manager=t,this.callback=e,this.element=t.element,this.target=t.options.inputTarget,this.domHandler=function(e){dK(t.options.enable,[t])&&i.handler(e)},this.init()}var e=t.prototype;return e.handler=function(){},e.init=function(){this.evEl&&CK(this.element,this.evEl,this.domHandler),this.evTarget&&CK(this.target,this.evTarget,this.domHandler),this.evWin&&CK(SK(this.element),this.evWin,this.domHandler)},e.destroy=function(){this.evEl&&xK(this.element,this.evEl,this.domHandler),this.evTarget&&xK(this.target,this.evTarget,this.domHandler),this.evWin&&xK(SK(this.element),this.evWin,this.domHandler)},t}();function MK(t,e,i){if(t.indexOf&&!i)return t.indexOf(e);for(var o=0;oi[e]})):o.sort()),o}var TK={touchstart:XG,touchmove:2,touchend:_G,touchcancel:$G},NK=function(t){function e(){var i;return e.prototype.evTarget="touchstart touchmove touchend touchcancel",(i=t.apply(this,arguments)||this).targetIds={},i}return SG(e,t),e.prototype.handler=function(t){var e=TK[t.type],i=jK.call(this,t,e);i&&this.callback(this.manager,e,{pointers:i[0],changedPointers:i[1],pointerType:YG,srcEvent:t})},e}(IK);function jK(t,e){var i,o,n=PK(t.touches),r=this.targetIds;if(e&(2|XG)&&1===n.length)return r[n[0].identifier]=!0,[n,n];var s=PK(t.changedTouches),a=[],l=this.target;if(o=n.filter((function(t){return pK(t.target,l)})),e===XG)for(i=0;i-1&&o.splice(t,1)}),QK)}}function VK(t,e){t&XG?(this.primaryTouch=e.changedPointers[0].identifier,HK.call(this,e)):t&(_G|$G)&&HK.call(this,e)}function WK(t){for(var e=t.srcEvent.clientX,i=t.srcEvent.clientY,o=0;o-1&&this.requireFail.splice(e,1),this},e.hasRequireFailures=function(){return this.requireFail.length>0},e.canRecognizeWith=function(t){return!!this.simultaneous[t.id]},e.emit=function(t){var e=this,i=this.state;function o(i){e.manager.emit(i,t)}i<8&&o(e.options.event+JK(i)),o(e.options.event),t.additionalEvent&&o(t.additionalEvent),i>=8&&o(e.options.event+JK(i))},e.tryEmit=function(t){if(this.canEmit())return this.emit(t);this.state=qK},e.canEmit=function(){for(var t=0;te.threshold&&n&e.direction},i.attrTest=function(t){return $K.prototype.attrTest.call(this,t)&&(2&this.state||!(2&this.state)&&this.directionTest(t))},i.emit=function(e){this.pX=e.deltaX,this.pY=e.deltaY;var i=tq(e.direction);i&&(e.additionalEvent=this.options.event+i),t.prototype.emit.call(this,e)},e}($K),iq=function(t){function e(e){return void 0===e&&(e={}),t.call(this,xG({event:"swipe",threshold:10,velocity:.3,direction:rK|sK,pointers:1},e))||this}SG(e,t);var i=e.prototype;return i.getTouchAction=function(){return eq.prototype.getTouchAction.call(this)},i.attrTest=function(e){var i,o=this.options.direction;return o&(rK|sK)?i=e.overallVelocity:o&rK?i=e.overallVelocityX:o&sK&&(i=e.overallVelocityY),t.prototype.attrTest.call(this,e)&&o&e.offsetDirection&&e.distance>this.options.threshold&&e.maxPointers===this.options.pointers&&zG(i)>this.options.velocity&&e.eventType&_G},i.emit=function(t){var e=tq(t.offsetDirection);e&&this.manager.emit(this.options.event+e,t),this.manager.emit(this.options.event,t)},e}($K),oq=function(t){function e(e){return void 0===e&&(e={}),t.call(this,xG({event:"pinch",threshold:0,pointers:2},e))||this}SG(e,t);var i=e.prototype;return i.getTouchAction=function(){return[QG]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.scale-1)>this.options.threshold||2&this.state)},i.emit=function(e){if(1!==e.scale){var i=e.scale<1?"in":"out";e.additionalEvent=this.options.event+i}t.prototype.emit.call(this,e)},e}($K),nq=function(t){function e(e){return void 0===e&&(e={}),t.call(this,xG({event:"rotate",threshold:0,pointers:2},e))||this}SG(e,t);var i=e.prototype;return i.getTouchAction=function(){return[QG]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.rotation)>this.options.threshold||2&this.state)},e}($K),rq=function(t){function e(e){var i;return void 0===e&&(e={}),(i=t.call(this,xG({event:"press",pointers:1,time:251,threshold:9},e))||this)._timer=null,i._input=null,i}SG(e,t);var i=e.prototype;return i.getTouchAction=function(){return[UG]},i.process=function(t){var e=this,i=this.options,o=t.pointers.length===i.pointers,n=t.distancei.time;if(this._input=t,!n||!o||t.eventType&(_G|$G)&&!r)this.reset();else if(t.eventType&XG)this.reset(),this._timer=setTimeout((function(){e.state=8,e.tryEmit()}),i.time);else if(t.eventType&_G)return 8;return qK},i.reset=function(){clearTimeout(this._timer)},i.emit=function(t){8===this.state&&(t&&t.eventType&_G?this.manager.emit(this.options.event+"up",t):(this._input.timeStamp=PG(),this.manager.emit(this.options.event,this._input)))},e}(XK),sq={domEvents:!1,touchAction:jG,enable:!0,inputTarget:null,inputClass:null,cssProps:{userSelect:"none",touchSelect:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}},aq=[[nq,{enable:!1}],[oq,{enable:!1},["rotate"]],[iq,{direction:rK}],[eq,{direction:rK},["swipe"]],[_K],[_K,{event:"doubletap",taps:2},["tap"]],[rq]];function lq(t,e){var i,o=t.element;o.style&&(cK(t.options.cssProps,(function(n,r){i=FG(o.style,r),e?(t.oldCssProps[i]=o.style[i],o.style[i]=n):o.style[i]=t.oldCssProps[i]||""})),e||(t.oldCssProps={}))}var hq=function(){function t(t,e){var i,o=this;this.options=OG({},sq,e||{}),this.options.inputTarget=this.options.inputTarget||t,this.handlers={},this.session={},this.recognizers=[],this.oldCssProps={},this.element=t,this.input=new((i=this).options.inputClass||(KG?zK:qG?NK:GG?GK:LK))(i,EK),this.touchAction=new fK(this,this.options.touchAction),lq(this,!0),cK(this.options.recognizers,(function(t){var e=o.add(new t[0](t[1]));t[2]&&e.recognizeWith(t[2]),t[3]&&e.requireFailure(t[3])}),this)}var e=t.prototype;return e.set=function(t){return OG(this.options,t),t.touchAction&&this.touchAction.update(),t.inputTarget&&(this.input.destroy(),this.input.target=t.inputTarget,this.input.init()),this},e.stop=function(t){this.session.stopped=t?2:1},e.recognize=function(t){var e=this.session;if(!e.stopped){var i;this.touchAction.preventDefaults(t);var o=this.recognizers,n=e.curRecognizer;(!n||n&&8&n.state)&&(e.curRecognizer=null,n=null);for(var r=0;r\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",n=window.console&&(window.console.warn||window.console.log);return n&&n.call(window.console,o,i),t.apply(this,arguments)}}var pq=fq((function(t,e,i){for(var o=Object.keys(e),n=0;n=t.length?{done:!0}:{done:!1,value:t[o++]}},e:function(t){throw t},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function Aq(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,o=new Array(e);i>>0,t=(n*=t)>>>0,t+=4294967296*(n-=t)}return 2.3283064365386963e-10*(t>>>0)}}(),e=t(" "),i=t(" "),o=t(" "),n=0;n2&&void 0!==arguments[2]&&arguments[2];for(var o in t)if(void 0!==e[o])if(null===e[o]||"object"!==pQ(e[o]))Bq(t,e,o,i);else{var n=t[o],r=e[o];Rq(n)&&Rq(r)&&zq(n,r,i)}}function Pq(t,e,i){var o=arguments.length>3&&void 0!==arguments[3]&&arguments[3];if(EH(i))throw new TypeError("Arrays are not supported by deepExtend");for(var n=0;n3&&void 0!==arguments[3]&&arguments[3];if(EH(i))throw new TypeError("Arrays are not supported by deepExtend");for(var n in i)if(Object.prototype.hasOwnProperty.call(i,n)&&!ZV(t).call(t,n))if(i[n]&&i[n].constructor===Object)void 0===e[n]&&(e[n]={}),e[n].constructor===Object?Tq(e[n],i[n]):Bq(e,i,n,o);else if(EH(i[n])){e[n]=[];for(var r=0;r2&&void 0!==arguments[2]&&arguments[2],o=arguments.length>3&&void 0!==arguments[3]&&arguments[3];for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)||!0===i)if("object"===pQ(e[n])&&null!==e[n]&&tW(e[n])===Object.prototype)void 0===t[n]?t[n]=Tq({},e[n],i):"object"===pQ(t[n])&&null!==t[n]&&tW(t[n])===Object.prototype?Tq(t[n],e[n],i):Bq(t,e,n,o);else if(EH(e[n])){var r;t[n]=vH(r=e[n]).call(r)}else Bq(t,e,n,o);return t}function Nq(t,e){var i;return pH(i=[]).call(i,aH(t),[e])}function jq(t){return t.getBoundingClientRect().top}function Uq(t,e){if(EH(t))for(var i=t.length,o=0;o3&&void 0!==arguments[3]?arguments[3]:{},n=function(t){return null!=t},r=function(t){return null!==t&&"object"===pQ(t)};if(!r(t))throw new Error("Parameter mergeTarget must be an object");if(!r(e))throw new Error("Parameter options must be an object");if(!n(i))throw new Error("Parameter option must have a value");if(!r(o))throw new Error("Parameter globalOptions must be an object");var s=e[i],a=r(o)&&!function(t){for(var e in t)if(Object.prototype.hasOwnProperty.call(t,e))return!1;return!0}(o),l=a?o[i]:void 0,h=l?l.enabled:void 0;if(void 0!==s){if("boolean"==typeof s)return r(t[i])||(t[i]={}),void(t[i].enabled=s);if(null===s&&!r(t[i])){if(!n(l))return;t[i]=WW(l)}if(r(s)){var c=!0;void 0!==s.enabled?c=s.enabled:void 0!==h&&(c=l.enabled),function(t,e,i){r(t[i])||(t[i]={});var o=e[i],n=t[i];for(var s in o)Object.prototype.hasOwnProperty.call(o,s)&&(n[s]=o[s])}(t,e,i),t[i].enabled=c}}}var Xq={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return t*(2-t)},easeInOutQuad:function(t){return t<.5?2*t*t:(4-2*t)*t-1},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return--t*t*t+1},easeInOutCubic:function(t){return t<.5?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return 1- --t*t*t*t},easeInOutQuart:function(t){return t<.5?8*t*t*t*t:1-8*--t*t*t*t},easeInQuint:function(t){return t*t*t*t*t},easeOutQuint:function(t){return 1+--t*t*t*t*t},easeInOutQuint:function(t){return t<.5?16*t*t*t*t*t:1+16*--t*t*t*t*t}};function _q(t,e){var i;EH(e)||(e=[e]);var o,n=wq(t);try{for(n.s();!(o=n.n()).done;){var r=o.value;if(r){i=r[e[0]];for(var s=1;s0&&void 0!==arguments[0]?arguments[0]:1;fN(this,t),this.pixelRatio=e,this.generated=!1,this.centerCoordinates={x:144.5,y:144.5},this.r=289*.49,this.color={r:255,g:255,b:255,a:1},this.hueCircle=void 0,this.initialColor={r:255,g:255,b:255,a:1},this.previousColor=void 0,this.applied=!1,this.updateCallback=function(){},this.closeCallback=function(){},this._create()}return mQ(t,[{key:"insertTo",value:function(t){void 0!==this.hammer&&(this.hammer.destroy(),this.hammer=void 0),this.container=t,this.container.appendChild(this.frame),this._bindHammer(),this._setSize()}},{key:"setUpdateCallback",value:function(t){if("function"!=typeof t)throw new Error("Function attempted to set as colorPicker update callback is not a function.");this.updateCallback=t}},{key:"setCloseCallback",value:function(t){if("function"!=typeof t)throw new Error("Function attempted to set as colorPicker closing callback is not a function.");this.closeCallback=t}},{key:"_isColorString",value:function(t){if("string"==typeof t)return $q[t]}},{key:"setColor",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if("none"!==t){var i,o=this._isColorString(t);if(void 0!==o&&(t=o),!0===Dq(t)){if(!0===Yq(t)){var n=t.substr(4).substr(0,t.length-5).split(",");i={r:n[0],g:n[1],b:n[2],a:1}}else if(!0===function(t){return Mq.test(t)}(t)){var r=t.substr(5).substr(0,t.length-6).split(",");i={r:r[0],g:r[1],b:r[2],a:r[3]}}else if(!0===qq(t)){var s=Lq(t);i={r:s.r,g:s.g,b:s.b,a:1}}}else if(t instanceof Object&&void 0!==t.r&&void 0!==t.g&&void 0!==t.b){var a=void 0!==t.a?t.a:"1.0";i={r:t.r,g:t.g,b:t.b,a:a}}if(void 0===i)throw new Error("Unknown color passed to the colorPicker. Supported are strings: rgb, hex, rgba. Object: rgb ({r:r,g:g,b:b,[a:a]}). Supplied: "+YW(t));this._setColor(i,e)}}},{key:"show",value:function(){void 0!==this.closeCallback&&(this.closeCallback(),this.closeCallback=void 0),this.applied=!1,this.frame.style.display="block",this._generateHueCircle()}},{key:"_hide",value:function(){var t=this;!0===(!(arguments.length>0&&void 0!==arguments[0])||arguments[0])&&(this.previousColor=AB({},this.color)),!0===this.applied&&this.updateCallback(this.initialColor),this.frame.style.display="none",fG((function(){void 0!==t.closeCallback&&(t.closeCallback(),t.closeCallback=void 0)}),0)}},{key:"_save",value:function(){this.updateCallback(this.color),this.applied=!1,this._hide()}},{key:"_apply",value:function(){this.applied=!0,this.updateCallback(this.color),this._updatePicker(this.color)}},{key:"_loadLast",value:function(){void 0!==this.previousColor?this.setColor(this.previousColor,!1):alert("There is no last color to load...")}},{key:"_setColor",value:function(t){!0===(!(arguments.length>1&&void 0!==arguments[1])||arguments[1])&&(this.initialColor=AB({},t)),this.color=t;var e=Wq(t.r,t.g,t.b),i=2*Math.PI,o=this.r*e.s,n=this.centerCoordinates.x+o*Math.sin(i*e.h),r=this.centerCoordinates.y+o*Math.cos(i*e.h);this.colorPickerSelector.style.left=n-.5*this.colorPickerSelector.clientWidth+"px",this.colorPickerSelector.style.top=r-.5*this.colorPickerSelector.clientHeight+"px",this._updatePicker(t)}},{key:"_setOpacity",value:function(t){this.color.a=t/100,this._updatePicker(this.color)}},{key:"_setBrightness",value:function(t){var e=Wq(this.color.r,this.color.g,this.color.b);e.v=t/100;var i=Gq(e.h,e.s,e.v);i.a=this.color.a,this.color=i,this._updatePicker()}},{key:"_updatePicker",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.color,e=Wq(t.r,t.g,t.b),i=this.colorPickerCanvas.getContext("2d");void 0===this.pixelRation&&(this.pixelRatio=(window.devicePixelRatio||1)/(i.webkitBackingStorePixelRatio||i.mozBackingStorePixelRatio||i.msBackingStorePixelRatio||i.oBackingStorePixelRatio||i.backingStorePixelRatio||1)),i.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var o=this.colorPickerCanvas.clientWidth,n=this.colorPickerCanvas.clientHeight;i.clearRect(0,0,o,n),i.putImageData(this.hueCircle,0,0),i.fillStyle="rgba(0,0,0,"+(1-e.v)+")",i.circle(this.centerCoordinates.x,this.centerCoordinates.y,this.r),CG(i).call(i),this.brightnessRange.value=100*e.v,this.opacityRange.value=100*t.a,this.initialColorDiv.style.backgroundColor="rgba("+this.initialColor.r+","+this.initialColor.g+","+this.initialColor.b+","+this.initialColor.a+")",this.newColorDiv.style.backgroundColor="rgba("+this.color.r+","+this.color.g+","+this.color.b+","+this.color.a+")"}},{key:"_setSize",value:function(){this.colorPickerCanvas.style.width="100%",this.colorPickerCanvas.style.height="100%",this.colorPickerCanvas.width=289*this.pixelRatio,this.colorPickerCanvas.height=289*this.pixelRatio}},{key:"_create",value:function(){var t,e,i,o;if(this.frame=document.createElement("div"),this.frame.className="vis-color-picker",this.colorPickerDiv=document.createElement("div"),this.colorPickerSelector=document.createElement("div"),this.colorPickerSelector.className="vis-selector",this.colorPickerDiv.appendChild(this.colorPickerSelector),this.colorPickerCanvas=document.createElement("canvas"),this.colorPickerDiv.appendChild(this.colorPickerCanvas),this.colorPickerCanvas.getContext){var n=this.colorPickerCanvas.getContext("2d");this.pixelRatio=(window.devicePixelRatio||1)/(n.webkitBackingStorePixelRatio||n.mozBackingStorePixelRatio||n.msBackingStorePixelRatio||n.oBackingStorePixelRatio||n.backingStorePixelRatio||1),this.colorPickerCanvas.getContext("2d").setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0)}else{var r=document.createElement("DIV");r.style.color="red",r.style.fontWeight="bold",r.style.padding="10px",r.innerText="Error: your browser does not support HTML canvas",this.colorPickerCanvas.appendChild(r)}this.colorPickerDiv.className="vis-color",this.opacityDiv=document.createElement("div"),this.opacityDiv.className="vis-opacity",this.brightnessDiv=document.createElement("div"),this.brightnessDiv.className="vis-brightness",this.arrowDiv=document.createElement("div"),this.arrowDiv.className="vis-arrow",this.opacityRange=document.createElement("input");try{this.opacityRange.type="range",this.opacityRange.min="0",this.opacityRange.max="100"}catch(t){}this.opacityRange.value="100",this.opacityRange.className="vis-range",this.brightnessRange=document.createElement("input");try{this.brightnessRange.type="range",this.brightnessRange.min="0",this.brightnessRange.max="100"}catch(t){}this.brightnessRange.value="100",this.brightnessRange.className="vis-range",this.opacityDiv.appendChild(this.opacityRange),this.brightnessDiv.appendChild(this.brightnessRange);var s=this;this.opacityRange.onchange=function(){s._setOpacity(this.value)},this.opacityRange.oninput=function(){s._setOpacity(this.value)},this.brightnessRange.onchange=function(){s._setBrightness(this.value)},this.brightnessRange.oninput=function(){s._setBrightness(this.value)},this.brightnessLabel=document.createElement("div"),this.brightnessLabel.className="vis-label vis-brightness",this.brightnessLabel.innerText="brightness:",this.opacityLabel=document.createElement("div"),this.opacityLabel.className="vis-label vis-opacity",this.opacityLabel.innerText="opacity:",this.newColorDiv=document.createElement("div"),this.newColorDiv.className="vis-new-color",this.newColorDiv.innerText="new",this.initialColorDiv=document.createElement("div"),this.initialColorDiv.className="vis-initial-color",this.initialColorDiv.innerText="initial",this.cancelButton=document.createElement("div"),this.cancelButton.className="vis-button vis-cancel",this.cancelButton.innerText="cancel",this.cancelButton.onclick=VB(t=this._hide).call(t,this,!1),this.applyButton=document.createElement("div"),this.applyButton.className="vis-button vis-apply",this.applyButton.innerText="apply",this.applyButton.onclick=VB(e=this._apply).call(e,this),this.saveButton=document.createElement("div"),this.saveButton.className="vis-button vis-save",this.saveButton.innerText="save",this.saveButton.onclick=VB(i=this._save).call(i,this),this.loadButton=document.createElement("div"),this.loadButton.className="vis-button vis-load",this.loadButton.innerText="load last",this.loadButton.onclick=VB(o=this._loadLast).call(o,this),this.frame.appendChild(this.colorPickerDiv),this.frame.appendChild(this.arrowDiv),this.frame.appendChild(this.brightnessLabel),this.frame.appendChild(this.brightnessDiv),this.frame.appendChild(this.opacityLabel),this.frame.appendChild(this.opacityDiv),this.frame.appendChild(this.newColorDiv),this.frame.appendChild(this.initialColorDiv),this.frame.appendChild(this.cancelButton),this.frame.appendChild(this.applyButton),this.frame.appendChild(this.saveButton),this.frame.appendChild(this.loadButton)}},{key:"_bindHammer",value:function(){var t=this;this.drag={},this.pinch={},this.hammer=new kq(this.colorPickerCanvas),this.hammer.get("pinch").set({enable:!0}),this.hammer.on("hammer.input",(function(e){e.isFirst&&t._moveSelector(e)})),this.hammer.on("tap",(function(e){t._moveSelector(e)})),this.hammer.on("panstart",(function(e){t._moveSelector(e)})),this.hammer.on("panmove",(function(e){t._moveSelector(e)})),this.hammer.on("panend",(function(e){t._moveSelector(e)}))}},{key:"_generateHueCircle",value:function(){if(!1===this.generated){var t=this.colorPickerCanvas.getContext("2d");void 0===this.pixelRation&&(this.pixelRatio=(window.devicePixelRatio||1)/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1)),t.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var e,i,o,n,r=this.colorPickerCanvas.clientWidth,s=this.colorPickerCanvas.clientHeight;t.clearRect(0,0,r,s),this.centerCoordinates={x:.5*r,y:.5*s},this.r=.49*r;var a,l=2*Math.PI/360,h=1/360,c=1/this.r;for(o=0;o<360;o++)for(n=0;n3&&void 0!==arguments[3]?arguments[3]:1,r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:function(){return!1};fN(this,t),this.parent=e,this.changedOptions=[],this.container=i,this.allowCreation=!1,this.hideOption=r,this.options={},this.initialized=!1,this.popupCounter=0,this.defaultOptions={enabled:!1,filter:!0,container:void 0,showButton:!0},AB(this.options,this.defaultOptions),this.configureOptions=o,this.moduleOptions={},this.domElements=[],this.popupDiv={},this.popupLimit=5,this.popupHistory={},this.colorPicker=new tY(n),this.wrapper=void 0}return mQ(t,[{key:"setOptions",value:function(t){if(void 0!==t){this.popupHistory={},this._removePopup();var e=!0;if("string"==typeof t)this.options.filter=t;else if(EH(t))this.options.filter=t.join();else if("object"===pQ(t)){if(null==t)throw new TypeError("options cannot be null");void 0!==t.container&&(this.options.container=t.container),void 0!==aW(t)&&(this.options.filter=aW(t)),void 0!==t.showButton&&(this.options.showButton=t.showButton),void 0!==t.enabled&&(e=t.enabled)}else"boolean"==typeof t?(this.options.filter=!0,e=t):"function"==typeof t&&(this.options.filter=t,e=!0);!1===aW(this.options)&&(e=!1),this.options.enabled=e}this._clean()}},{key:"setModuleOptions",value:function(t){this.moduleOptions=t,!0===this.options.enabled&&(this._clean(),void 0!==this.options.container&&(this.container=this.options.container),this._create())}},{key:"_create",value:function(){this._clean(),this.changedOptions=[];var t=aW(this.options),e=0,i=!1;for(var o in this.configureOptions)Object.prototype.hasOwnProperty.call(this.configureOptions,o)&&(this.allowCreation=!1,i=!1,"function"==typeof t?i=(i=t(o,[]))||this._handleObject(this.configureOptions[o],[o],!0):!0!==t&&-1===LW(t).call(t,o)||(i=!0),!1!==i&&(this.allowCreation=!0,e>0&&this._makeItem([]),this._makeHeader(o),this._handleObject(this.configureOptions[o],[o])),e++);this._makeButton(),this._push()}},{key:"_push",value:function(){this.wrapper=document.createElement("div"),this.wrapper.className="vis-configuration-wrapper",this.container.appendChild(this.wrapper);for(var t=0;t1?i-1:0),n=1;n2&&void 0!==arguments[2]&&arguments[2],o=document.createElement("div");if(o.className="vis-configuration vis-config-label vis-config-s"+e.length,!0===i){for(;o.firstChild;)o.removeChild(o.firstChild);o.appendChild(eY("i","b",t))}else o.innerText=t+":";return o}},{key:"_makeDropdown",value:function(t,e,i){var o=document.createElement("select");o.className="vis-configuration vis-config-select";var n=0;void 0!==e&&-1!==LW(t).call(t,e)&&(n=LW(t).call(t,e));for(var r=0;rr&&1!==r&&(a.max=Math.ceil(e*c),h=a.max,l="range increased"),a.value=e}else a.value=o;var d=document.createElement("input");d.className="vis-configuration vis-config-rangeinput",d.value=a.value;var u=this;a.onchange=function(){d.value=this.value,u._update(Number(this.value),i)},a.oninput=function(){d.value=this.value};var f=this._makeLabel(i[i.length-1],i),p=this._makeItem(i,f,a,d);""!==l&&this.popupHistory[p]!==h&&(this.popupHistory[p]=h,this._setupPopup(l,p))}},{key:"_makeButton",value:function(){var t=this;if(!0===this.options.showButton){var e=document.createElement("div");e.className="vis-configuration vis-config-button",e.innerText="generate options",e.onclick=function(){t._printOptions()},e.onmouseover=function(){e.className="vis-configuration vis-config-button hover"},e.onmouseout=function(){e.className="vis-configuration vis-config-button"},this.optionsContainer=document.createElement("div"),this.optionsContainer.className="vis-configuration vis-config-option-container",this.domElements.push(this.optionsContainer),this.domElements.push(e)}}},{key:"_setupPopup",value:function(t,e){var i=this;if(!0===this.initialized&&!0===this.allowCreation&&this.popupCounter1&&void 0!==arguments[1]?arguments[1]:[],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],o=!1,n=aW(this.options),r=!1;for(var s in t)if(Object.prototype.hasOwnProperty.call(t,s)){o=!0;var a=t[s],l=Nq(e,s);if("function"==typeof n&&!1===(o=n(s,e))&&!EH(a)&&"string"!=typeof a&&"boolean"!=typeof a&&a instanceof Object&&(this.allowCreation=!1,o=this._handleObject(a,l,!0),this.allowCreation=!1===i),!1!==o){r=!0;var h=this._getValue(l);if(EH(a))this._handleArray(a,h,l);else if("string"==typeof a)this._makeTextInput(a,h,l);else if("boolean"==typeof a)this._makeCheckbox(a,h,l);else if(a instanceof Object){if(!this.hideOption(e,s,this.moduleOptions))if(void 0!==a.enabled){var c=Nq(l,"enabled"),d=this._getValue(c);if(!0===d){var u=this._makeLabel(s,l,!0);this._makeItem(l,u),r=this._handleObject(a,l)||r}else this._makeCheckbox(a,d,l)}else{var f=this._makeLabel(s,l,!0);this._makeItem(l,f),r=this._handleObject(a,l)||r}}else console.error("dont know how to handle",a,s,l)}}return r}},{key:"_handleArray",value:function(t,e,i){"string"==typeof t[0]&&"color"===t[0]?(this._makeColorField(t,e,i),t[1]!==e&&this.changedOptions.push({path:i,value:e})):"string"==typeof t[0]?(this._makeDropdown(t,e,i),t[0]!==e&&this.changedOptions.push({path:i,value:e})):"number"==typeof t[0]&&(this._makeRange(t,e,i),t[0]!==e&&this.changedOptions.push({path:i,value:Number(e)}))}},{key:"_update",value:function(t,e){var i=this._constructOptions(t,e);this.parent.body&&this.parent.body.emitter&&this.parent.body.emitter.emit&&this.parent.body.emitter.emit("configChange",i),this.initialized=!0,this.parent.setOptions(i)}},{key:"_constructOptions",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},o=i;t="false"!==(t="true"===t||t)&&t;for(var n=0;nn-this.padding&&(a=!0),r=a?this.x-i:this.x,s=l?this.y-e:this.y}else(s=this.y-e)+e+this.padding>o&&(s=o-e-this.padding),sn&&(r=n-i-this.padding),rs.distance?" in "+t.printLocation(r.path,e,"")+"Perhaps it was misplaced? Matching option found at: "+t.printLocation(s.path,s.closestMatch,""):r.distance<=8?'. Did you mean "'+r.closestMatch+'"?'+t.printLocation(r.path,e):". Did you mean one of these: "+t.print(BH(i))+t.printLocation(o,e),console.error('%cUnknown option detected: "'+e+'"'+n,sY),rY=!0}},{key:"findInOptions",value:function(e,i,o){var n,r=arguments.length>3&&void 0!==arguments[3]&&arguments[3],s=1e9,a="",l=[],h=e.toLowerCase(),c=void 0;for(var d in i){var u=void 0;if(void 0!==i[d].__type__&&!0===r){var f=t.findInOptions(e,i[d],Nq(o,d));s>f.distance&&(a=f.closestMatch,l=f.path,s=f.distance,c=f.indexMatch)}else{var p;-1!==LW(p=d.toLowerCase()).call(p,h)&&(c=d),s>(u=t.levenshteinDistance(e,d))&&(a=d,l=vH(n=o).call(n),s=u)}}return{closestMatch:a,path:l,distance:s,indexMatch:c}}},{key:"printLocation",value:function(t,e){for(var i="\n\n"+(arguments.length>2&&void 0!==arguments[2]?arguments[2]:"Problem value found at: \n")+"options = {\n",o=0;o":!0,"--":!0},bY="",wY=0,AY="",EY="",kY=yY.NULL;function CY(){wY++,AY=bY.charAt(wY)}function xY(){return bY.charAt(wY+1)}function SY(t){var e=t.charCodeAt(0);return e<47?35===e||46===e:e<59?e>47:e<91?e>64:e<96?95===e:e<123&&e>96}function IY(t,e){if(t||(t={}),e)for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function MY(t,e,i){for(var o=e.split("."),n=t;o.length;){var r=o.shift();o.length?(n[r]||(n[r]={}),n=n[r]):n[r]=i}}function OY(t,e){for(var i,o,n=null,r=[t],s=t;s.parent;)r.push(s.parent),s=s.parent;if(s.nodes)for(i=0,o=s.nodes.length;i=0;i--){var a,l=r[i];l.nodes||(l.nodes=[]),-1===LW(a=l.nodes).call(a,n)&&l.nodes.push(n)}e.attr&&(n.attr=IY(n.attr,e.attr))}function DY(t,e){if(t.edges||(t.edges=[]),t.edges.push(e),t.edge){var i=IY({},t.edge);e.attr=IY(i,e.attr)}}function RY(t,e,i,o,n){var r={from:e,to:i,type:o};return t.edge&&(r.attr=IY({},t.edge)),r.attr=IY(r.attr||{},n),null!=n&&n.hasOwnProperty("arrows")&&null!=n.arrows&&(r.arrows={to:{enabled:!0,type:n.arrows.type}},n.arrows=null),r}function BY(){for(kY=yY.NULL,EY="";" "===AY||"\t"===AY||"\n"===AY||"\r"===AY;)CY();do{var t=!1;if("#"===AY){for(var e=wY-1;" "===bY.charAt(e)||"\t"===bY.charAt(e);)e--;if("\n"===bY.charAt(e)||""===bY.charAt(e)){for(;""!=AY&&"\n"!=AY;)CY();t=!0}}if("/"===AY&&"/"===xY()){for(;""!=AY&&"\n"!=AY;)CY();t=!0}if("/"===AY&&"*"===xY()){for(;""!=AY;){if("*"===AY&&"/"===xY()){CY(),CY();break}CY()}t=!0}for(;" "===AY||"\t"===AY||"\n"===AY||"\r"===AY;)CY()}while(t);if(""!==AY){var i=AY+xY();if(mY[i])return kY=yY.DELIMITER,EY=i,CY(),void CY();if(mY[AY])return kY=yY.DELIMITER,EY=AY,void CY();if(SY(AY)||"-"===AY){for(EY+=AY,CY();SY(AY);)EY+=AY,CY();return"false"===EY?EY=!1:"true"===EY?EY=!0:isNaN(Number(EY))||(EY=Number(EY)),void(kY=yY.IDENTIFIER)}if('"'===AY){for(CY();""!=AY&&('"'!=AY||'"'===AY&&'"'===xY());)'"'===AY?(EY+=AY,CY()):"\\"===AY&&"n"===xY()?(EY+="\n",CY()):EY+=AY,CY();if('"'!=AY)throw jY('End of string " expected');return CY(),void(kY=yY.IDENTIFIER)}for(kY=yY.UNKNOWN;""!=AY;)EY+=AY,CY();throw new SyntaxError('Syntax error in part "'+UY(EY,30)+'"')}kY=yY.DELIMITER}function zY(t){for(;""!==EY&&"}"!=EY;)PY(t),";"===EY&&BY()}function PY(t){var e=FY(t);if(e)TY(t,e);else{var i=function(t){if("node"===EY)return BY(),t.node=NY(),"node";if("edge"===EY)return BY(),t.edge=NY(),"edge";if("graph"===EY)return BY(),t.graph=NY(),"graph";return null}(t);if(!i){if(kY!=yY.IDENTIFIER)throw jY("Identifier expected");var o=EY;if(BY(),"="===EY){if(BY(),kY!=yY.IDENTIFIER)throw jY("Identifier expected");t[o]=EY,BY()}else!function(t,e){var i={id:e},o=NY();o&&(i.attr=o);OY(t,i),TY(t,e)}(t,o)}}}function FY(t){var e=null;if("subgraph"===EY&&((e={}).type="subgraph",BY(),kY===yY.IDENTIFIER&&(e.id=EY,BY())),"{"===EY){if(BY(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,zY(e),"}"!=EY)throw jY("Angle bracket } expected");BY(),delete e.node,delete e.edge,delete e.graph,delete e.parent,t.subgraphs||(t.subgraphs=[]),t.subgraphs.push(e)}return e}function TY(t,e){for(;"->"===EY||"--"===EY;){var i,o=EY;BY();var n=FY(t);if(n)i=n;else{if(kY!=yY.IDENTIFIER)throw jY("Identifier or subgraph expected");OY(t,{id:i=EY}),BY()}DY(t,RY(t,e,i,o,NY())),e=i}}function NY(){for(var t,e,i=null,o={dashed:!0,solid:!1,dotted:[1,5]},n={dot:"circle",box:"box",crow:"crow",curve:"curve",icurve:"inv_curve",normal:"triangle",inv:"inv_triangle",diamond:"diamond",tee:"bar",vee:"vee"},r=new Array,s=new Array;"["===EY;){for(BY(),i={};""!==EY&&"]"!=EY;){if(kY!=yY.IDENTIFIER)throw jY("Attribute name expected");var a=EY;if(BY(),"="!=EY)throw jY("Equal sign = expected");if(BY(),kY!=yY.IDENTIFIER)throw jY("Attribute value expected");var l=EY;"style"===a&&(l=o[l]),"arrowhead"===a&&(a="arrows",l={to:{enabled:!0,type:n[l]}}),"arrowtail"===a&&(a="arrows",l={from:{enabled:!0,type:n[l]}}),r.push({attr:i,name:a,value:l}),s.push(a),BY(),","==EY&&BY()}if("]"!=EY)throw jY("Bracket ] expected");BY()}if(ZV(s).call(s,"dir")){var h={arrows:{}};for(t=0;t"===t.type&&(e.arrows="to"),e};ZH(n=i.edges).call(n,(function(t){var e,i,n,s,a,l,h;(e=t.from instanceof Object?t.from.nodes:{id:t.from},i=t.to instanceof Object?t.to.nodes:{id:t.to},t.from instanceof Object&&t.from.edges)&&ZH(n=t.from.edges).call(n,(function(t){var e=r(t);o.edges.push(e)}));(a=i,l=function(e,i){var n=RY(o,e.id,i.id,t.type,t.attr),s=r(n);o.edges.push(s)},EH(s=e)?ZH(s).call(s,(function(t){EH(a)?ZH(a).call(a,(function(e){l(t,e)})):l(t,a)})):EH(a)?ZH(a).call(a,(function(t){l(s,t)})):l(s,a),t.to instanceof Object&&t.to.edges)&&ZH(h=t.to.edges).call(h,(function(t){var e=r(t);o.edges.push(e)}))}))}return i.attr&&(o.options=i.attr),o}var VY=Object.freeze({__proto__:null,cn:{addDescription:"单击空白处放置新节点。",addEdge:"添加连接线",addNode:"添加节点",back:"返回",close:"關閉",createEdgeError:"无法将连接线连接到群集。",del:"删除选定",deleteClusterError:"无法删除群集。",edgeDescription:"单击某个节点并将该连接线拖动到另一个节点以连接它们。",edit:"编辑",editClusterError:"无法编辑群集。",editEdge:"编辑连接线",editEdgeDescription:"单击控制节点并将它们拖到节点上连接。",editNode:"编辑节点"},cs:{addDescription:"Kluknutím do prázdného prostoru můžete přidat nový vrchol.",addEdge:"Přidat hranu",addNode:"Přidat vrchol",back:"Zpět",close:"Zavřít",createEdgeError:"Nelze připojit hranu ke shluku.",del:"Smazat výběr",deleteClusterError:"Nelze mazat shluky.",edgeDescription:"Přetažením z jednoho vrcholu do druhého můžete spojit tyto vrcholy novou hranou.",edit:"Upravit",editClusterError:"Nelze upravovat shluky.",editEdge:"Upravit hranu",editEdgeDescription:"Přetažením kontrolního vrcholu hrany ji můžete připojit k jinému vrcholu.",editNode:"Upravit vrchol"},de:{addDescription:"Klicke auf eine freie Stelle, um einen neuen Knoten zu plazieren.",addEdge:"Kante hinzufügen",addNode:"Knoten hinzufügen",back:"Zurück",close:"Schließen",createEdgeError:"Es ist nicht möglich, Kanten mit Clustern zu verbinden.",del:"Lösche Auswahl",deleteClusterError:"Cluster können nicht gelöscht werden.",edgeDescription:"Klicke auf einen Knoten und ziehe die Kante zu einem anderen Knoten, um diese zu verbinden.",edit:"Editieren",editClusterError:"Cluster können nicht editiert werden.",editEdge:"Kante editieren",editEdgeDescription:"Klicke auf die Verbindungspunkte und ziehe diese auf einen Knoten, um sie zu verbinden.",editNode:"Knoten editieren"},en:{addDescription:"Click in an empty space to place a new node.",addEdge:"Add Edge",addNode:"Add Node",back:"Back",close:"Close",createEdgeError:"Cannot link edges to a cluster.",del:"Delete selected",deleteClusterError:"Clusters cannot be deleted.",edgeDescription:"Click on a node and drag the edge to another node to connect them.",edit:"Edit",editClusterError:"Clusters cannot be edited.",editEdge:"Edit Edge",editEdgeDescription:"Click on the control points and drag them to a node to connect to it.",editNode:"Edit Node"},es:{addDescription:"Haga clic en un lugar vacío para colocar un nuevo nodo.",addEdge:"Añadir arista",addNode:"Añadir nodo",back:"Atrás",close:"Cerrar",createEdgeError:"No se puede conectar una arista a un grupo.",del:"Eliminar selección",deleteClusterError:"No es posible eliminar grupos.",edgeDescription:"Haga clic en un nodo y arrastre la arista hacia otro nodo para conectarlos.",edit:"Editar",editClusterError:"No es posible editar grupos.",editEdge:"Editar arista",editEdgeDescription:"Haga clic en un punto de control y arrastrelo a un nodo para conectarlo.",editNode:"Editar nodo"},fr:{addDescription:"Cliquez dans un endroit vide pour placer un nœud.",addEdge:"Ajouter un lien",addNode:"Ajouter un nœud",back:"Retour",close:"Fermer",createEdgeError:"Impossible de créer un lien vers un cluster.",del:"Effacer la sélection",deleteClusterError:"Les clusters ne peuvent pas être effacés.",edgeDescription:"Cliquez sur un nœud et glissez le lien vers un autre nœud pour les connecter.",edit:"Éditer",editClusterError:"Les clusters ne peuvent pas être édités.",editEdge:"Éditer le lien",editEdgeDescription:"Cliquez sur les points de contrôle et glissez-les pour connecter un nœud.",editNode:"Éditer le nœud"},it:{addDescription:"Clicca per aggiungere un nuovo nodo",addEdge:"Aggiungi un vertice",addNode:"Aggiungi un nodo",back:"Indietro",close:"Chiudere",createEdgeError:"Non si possono collegare vertici ad un cluster",del:"Cancella la selezione",deleteClusterError:"I cluster non possono essere cancellati",edgeDescription:"Clicca su un nodo e trascinalo ad un altro nodo per connetterli.",edit:"Modifica",editClusterError:"I clusters non possono essere modificati.",editEdge:"Modifica il vertice",editEdgeDescription:"Clicca sui Punti di controllo e trascinali ad un nodo per connetterli.",editNode:"Modifica il nodo"},nl:{addDescription:"Klik op een leeg gebied om een nieuwe node te maken.",addEdge:"Link toevoegen",addNode:"Node toevoegen",back:"Terug",close:"Sluiten",createEdgeError:"Kan geen link maken naar een cluster.",del:"Selectie verwijderen",deleteClusterError:"Clusters kunnen niet worden verwijderd.",edgeDescription:"Klik op een node en sleep de link naar een andere node om ze te verbinden.",edit:"Wijzigen",editClusterError:"Clusters kunnen niet worden aangepast.",editEdge:"Link wijzigen",editEdgeDescription:"Klik op de verbindingspunten en sleep ze naar een node om daarmee te verbinden.",editNode:"Node wijzigen"},pt:{addDescription:"Clique em um espaço em branco para adicionar um novo nó",addEdge:"Adicionar aresta",addNode:"Adicionar nó",back:"Voltar",close:"Fechar",createEdgeError:"Não foi possível linkar arestas a um cluster.",del:"Remover selecionado",deleteClusterError:"Clusters não puderam ser removidos.",edgeDescription:"Clique em um nó e arraste a aresta até outro nó para conectá-los",edit:"Editar",editClusterError:"Clusters não puderam ser editados.",editEdge:"Editar aresta",editEdgeDescription:"Clique nos pontos de controle e os arraste para um nó para conectá-los",editNode:"Editar nó"},ru:{addDescription:"Кликните в свободное место, чтобы добавить новый узел.",addEdge:"Добавить ребро",addNode:"Добавить узел",back:"Назад",close:"Закрывать",createEdgeError:"Невозможно соединить ребра в кластер.",del:"Удалить выбранное",deleteClusterError:"Кластеры не могут быть удалены",edgeDescription:"Кликните на узел и протяните ребро к другому узлу, чтобы соединить их.",edit:"Редактировать",editClusterError:"Кластеры недоступны для редактирования.",editEdge:"Редактировать ребро",editEdgeDescription:"Кликните на контрольные точки и перетащите их в узел, чтобы подключиться к нему.",editNode:"Редактировать узел"},uk:{addDescription:"Kлікніть на вільне місце, щоб додати новий вузол.",addEdge:"Додати край",addNode:"Додати вузол",back:"Назад",close:"Закрити",createEdgeError:"Не можливо об'єднати краї в групу.",del:"Видалити обране",deleteClusterError:"Групи не можуть бути видалені.",edgeDescription:"Клікніть на вузол і перетягніть край до іншого вузла, щоб їх з'єднати.",edit:"Редагувати",editClusterError:"Групи недоступні для редагування.",editEdge:"Редагувати край",editEdgeDescription:"Клікніть на контрольні точки і перетягніть їх у вузол, щоб підключитися до нього.",editNode:"Редагувати вузол"}});var WY=function(){function t(){fN(this,t),this.NUM_ITERATIONS=4,this.image=new Image,this.canvas=document.createElement("canvas")}return mQ(t,[{key:"init",value:function(){if(!this.initialized()){this.src=this.image.src;var t=this.image.width,e=this.image.height;this.width=t,this.height=e;var i=Math.floor(e/2),o=Math.floor(e/4),n=Math.floor(e/8),r=Math.floor(e/16),s=Math.floor(t/2),a=Math.floor(t/4),l=Math.floor(t/8),h=Math.floor(t/16);this.canvas.width=3*a,this.canvas.height=i,this.coordinates=[[0,0,s,i],[s,0,a,o],[s,o,l,n],[5*l,o,h,r]],this._fillMipMap()}}},{key:"initialized",value:function(){return void 0!==this.coordinates}},{key:"_fillMipMap",value:function(){var t=this.canvas.getContext("2d"),e=this.coordinates[0];t.drawImage(this.image,e[0],e[1],e[2],e[3]);for(var i=1;i2){e*=.5;for(var s=0;e>2&&s=this.NUM_ITERATIONS&&(s=this.NUM_ITERATIONS-1);var a=this.coordinates[s];t.drawImage(this.canvas,a[0],a[1],a[2],a[3],i,o,n,r)}else t.drawImage(this.image,i,o,n,r)}}]),t}(),GY=function(){function t(e){fN(this,t),this.images={},this.imageBroken={},this.callback=e}return mQ(t,[{key:"_tryloadBrokenUrl",value:function(t,e,i){void 0!==t&&void 0!==i&&(void 0!==e?(i.image.onerror=function(){console.error("Could not load brokenImage:",e)},i.image.src=e):console.warn("No broken url image defined"))}},{key:"_redrawWithImage",value:function(t){this.callback&&this.callback(t)}},{key:"load",value:function(t,e){var i=this,o=this.images[t];if(o)return o;var n=new WY;return this.images[t]=n,n.image.onload=function(){i._fixImageCoordinates(n.image),n.init(),i._redrawWithImage(n)},n.image.onerror=function(){console.error("Could not load image:",t),i._tryloadBrokenUrl(t,e,n)},n.image.src=t,n}},{key:"_fixImageCoordinates",value:function(t){0===t.width&&(document.body.appendChild(t),t.width=t.offsetWidth,t.height=t.offsetHeight,document.body.removeChild(t))}}]),t}(),KY={exports:{}},qY=aM((function(){if("function"==typeof ArrayBuffer){var t=new ArrayBuffer(8);Object.isExtensible(t)&&Object.defineProperty(t,"a",{value:8})}})),YY=aM,ZY=iO,JY=EM,XY=qY,_Y=Object.isExtensible,$Y=YY((function(){_Y(1)}))||XY?function(t){return!!ZY(t)&&((!XY||"ArrayBuffer"!==JY(t))&&(!_Y||_Y(t)))}:_Y,tZ=!aM((function(){return Object.isExtensible(Object.preventExtensions({}))})),eZ=DR,iZ=mM,oZ=ZR,nZ=iO,rZ=tD,sZ=$D.f,aZ=XN,lZ=tj,hZ=$Y,cZ=tZ,dZ=!1,uZ=rD("meta"),fZ=0,pZ=function(t){sZ(t,uZ,{value:{objectID:"O"+fZ++,weakData:{}}})},vZ=KY.exports={enable:function(){vZ.enable=function(){},dZ=!0;var t=aZ.f,e=iZ([].splice),i={};i[uZ]=1,t(i).length&&(aZ.f=function(i){for(var o=t(i),n=0,r=o.length;nr;r++)if((a=y(t[r]))&&kZ(OZ,a))return a;return new MZ(!1)}o=CZ(t,n)}for(l=u?t.next:o.next;!(h=mZ(l,o)).done;){try{a=y(h.value)}catch(t){SZ(o,"throw",t)}if("object"==typeof a&&a&&kZ(OZ,a))return a}return new MZ(!1)},RZ=hO,BZ=TypeError,zZ=function(t,e){if(RZ(e,t))return t;throw new BZ("Incorrect invocation")},PZ=DR,FZ=sM,TZ=gZ,NZ=aM,jZ=mR,UZ=DZ,LZ=zZ,QZ=OM,HZ=iO,VZ=qM,WZ=ZP,GZ=$D.f,KZ=zj.forEach,qZ=RM,YZ=Qz.set,ZZ=Qz.getterFor,JZ=function(t,e,i){var o,n=-1!==t.indexOf("Map"),r=-1!==t.indexOf("Weak"),s=n?"set":"add",a=FZ[t],l=a&&a.prototype,h={};if(qZ&&QZ(a)&&(r||l.forEach&&!NZ((function(){(new a).entries().next()})))){var c=(o=e((function(e,i){YZ(LZ(e,c),{type:t,collection:new a}),VZ(i)||UZ(i,e[s],{that:e,AS_ENTRIES:n})}))).prototype,d=ZZ(t);KZ(["add","clear","delete","forEach","get","has","set","keys","values","entries"],(function(t){var e="add"===t||"set"===t;!(t in l)||r&&"clear"===t||jZ(c,t,(function(i,o){var n=d(this).collection;if(!e&&r&&!HZ(i))return"get"===t&&void 0;var s=n[t](0===i?0:i,o);return e?this:s}))})),r||GZ(c,"size",{configurable:!0,get:function(){return d(this).collection.size}})}else o=i.getConstructor(e,t,n,s),TZ.enable();return WZ(o,t,!1,!0),h[t]=o,PZ({global:!0,forced:!0},h),r||i.setStrong(o,t,n),o},XZ=DP,_Z=function(t,e,i){for(var o in e)i&&i.unsafe&&t[o]?t[o]=e[o]:XZ(t,o,e[o],i);return t},$Z=lO,tJ=fj,eJ=RM,iJ=pD("species"),oJ=bP,nJ=fj,rJ=_Z,sJ=_D,aJ=zZ,lJ=qM,hJ=DZ,cJ=SF,dJ=IF,uJ=function(t){var e=$Z(t);eJ&&e&&!e[iJ]&&tJ(e,iJ,{configurable:!0,get:function(){return this}})},fJ=RM,pJ=gZ.fastKey,vJ=Qz.set,gJ=Qz.getterFor,yJ={getConstructor:function(t,e,i,o){var n=t((function(t,n){aJ(t,r),vJ(t,{type:e,index:oJ(null),first:void 0,last:void 0,size:0}),fJ||(t.size=0),lJ(n)||hJ(n,t[o],{that:t,AS_ENTRIES:i})})),r=n.prototype,s=gJ(e),a=function(t,e,i){var o,n,r=s(t),a=l(t,e);return a?a.value=i:(r.last=a={index:n=pJ(e,!0),key:e,value:i,previous:o=r.last,next:void 0,removed:!1},r.first||(r.first=a),o&&(o.next=a),fJ?r.size++:t.size++,"F"!==n&&(r.index[n]=a)),t},l=function(t,e){var i,o=s(t),n=pJ(e);if("F"!==n)return o.index[n];for(i=o.first;i;i=i.next)if(i.key===e)return i};return rJ(r,{clear:function(){for(var t=s(this),e=t.index,i=t.first;i;)i.removed=!0,i.previous&&(i.previous=i.previous.next=void 0),delete e[i.index],i=i.next;t.first=t.last=void 0,fJ?t.size=0:this.size=0},delete:function(t){var e=this,i=s(e),o=l(e,t);if(o){var n=o.next,r=o.previous;delete i.index[o.index],o.removed=!0,r&&(r.next=n),n&&(n.previous=r),i.first===o&&(i.first=n),i.last===o&&(i.last=r),fJ?i.size--:e.size--}return!!o},forEach:function(t){for(var e,i=s(this),o=sJ(t,arguments.length>1?arguments[1]:void 0);e=e?e.next:i.first;)for(o(e.value,e.key,this);e&&e.removed;)e=e.previous},has:function(t){return!!l(this,t)}}),rJ(r,i?{get:function(t){var e=l(this,t);return e&&e.value},set:function(t,e){return a(this,0===t?0:t,e)}}:{add:function(t){return a(this,t=0===t?0:t,t)}}),fJ&&nJ(r,"size",{configurable:!0,get:function(){return s(this).size}}),n},setStrong:function(t,e,i){var o=e+" Iterator",n=gJ(e),r=gJ(o);cJ(t,e,(function(t,e){vJ(this,{type:o,target:t,state:n(t),kind:e,last:void 0})}),(function(){for(var t=r(this),e=t.kind,i=t.last;i&&i.removed;)i=i.previous;return t.target&&(t.last=i=i?i.next:t.state.first)?dJ("keys"===e?i.key:"values"===e?i.value:[i.key,i.value],!1):(t.target=void 0,dJ(void 0,!0))}),i?"entries":"values",!i,!0),uJ(e)}};JZ("Map",(function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}}),yJ);var mJ=nM(oO.Map),bJ=function(){function t(){fN(this,t),this.clear(),this._defaultIndex=0,this._groupIndex=0,this._defaultGroups=[{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"},hover:{border:"#2B7CE9",background:"#D2E5FF"}},{border:"#FFA500",background:"#FFFF00",highlight:{border:"#FFA500",background:"#FFFFA3"},hover:{border:"#FFA500",background:"#FFFFA3"}},{border:"#FA0A10",background:"#FB7E81",highlight:{border:"#FA0A10",background:"#FFAFB1"},hover:{border:"#FA0A10",background:"#FFAFB1"}},{border:"#41A906",background:"#7BE141",highlight:{border:"#41A906",background:"#A1EC76"},hover:{border:"#41A906",background:"#A1EC76"}},{border:"#E129F0",background:"#EB7DF4",highlight:{border:"#E129F0",background:"#F0B3F5"},hover:{border:"#E129F0",background:"#F0B3F5"}},{border:"#7C29F0",background:"#AD85E4",highlight:{border:"#7C29F0",background:"#D3BDF0"},hover:{border:"#7C29F0",background:"#D3BDF0"}},{border:"#C37F00",background:"#FFA807",highlight:{border:"#C37F00",background:"#FFCA66"},hover:{border:"#C37F00",background:"#FFCA66"}},{border:"#4220FB",background:"#6E6EFD",highlight:{border:"#4220FB",background:"#9B9BFD"},hover:{border:"#4220FB",background:"#9B9BFD"}},{border:"#FD5A77",background:"#FFC0CB",highlight:{border:"#FD5A77",background:"#FFD1D9"},hover:{border:"#FD5A77",background:"#FFD1D9"}},{border:"#4AD63A",background:"#C2FABC",highlight:{border:"#4AD63A",background:"#E6FFE3"},hover:{border:"#4AD63A",background:"#E6FFE3"}},{border:"#990000",background:"#EE0000",highlight:{border:"#BB0000",background:"#FF3333"},hover:{border:"#BB0000",background:"#FF3333"}},{border:"#FF6000",background:"#FF6000",highlight:{border:"#FF6000",background:"#FF6000"},hover:{border:"#FF6000",background:"#FF6000"}},{border:"#97C2FC",background:"#2B7CE9",highlight:{border:"#D2E5FF",background:"#2B7CE9"},hover:{border:"#D2E5FF",background:"#2B7CE9"}},{border:"#399605",background:"#255C03",highlight:{border:"#399605",background:"#255C03"},hover:{border:"#399605",background:"#255C03"}},{border:"#B70054",background:"#FF007E",highlight:{border:"#B70054",background:"#FF007E"},hover:{border:"#B70054",background:"#FF007E"}},{border:"#AD85E4",background:"#7C29F0",highlight:{border:"#D3BDF0",background:"#7C29F0"},hover:{border:"#D3BDF0",background:"#7C29F0"}},{border:"#4557FA",background:"#000EA1",highlight:{border:"#6E6EFD",background:"#000EA1"},hover:{border:"#6E6EFD",background:"#000EA1"}},{border:"#FFC0CB",background:"#FD5A77",highlight:{border:"#FFD1D9",background:"#FD5A77"},hover:{border:"#FFD1D9",background:"#FD5A77"}},{border:"#C2FABC",background:"#74D66A",highlight:{border:"#E6FFE3",background:"#74D66A"},hover:{border:"#E6FFE3",background:"#74D66A"}},{border:"#EE0000",background:"#990000",highlight:{border:"#FF3333",background:"#BB0000"},hover:{border:"#FF3333",background:"#BB0000"}}],this.options={},this.defaultOptions={useDefaultGroups:!0},AB(this.options,this.defaultOptions)}return mQ(t,[{key:"setOptions",value:function(t){var e=["useDefaultGroups"];if(void 0!==t)for(var i in t)if(Object.prototype.hasOwnProperty.call(t,i)&&-1===LW(e).call(e,i)){var o=t[i];this.add(i,o)}}},{key:"clear",value:function(){this._groups=new mJ,this._groupNames=[]}},{key:"get",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=this._groups.get(t);if(void 0===i&&e)if(!1===this.options.useDefaultGroups&&this._groupNames.length>0){var o=this._groupIndex%this._groupNames.length;++this._groupIndex,(i={}).color=this._groups.get(this._groupNames[o]),this._groups.set(t,i)}else{var n=this._defaultIndex%this._defaultGroups.length;this._defaultIndex++,(i={}).color=this._defaultGroups[n],this._groups.set(t,i)}return i}},{key:"add",value:function(t,e){return this._groups.has(t)||this._groupNames.push(t),this._groups.set(t,e),e}}]),t}();DR({target:"Number",stat:!0},{isNaN:function(t){return t!=t}});var wJ=nM(oO.Number.isNaN),AJ=sM.isFinite,EJ=Number.isFinite||function(t){return"number"==typeof t&&AJ(t)};DR({target:"Number",stat:!0},{isFinite:EJ});var kJ=nM(oO.Number.isFinite),CJ=zj.some;DR({target:"Array",proto:!0,forced:!jH("some")},{some:function(t){return CJ(this,t,arguments.length>1?arguments[1]:void 0)}});var xJ=TB("Array").some,SJ=hO,IJ=xJ,MJ=Array.prototype,OJ=function(t){var e=t.some;return t===MJ||SJ(MJ,t)&&e===MJ.some?IJ:e},DJ=nM(OJ),RJ=nM(oO.Object.getOwnPropertySymbols),BJ={exports:{}},zJ=DR,PJ=aM,FJ=$M,TJ=DM.f,NJ=RM;zJ({target:"Object",stat:!0,forced:!NJ||PJ((function(){TJ(1)})),sham:!NJ},{getOwnPropertyDescriptor:function(t,e){return TJ(FJ(t),e)}});var jJ=oO.Object,UJ=BJ.exports=function(t,e){return jJ.getOwnPropertyDescriptor(t,e)};jJ.getOwnPropertyDescriptor.sham&&(UJ.sham=!0);var LJ=BJ.exports,QJ=nM(LJ),HJ=AH,VJ=$M,WJ=DM,GJ=fT;DR({target:"Object",stat:!0,sham:!RM},{getOwnPropertyDescriptors:function(t){for(var e,i,o=VJ(t),n=WJ.f,r=HJ(o),s={},a=0;r.length>a;)void 0!==(i=n(o,e=r[a++]))&&GJ(s,e,i);return s}});var KJ=nM(oO.Object.getOwnPropertyDescriptors),qJ={exports:{}},YJ=DR,ZJ=RM,JJ=Yz.f;YJ({target:"Object",stat:!0,forced:Object.defineProperties!==JJ,sham:!ZJ},{defineProperties:JJ});var XJ=oO.Object,_J=qJ.exports=function(t,e){return XJ.defineProperties(t,e)};XJ.defineProperties.sham&&(_J.sham=!0);var $J=nM(qJ.exports),tX=nM(wN);function eX(t,e,i){return(e=gQ(e))in t?AN(t,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[e]=i,t}var iX=sM,oX=aM,nX=uz,rX=gW.trim,sX=lW,aX=mM("".charAt),lX=iX.parseFloat,hX=iX.Symbol,cX=hX&&hX.iterator,dX=1/lX(sX+"-0")!=-1/0||cX&&!oX((function(){lX(Object(cX))}))?function(t){var e=rX(nX(t)),i=lX(e);return 0===i&&"-"===aX(e,0)?-0:i}:lX;DR({global:!0,forced:parseFloat!==dX},{parseFloat:dX});var uX=nM(oO.parseFloat),fX=DR,pX=aM,vX=tj.f;fX({target:"Object",stat:!0,forced:pX((function(){return!Object.getOwnPropertyNames(1)}))},{getOwnPropertyNames:vX});var gX=oO.Object,yX=function(t){return gX.getOwnPropertyNames(t)},mX=nM(yX);function bX(t,e){var i=["node","edge","label"],o=!0,n=_q(e,"chosen");if("boolean"==typeof n)o=n;else if("object"===pQ(n)){if(-1===LW(i).call(i,t))throw new Error("choosify: subOption '"+t+"' should be one of '"+i.join("', '")+"'");var r=_q(e,["chosen",t]);"boolean"!=typeof r&&"function"!=typeof r||(o=r)}return o}function wX(t,e,i){if(t.width<=0||t.height<=0)return!1;if(void 0!==i){var o={x:e.x-i.x,y:e.y-i.y};if(0!==i.angle){var n=-i.angle;e={x:Math.cos(n)*o.x-Math.sin(n)*o.y,y:Math.sin(n)*o.x+Math.cos(n)*o.y}}else e=o}var r=t.x+t.width,s=t.y+t.width;return t.lefte.x&&t.tope.y}function AX(t){return"string"==typeof t&&""!==t}function EX(t,e,i,o){var n=o.x,r=o.y;if("function"==typeof o.distanceToBorder){var s=o.distanceToBorder(t,e),a=Math.sin(e)*s,l=Math.cos(e)*s;l===s?(n+=s,r=o.y):a===s?(n=o.x,r-=s):(n+=l,r-=a)}else o.shape.width>o.shape.height?(n=o.x+.5*o.shape.width,r=o.y-i):(n=o.x+i,r=o.y-.5*o.shape.height);return{x:n,y:r}}var kX=TB("Array").values,CX=hz,xX=tD,SX=hO,IX=kX,MX=Array.prototype,OX={DOMTokenList:!0,NodeList:!0},DX=function(t){var e=t.values;return t===MX||SX(MX,t)&&e===MX.values||xX(OX,CX(t))?IX:e},RX=nM(DX),BX=function(){function t(e){fN(this,t),this.measureText=e,this.current=0,this.width=0,this.height=0,this.lines=[]}return mQ(t,[{key:"_add",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"normal";void 0===this.lines[t]&&(this.lines[t]={width:0,height:0,blocks:[]});var o=e;void 0!==e&&""!==e||(o=" ");var n=this.measureText(o,i),r=AB({},RX(n));r.text=e,r.width=n.width,r.mod=i,void 0!==e&&""!==e||(r.width=0),this.lines[t].blocks.push(r),this.lines[t].width+=r.width}},{key:"curWidth",value:function(){var t=this.lines[this.current];return void 0===t?0:t.width}},{key:"append",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"normal";this._add(this.current,t,e)}},{key:"newLine",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"normal";this._add(this.current,t,e),this.current++}},{key:"determineLineHeights",value:function(){for(var t=0;tt&&(t=o.width),e+=o.height}this.width=t,this.height=e}},{key:"removeEmptyBlocks",value:function(){for(var t=[],e=0;e"://,""://,""://,"":/<\/b>/,"":/<\/i>/,"":/<\/code>/,"*":/\*/,_:/_/,"`":/`/,afterBold:/[^*]/,afterItal:/[^_]/,afterMono:/[^`]/},PX=function(){function t(e){fN(this,t),this.text=e,this.bold=!1,this.ital=!1,this.mono=!1,this.spacing=!1,this.position=0,this.buffer="",this.modStack=[],this.blocks=[]}return mQ(t,[{key:"mod",value:function(){return 0===this.modStack.length?"normal":this.modStack[0]}},{key:"modName",value:function(){return 0===this.modStack.length?"normal":"mono"===this.modStack[0]?"mono":this.bold&&this.ital?"boldital":this.bold?"bold":this.ital?"ital":void 0}},{key:"emitBlock",value:function(){this.spacing&&(this.add(" "),this.spacing=!1),this.buffer.length>0&&(this.blocks.push({text:this.buffer,mod:this.modName()}),this.buffer="")}},{key:"add",value:function(t){" "===t&&(this.spacing=!0),this.spacing&&(this.buffer+=" ",this.spacing=!1)," "!=t&&(this.buffer+=t)}},{key:"parseWS",value:function(t){return!!/[ \t]/.test(t)&&(this.mono?this.add(t):this.spacing=!0,!0)}},{key:"setTag",value:function(t){this.emitBlock(),this[t]=!0,this.modStack.unshift(t)}},{key:"unsetTag",value:function(t){this.emitBlock(),this[t]=!1,this.modStack.shift()}},{key:"parseStartTag",value:function(t,e){return!(this.mono||this[t]||!this.match(e))&&(this.setTag(t),!0)}},{key:"match",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=sH(this.prepareRegExp(t),2),o=i[0],n=i[1],r=o.test(this.text.substr(this.position,n));return r&&e&&(this.position+=n-1),r}},{key:"parseEndTag",value:function(t,e,i){var o=this.mod()===t;return!(!(o="mono"===t?o&&this.mono:o&&!this.mono)||!this.match(e))&&(void 0!==i?(this.position===this.text.length-1||this.match(i,!1))&&this.unsetTag(t):this.unsetTag(t),!0)}},{key:"replace",value:function(t,e){return!!this.match(t)&&(this.add(e),this.position+=length-1,!0)}},{key:"prepareRegExp",value:function(t){var e,i;if(t instanceof RegExp)i=t,e=1;else{var o=zX[t];i=void 0!==o?o:new RegExp(t),e=t.length}return[i,e]}}]),t}(),FX=function(){function t(e,i,o,n){var r=this;fN(this,t),this.ctx=e,this.parent=i,this.selected=o,this.hover=n;this.lines=new BX((function(t,i){if(void 0===t)return 0;var s=r.parent.getFormattingValues(e,o,n,i),a=0;""!==t&&(a=r.ctx.measureText(t).width);return{width:a,values:s}}))}return mQ(t,[{key:"process",value:function(t){if(!AX(t))return this.lines.finalize();var e=this.parent.fontOptions;t=(t=t.replace(/\r\n/g,"\n")).replace(/\r/g,"\n");var i=String(t).split("\n"),o=i.length;if(e.multi)for(var n=0;n0)for(var s=0;s0)for(var u=0;u")||e.parseStartTag("ital","")||e.parseStartTag("mono","")||e.parseEndTag("bold","")||e.parseEndTag("ital","")||e.parseEndTag("mono",""))||i(o)||e.add(o),e.position++}return e.emitBlock(),e.blocks}},{key:"splitMarkdownBlocks",value:function(t){for(var e=this,i=new PX(t),o=!0,n=function(t){return!!/\\/.test(t)&&(i.positionthis.parent.fontOptions.maxWdt}},{key:"getLongestFit",value:function(t){for(var e="",i=0;i1&&void 0!==arguments[1]?arguments[1]:"normal",i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];this.parent.getFormattingValues(this.ctx,this.selected,this.hover,e);for(var o=(t=(t=t.replace(/^( +)/g,"$1\r")).replace(/([^\r][^ ]*)( +)/g,"$1\r$2\r")).split("\r");o.length>0;){var n=this.getLongestFit(o);if(0===n){var r=o[0],s=this.getLongestFitWord(r);this.lines.newLine(vH(r).call(r,0,s),e),o[0]=vH(r).call(r,s)}else{var a=n;" "===o[n-1]?n--:" "===o[a]&&a++;var l=vH(o).call(o,0,n).join("");n==o.length&&i?this.lines.append(l,e):this.lines.newLine(l,e),o=vH(o).call(o,a)}}}}]),t}(),TX=["bold","ital","boldital","mono"],NX=function(){function t(e,i){var o=arguments.length>2&&void 0!==arguments[2]&&arguments[2];fN(this,t),this.body=e,this.pointToSelf=!1,this.baseSize=void 0,this.fontOptions={},this.setOptions(i),this.size={top:0,left:0,width:0,height:0,yLine:0},this.isEdgeLabel=o}return mQ(t,[{key:"setOptions",value:function(t){if(this.elementOptions=t,this.initFontOptions(t.font),AX(t.label)?this.labelDirty=!0:t.label=void 0,void 0!==t.font&&null!==t.font)if("string"==typeof t.font)this.baseSize=this.fontOptions.size;else if("object"===pQ(t.font)){var e=t.font.size;void 0!==e&&(this.baseSize=e)}}},{key:"initFontOptions",value:function(e){var i=this;Uq(TX,(function(t){i.fontOptions[t]={}})),t.parseFontString(this.fontOptions,e)?this.fontOptions.vadjust=0:Uq(e,(function(t,e){null!=t&&"object"!==pQ(t)&&(i.fontOptions[e]=t)}))}},{key:"constrain",value:function(t){var e={constrainWidth:!1,maxWdt:-1,minWdt:-1,constrainHeight:!1,minHgt:-1,valign:"middle"},i=_q(t,"widthConstraint");if("number"==typeof i)e.maxWdt=Number(i),e.minWdt=Number(i);else if("object"===pQ(i)){var o=_q(t,["widthConstraint","maximum"]);"number"==typeof o&&(e.maxWdt=Number(o));var n=_q(t,["widthConstraint","minimum"]);"number"==typeof n&&(e.minWdt=Number(n))}var r=_q(t,"heightConstraint");if("number"==typeof r)e.minHgt=Number(r);else if("object"===pQ(r)){var s=_q(t,["heightConstraint","minimum"]);"number"==typeof s&&(e.minHgt=Number(s));var a=_q(t,["heightConstraint","valign"]);"string"==typeof a&&("top"!==a&&"bottom"!==a||(e.valign=a))}return e}},{key:"update",value:function(t,e){this.setOptions(t,!0),this.propagateFonts(e),Tq(this.fontOptions,this.constrain(e)),this.fontOptions.chooser=bX("label",e)}},{key:"adjustSizes",value:function(t){var e=t?t.right+t.left:0;this.fontOptions.constrainWidth&&(this.fontOptions.maxWdt-=e,this.fontOptions.minWdt-=e);var i=t?t.top+t.bottom:0;this.fontOptions.constrainHeight&&(this.fontOptions.minHgt-=i)}},{key:"addFontOptionsToPile",value:function(t,e){for(var i=0;i5&&void 0!==arguments[5]?arguments[5]:"middle";if(void 0!==this.elementOptions.label){var s=this.fontOptions.size*this.body.view.scale;this.elementOptions.label&&s=this.elementOptions.scaling.label.maxVisible&&(s=Number(this.elementOptions.scaling.label.maxVisible)/this.body.view.scale),this.calculateLabelSize(t,o,n,e,i,r),this._drawBackground(t),this._drawText(t,e,this.size.yLine,r,s))}}},{key:"_drawBackground",value:function(t){if(void 0!==this.fontOptions.background&&"none"!==this.fontOptions.background){t.fillStyle=this.fontOptions.background;var e=this.getSize();t.fillRect(e.left,e.top,e.width,e.height)}}},{key:"_drawText",value:function(t,e,i){var o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"middle",n=arguments.length>4?arguments[4]:void 0,r=sH(this._setAlignment(t,e,i,o),2);e=r[0],i=r[1],t.textAlign="left",e-=this.size.width/2,this.fontOptions.valign&&this.size.height>this.size.labelHeight&&("top"===this.fontOptions.valign&&(i-=(this.size.height-this.size.labelHeight)/2),"bottom"===this.fontOptions.valign&&(i+=(this.size.height-this.size.labelHeight)/2));for(var s=0;s0&&(t.lineWidth=c.strokeWidth,t.strokeStyle=f,t.lineJoin="round"),t.fillStyle=u,c.strokeWidth>0&&t.strokeText(c.text,e+l,i+c.vadjust),t.fillText(c.text,e+l,i+c.vadjust),l+=c.width}i+=a.height}}}},{key:"_setAlignment",value:function(t,e,i,o){if(this.isEdgeLabel&&"horizontal"!==this.fontOptions.align&&!1===this.pointToSelf){e=0,i=0;"top"===this.fontOptions.align?(t.textBaseline="alphabetic",i-=4):"bottom"===this.fontOptions.align?(t.textBaseline="hanging",i+=4):t.textBaseline="middle"}else t.textBaseline=o;return[e,i]}},{key:"_getColor",value:function(t,e,i){var o=t||"#000000",n=i||"#ffffff";if(e<=this.elementOptions.scaling.label.drawThreshold){var r=Math.max(0,Math.min(1,1-(this.elementOptions.scaling.label.drawThreshold-e)));o=Qq(o,r),n=Qq(n,r)}return[o,n]}},{key:"getTextSize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return this._processLabel(t,e,i),{width:this.size.width,height:this.size.height,lineCount:this.lineCount}}},{key:"getSize",value:function(){var t=this.size.left,e=this.size.top-1;if(this.isEdgeLabel){var i=.5*-this.size.width;switch(this.fontOptions.align){case"middle":t=i,e=.5*-this.size.height;break;case"top":t=i,e=-(this.size.height+2);break;case"bottom":t=i,e=2}}return{left:t,top:e,width:this.size.width,height:this.size.height}}},{key:"calculateLabelSize",value:function(t,e,i){var o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,n=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,r=arguments.length>5&&void 0!==arguments[5]?arguments[5]:"middle";this._processLabel(t,e,i),this.size.left=o-.5*this.size.width,this.size.top=n-.5*this.size.height,this.size.yLine=n+.5*(1-this.lineCount)*this.fontOptions.size,"hanging"===r&&(this.size.top+=.5*this.fontOptions.size,this.size.top+=4,this.size.yLine+=4)}},{key:"getFormattingValues",value:function(t,e,i,o){var n=function(t,e,i){return"normal"===e?"mod"===i?"":t[i]:void 0!==t[e][i]?t[e][i]:t[i]},r={color:n(this.fontOptions,o,"color"),size:n(this.fontOptions,o,"size"),face:n(this.fontOptions,o,"face"),mod:n(this.fontOptions,o,"mod"),vadjust:n(this.fontOptions,o,"vadjust"),strokeWidth:this.fontOptions.strokeWidth,strokeColor:this.fontOptions.strokeColor};(e||i)&&("normal"===o&&!0===this.fontOptions.chooser&&this.elementOptions.labelHighlightBold?r.mod="bold":"function"==typeof this.fontOptions.chooser&&this.fontOptions.chooser(r,this.elementOptions.id,e,i));var s="";return void 0!==r.mod&&""!==r.mod&&(s+=r.mod+" "),s+=r.size+"px "+r.face,t.font=s.replace(/"/g,""),r.font=t.font,r.height=r.size,r}},{key:"differentState",value:function(t,e){return t!==this.selectedState||e!==this.hoverState}},{key:"_processLabelText",value:function(t,e,i,o){return new FX(t,this,e,i).process(o)}},{key:"_processLabel",value:function(t,e,i){if(!1!==this.labelDirty||this.differentState(e,i)){var o=this._processLabelText(t,e,i,this.elementOptions.label);this.fontOptions.minWdt>0&&o.width0&&o.height0&&(this.enableBorderDashes(t,e),t.stroke(),this.disableBorderDashes(t,e)),t.restore()}},{key:"performFill",value:function(t,e){t.save(),t.fillStyle=e.color,this.enableShadow(t,e),CG(t).call(t),this.disableShadow(t,e),t.restore(),this.performStroke(t,e)}},{key:"_addBoundingBoxMargin",value:function(t){this.boundingBox.left-=t,this.boundingBox.top-=t,this.boundingBox.bottom+=t,this.boundingBox.right+=t}},{key:"_updateBoundingBox",value:function(t,e,i,o,n){void 0!==i&&this.resize(i,o,n),this.left=t-this.width/2,this.top=e-this.height/2,this.boundingBox.left=this.left,this.boundingBox.top=this.top,this.boundingBox.bottom=this.top+this.height,this.boundingBox.right=this.left+this.width}},{key:"updateBoundingBox",value:function(t,e,i,o,n){this._updateBoundingBox(t,e,i,o,n)}},{key:"getDimensionsFromLabel",value:function(t,e,i){this.textSize=this.labelModule.getTextSize(t,e,i);var o=this.textSize.width,n=this.textSize.height;return 0===o&&(o=14,n=14),{width:o,height:n}}}]),t}();function d_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var u_=function(t){s_(i,t);var e=d_(i);function i(t,o,n){var r;return fN(this,i),(r=e.call(this,t,o,n))._setMargins(n),r}return mQ(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(this.needsRefresh(e,i)){var o=this.getDimensionsFromLabel(t,e,i);this.width=o.width+this.margin.right+this.margin.left,this.height=o.height+this.margin.top+this.margin.bottom,this.radius=this.width/2}}},{key:"draw",value:function(t,e,i,o,n,r){this.resize(t,o,n),this.left=e-this.width/2,this.top=i-this.height/2,this.initContextForDraw(t,r),GB(t,this.left,this.top,this.width,this.height,r.borderRadius),this.performFill(t,r),this.updateBoundingBox(e,i,t,o,n),this.labelModule.draw(t,this.left+this.textSize.width/2+this.margin.left,this.top+this.textSize.height/2+this.margin.top,o,n)}},{key:"updateBoundingBox",value:function(t,e,i,o,n){this._updateBoundingBox(t,e,i,o,n);var r=this.options.shapeProperties.borderRadius;this._addBoundingBoxMargin(r)}},{key:"distanceToBorder",value:function(t,e){t&&this.resize(t);var i=this.options.borderWidth;return Math.min(Math.abs(this.width/2/Math.cos(e)),Math.abs(this.height/2/Math.sin(e)))+i}}]),i}(c_);function f_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var p_=function(t){s_(i,t);var e=f_(i);function i(t,o,n){var r;return fN(this,i),(r=e.call(this,t,o,n)).labelOffset=0,r.selected=!1,r}return mQ(i,[{key:"setOptions",value:function(t,e,i){this.options=t,void 0===e&&void 0===i||this.setImages(e,i)}},{key:"setImages",value:function(t,e){e&&this.selected?(this.imageObj=e,this.imageObjAlt=t):(this.imageObj=t,this.imageObjAlt=e)}},{key:"switchImages",value:function(t){var e=t&&!this.selected||!t&&this.selected;if(this.selected=t,void 0!==this.imageObjAlt&&e){var i=this.imageObj;this.imageObj=this.imageObjAlt,this.imageObjAlt=i}}},{key:"_getImagePadding",value:function(){var t={top:0,right:0,bottom:0,left:0};if(this.options.imagePadding){var e=this.options.imagePadding;"object"==pQ(e)?(t.top=e.top,t.right=e.right,t.bottom=e.bottom,t.left=e.left):(t.top=e,t.right=e,t.bottom=e,t.left=e)}return t}},{key:"_resizeImage",value:function(){var t,e;if(!1===this.options.shapeProperties.useImageSize){var i=1,o=1;this.imageObj.width&&this.imageObj.height&&(this.imageObj.width>this.imageObj.height?i=this.imageObj.width/this.imageObj.height:o=this.imageObj.height/this.imageObj.width),t=2*this.options.size*i,e=2*this.options.size*o}else{var n=this._getImagePadding();t=this.imageObj.width+n.left+n.right,e=this.imageObj.height+n.top+n.bottom}this.width=t,this.height=e,this.radius=.5*this.width}},{key:"_drawRawCircle",value:function(t,e,i,o){this.initContextForDraw(t,o),WB(t,e,i,o.size),this.performFill(t,o)}},{key:"_drawImageAtPosition",value:function(t,e){if(0!=this.imageObj.width){t.globalAlpha=void 0!==e.opacity?e.opacity:1,this.enableShadow(t,e);var i=1;!0===this.options.shapeProperties.interpolation&&(i=this.imageObj.width/this.width/this.body.view.scale);var o=this._getImagePadding(),n=this.left+o.left,r=this.top+o.top,s=this.width-o.left-o.right,a=this.height-o.top-o.bottom;this.imageObj.drawImageAtPosition(t,i,n,r,s,a),this.disableShadow(t,e)}}},{key:"_drawImageLabel",value:function(t,e,i,o,n){var r=0;if(void 0!==this.height){r=.5*this.height;var s=this.labelModule.getTextSize(t,o,n);s.lineCount>=1&&(r+=s.height/2)}var a=i+r;this.options.label&&(this.labelOffset=r),this.labelModule.draw(t,e,a,o,n,"hanging")}}]),i}(c_);function v_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var g_=function(t){s_(i,t);var e=v_(i);function i(t,o,n){var r;return fN(this,i),(r=e.call(this,t,o,n))._setMargins(n),r}return mQ(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(this.needsRefresh(e,i)){var o=this.getDimensionsFromLabel(t,e,i),n=Math.max(o.width+this.margin.right+this.margin.left,o.height+this.margin.top+this.margin.bottom);this.options.size=n/2,this.width=n,this.height=n,this.radius=this.width/2}}},{key:"draw",value:function(t,e,i,o,n,r){this.resize(t,o,n),this.left=e-this.width/2,this.top=i-this.height/2,this._drawRawCircle(t,e,i,r),this.updateBoundingBox(e,i),this.labelModule.draw(t,this.left+this.textSize.width/2+this.margin.left,i,o,n)}},{key:"updateBoundingBox",value:function(t,e){this.boundingBox.top=e-this.options.size,this.boundingBox.left=t-this.options.size,this.boundingBox.right=t+this.options.size,this.boundingBox.bottom=e+this.options.size}},{key:"distanceToBorder",value:function(t){return t&&this.resize(t),.5*this.width}}]),i}(p_);function y_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var m_=function(t){s_(i,t);var e=y_(i);function i(t,o,n,r,s){var a;return fN(this,i),(a=e.call(this,t,o,n)).setImages(r,s),a}return mQ(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(void 0===this.imageObj.src||void 0===this.imageObj.width||void 0===this.imageObj.height){var o=2*this.options.size;return this.width=o,this.height=o,void(this.radius=.5*this.width)}this.needsRefresh(e,i)&&this._resizeImage()}},{key:"draw",value:function(t,e,i,o,n,r){this.switchImages(o),this.resize();var s=e,a=i;"top-left"===this.options.shapeProperties.coordinateOrigin?(this.left=e,this.top=i,s+=this.width/2,a+=this.height/2):(this.left=e-this.width/2,this.top=i-this.height/2),this._drawRawCircle(t,s,a,r),t.save(),t.clip(),this._drawImageAtPosition(t,r),t.restore(),this._drawImageLabel(t,s,a,o,n),this.updateBoundingBox(e,i)}},{key:"updateBoundingBox",value:function(t,e){"top-left"===this.options.shapeProperties.coordinateOrigin?(this.boundingBox.top=e,this.boundingBox.left=t,this.boundingBox.right=t+2*this.options.size,this.boundingBox.bottom=e+2*this.options.size):(this.boundingBox.top=e-this.options.size,this.boundingBox.left=t-this.options.size,this.boundingBox.right=t+this.options.size,this.boundingBox.bottom=e+this.options.size),this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelOffset)}},{key:"distanceToBorder",value:function(t){return t&&this.resize(t),.5*this.width}}]),i}(p_);function b_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var w_=function(t){s_(i,t);var e=b_(i);function i(t,o,n){return fN(this,i),e.call(this,t,o,n)}return mQ(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{size:this.options.size};if(this.needsRefresh(e,i)){var n,r;this.labelModule.getTextSize(t,e,i);var s=2*o.size;this.width=null!==(n=this.customSizeWidth)&&void 0!==n?n:s,this.height=null!==(r=this.customSizeHeight)&&void 0!==r?r:s,this.radius=.5*this.width}}},{key:"_drawShape",value:function(t,e,i,o,n,r,s,a){var l,h=this;return this.resize(t,r,s,a),this.left=o-this.width/2,this.top=n-this.height/2,this.initContextForDraw(t,a),(l=e,Object.prototype.hasOwnProperty.call(ZB,l)?ZB[l]:function(t){for(var e=arguments.length,i=new Array(e>1?e-1:0),o=1;o0&&(this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelModule.size.height))}}]),i}(c_);function A_(t,e){var i=BH(t);if(RJ){var o=RJ(t);e&&(o=aW(o).call(o,(function(e){return QJ(t,e).enumerable}))),i.push.apply(i,o)}return i}function E_(t){for(var e=1;e1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(this.needsRefresh(e,i)){var o=this.getDimensionsFromLabel(t,e,i);this.height=2*o.height,this.width=o.width+o.height,this.radius=.5*this.width}}},{key:"draw",value:function(t,e,i,o,n,r){this.resize(t,o,n),this.left=e-.5*this.width,this.top=i-.5*this.height,this.initContextForDraw(t,r),KB(t,this.left,this.top,this.width,this.height),this.performFill(t,r),this.updateBoundingBox(e,i,t,o,n),this.labelModule.draw(t,e,i,o,n)}},{key:"distanceToBorder",value:function(t,e){t&&this.resize(t);var i=.5*this.width,o=.5*this.height,n=Math.sin(e)*i,r=Math.cos(e)*o;return i*o/Math.sqrt(n*n+r*r)}}]),i}(c_);function z_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var P_=function(t){s_(i,t);var e=z_(i);function i(t,o,n){var r;return fN(this,i),(r=e.call(this,t,o,n))._setMargins(n),r}return mQ(i,[{key:"resize",value:function(t,e,i){this.needsRefresh(e,i)&&(this.iconSize={width:Number(this.options.icon.size),height:Number(this.options.icon.size)},this.width=this.iconSize.width+this.margin.right+this.margin.left,this.height=this.iconSize.height+this.margin.top+this.margin.bottom,this.radius=.5*this.width)}},{key:"draw",value:function(t,e,i,o,n,r){var s=this;return this.resize(t,o,n),this.options.icon.size=this.options.icon.size||50,this.left=e-this.width/2,this.top=i-this.height/2,this._icon(t,e,i,o,n,r),{drawExternalLabel:function(){if(void 0!==s.options.label){s.labelModule.draw(t,s.left+s.iconSize.width/2+s.margin.left,i+s.height/2+5,o)}s.updateBoundingBox(e,i)}}}},{key:"updateBoundingBox",value:function(t,e){if(this.boundingBox.top=e-.5*this.options.icon.size,this.boundingBox.left=t-.5*this.options.icon.size,this.boundingBox.right=t+.5*this.options.icon.size,this.boundingBox.bottom=e+.5*this.options.icon.size,void 0!==this.options.label&&this.labelModule.size.width>0){this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelModule.size.height+5)}}},{key:"_icon",value:function(t,e,i,o,n,r){var s=Number(this.options.icon.size);void 0!==this.options.icon.code?(t.font=[null!=this.options.icon.weight?this.options.icon.weight:o?"bold":"",(null!=this.options.icon.weight&&o?5:0)+s+"px",this.options.icon.face].join(" "),t.fillStyle=this.options.icon.color||"black",t.textAlign="center",t.textBaseline="middle",this.enableShadow(t,r),t.fillText(this.options.icon.code,e,i),this.disableShadow(t,r)):console.error("When using the icon shape, you need to define the code in the icon options object. This can be done per node or globally.")}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(c_);function F_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var T_=function(t){s_(i,t);var e=F_(i);function i(t,o,n,r,s){var a;return fN(this,i),(a=e.call(this,t,o,n)).setImages(r,s),a}return mQ(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(void 0===this.imageObj.src||void 0===this.imageObj.width||void 0===this.imageObj.height){var o=2*this.options.size;return this.width=o,void(this.height=o)}this.needsRefresh(e,i)&&this._resizeImage()}},{key:"draw",value:function(t,e,i,o,n,r){t.save(),this.switchImages(o),this.resize();var s=e,a=i;if("top-left"===this.options.shapeProperties.coordinateOrigin?(this.left=e,this.top=i,s+=this.width/2,a+=this.height/2):(this.left=e-this.width/2,this.top=i-this.height/2),!0===this.options.shapeProperties.useBorderWithImage){var l=this.options.borderWidth,h=this.options.borderWidthSelected||2*this.options.borderWidth,c=(o?h:l)/this.body.view.scale;t.lineWidth=Math.min(this.width,c),t.beginPath();var d=o?this.options.color.highlight.border:n?this.options.color.hover.border:this.options.color.border,u=o?this.options.color.highlight.background:n?this.options.color.hover.background:this.options.color.background;void 0!==r.opacity&&(d=Qq(d,r.opacity),u=Qq(u,r.opacity)),t.strokeStyle=d,t.fillStyle=u,t.rect(this.left-.5*t.lineWidth,this.top-.5*t.lineWidth,this.width+t.lineWidth,this.height+t.lineWidth),CG(t).call(t),this.performStroke(t,r),t.closePath()}this._drawImageAtPosition(t,r),this._drawImageLabel(t,s,a,o,n),this.updateBoundingBox(e,i),t.restore()}},{key:"updateBoundingBox",value:function(t,e){this.resize(),"top-left"===this.options.shapeProperties.coordinateOrigin?(this.left=t,this.top=e):(this.left=t-this.width/2,this.top=e-this.height/2),this.boundingBox.left=this.left,this.boundingBox.top=this.top,this.boundingBox.bottom=this.top+this.height,this.boundingBox.right=this.left+this.width,void 0!==this.options.label&&this.labelModule.size.width>0&&(this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelOffset))}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(p_);function N_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var j_=function(t){s_(i,t);var e=N_(i);function i(t,o,n){return fN(this,i),e.call(this,t,o,n)}return mQ(i,[{key:"draw",value:function(t,e,i,o,n,r){return this._drawShape(t,"square",2,e,i,o,n,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(w_);function U_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var L_=function(t){s_(i,t);var e=U_(i);function i(t,o,n){return fN(this,i),e.call(this,t,o,n)}return mQ(i,[{key:"draw",value:function(t,e,i,o,n,r){return this._drawShape(t,"hexagon",4,e,i,o,n,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(w_);function Q_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var H_=function(t){s_(i,t);var e=Q_(i);function i(t,o,n){return fN(this,i),e.call(this,t,o,n)}return mQ(i,[{key:"draw",value:function(t,e,i,o,n,r){return this._drawShape(t,"star",4,e,i,o,n,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(w_);function V_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var W_=function(t){s_(i,t);var e=V_(i);function i(t,o,n){var r;return fN(this,i),(r=e.call(this,t,o,n))._setMargins(n),r}return mQ(i,[{key:"resize",value:function(t,e,i){this.needsRefresh(e,i)&&(this.textSize=this.labelModule.getTextSize(t,e,i),this.width=this.textSize.width+this.margin.right+this.margin.left,this.height=this.textSize.height+this.margin.top+this.margin.bottom,this.radius=.5*this.width)}},{key:"draw",value:function(t,e,i,o,n,r){this.resize(t,o,n),this.left=e-this.width/2,this.top=i-this.height/2,this.enableShadow(t,r),this.labelModule.draw(t,this.left+this.textSize.width/2+this.margin.left,this.top+this.textSize.height/2+this.margin.top,o,n),this.disableShadow(t,r),this.updateBoundingBox(e,i,t,o,n)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(c_);function G_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var K_=function(t){s_(i,t);var e=G_(i);function i(t,o,n){return fN(this,i),e.call(this,t,o,n)}return mQ(i,[{key:"draw",value:function(t,e,i,o,n,r){return this._drawShape(t,"triangle",3,e,i,o,n,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(w_);function q_(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var Y_=function(t){s_(i,t);var e=q_(i);function i(t,o,n){return fN(this,i),e.call(this,t,o,n)}return mQ(i,[{key:"draw",value:function(t,e,i,o,n,r){return this._drawShape(t,"triangleDown",3,e,i,o,n,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(w_);function Z_(t,e){var i=BH(t);if(RJ){var o=RJ(t);e&&(o=aW(o).call(o,(function(e){return QJ(t,e).enumerable}))),i.push.apply(i,o)}return i}function J_(t){for(var e=1;et.left&&this.shape.topt.top}},{key:"isBoundingBoxOverlappingWith",value:function(t){return this.shape.boundingBox.leftt.left&&this.shape.boundingBox.topt.top}}],[{key:"checkOpacity",value:function(t){return 0<=t&&t<=1}},{key:"checkCoordinateOrigin",value:function(t){return void 0===t||"center"===t||"top-left"===t}},{key:"updateGroupOptions",value:function(e,i,o){var n;if(void 0!==o){var r=e.group;if(void 0!==i&&void 0!==i.group&&r!==i.group)throw new Error("updateGroupOptions: group values in options don't match.");if("number"==typeof r||"string"==typeof r&&""!=r){var s=o.get(r);void 0!==s.opacity&&void 0===i.opacity&&(t.checkOpacity(s.opacity)||(console.error("Invalid option for node opacity. Value must be between 0 and 1, found: "+s.opacity),s.opacity=void 0));var a=aW(n=mX(i)).call(n,(function(t){return null!=i[t]}));a.push("font"),Fq(a,e,s),e.color=Vq(e.color)}}}},{key:"parseOptions",value:function(e,i){var o=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},r=arguments.length>4?arguments[4]:void 0;if(Fq(["color","fixed","shadow"],e,i,o),t.checkMass(i),void 0!==e.opacity&&(t.checkOpacity(e.opacity)||(console.error("Invalid option for node opacity. Value must be between 0 and 1, found: "+e.opacity),e.opacity=void 0)),void 0!==i.opacity&&(t.checkOpacity(i.opacity)||(console.error("Invalid option for node opacity. Value must be between 0 and 1, found: "+i.opacity),i.opacity=void 0)),i.shapeProperties&&!t.checkCoordinateOrigin(i.shapeProperties.coordinateOrigin)&&console.error("Invalid option for node coordinateOrigin, found: "+i.shapeProperties.coordinateOrigin),Jq(e,i,"shadow",n),void 0!==i.color&&null!==i.color){var s=Vq(i.color);zq(e.color,s)}else!0===o&&null===i.color&&(e.color=Zq(n.color));void 0!==i.fixed&&null!==i.fixed&&("boolean"==typeof i.fixed?(e.fixed.x=i.fixed,e.fixed.y=i.fixed):(void 0!==i.fixed.x&&"boolean"==typeof i.fixed.x&&(e.fixed.x=i.fixed.x),void 0!==i.fixed.y&&"boolean"==typeof i.fixed.y&&(e.fixed.y=i.fixed.y))),!0===o&&null===i.font&&(e.font=Zq(n.font)),t.updateGroupOptions(e,i,r),void 0!==i.scaling&&Jq(e.scaling,i.scaling,"label",n.scaling)}},{key:"checkMass",value:function(t,e){if(void 0!==t.mass&&t.mass<=0){var i="";void 0!==e&&(i=" in node id: "+e),console.error("%cNegative or zero mass disallowed"+i+", setting mass to 1.",uY),t.mass=1}}}]),t}();function __(t,e){var i=void 0!==lH&&uN(t)||t["@@iterator"];if(!i){if(EH(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return $_(t,e);var o=vH(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===o&&t.constructor&&(o=t.constructor.name);if("Map"===o||"Set"===o)return GT(t);if("Arguments"===o||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(o))return $_(t,e)}(t))||e){i&&(t=i);var o=0,n=function(){};return{s:n,n:function(){return o>=t.length?{done:!0}:{done:!1,value:t[o++]}},e:function(t){throw t},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function $_(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,o=new Array(e);i1?console.error("Invalid option for node opacity. Value must be between 0 and 1, found: "+t.opacity):this.options.opacity=t.opacity),void 0!==t.shape)for(var e in this.body.nodes)Object.prototype.hasOwnProperty.call(this.body.nodes,e)&&this.body.nodes[e].updateShape();if(void 0!==t.font||void 0!==t.widthConstraint||void 0!==t.heightConstraint)for(var i=0,o=BH(this.body.nodes);i1&&void 0!==arguments[1]&&arguments[1],i=this.body.data.nodes;if(iM("id",t))this.body.data.nodes=t;else if(EH(t))this.body.data.nodes=new eM,this.body.data.nodes.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.body.data.nodes=new eM}if(i&&Uq(this.nodesListeners,(function(t,e){i.off(e,t)})),this.body.nodes={},this.body.data.nodes){var o=this;Uq(this.nodesListeners,(function(t,e){o.body.data.nodes.on(e,t)}));var n=this.body.data.nodes.getIds();this.add(n,!0)}!1===e&&this.body.emitter.emit("_dataChanged")}},{key:"add",value:function(t){for(var e,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],o=[],n=0;n1&&void 0!==arguments[1]?arguments[1]:X_)(t,this.body,this.images,this.groups,this.options,this.defaultOptions)}},{key:"refresh",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];Uq(this.body.nodes,(function(i,o){var n=t.body.data.nodes.get(o);void 0!==n&&(!0===e&&i.setOptions({x:null,y:null}),i.setOptions({fixed:!1}),i.setOptions(n))}))}},{key:"getPositions",value:function(t){var e={};if(void 0!==t){if(!0===EH(t)){for(var i=0;i0?(o=i/a)*o:i;return a===1/0?1/0:a*p$(n)}});var v$=nM(oO.Math.hypot);function g$(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var y$=function(){function t(){fN(this,t)}return mQ(t,null,[{key:"transform",value:function(t,e){EH(t)||(t=[t]);for(var i=e.point.x,o=e.point.y,n=e.angle,r=e.length,s=0;s4&&void 0!==arguments[4]?arguments[4]:this.getViaNode();t.strokeStyle=this.getColor(t,e),t.lineWidth=e.width,!1!==e.dashes?this._drawDashedLine(t,e,n):this._drawLine(t,e,n)}},{key:"_drawLine",value:function(t,e,i,o,n){if(this.from!=this.to)this._line(t,e,i,o,n);else{var r=sH(this._getCircleData(t),3),s=r[0],a=r[1],l=r[2];this._circle(t,e,s,a,l)}}},{key:"_drawDashedLine",value:function(t,e,i,o,n){t.lineCap="round";var r=EH(e.dashes)?e.dashes:[5,5];if(void 0!==t.setLineDash){if(t.save(),t.setLineDash(r),t.lineDashOffset=0,this.from!=this.to)this._line(t,e,i);else{var s=sH(this._getCircleData(t),3),a=s[0],l=s[1],h=s[2];this._circle(t,e,a,l,h)}t.setLineDash([0]),t.lineDashOffset=0,t.restore()}else{if(this.from!=this.to)YB(t,this.from.x,this.from.y,this.to.x,this.to.y,r);else{var c=sH(this._getCircleData(t),3),d=c[0],u=c[1],f=c[2];this._circle(t,e,d,u,f)}this.enableShadow(t,e),t.stroke(),this.disableShadow(t,e)}}},{key:"findBorderPosition",value:function(t,e,i){return this.from!=this.to?this._findBorderPosition(t,e,i):this._findBorderPositionCircle(t,e,i)}},{key:"findBorderPositions",value:function(t){if(this.from!=this.to)return{from:this._findBorderPosition(this.from,t),to:this._findBorderPosition(this.to,t)};var e,i=sH(vH(e=this._getCircleData(t)).call(e,0,2),2),o=i[0],n=i[1];return{from:this._findBorderPositionCircle(this.from,t,{x:o,y:n,low:.25,high:.6,direction:-1}),to:this._findBorderPositionCircle(this.from,t,{x:o,y:n,low:.6,high:.8,direction:1})}}},{key:"_getCircleData",value:function(t){var e=this.options.selfReference.size;void 0!==t&&void 0===this.from.shape.width&&this.from.shape.resize(t);var i=EX(t,this.options.selfReference.angle,e,this.from);return[i.x,i.y,e]}},{key:"_pointOnCircle",value:function(t,e,i,o){var n=2*o*Math.PI;return{x:t+i*Math.cos(n),y:e-i*Math.sin(n)}}},{key:"_findBorderPositionCircle",value:function(t,e,i){var o,n=i.x,r=i.y,s=i.low,a=i.high,l=i.direction,h=this.options.selfReference.size,c=.5*(s+a),d=0;!0===this.options.arrowStrikethrough&&(-1===l?d=this.options.endPointOffset.from:1===l&&(d=this.options.endPointOffset.to));var u=0;do{c=.5*(s+a),o=this._pointOnCircle(n,r,h,c);var f=Math.atan2(t.y-o.y,t.x-o.x),p=t.distanceToBorder(e,f)+d-Math.sqrt(Math.pow(o.x-t.x,2)+Math.pow(o.y-t.y,2));if(Math.abs(p)<.05)break;p>0?l>0?s=c:a=c:l>0?a=c:s=c,++u}while(s<=a&&u<10);return B$(B$({},o),{},{t:c})}},{key:"getLineWidth",value:function(t,e){return!0===t?Math.max(this.selectionWidth,.3/this._body.view.scale):!0===e?Math.max(this.hoverWidth,.3/this._body.view.scale):Math.max(this.options.width,.3/this._body.view.scale)}},{key:"getColor",value:function(t,e){if(!1!==e.inheritsColor){if("both"===e.inheritsColor&&this.from.id!==this.to.id){var i=t.createLinearGradient(this.from.x,this.from.y,this.to.x,this.to.y),o=this.from.options.color.highlight.border,n=this.to.options.color.highlight.border;return!1===this.from.selected&&!1===this.to.selected?(o=Qq(this.from.options.color.border,e.opacity),n=Qq(this.to.options.color.border,e.opacity)):!0===this.from.selected&&!1===this.to.selected?n=this.to.options.color.border:!1===this.from.selected&&!0===this.to.selected&&(o=this.from.options.color.border),i.addColorStop(0,o),i.addColorStop(1,n),i}return"to"===e.inheritsColor?Qq(this.to.options.color.border,e.opacity):Qq(this.from.options.color.border,e.opacity)}return Qq(e.color,e.opacity)}},{key:"_circle",value:function(t,e,i,o,n){this.enableShadow(t,e);var r=0,s=2*Math.PI;if(!this.options.selfReference.renderBehindTheNode){var a=this.options.selfReference.angle,l=this.options.selfReference.angle+Math.PI,h=this._findBorderPositionCircle(this.from,t,{x:i,y:o,low:a,high:l,direction:-1}),c=this._findBorderPositionCircle(this.from,t,{x:i,y:o,low:a,high:l,direction:1});r=Math.atan2(h.y-o,h.x-i),s=Math.atan2(c.y-o,c.x-i)}t.beginPath(),t.arc(i,o,n,r,s,!1),t.stroke(),this.disableShadow(t,e)}},{key:"getDistanceToEdge",value:function(t,e,i,o,n,r){if(this.from!=this.to)return this._getDistanceToEdge(t,e,i,o,n,r);var s=sH(this._getCircleData(void 0),3),a=s[0],l=s[1],h=s[2],c=a-n,d=l-r;return Math.abs(Math.sqrt(c*c+d*d)-h)}},{key:"_getDistanceToLine",value:function(t,e,i,o,n,r){var s=i-t,a=o-e,l=((n-t)*s+(r-e)*a)/(s*s+a*a);l>1?l=1:l<0&&(l=0);var h=t+l*s-n,c=e+l*a-r;return Math.sqrt(h*h+c*c)}},{key:"getArrowData",value:function(t,e,i,o,n,r){var s,a,l,h,c,d,u,f=r.width;"from"===e?(l=this.from,h=this.to,c=r.fromArrowScale<0,d=Math.abs(r.fromArrowScale),u=r.fromArrowType):"to"===e?(l=this.to,h=this.from,c=r.toArrowScale<0,d=Math.abs(r.toArrowScale),u=r.toArrowType):(l=this.to,h=this.from,c=r.middleArrowScale<0,d=Math.abs(r.middleArrowScale),u=r.middleArrowType);var p=15*d+3*f;if(l!=h){var v=p/v$(l.x-h.x,l.y-h.y);if("middle"!==e)if(!0===this.options.smooth.enabled){var g=this._findBorderPosition(l,t,{via:i}),y=this.getPoint(g.t+v*("from"===e?1:-1),i);s=Math.atan2(g.y-y.y,g.x-y.x),a=g}else s=Math.atan2(l.y-h.y,l.x-h.x),a=this._findBorderPosition(l,t);else{var m=(c?-v:v)/2,b=this.getPoint(.5+m,i),w=this.getPoint(.5-m,i);s=Math.atan2(b.y-w.y,b.x-w.x),a=this.getPoint(.5,i)}}else{var A=sH(this._getCircleData(t),3),E=A[0],k=A[1],C=A[2];if("from"===e){var x=this.options.selfReference.angle,S=this.options.selfReference.angle+Math.PI,I=this._findBorderPositionCircle(this.from,t,{x:E,y:k,low:x,high:S,direction:-1});s=-2*I.t*Math.PI+1.5*Math.PI+.1*Math.PI,a=I}else if("to"===e){var M=this.options.selfReference.angle,O=this.options.selfReference.angle+Math.PI,D=this._findBorderPositionCircle(this.from,t,{x:E,y:k,low:M,high:O,direction:1});s=-2*D.t*Math.PI+1.5*Math.PI-1.1*Math.PI,a=D}else{var R=this.options.selfReference.angle/(2*Math.PI);a=this._pointOnCircle(E,k,C,R),s=-2*R*Math.PI+1.5*Math.PI+.1*Math.PI}}return{point:a,core:{x:a.x-.9*p*Math.cos(s),y:a.y-.9*p*Math.sin(s)},angle:s,length:p,type:u}}},{key:"drawArrowHead",value:function(t,e,i,o,n){t.strokeStyle=this.getColor(t,e),t.fillStyle=t.strokeStyle,t.lineWidth=e.width,D$.draw(t,n)&&(this.enableShadow(t,e),CG(t).call(t),this.disableShadow(t,e))}},{key:"enableShadow",value:function(t,e){!0===e.shadow&&(t.shadowColor=e.shadowColor,t.shadowBlur=e.shadowSize,t.shadowOffsetX=e.shadowX,t.shadowOffsetY=e.shadowY)}},{key:"disableShadow",value:function(t,e){!0===e.shadow&&(t.shadowColor="rgba(0,0,0,0)",t.shadowBlur=0,t.shadowOffsetX=0,t.shadowOffsetY=0)}},{key:"drawBackground",value:function(t,e){if(!1!==e.background){var i={strokeStyle:t.strokeStyle,lineWidth:t.lineWidth,dashes:t.dashes};t.strokeStyle=e.backgroundColor,t.lineWidth=e.backgroundSize,this.setStrokeDashed(t,e.backgroundDashes),t.stroke(),t.strokeStyle=i.strokeStyle,t.lineWidth=i.lineWidth,t.dashes=i.dashes,this.setStrokeDashed(t,e.dashes)}}},{key:"setStrokeDashed",value:function(t,e){if(!1!==e)if(void 0!==t.setLineDash){var i=EH(e)?e:[5,5];t.setLineDash(i)}else console.warn("setLineDash is not supported in this browser. The dashed stroke cannot be used.");else void 0!==t.setLineDash?t.setLineDash([]):console.warn("setLineDash is not supported in this browser. The dashed stroke cannot be used.")}}]),t}();function P$(t,e){var i=BH(t);if(RJ){var o=RJ(t);e&&(o=aW(o).call(o,(function(e){return QJ(t,e).enumerable}))),i.push.apply(i,o)}return i}function F$(t){for(var e=1;e2&&void 0!==arguments[2]?arguments[2]:this._getViaCoordinates(),r=!1,s=1,a=0,l=this.to,h=this.options.endPointOffset?this.options.endPointOffset.to:0;t.id===this.from.id&&(l=this.from,r=!0,h=this.options.endPointOffset?this.options.endPointOffset.from:0),!1===this.options.arrowStrikethrough&&(h=0);var c=0;do{o=.5*(a+s),i=this.getPoint(o,n);var d=Math.atan2(l.y-i.y,l.x-i.x),u=l.distanceToBorder(e,d)+h-Math.sqrt(Math.pow(i.x-l.x,2)+Math.pow(i.y-l.y,2));if(Math.abs(u)<.2)break;u<0?!1===r?a=o:s=o:!1===r?s=o:a=o,++c}while(a<=s&&c<10);return F$(F$({},i),{},{t:o})}},{key:"_getDistanceToBezierEdge",value:function(t,e,i,o,n,r,s){var a,l,h,c,d,u=1e9,f=t,p=e;for(l=1;l<10;l++)h=.1*l,c=Math.pow(1-h,2)*t+2*h*(1-h)*s.x+Math.pow(h,2)*i,d=Math.pow(1-h,2)*e+2*h*(1-h)*s.y+Math.pow(h,2)*o,l>0&&(u=(a=this._getDistanceToLine(f,p,c,d,n,r))1&&void 0!==arguments[1]?arguments[1]:this.via;if(this.from===this.to){var i=sH(this._getCircleData(),3),o=i[0],n=i[1],r=i[2],s=2*Math.PI*(1-t);return{x:o+r*Math.sin(s),y:n+r-r*(1-Math.cos(s))}}return{x:Math.pow(1-t,2)*this.fromPoint.x+2*t*(1-t)*e.x+Math.pow(t,2)*this.toPoint.x,y:Math.pow(1-t,2)*this.fromPoint.y+2*t*(1-t)*e.y+Math.pow(t,2)*this.toPoint.y}}},{key:"_findBorderPosition",value:function(t,e){return this._findBorderPositionBezier(t,e,this.via)}},{key:"_getDistanceToEdge",value:function(t,e,i,o,n,r){return this._getDistanceToBezierEdge(t,e,i,o,n,r,this.via)}}]),i}(N$);function L$(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var Q$=function(t){s_(i,t);var e=L$(i);function i(t,o,n){return fN(this,i),e.call(this,t,o,n)}return mQ(i,[{key:"_line",value:function(t,e,i){this._bezierCurve(t,e,i)}},{key:"getViaNode",value:function(){return this._getViaCoordinates()}},{key:"_getViaCoordinates",value:function(){var t,e,i=this.options.smooth.roundness,o=this.options.smooth.type,n=Math.abs(this.from.x-this.to.x),r=Math.abs(this.from.y-this.to.y);if("discrete"===o||"diagonalCross"===o){var s,a;s=a=n<=r?i*r:i*n,this.from.x>this.to.x&&(s=-s),this.from.y>=this.to.y&&(a=-a);var l=this.from.x+s,h=this.from.y+a;return"discrete"===o&&(n<=r?l=nthis.to.x&&(t=-t),this.from.y>=this.to.y&&(e=-e);var w=this.from.x+t,A=this.from.y+e;return n<=r?w=this.from.x<=this.to.x?this.to.xw?this.to.x:w:A=this.from.y>=this.to.y?this.to.y>A?this.to.y:A:this.to.y2&&void 0!==arguments[2]?arguments[2]:{};return this._findBorderPositionBezier(t,e,i.via)}},{key:"_getDistanceToEdge",value:function(t,e,i,o,n,r){var s=arguments.length>6&&void 0!==arguments[6]?arguments[6]:this._getViaCoordinates();return this._getDistanceToBezierEdge(t,e,i,o,n,r,s)}},{key:"getPoint",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this._getViaCoordinates(),i=t;return{x:Math.pow(1-i,2)*this.fromPoint.x+2*i*(1-i)*e.x+Math.pow(i,2)*this.toPoint.x,y:Math.pow(1-i,2)*this.fromPoint.y+2*i*(1-i)*e.y+Math.pow(i,2)*this.toPoint.y}}}]),i}(N$);function H$(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var V$=function(t){s_(i,t);var e=H$(i);function i(t,o,n){return fN(this,i),e.call(this,t,o,n)}return mQ(i,[{key:"_getDistanceToBezierEdge2",value:function(t,e,i,o,n,r,s,a){for(var l=1e9,h=t,c=e,d=[0,0,0,0],u=1;u<10;u++){var f=.1*u;d[0]=Math.pow(1-f,3),d[1]=3*f*Math.pow(1-f,2),d[2]=3*Math.pow(f,2)*(1-f),d[3]=Math.pow(f,3);var p=d[0]*t+d[1]*s.x+d[2]*a.x+d[3]*i,v=d[0]*e+d[1]*s.y+d[2]*a.y+d[3]*o;if(u>0){var g=this._getDistanceToLine(h,c,p,v,n,r);l=gMath.abs(r)||!0===this.options.smooth.forceDirection||"horizontal"===this.options.smooth.forceDirection)&&"vertical"!==this.options.smooth.forceDirection?(e=this.from.y,o=this.to.y,t=this.from.x-s*n,i=this.to.x+s*n):(e=this.from.y-s*r,o=this.to.y+s*r,t=this.from.x,i=this.to.x),[{x:t,y:e},{x:i,y:o}]}},{key:"getViaNode",value:function(){return this._getViaCoordinates()}},{key:"_findBorderPosition",value:function(t,e){return this._findBorderPositionBezier(t,e)}},{key:"_getDistanceToEdge",value:function(t,e,i,o,n,r){var s=sH(arguments.length>6&&void 0!==arguments[6]?arguments[6]:this._getViaCoordinates(),2),a=s[0],l=s[1];return this._getDistanceToBezierEdge2(t,e,i,o,n,r,a,l)}},{key:"getPoint",value:function(t){var e=sH(arguments.length>1&&void 0!==arguments[1]?arguments[1]:this._getViaCoordinates(),2),i=e[0],o=e[1],n=t,r=[Math.pow(1-n,3),3*n*Math.pow(1-n,2),3*Math.pow(n,2)*(1-n),Math.pow(n,3)];return{x:r[0]*this.fromPoint.x+r[1]*i.x+r[2]*o.x+r[3]*this.toPoint.x,y:r[0]*this.fromPoint.y+r[1]*i.y+r[2]*o.y+r[3]*this.toPoint.y}}}]),i}(V$);function K$(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var q$=function(t){s_(i,t);var e=K$(i);function i(t,o,n){return fN(this,i),e.call(this,t,o,n)}return mQ(i,[{key:"_line",value:function(t,e){t.beginPath(),t.moveTo(this.fromPoint.x,this.fromPoint.y),t.lineTo(this.toPoint.x,this.toPoint.y),this.enableShadow(t,e),t.stroke(),this.disableShadow(t,e)}},{key:"getViaNode",value:function(){}},{key:"getPoint",value:function(t){return{x:(1-t)*this.fromPoint.x+t*this.toPoint.x,y:(1-t)*this.fromPoint.y+t*this.toPoint.y}}},{key:"_findBorderPosition",value:function(t,e){var i=this.to,o=this.from;t.id===this.from.id&&(i=this.from,o=this.to);var n=Math.atan2(i.y-o.y,i.x-o.x),r=i.x-o.x,s=i.y-o.y,a=Math.sqrt(r*r+s*s),l=(a-t.distanceToBorder(e,n))/a;return{x:(1-l)*o.x+l*i.x,y:(1-l)*o.y+l*i.y,t:0}}},{key:"_getDistanceToEdge",value:function(t,e,i,o,n,r){return this._getDistanceToLine(t,e,i,o,n,r)}}]),i}(z$),Y$=function(){function t(e,i,o,n,r){if(fN(this,t),void 0===i)throw new Error("No body provided");this.options=Zq(n),this.globalOptions=n,this.defaultOptions=r,this.body=i,this.imagelist=o,this.id=void 0,this.fromId=void 0,this.toId=void 0,this.selected=!1,this.hover=!1,this.labelDirty=!0,this.baseWidth=this.options.width,this.baseFontSize=this.options.font.size,this.from=void 0,this.to=void 0,this.edgeType=void 0,this.connected=!1,this.labelModule=new NX(this.body,this.options,!0),this.setOptions(e)}return mQ(t,[{key:"setOptions",value:function(e){if(e){var i=void 0!==e.physics&&this.options.physics!==e.physics||void 0!==e.hidden&&(this.options.hidden||!1)!==(e.hidden||!1)||void 0!==e.from&&this.options.from!==e.from||void 0!==e.to&&this.options.to!==e.to;t.parseOptions(this.options,e,!0,this.globalOptions),void 0!==e.id&&(this.id=e.id),void 0!==e.from&&(this.fromId=e.from),void 0!==e.to&&(this.toId=e.to),void 0!==e.title&&(this.title=e.title),void 0!==e.value&&(e.value=uX(e.value));var o=[e,this.options,this.defaultOptions];return this.chooser=bX("edge",o),this.updateLabelModule(e),i=this.updateEdgeType()||i,this._setInteractionWidths(),this.connect(),i}}},{key:"getFormattingValues",value:function(){var t=!0===this.options.arrows.to||!0===this.options.arrows.to.enabled,e=!0===this.options.arrows.from||!0===this.options.arrows.from.enabled,i=!0===this.options.arrows.middle||!0===this.options.arrows.middle.enabled,o=this.options.color.inherit,n={toArrow:t,toArrowScale:this.options.arrows.to.scaleFactor,toArrowType:this.options.arrows.to.type,toArrowSrc:this.options.arrows.to.src,toArrowImageWidth:this.options.arrows.to.imageWidth,toArrowImageHeight:this.options.arrows.to.imageHeight,middleArrow:i,middleArrowScale:this.options.arrows.middle.scaleFactor,middleArrowType:this.options.arrows.middle.type,middleArrowSrc:this.options.arrows.middle.src,middleArrowImageWidth:this.options.arrows.middle.imageWidth,middleArrowImageHeight:this.options.arrows.middle.imageHeight,fromArrow:e,fromArrowScale:this.options.arrows.from.scaleFactor,fromArrowType:this.options.arrows.from.type,fromArrowSrc:this.options.arrows.from.src,fromArrowImageWidth:this.options.arrows.from.imageWidth,fromArrowImageHeight:this.options.arrows.from.imageHeight,arrowStrikethrough:this.options.arrowStrikethrough,color:o?void 0:this.options.color.color,inheritsColor:o,opacity:this.options.color.opacity,hidden:this.options.hidden,length:this.options.length,shadow:this.options.shadow.enabled,shadowColor:this.options.shadow.color,shadowSize:this.options.shadow.size,shadowX:this.options.shadow.x,shadowY:this.options.shadow.y,dashes:this.options.dashes,width:this.options.width,background:this.options.background.enabled,backgroundColor:this.options.background.color,backgroundSize:this.options.background.size,backgroundDashes:this.options.background.dashes};if(this.selected||this.hover)if(!0===this.chooser){if(this.selected){var r=this.options.selectionWidth;"function"==typeof r?n.width=r(n.width):"number"==typeof r&&(n.width+=r),n.width=Math.max(n.width,.3/this.body.view.scale),n.color=this.options.color.highlight,n.shadow=this.options.shadow.enabled}else if(this.hover){var s=this.options.hoverWidth;"function"==typeof s?n.width=s(n.width):"number"==typeof s&&(n.width+=s),n.width=Math.max(n.width,.3/this.body.view.scale),n.color=this.options.color.hover,n.shadow=this.options.shadow.enabled}}else"function"==typeof this.chooser&&(this.chooser(n,this.options.id,this.selected,this.hover),void 0!==n.color&&(n.inheritsColor=!1),!1===n.shadow&&(n.shadowColor===this.options.shadow.color&&n.shadowSize===this.options.shadow.size&&n.shadowX===this.options.shadow.x&&n.shadowY===this.options.shadow.y||(n.shadow=!0)));else n.shadow=this.options.shadow.enabled,n.width=Math.max(n.width,.3/this.body.view.scale);return n}},{key:"updateLabelModule",value:function(t){var e=[t,this.options,this.globalOptions,this.defaultOptions];this.labelModule.update(this.options,e),void 0!==this.labelModule.baseSize&&(this.baseFontSize=this.labelModule.baseSize)}},{key:"updateEdgeType",value:function(){var t=this.options.smooth,e=!1,i=!0;return void 0!==this.edgeType&&((this.edgeType instanceof U$&&!0===t.enabled&&"dynamic"===t.type||this.edgeType instanceof G$&&!0===t.enabled&&"cubicBezier"===t.type||this.edgeType instanceof Q$&&!0===t.enabled&&"dynamic"!==t.type&&"cubicBezier"!==t.type||this.edgeType instanceof q$&&!1===t.type.enabled)&&(i=!1),!0===i&&(e=this.cleanup())),!0===i?!0===t.enabled?"dynamic"===t.type?(e=!0,this.edgeType=new U$(this.options,this.body,this.labelModule)):"cubicBezier"===t.type?this.edgeType=new G$(this.options,this.body,this.labelModule):this.edgeType=new Q$(this.options,this.body,this.labelModule):this.edgeType=new q$(this.options,this.body,this.labelModule):this.edgeType.setOptions(this.options),e}},{key:"connect",value:function(){this.disconnect(),this.from=this.body.nodes[this.fromId]||void 0,this.to=this.body.nodes[this.toId]||void 0,this.connected=void 0!==this.from&&void 0!==this.to,!0===this.connected?(this.from.attachEdge(this),this.to.attachEdge(this)):(this.from&&this.from.detachEdge(this),this.to&&this.to.detachEdge(this)),this.edgeType.connect()}},{key:"disconnect",value:function(){this.from&&(this.from.detachEdge(this),this.from=void 0),this.to&&(this.to.detachEdge(this),this.to=void 0),this.connected=!1}},{key:"getTitle",value:function(){return this.title}},{key:"isSelected",value:function(){return this.selected}},{key:"getValue",value:function(){return this.options.value}},{key:"setValueRange",value:function(t,e,i){if(void 0!==this.options.value){var o=this.options.scaling.customScalingFunction(t,e,i,this.options.value),n=this.options.scaling.max-this.options.scaling.min;if(!0===this.options.scaling.label.enabled){var r=this.options.scaling.label.max-this.options.scaling.label.min;this.options.font.size=this.options.scaling.label.min+o*r}this.options.width=this.options.scaling.min+o*n}else this.options.width=this.baseWidth,this.options.font.size=this.baseFontSize;this._setInteractionWidths(),this.updateLabelModule()}},{key:"_setInteractionWidths",value:function(){"function"==typeof this.options.hoverWidth?this.edgeType.hoverWidth=this.options.hoverWidth(this.options.width):this.edgeType.hoverWidth=this.options.hoverWidth+this.options.width,"function"==typeof this.options.selectionWidth?this.edgeType.selectionWidth=this.options.selectionWidth(this.options.width):this.edgeType.selectionWidth=this.options.selectionWidth+this.options.width}},{key:"draw",value:function(t){var e=this.getFormattingValues();if(!e.hidden){var i=this.edgeType.getViaNode();this.edgeType.drawLine(t,e,this.selected,this.hover,i),this.drawLabel(t,i)}}},{key:"drawArrows",value:function(t){var e=this.getFormattingValues();if(!e.hidden){var i=this.edgeType.getViaNode(),o={};this.edgeType.fromPoint=this.edgeType.from,this.edgeType.toPoint=this.edgeType.to,e.fromArrow&&(o.from=this.edgeType.getArrowData(t,"from",i,this.selected,this.hover,e),!1===e.arrowStrikethrough&&(this.edgeType.fromPoint=o.from.core),e.fromArrowSrc&&(o.from.image=this.imagelist.load(e.fromArrowSrc)),e.fromArrowImageWidth&&(o.from.imageWidth=e.fromArrowImageWidth),e.fromArrowImageHeight&&(o.from.imageHeight=e.fromArrowImageHeight)),e.toArrow&&(o.to=this.edgeType.getArrowData(t,"to",i,this.selected,this.hover,e),!1===e.arrowStrikethrough&&(this.edgeType.toPoint=o.to.core),e.toArrowSrc&&(o.to.image=this.imagelist.load(e.toArrowSrc)),e.toArrowImageWidth&&(o.to.imageWidth=e.toArrowImageWidth),e.toArrowImageHeight&&(o.to.imageHeight=e.toArrowImageHeight)),e.middleArrow&&(o.middle=this.edgeType.getArrowData(t,"middle",i,this.selected,this.hover,e),e.middleArrowSrc&&(o.middle.image=this.imagelist.load(e.middleArrowSrc)),e.middleArrowImageWidth&&(o.middle.imageWidth=e.middleArrowImageWidth),e.middleArrowImageHeight&&(o.middle.imageHeight=e.middleArrowImageHeight)),e.fromArrow&&this.edgeType.drawArrowHead(t,e,this.selected,this.hover,o.from),e.middleArrow&&this.edgeType.drawArrowHead(t,e,this.selected,this.hover,o.middle),e.toArrow&&this.edgeType.drawArrowHead(t,e,this.selected,this.hover,o.to)}}},{key:"drawLabel",value:function(t,e){if(void 0!==this.options.label){var i,o=this.from,n=this.to;if(this.labelModule.differentState(this.selected,this.hover)&&this.labelModule.getTextSize(t,this.selected,this.hover),o.id!=n.id){this.labelModule.pointToSelf=!1,i=this.edgeType.getPoint(.5,e),t.save();var r=this._getRotation(t);0!=r.angle&&(t.translate(r.x,r.y),t.rotate(r.angle)),this.labelModule.draw(t,i.x,i.y,this.selected,this.hover),t.restore()}else{this.labelModule.pointToSelf=!0;var s=EX(t,this.options.selfReference.angle,this.options.selfReference.size,o);i=this._pointOnCircle(s.x,s.y,this.options.selfReference.size,this.options.selfReference.angle),this.labelModule.draw(t,i.x,i.y,this.selected,this.hover)}}}},{key:"getItemsOnPoint",value:function(t){var e=[];if(this.labelModule.visible()){var i=this._getRotation();wX(this.labelModule.getSize(),t,i)&&e.push({edgeId:this.id,labelId:0})}var o={left:t.x,top:t.y};return this.isOverlappingWith(o)&&e.push({edgeId:this.id}),e}},{key:"isOverlappingWith",value:function(t){if(this.connected){var e=this.from.x,i=this.from.y,o=this.to.x,n=this.to.y,r=t.left,s=t.top;return this.edgeType.getDistanceToEdge(e,i,o,n,r,s)<10}return!1}},{key:"_getRotation",value:function(t){var e=this.edgeType.getViaNode(),i=this.edgeType.getPoint(.5,e);void 0!==t&&this.labelModule.calculateLabelSize(t,this.selected,this.hover,i.x,i.y);var o={x:i.x,y:this.labelModule.size.yLine,angle:0};if(!this.labelModule.visible())return o;if("horizontal"===this.options.font.align)return o;var n=this.from.y-this.to.y,r=this.from.x-this.to.x,s=Math.atan2(n,r);return(s<-1&&r<0||s>0&&r<0)&&(s+=Math.PI),o.angle=s,o}},{key:"_pointOnCircle",value:function(t,e,i,o){return{x:t+i*Math.cos(o),y:e-i*Math.sin(o)}}},{key:"select",value:function(){this.selected=!0}},{key:"unselect",value:function(){this.selected=!1}},{key:"cleanup",value:function(){return this.edgeType.cleanup()}},{key:"remove",value:function(){this.cleanup(),this.disconnect(),delete this.body.edges[this.id]}},{key:"endPointsValid",value:function(){return void 0!==this.body.nodes[this.fromId]&&void 0!==this.body.nodes[this.toId]}}],[{key:"parseOptions",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},n=arguments.length>4&&void 0!==arguments[4]&&arguments[4];if(Pq(["endPointOffset","arrowStrikethrough","id","from","hidden","hoverWidth","labelHighlightBold","length","line","opacity","physics","scaling","selectionWidth","selfReferenceSize","selfReference","to","title","value","width","font","chosen","widthConstraint"],t,e,i),void 0!==e.endPointOffset&&void 0!==e.endPointOffset.from&&(kJ(e.endPointOffset.from)?t.endPointOffset.from=e.endPointOffset.from:(t.endPointOffset.from=void 0!==o.endPointOffset.from?o.endPointOffset.from:0,console.error("endPointOffset.from is not a valid number"))),void 0!==e.endPointOffset&&void 0!==e.endPointOffset.to&&(kJ(e.endPointOffset.to)?t.endPointOffset.to=e.endPointOffset.to:(t.endPointOffset.to=void 0!==o.endPointOffset.to?o.endPointOffset.to:0,console.error("endPointOffset.to is not a valid number"))),AX(e.label)?t.label=e.label:AX(t.label)||(t.label=void 0),Jq(t,e,"smooth",o),Jq(t,e,"shadow",o),Jq(t,e,"background",o),void 0!==e.dashes&&null!==e.dashes?t.dashes=e.dashes:!0===i&&null===e.dashes&&(t.dashes=WW(o.dashes)),void 0!==e.scaling&&null!==e.scaling?(void 0!==e.scaling.min&&(t.scaling.min=e.scaling.min),void 0!==e.scaling.max&&(t.scaling.max=e.scaling.max),Jq(t.scaling,e.scaling,"label",o.scaling)):!0===i&&null===e.scaling&&(t.scaling=WW(o.scaling)),void 0!==e.arrows&&null!==e.arrows)if("string"==typeof e.arrows){var r=e.arrows.toLowerCase();t.arrows.to.enabled=-1!=LW(r).call(r,"to"),t.arrows.middle.enabled=-1!=LW(r).call(r,"middle"),t.arrows.from.enabled=-1!=LW(r).call(r,"from")}else{if("object"!==pQ(e.arrows))throw new Error("The arrow newOptions can only be an object or a string. Refer to the documentation. You used:"+YW(e.arrows));Jq(t.arrows,e.arrows,"to",o.arrows),Jq(t.arrows,e.arrows,"middle",o.arrows),Jq(t.arrows,e.arrows,"from",o.arrows)}else!0===i&&null===e.arrows&&(t.arrows=WW(o.arrows));if(void 0!==e.color&&null!==e.color){var s=Dq(e.color)?{color:e.color,highlight:e.color,hover:e.color,inherit:!1,opacity:1}:e.color,a=t.color;if(n)Tq(a,o.color,!1,i);else for(var l in a)Object.prototype.hasOwnProperty.call(a,l)&&delete a[l];if(Dq(a))a.color=a,a.highlight=a,a.hover=a,a.inherit=!1,void 0===s.opacity&&(a.opacity=1);else{var h=!1;void 0!==s.color&&(a.color=s.color,h=!0),void 0!==s.highlight&&(a.highlight=s.highlight,h=!0),void 0!==s.hover&&(a.hover=s.hover,h=!0),void 0!==s.inherit&&(a.inherit=s.inherit),void 0!==s.opacity&&(a.opacity=Math.min(1,Math.max(0,s.opacity))),!0===h?a.inherit=!1:void 0===a.inherit&&(a.inherit="from")}}else!0===i&&null===e.color&&(t.color=Zq(o.color));!0===i&&null===e.font&&(t.font=Zq(o.font)),Object.prototype.hasOwnProperty.call(e,"selfReferenceSize")&&(console.warn("The selfReferenceSize property has been deprecated. Please use selfReference property instead. The selfReference can be set like thise selfReference:{size:30, angle:Math.PI / 4}"),t.selfReference.size=e.selfReferenceSize)}}]),t}(),Z$=function(){function t(e,i,o){var n,r=this;fN(this,t),this.body=e,this.images=i,this.groups=o,this.body.functions.createEdge=VB(n=this.create).call(n,this),this.edgesListeners={add:function(t,e){r.add(e.items)},update:function(t,e){r.update(e.items)},remove:function(t,e){r.remove(e.items)}},this.options={},this.defaultOptions={arrows:{to:{enabled:!1,scaleFactor:1,type:"arrow"},middle:{enabled:!1,scaleFactor:1,type:"arrow"},from:{enabled:!1,scaleFactor:1,type:"arrow"}},endPointOffset:{from:0,to:0},arrowStrikethrough:!0,color:{color:"#848484",highlight:"#848484",hover:"#848484",inherit:"from",opacity:1},dashes:!1,font:{color:"#343434",size:14,face:"arial",background:"none",strokeWidth:2,strokeColor:"#ffffff",align:"horizontal",multi:!1,vadjust:0,bold:{mod:"bold"},boldital:{mod:"bold italic"},ital:{mod:"italic"},mono:{mod:"",size:15,face:"courier new",vadjust:2}},hidden:!1,hoverWidth:1.5,label:void 0,labelHighlightBold:!0,length:void 0,physics:!0,scaling:{min:1,max:15,label:{enabled:!0,min:14,max:30,maxVisible:30,drawThreshold:5},customScalingFunction:function(t,e,i,o){if(e===t)return.5;var n=1/(e-t);return Math.max(0,(o-t)*n)}},selectionWidth:1.5,selfReference:{size:20,angle:Math.PI/4,renderBehindTheNode:!0},shadow:{enabled:!1,color:"rgba(0,0,0,0.5)",size:10,x:5,y:5},background:{enabled:!1,color:"rgba(111,111,111,1)",size:10,dashes:!1},smooth:{enabled:!0,type:"dynamic",forceDirection:"none",roundness:.5},title:void 0,width:1,value:void 0},Tq(this.options,this.defaultOptions),this.bindEventListeners()}return mQ(t,[{key:"bindEventListeners",value:function(){var t,e,i=this;this.body.emitter.on("_forceDisableDynamicCurves",(function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];"dynamic"===t&&(t="continuous");var o=!1;for(var n in i.body.edges)if(Object.prototype.hasOwnProperty.call(i.body.edges,n)){var r=i.body.edges[n],s=i.body.data.edges.get(n);if(null!=s){var a=s.smooth;void 0!==a&&!0===a.enabled&&"dynamic"===a.type&&(void 0===t?r.setOptions({smooth:!1}):r.setOptions({smooth:{type:t}}),o=!0)}}!0===e&&!0===o&&i.body.emitter.emit("_dataChanged")})),this.body.emitter.on("_dataUpdated",(function(){i.reconnectEdges()})),this.body.emitter.on("refreshEdges",VB(t=this.refresh).call(t,this)),this.body.emitter.on("refresh",VB(e=this.refresh).call(e,this)),this.body.emitter.on("destroy",(function(){Uq(i.edgesListeners,(function(t,e){i.body.data.edges&&i.body.data.edges.off(e,t)})),delete i.body.functions.createEdge,delete i.edgesListeners.add,delete i.edgesListeners.update,delete i.edgesListeners.remove,delete i.edgesListeners}))}},{key:"setOptions",value:function(t){if(void 0!==t){Y$.parseOptions(this.options,t,!0,this.defaultOptions,!0);var e=!1;if(void 0!==t.smooth)for(var i in this.body.edges)Object.prototype.hasOwnProperty.call(this.body.edges,i)&&(e=this.body.edges[i].updateEdgeType()||e);if(void 0!==t.font)for(var o in this.body.edges)Object.prototype.hasOwnProperty.call(this.body.edges,o)&&this.body.edges[o].updateLabelModule();void 0===t.hidden&&void 0===t.physics&&!0!==e||this.body.emitter.emit("_dataChanged")}}},{key:"setData",value:function(t){var e=this,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],o=this.body.data.edges;if(iM("id",t))this.body.data.edges=t;else if(EH(t))this.body.data.edges=new eM,this.body.data.edges.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.body.data.edges=new eM}if(o&&Uq(this.edgesListeners,(function(t,e){o.off(e,t)})),this.body.edges={},this.body.data.edges){Uq(this.edgesListeners,(function(t,i){e.body.data.edges.on(i,t)}));var n=this.body.data.edges.getIds();this.add(n,!0)}this.body.emitter.emit("_adjustEdgesForHierarchicalLayout"),!1===i&&this.body.emitter.emit("_dataChanged")}},{key:"add",value:function(t){for(var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=this.body.edges,o=this.body.data.edges,n=0;n1&&void 0!==arguments[1])||arguments[1];if(0!==t.length){var i=this.body.edges;Uq(t,(function(t){var e=i[t];void 0!==e&&e.remove()})),e&&this.body.emitter.emit("_dataChanged")}}},{key:"refresh",value:function(){var t=this;Uq(this.body.edges,(function(e,i){var o=t.body.data.edges.get(i);void 0!==o&&e.setOptions(o)}))}},{key:"create",value:function(t){return new Y$(t,this.body,this.images,this.options,this.defaultOptions)}},{key:"reconnectEdges",value:function(){var t,e=this.body.nodes,i=this.body.edges;for(t in e)Object.prototype.hasOwnProperty.call(e,t)&&(e[t].edges=[]);for(t in i)if(Object.prototype.hasOwnProperty.call(i,t)){var o=i[t];o.from=null,o.to=null,o.connect()}}},{key:"getConnectedNodes",value:function(t){var e=[];if(void 0!==this.body.edges[t]){var i=this.body.edges[t];void 0!==i.fromId&&e.push(i.fromId),void 0!==i.toId&&e.push(i.toId)}return e}},{key:"_updateState",value:function(){this._addMissingEdges(),this._removeInvalidEdges()}},{key:"_removeInvalidEdges",value:function(){var t=this,e=[];Uq(this.body.edges,(function(i,o){var n=t.body.nodes[i.toId],r=t.body.nodes[i.fromId];void 0!==n&&!0===n.isCluster||void 0!==r&&!0===r.isCluster||void 0!==n&&void 0!==r||e.push(o)})),this.remove(e,!1)}},{key:"_addMissingEdges",value:function(){var t=this.body.data.edges;if(null!=t){var e=this.body.edges,i=[];ZH(t).call(t,(function(t,o){void 0===e[o]&&i.push(o)})),this.add(i,!0)}}}]),t}(),J$=function(){function t(e,i,o){fN(this,t),this.body=e,this.physicsBody=i,this.barnesHutTree,this.setOptions(o),this._rng=Eq("BARNES HUT SOLVER")}return mQ(t,[{key:"setOptions",value:function(t){this.options=t,this.thetaInversed=1/this.options.theta,this.overlapAvoidanceFactor=1-Math.max(0,Math.min(1,this.options.avoidOverlap))}},{key:"solve",value:function(){if(0!==this.options.gravitationalConstant&&this.physicsBody.physicsNodeIndices.length>0){var t,e=this.body.nodes,i=this.physicsBody.physicsNodeIndices,o=i.length,n=this._formBarnesHutTree(e,i);this.barnesHutTree=n;for(var r=0;r0&&this._getForceContributions(n.root,t)}}},{key:"_getForceContributions",value:function(t,e){this._getForceContribution(t.children.NW,e),this._getForceContribution(t.children.NE,e),this._getForceContribution(t.children.SW,e),this._getForceContribution(t.children.SE,e)}},{key:"_getForceContribution",value:function(t,e){if(t.childrenCount>0){var i=t.centerOfMass.x-e.x,o=t.centerOfMass.y-e.y,n=Math.sqrt(i*i+o*o);n*t.calcSize>this.thetaInversed?this._calculateForces(n,i,o,e,t):4===t.childrenCount?this._getForceContributions(t,e):t.children.data.id!=e.id&&this._calculateForces(n,i,o,e,t)}}},{key:"_calculateForces",value:function(t,e,i,o,n){0===t&&(e=t=.1),this.overlapAvoidanceFactor<1&&o.shape.radius&&(t=Math.max(.1+this.overlapAvoidanceFactor*o.shape.radius,t-o.shape.radius));var r=this.options.gravitationalConstant*n.mass*o.options.mass/Math.pow(t,3),s=e*r,a=i*r;this.physicsBody.forces[o.id].x+=s,this.physicsBody.forces[o.id].y+=a}},{key:"_formBarnesHutTree",value:function(t,e){for(var i,o=e.length,n=t[e[0]].x,r=t[e[0]].y,s=t[e[0]].x,a=t[e[0]].y,l=1;l0&&(cs&&(s=c),da&&(a=d))}var u=Math.abs(s-n)-Math.abs(a-r);u>0?(r-=.5*u,a+=.5*u):(n+=.5*u,s-=.5*u);var f=Math.max(1e-5,Math.abs(s-n)),p=.5*f,v=.5*(n+s),g=.5*(r+a),y={root:{centerOfMass:{x:0,y:0},mass:0,range:{minX:v-p,maxX:v+p,minY:g-p,maxY:g+p},size:f,calcSize:1/f,children:{data:null},maxWidth:0,level:0,childrenCount:4}};this._splitBranch(y.root);for(var m=0;m0&&this._placeInTree(y.root,i);return y}},{key:"_updateBranchMass",value:function(t,e){var i=t.centerOfMass,o=t.mass+e.options.mass,n=1/o;i.x=i.x*t.mass+e.x*e.options.mass,i.x*=n,i.y=i.y*t.mass+e.y*e.options.mass,i.y*=n,t.mass=o;var r=Math.max(Math.max(e.height,e.radius),e.width);t.maxWidth=t.maxWidthe.x?n.maxY>e.y?"NW":"SW":n.maxY>e.y?"NE":"SE",this._placeInRegion(t,e,o)}},{key:"_placeInRegion",value:function(t,e,i){var o=t.children[i];switch(o.childrenCount){case 0:o.children.data=e,o.childrenCount=1,this._updateBranchMass(o,e);break;case 1:o.children.data.x===e.x&&o.children.data.y===e.y?(e.x+=this._rng(),e.y+=this._rng()):(this._splitBranch(o),this._placeInTree(o,e));break;case 4:this._placeInTree(o,e)}}},{key:"_splitBranch",value:function(t){var e=null;1===t.childrenCount&&(e=t.children.data,t.mass=0,t.centerOfMass.x=0,t.centerOfMass.y=0),t.childrenCount=4,t.children.data=null,this._insertRegion(t,"NW"),this._insertRegion(t,"NE"),this._insertRegion(t,"SW"),this._insertRegion(t,"SE"),null!=e&&this._placeInTree(t,e)}},{key:"_insertRegion",value:function(t,e){var i,o,n,r,s=.5*t.size;switch(e){case"NW":i=t.range.minX,o=t.range.minX+s,n=t.range.minY,r=t.range.minY+s;break;case"NE":i=t.range.minX+s,o=t.range.maxX,n=t.range.minY,r=t.range.minY+s;break;case"SW":i=t.range.minX,o=t.range.minX+s,n=t.range.minY+s,r=t.range.maxY;break;case"SE":i=t.range.minX+s,o=t.range.maxX,n=t.range.minY+s,r=t.range.maxY}t.children[e]={centerOfMass:{x:0,y:0},mass:0,range:{minX:i,maxX:o,minY:n,maxY:r},size:.5*t.size,calcSize:2*t.calcSize,children:{data:null},maxWidth:0,level:t.level+1,childrenCount:0}}},{key:"_debug",value:function(t,e){void 0!==this.barnesHutTree&&(t.lineWidth=1,this._drawBranch(this.barnesHutTree.root,t,e))}},{key:"_drawBranch",value:function(t,e,i){void 0===i&&(i="#FF0000"),4===t.childrenCount&&(this._drawBranch(t.children.NW,e),this._drawBranch(t.children.NE,e),this._drawBranch(t.children.SE,e),this._drawBranch(t.children.SW,e)),e.strokeStyle=i,e.beginPath(),e.moveTo(t.range.minX,t.range.minY),e.lineTo(t.range.maxX,t.range.minY),e.stroke(),e.beginPath(),e.moveTo(t.range.maxX,t.range.minY),e.lineTo(t.range.maxX,t.range.maxY),e.stroke(),e.beginPath(),e.moveTo(t.range.maxX,t.range.maxY),e.lineTo(t.range.minX,t.range.maxY),e.stroke(),e.beginPath(),e.moveTo(t.range.minX,t.range.maxY),e.lineTo(t.range.minX,t.range.minY),e.stroke()}}]),t}(),X$=function(){function t(e,i,o){fN(this,t),this._rng=Eq("REPULSION SOLVER"),this.body=e,this.physicsBody=i,this.setOptions(o)}return mQ(t,[{key:"setOptions",value:function(t){this.options=t}},{key:"solve",value:function(){for(var t,e,i,o,n,r,s,a,l=this.body.nodes,h=this.physicsBody.physicsNodeIndices,c=this.physicsBody.forces,d=this.options.nodeDistance,u=-2/3/d,f=4/3,p=0;p0){var r=n.edges.length+1,s=this.options.centralGravity*r*n.options.mass;o[n.id].x=e*s,o[n.id].y=i*s}}}]),i}(e0),s0=function(){function t(e){fN(this,t),this.body=e,this.physicsBody={physicsNodeIndices:[],physicsEdgeIndices:[],forces:{},velocities:{}},this.physicsEnabled=!0,this.simulationInterval=1e3/60,this.requiresTimeout=!0,this.previousStates={},this.referenceState={},this.freezeCache={},this.renderTimer=void 0,this.adaptiveTimestep=!1,this.adaptiveTimestepEnabled=!1,this.adaptiveCounter=0,this.adaptiveInterval=3,this.stabilized=!1,this.startedStabilization=!1,this.stabilizationIterations=0,this.ready=!1,this.options={},this.defaultOptions={enabled:!0,barnesHut:{theta:.5,gravitationalConstant:-2e3,centralGravity:.3,springLength:95,springConstant:.04,damping:.09,avoidOverlap:0},forceAtlas2Based:{theta:.5,gravitationalConstant:-50,centralGravity:.01,springConstant:.08,springLength:100,damping:.4,avoidOverlap:0},repulsion:{centralGravity:.2,springLength:200,springConstant:.05,nodeDistance:100,damping:.09,avoidOverlap:0},hierarchicalRepulsion:{centralGravity:0,springLength:100,springConstant:.01,nodeDistance:120,damping:.09},maxVelocity:50,minVelocity:.75,solver:"barnesHut",stabilization:{enabled:!0,iterations:1e3,updateInterval:50,onlyDynamicEdges:!1,fit:!0},timestep:.5,adaptiveTimestep:!0,wind:{x:0,y:0}},AB(this.options,this.defaultOptions),this.timestep=.5,this.layoutFailed=!1,this.bindEventListeners()}return mQ(t,[{key:"bindEventListeners",value:function(){var t=this;this.body.emitter.on("initPhysics",(function(){t.initPhysics()})),this.body.emitter.on("_layoutFailed",(function(){t.layoutFailed=!0})),this.body.emitter.on("resetPhysics",(function(){t.stopSimulation(),t.ready=!1})),this.body.emitter.on("disablePhysics",(function(){t.physicsEnabled=!1,t.stopSimulation()})),this.body.emitter.on("restorePhysics",(function(){t.setOptions(t.options),!0===t.ready&&t.startSimulation()})),this.body.emitter.on("startSimulation",(function(){!0===t.ready&&t.startSimulation()})),this.body.emitter.on("stopSimulation",(function(){t.stopSimulation()})),this.body.emitter.on("destroy",(function(){t.stopSimulation(!1),t.body.emitter.off()})),this.body.emitter.on("_dataChanged",(function(){t.updatePhysicsData()}))}},{key:"setOptions",value:function(t){if(void 0!==t)if(!1===t)this.options.enabled=!1,this.physicsEnabled=!1,this.stopSimulation();else if(!0===t)this.options.enabled=!0,this.physicsEnabled=!0,this.startSimulation();else{this.physicsEnabled=!0,Fq(["stabilization"],this.options,t),Jq(this.options,t,"stabilization"),void 0===t.enabled&&(this.options.enabled=!0),!1===this.options.enabled&&(this.physicsEnabled=!1,this.stopSimulation());var e=this.options.wind;e&&(("number"!=typeof e.x||wJ(e.x))&&(e.x=0),("number"!=typeof e.y||wJ(e.y))&&(e.y=0)),this.timestep=this.options.timestep}this.init()}},{key:"init",value:function(){var t;"forceAtlas2Based"===this.options.solver?(t=this.options.forceAtlas2Based,this.nodesSolver=new o0(this.body,this.physicsBody,t),this.edgesSolver=new $$(this.body,this.physicsBody,t),this.gravitySolver=new r0(this.body,this.physicsBody,t)):"repulsion"===this.options.solver?(t=this.options.repulsion,this.nodesSolver=new X$(this.body,this.physicsBody,t),this.edgesSolver=new $$(this.body,this.physicsBody,t),this.gravitySolver=new e0(this.body,this.physicsBody,t)):"hierarchicalRepulsion"===this.options.solver?(t=this.options.hierarchicalRepulsion,this.nodesSolver=new _$(this.body,this.physicsBody,t),this.edgesSolver=new t0(this.body,this.physicsBody,t),this.gravitySolver=new e0(this.body,this.physicsBody,t)):(t=this.options.barnesHut,this.nodesSolver=new J$(this.body,this.physicsBody,t),this.edgesSolver=new $$(this.body,this.physicsBody,t),this.gravitySolver=new e0(this.body,this.physicsBody,t)),this.modelOptions=t}},{key:"initPhysics",value:function(){!0===this.physicsEnabled&&!0===this.options.enabled?!0===this.options.stabilization.enabled?this.stabilize():(this.stabilized=!1,this.ready=!0,this.body.emitter.emit("fit",{},this.layoutFailed),this.startSimulation()):(this.ready=!0,this.body.emitter.emit("fit"))}},{key:"startSimulation",value:function(){var t;!0===this.physicsEnabled&&!0===this.options.enabled?(this.stabilized=!1,this.adaptiveTimestep=!1,this.body.emitter.emit("_resizeNodes"),void 0===this.viewFunction&&(this.viewFunction=VB(t=this.simulationStep).call(t,this),this.body.emitter.on("initRedraw",this.viewFunction),this.body.emitter.emit("_startRendering"))):this.body.emitter.emit("_redraw")}},{key:"stopSimulation",value:function(){var t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];this.stabilized=!0,!0===t&&this._emitStabilized(),void 0!==this.viewFunction&&(this.body.emitter.off("initRedraw",this.viewFunction),this.viewFunction=void 0,!0===t&&this.body.emitter.emit("_stopRendering"))}},{key:"simulationStep",value:function(){var t=TH();this.physicsTick(),(TH()-t<.4*this.simulationInterval||!0===this.runDoubleSpeed)&&!1===this.stabilized&&(this.physicsTick(),this.runDoubleSpeed=!0),!0===this.stabilized&&this.stopSimulation()}},{key:"_emitStabilized",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.stabilizationIterations;(this.stabilizationIterations>1||!0===this.startedStabilization)&&fG((function(){t.body.emitter.emit("stabilized",{iterations:e}),t.startedStabilization=!1,t.stabilizationIterations=0}),0)}},{key:"physicsStep",value:function(){this.gravitySolver.solve(),this.nodesSolver.solve(),this.edgesSolver.solve(),this.moveNodes()}},{key:"adjustTimeStep",value:function(){!0===this._evaluateStepQuality()?this.timestep=1.2*this.timestep:this.timestep/1.2.3))return!1;return!0}},{key:"moveNodes",value:function(){for(var t=this.physicsBody.physicsNodeIndices,e=0,i=0,o=0;oo&&(t=t>0?o:-o),t}},{key:"_performStep",value:function(t){var e=this.body.nodes[t],i=this.physicsBody.forces[t];this.options.wind&&(i.x+=this.options.wind.x,i.y+=this.options.wind.y);var o=this.physicsBody.velocities[t];return this.previousStates[t]={x:e.x,y:e.y,vx:o.x,vy:o.y},!1===e.options.fixed.x?(o.x=this.calculateComponentVelocity(o.x,i.x,e.options.mass),e.x+=o.x*this.timestep):(i.x=0,o.x=0),!1===e.options.fixed.y?(o.y=this.calculateComponentVelocity(o.y,i.y,e.options.mass),e.y+=o.y*this.timestep):(i.y=0,o.y=0),Math.sqrt(Math.pow(o.x,2)+Math.pow(o.y,2))}},{key:"_freezeNodes",value:function(){var t=this.body.nodes;for(var e in t)if(Object.prototype.hasOwnProperty.call(t,e)&&t[e].x&&t[e].y){var i=t[e].options.fixed;this.freezeCache[e]={x:i.x,y:i.y},i.x=!0,i.y=!0}}},{key:"_restoreFrozenNodes",value:function(){var t=this.body.nodes;for(var e in t)Object.prototype.hasOwnProperty.call(t,e)&&void 0!==this.freezeCache[e]&&(t[e].options.fixed.x=this.freezeCache[e].x,t[e].options.fixed.y=this.freezeCache[e].y);this.freezeCache={}}},{key:"stabilize",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.options.stabilization.iterations;"number"!=typeof e&&(e=this.options.stabilization.iterations,console.error("The stabilize method needs a numeric amount of iterations. Switching to default: ",e)),0!==this.physicsBody.physicsNodeIndices.length?(this.adaptiveTimestep=this.options.adaptiveTimestep,this.body.emitter.emit("_resizeNodes"),this.stopSimulation(),this.stabilized=!1,this.body.emitter.emit("_blockRedraw"),this.targetIterations=e,!0===this.options.stabilization.onlyDynamicEdges&&this._freezeNodes(),this.stabilizationIterations=0,fG((function(){return t._stabilizationBatch()}),0)):this.ready=!0}},{key:"_startStabilizing",value:function(){return!0!==this.startedStabilization&&(this.body.emitter.emit("startStabilizing"),this.startedStabilization=!0,!0)}},{key:"_stabilizationBatch",value:function(){var t=this,e=function(){return!1===t.stabilized&&t.stabilizationIterations1&&void 0!==arguments[1]?arguments[1]:[],o=1e9,n=-1e9,r=1e9,s=-1e9;if(i.length>0)for(var a=0;a(e=t[i[a]]).shape.boundingBox.left&&(r=e.shape.boundingBox.left),se.shape.boundingBox.top&&(o=e.shape.boundingBox.top),n1&&void 0!==arguments[1]?arguments[1]:[],o=1e9,n=-1e9,r=1e9,s=-1e9;if(i.length>0)for(var a=0;a(e=t[i[a]]).x&&(r=e.x),se.y&&(o=e.y),n=t&&i.push(n.id)}for(var r=0;r0&&void 0!==arguments[0]?arguments[0]:{},i=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(void 0===e.joinCondition)throw new Error("Cannot call clusterByNodeData without a joinCondition function in the options.");e=this._checkOptions(e);var o={},n={};Uq(this.body.nodes,(function(i,r){i.options&&!0===e.joinCondition(i.options)&&(o[r]=i,Uq(i.edges,(function(e){void 0===t.clusteredEdges[e.id]&&(n[e.id]=e)})))})),this._cluster(o,n,e,i)}},{key:"clusterByEdgeCount",value:function(t,e){var i=this,o=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];e=this._checkOptions(e);for(var n,r,s,a=[],l={},h=function(){var o={},h={},d=i.body.nodeIndices[c],u=i.body.nodes[d];if(void 0===l[d]){s=0,r=[];for(var f=0;f0&&BH(h).length>0&&!0===v){var m=function(){for(var t=0;t1&&void 0!==arguments[1])||arguments[1];this.clusterByEdgeCount(1,t,e)}},{key:"clusterBridges",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];this.clusterByEdgeCount(2,t,e)}},{key:"clusterByConnection",value:function(t,e){var i,o=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];if(void 0===t)throw new Error("No nodeId supplied to clusterByConnection!");if(void 0===this.body.nodes[t])throw new Error("The nodeId given to clusterByConnection does not exist!");var n=this.body.nodes[t];void 0===(e=this._checkOptions(e,n)).clusterNodeProperties.x&&(e.clusterNodeProperties.x=n.x),void 0===e.clusterNodeProperties.y&&(e.clusterNodeProperties.y=n.y),void 0===e.clusterNodeProperties.fixed&&(e.clusterNodeProperties.fixed={},e.clusterNodeProperties.fixed.x=n.options.fixed.x,e.clusterNodeProperties.fixed.y=n.options.fixed.y);var r={},s={},a=n.id,l=f0.cloneOptions(n);r[a]=n;for(var h=0;h-1&&(s[y.id]=y)}this._cluster(r,s,e,o)}},{key:"_createClusterEdges",value:function(t,e,i,o){for(var n,r,s,a,l,h,c=BH(t),d=[],u=0;u0&&void 0!==arguments[0]?arguments[0]:{};return void 0===t.clusterEdgeProperties&&(t.clusterEdgeProperties={}),void 0===t.clusterNodeProperties&&(t.clusterNodeProperties={}),t}},{key:"_cluster",value:function(t,e,i){var o=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],n=[];for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&void 0!==this.clusteredNodes[r]&&n.push(r);for(var s=0;sn?e.x:n,r=e.ys?e.y:s;return{x:.5*(o+n),y:.5*(r+s)}}},{key:"openCluster",value:function(t,e){var i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];if(void 0===t)throw new Error("No clusterNodeId supplied to openCluster.");var o=this.body.nodes[t];if(void 0===o)throw new Error("The clusterNodeId supplied to openCluster does not exist.");if(!0!==o.isCluster||void 0===o.containedNodes||void 0===o.containedEdges)throw new Error("The node:"+t+" is not a valid cluster.");var n=this.findNode(t),r=LW(n).call(n,t)-1;if(r>=0){var s=n[r];return this.body.nodes[s]._openChildCluster(t),delete this.body.nodes[t],void(!0===i&&this.body.emitter.emit("_dataChanged"))}var a=o.containedNodes,l=o.containedEdges;if(void 0!==e&&void 0!==e.releaseFunction&&"function"==typeof e.releaseFunction){var h={},c={x:o.x,y:o.y};for(var d in a)if(Object.prototype.hasOwnProperty.call(a,d)){var u=this.body.nodes[d];h[d]={x:u.x,y:u.y}}var f=e.releaseFunction(c,h);for(var p in a)if(Object.prototype.hasOwnProperty.call(a,p)){var v=this.body.nodes[p];void 0!==f[p]&&(v.x=void 0===f[p].x?o.x:f[p].x,v.y=void 0===f[p].y?o.y:f[p].y)}}else Uq(a,(function(t){!1===t.options.fixed.x&&(t.x=o.x),!1===t.options.fixed.y&&(t.y=o.y)}));for(var g in a)if(Object.prototype.hasOwnProperty.call(a,g)){var y=this.body.nodes[g];y.vx=o.vx,y.vy=o.vy,y.setOptions({physics:!0}),delete this.clusteredNodes[g]}for(var m=[],b=0;b0&&n<100;){var r=e.pop();if(void 0!==r){var s=this.body.edges[r];if(void 0!==s){n++;var a=s.clusteringEdgeReplacingIds;if(void 0===a)o.push(r);else for(var l=0;lo&&(o=r.edges.length),t+=r.edges.length,e+=Math.pow(r.edges.length,2),i+=1}t/=i;var s=(e/=i)-Math.pow(t,2),a=Math.sqrt(s),l=Math.floor(t+2*a);return l>o&&(l=o),l}},{key:"_createClusteredEdge",value:function(t,e,i,o,n){var r=f0.cloneOptions(i,"edge");Tq(r,o),r.from=t,r.to=e,r.id="clusterEdge:"+u0(),void 0!==n&&Tq(r,n);var s=this.body.functions.createEdge(r);return s.clusteringEdgeReplacingIds=[i.id],s.connect(),this.body.edges[s.id]=s,s}},{key:"_clusterEdges",value:function(t,e,i,o){if(e instanceof Y$){var n=e,r={};r[n.id]=n,e=r}if(t instanceof X_){var s=t,a={};a[s.id]=s,t=a}if(null==i)throw new Error("_clusterEdges: parameter clusterNode required");for(var l in void 0===o&&(o=i.clusterEdgeProperties),this._createClusterEdges(t,e,i,o),e)if(Object.prototype.hasOwnProperty.call(e,l)&&void 0!==this.body.edges[l]){var h=this.body.edges[l];this._backupEdgeOptions(h),h.setOptions({physics:!1})}for(var c in t)Object.prototype.hasOwnProperty.call(t,c)&&(this.clusteredNodes[c]={clusterId:i.id,node:this.body.nodes[c]},this.body.nodes[c].setOptions({physics:!1}))}},{key:"_getClusterNodeForNode",value:function(t){if(void 0!==t){var e=this.clusteredNodes[t];if(void 0!==e){var i=e.clusterId;if(void 0!==i)return this.body.nodes[i]}}}},{key:"_filter",value:function(t,e){var i=[];return Uq(t,(function(t){e(t)&&i.push(t)})),i}},{key:"_updateState",value:function(){var t,e=this,i=[],o={},n=function(t){Uq(e.body.nodes,(function(e){!0===e.isCluster&&t(e)}))};for(t in this.clusteredNodes){if(Object.prototype.hasOwnProperty.call(this.clusteredNodes,t))void 0===this.body.nodes[t]&&i.push(t)}n((function(t){for(var e=0;e0}t.endPointsValid()&&n||(o[i]=i)})),n((function(t){Uq(o,(function(i){delete t.containedEdges[i],Uq(t.edges,(function(n,r){n.id!==i?n.clusteringEdgeReplacingIds=e._filter(n.clusteringEdgeReplacingIds,(function(t){return!o[t]})):t.edges[r]=null})),t.edges=e._filter(t.edges,(function(t){return null!==t}))}))})),Uq(o,(function(t){delete e.clusteredEdges[t]})),Uq(o,(function(t){delete e.body.edges[t]})),Uq(BH(this.body.edges),(function(t){var i=e.body.edges[t],o=e._isClusteredNode(i.fromId)||e._isClusteredNode(i.toId);if(o!==e._isClusteredEdge(i.id))if(o){var n=e._getClusterNodeForNode(i.fromId);void 0!==n&&e._clusterEdges(e.body.nodes[i.fromId],i,n);var r=e._getClusterNodeForNode(i.toId);void 0!==r&&e._clusterEdges(e.body.nodes[i.toId],i,r)}else delete e._clusterEdges[t],e._restoreEdge(i)}));for(var s=!1,a=!0,l=function(){var t=[];n((function(e){var i=BH(e.containedNodes).length,o=!0===e.options.allowSingleNodeCluster;(o&&i<1||!o&&i<2)&&t.push(e.id)}));for(var i=0;i0,s=s||a};a;)l();s&&this._updateState()}},{key:"_isClusteredNode",value:function(t){return void 0!==this.clusteredNodes[t]}},{key:"_isClusteredEdge",value:function(t){return void 0!==this.clusteredEdges[t]}}]),t}();var y0=function(){function t(e,i){var o;fN(this,t),void 0!==window&&(o=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame),window.requestAnimationFrame=void 0===o?function(t){t()}:o,this.body=e,this.canvas=i,this.redrawRequested=!1,this.renderTimer=void 0,this.requiresTimeout=!0,this.renderingActive=!1,this.renderRequests=0,this.allowRedraw=!0,this.dragging=!1,this.zooming=!1,this.options={},this.defaultOptions={hideEdgesOnDrag:!1,hideEdgesOnZoom:!1,hideNodesOnDrag:!1},AB(this.options,this.defaultOptions),this._determineBrowserMethod(),this.bindEventListeners()}return mQ(t,[{key:"bindEventListeners",value:function(){var t,e=this;this.body.emitter.on("dragStart",(function(){e.dragging=!0})),this.body.emitter.on("dragEnd",(function(){e.dragging=!1})),this.body.emitter.on("zoom",(function(){e.zooming=!0,window.clearTimeout(e.zoomTimeoutId),e.zoomTimeoutId=fG((function(){var t;e.zooming=!1,VB(t=e._requestRedraw).call(t,e)()}),250)})),this.body.emitter.on("_resizeNodes",(function(){e._resizeNodes()})),this.body.emitter.on("_redraw",(function(){!1===e.renderingActive&&e._redraw()})),this.body.emitter.on("_blockRedraw",(function(){e.allowRedraw=!1})),this.body.emitter.on("_allowRedraw",(function(){e.allowRedraw=!0,e.redrawRequested=!1})),this.body.emitter.on("_requestRedraw",VB(t=this._requestRedraw).call(t,this)),this.body.emitter.on("_startRendering",(function(){e.renderRequests+=1,e.renderingActive=!0,e._startRendering()})),this.body.emitter.on("_stopRendering",(function(){e.renderRequests-=1,e.renderingActive=e.renderRequests>0,e.renderTimer=void 0})),this.body.emitter.on("destroy",(function(){e.renderRequests=0,e.allowRedraw=!1,e.renderingActive=!1,!0===e.requiresTimeout?clearTimeout(e.renderTimer):window.cancelAnimationFrame(e.renderTimer),e.body.emitter.off()}))}},{key:"setOptions",value:function(t){if(void 0!==t){Pq(["hideEdgesOnDrag","hideEdgesOnZoom","hideNodesOnDrag"],this.options,t)}}},{key:"_requestNextFrame",value:function(t,e){if("undefined"!=typeof window){var i,o=window;return!0===this.requiresTimeout?i=fG(t,e):o.requestAnimationFrame&&(i=o.requestAnimationFrame(t)),i}}},{key:"_startRendering",value:function(){var t;!0===this.renderingActive&&(void 0===this.renderTimer&&(this.renderTimer=this._requestNextFrame(VB(t=this._renderStep).call(t,this),this.simulationInterval)))}},{key:"_renderStep",value:function(){!0===this.renderingActive&&(this.renderTimer=void 0,!0===this.requiresTimeout&&this._startRendering(),this._redraw(),!1===this.requiresTimeout&&this._startRendering())}},{key:"redraw",value:function(){this.body.emitter.emit("setSize"),this._redraw()}},{key:"_requestRedraw",value:function(){var t=this;!0!==this.redrawRequested&&!1===this.renderingActive&&!0===this.allowRedraw&&(this.redrawRequested=!0,this._requestNextFrame((function(){t._redraw(!1)}),0))}},{key:"_redraw",value:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(!0===this.allowRedraw){this.body.emitter.emit("initRedraw"),this.redrawRequested=!1;var e={drawExternalLabels:null};0!==this.canvas.frame.canvas.width&&0!==this.canvas.frame.canvas.height||this.canvas.setSize(),this.canvas.setTransform();var i=this.canvas.getContext(),o=this.canvas.frame.canvas.clientWidth,n=this.canvas.frame.canvas.clientHeight;if(i.clearRect(0,0,o,n),0===this.canvas.frame.clientWidth)return;if(i.save(),i.translate(this.body.view.translation.x,this.body.view.translation.y),i.scale(this.body.view.scale,this.body.view.scale),i.beginPath(),this.body.emitter.emit("beforeDrawing",i),i.closePath(),!1===t&&(!1===this.dragging||!0===this.dragging&&!1===this.options.hideEdgesOnDrag)&&(!1===this.zooming||!0===this.zooming&&!1===this.options.hideEdgesOnZoom)&&this._drawEdges(i),!1===this.dragging||!0===this.dragging&&!1===this.options.hideNodesOnDrag){var r=this._drawNodes(i,t).drawExternalLabels;e.drawExternalLabels=r}!1===t&&(!1===this.dragging||!0===this.dragging&&!1===this.options.hideEdgesOnDrag)&&(!1===this.zooming||!0===this.zooming&&!1===this.options.hideEdgesOnZoom)&&this._drawArrows(i),null!=e.drawExternalLabels&&e.drawExternalLabels(),!1===t&&this._drawSelectionBox(i),i.beginPath(),this.body.emitter.emit("afterDrawing",i),i.closePath(),i.restore(),!0===t&&i.clearRect(0,0,o,n)}}},{key:"_resizeNodes",value:function(){this.canvas.setTransform();var t=this.canvas.getContext();t.save(),t.translate(this.body.view.translation.x,this.body.view.translation.y),t.scale(this.body.view.scale,this.body.view.scale);var e,i=this.body.nodes;for(var o in i)Object.prototype.hasOwnProperty.call(i,o)&&((e=i[o]).resize(t),e.updateBoundingBox(t,e.selected));t.restore()}},{key:"_drawNodes",value:function(t){for(var e,i,o=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=this.body.nodes,r=this.body.nodeIndices,s=[],a=[],l=this.canvas.DOMtoCanvas({x:-20,y:-20}),h=this.canvas.DOMtoCanvas({x:this.canvas.frame.canvas.clientWidth+20,y:this.canvas.frame.canvas.clientHeight+20}),c={top:l.y,left:l.x,bottom:h.y,right:h.x},d=[],u=0;u0&&void 0!==arguments[0]?arguments[0]:this.pixelRatio;!0===this.initialized&&(this.cameraState.previousWidth=this.frame.canvas.width/t,this.cameraState.previousHeight=this.frame.canvas.height/t,this.cameraState.scale=this.body.view.scale,this.cameraState.position=this.DOMtoCanvas({x:.5*this.frame.canvas.width/t,y:.5*this.frame.canvas.height/t}))}},{key:"_setCameraState",value:function(){if(void 0!==this.cameraState.scale&&0!==this.frame.canvas.clientWidth&&0!==this.frame.canvas.clientHeight&&0!==this.pixelRatio&&this.cameraState.previousWidth>0&&this.cameraState.previousHeight>0){var t=this.frame.canvas.width/this.pixelRatio/this.cameraState.previousWidth,e=this.frame.canvas.height/this.pixelRatio/this.cameraState.previousHeight,i=this.cameraState.scale;1!=t&&1!=e?i=.5*this.cameraState.scale*(t+e):1!=t?i=this.cameraState.scale*t:1!=e&&(i=this.cameraState.scale*e),this.body.view.scale=i;var o=this.DOMtoCanvas({x:.5*this.frame.canvas.clientWidth,y:.5*this.frame.canvas.clientHeight}),n={x:o.x-this.cameraState.position.x,y:o.y-this.cameraState.position.y};this.body.view.translation.x+=n.x*this.body.view.scale,this.body.view.translation.y+=n.y*this.body.view.scale}}},{key:"_prepareValue",value:function(t){if("number"==typeof t)return t+"px";if("string"==typeof t){if(-1!==LW(t).call(t,"%")||-1!==LW(t).call(t,"px"))return t;if(-1===LW(t).call(t,"%"))return t+"px"}throw new Error("Could not use the value supplied for width or height:"+t)}},{key:"_create",value:function(){for(;this.body.container.hasChildNodes();)this.body.container.removeChild(this.body.container.firstChild);if(this.frame=document.createElement("div"),this.frame.className="vis-network",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.tabIndex=0,this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),this.frame.canvas.getContext)this._setPixelRatio(),this.setTransform();else{var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerText="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t)}this.body.container.appendChild(this.frame),this.body.view.scale=1,this.body.view.translation={x:.5*this.frame.canvas.clientWidth,y:.5*this.frame.canvas.clientHeight},this._bindHammer()}},{key:"_bindHammer",value:function(){var t=this;void 0!==this.hammer&&this.hammer.destroy(),this.drag={},this.pinch={},this.hammer=new cY(this.frame.canvas),this.hammer.get("pinch").set({enable:!0}),this.hammer.get("pan").set({threshold:5,direction:cY.DIRECTION_ALL}),b0(this.hammer,(function(e){t.body.eventListeners.onTouch(e)})),this.hammer.on("tap",(function(e){t.body.eventListeners.onTap(e)})),this.hammer.on("doubletap",(function(e){t.body.eventListeners.onDoubleTap(e)})),this.hammer.on("press",(function(e){t.body.eventListeners.onHold(e)})),this.hammer.on("panstart",(function(e){t.body.eventListeners.onDragStart(e)})),this.hammer.on("panmove",(function(e){t.body.eventListeners.onDrag(e)})),this.hammer.on("panend",(function(e){t.body.eventListeners.onDragEnd(e)})),this.hammer.on("pinch",(function(e){t.body.eventListeners.onPinch(e)})),this.frame.canvas.addEventListener("wheel",(function(e){t.body.eventListeners.onMouseWheel(e)})),this.frame.canvas.addEventListener("mousemove",(function(e){t.body.eventListeners.onMouseMove(e)})),this.frame.canvas.addEventListener("contextmenu",(function(e){t.body.eventListeners.onContext(e)})),this.hammerFrame=new cY(this.frame),w0(this.hammerFrame,(function(e){t.body.eventListeners.onRelease(e)}))}},{key:"setSize",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.options.width,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.options.height;t=this._prepareValue(t),e=this._prepareValue(e);var i=!1,o=this.frame.canvas.width,n=this.frame.canvas.height,r=this.pixelRatio;if(this._setPixelRatio(),t!=this.options.width||e!=this.options.height||this.frame.style.width!=t||this.frame.style.height!=e)this._getCameraState(r),this.frame.style.width=t,this.frame.style.height=e,this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=Math.round(this.frame.canvas.clientWidth*this.pixelRatio),this.frame.canvas.height=Math.round(this.frame.canvas.clientHeight*this.pixelRatio),this.options.width=t,this.options.height=e,this.canvasViewCenter={x:.5*this.frame.clientWidth,y:.5*this.frame.clientHeight},i=!0;else{var s=Math.round(this.frame.canvas.clientWidth*this.pixelRatio),a=Math.round(this.frame.canvas.clientHeight*this.pixelRatio);this.frame.canvas.width===s&&this.frame.canvas.height===a||this._getCameraState(r),this.frame.canvas.width!==s&&(this.frame.canvas.width=s,i=!0),this.frame.canvas.height!==a&&(this.frame.canvas.height=a,i=!0)}return!0===i&&(this.body.emitter.emit("resize",{width:Math.round(this.frame.canvas.width/this.pixelRatio),height:Math.round(this.frame.canvas.height/this.pixelRatio),oldWidth:Math.round(o/this.pixelRatio),oldHeight:Math.round(n/this.pixelRatio)}),this._setCameraState()),this.initialized=!0,i}},{key:"getContext",value:function(){return this.frame.canvas.getContext("2d")}},{key:"_determinePixelRatio",value:function(){var t=this.getContext();if(void 0===t)throw new Error("Could not get canvax context");var e=1;return"undefined"!=typeof window&&(e=window.devicePixelRatio||1),e/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1)}},{key:"_setPixelRatio",value:function(){this.pixelRatio=this._determinePixelRatio()}},{key:"setTransform",value:function(){var t=this.getContext();if(void 0===t)throw new Error("Could not get canvax context");t.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0)}},{key:"_XconvertDOMtoCanvas",value:function(t){return(t-this.body.view.translation.x)/this.body.view.scale}},{key:"_XconvertCanvasToDOM",value:function(t){return t*this.body.view.scale+this.body.view.translation.x}},{key:"_YconvertDOMtoCanvas",value:function(t){return(t-this.body.view.translation.y)/this.body.view.scale}},{key:"_YconvertCanvasToDOM",value:function(t){return t*this.body.view.scale+this.body.view.translation.y}},{key:"canvasToDOM",value:function(t){return{x:this._XconvertCanvasToDOM(t.x),y:this._YconvertCanvasToDOM(t.y)}}},{key:"DOMtoCanvas",value:function(t){return{x:this._XconvertDOMtoCanvas(t.x),y:this._YconvertDOMtoCanvas(t.y)}}}]),t}();var E0=function(){function t(e,i){var o,n,r=this;fN(this,t),this.body=e,this.canvas=i,this.animationSpeed=1/this.renderRefreshRate,this.animationEasingFunction="easeInOutQuint",this.easingTime=0,this.sourceScale=0,this.targetScale=0,this.sourceTranslation=0,this.targetTranslation=0,this.lockedOnNodeId=void 0,this.lockedOnNodeOffset=void 0,this.touchTime=0,this.viewFunction=void 0,this.body.emitter.on("fit",VB(o=this.fit).call(o,this)),this.body.emitter.on("animationFinished",(function(){r.body.emitter.emit("_stopRendering")})),this.body.emitter.on("unlockNode",VB(n=this.releaseNode).call(n,this))}return mQ(t,[{key:"setOptions",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.options=t}},{key:"fit",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];t=function(t,e){var i=AB({nodes:e,minZoomLevel:Number.MIN_VALUE,maxZoomLevel:1},null!=t?t:{});if(!EH(i.nodes))throw new TypeError("Nodes has to be an array of ids.");if(0===i.nodes.length&&(i.nodes=e),!("number"==typeof i.minZoomLevel&&i.minZoomLevel>0))throw new TypeError("Min zoom level has to be a number higher than zero.");if(!("number"==typeof i.maxZoomLevel&&i.minZoomLevel<=i.maxZoomLevel))throw new TypeError("Max zoom level has to be a number higher than min zoom level.");return i}(t,this.body.nodeIndices);var i,o,n=this.canvas.frame.canvas.clientWidth,r=this.canvas.frame.canvas.clientHeight;if(0===n||0===r)o=1,i=f0.getRange(this.body.nodes,t.nodes);else if(!0===e){var s=0;for(var a in this.body.nodes){if(Object.prototype.hasOwnProperty.call(this.body.nodes,a))!0===this.body.nodes[a].predefinedPosition&&(s+=1)}if(s>.5*this.body.nodeIndices.length)return void this.fit(t,!1);i=f0.getRange(this.body.nodes,t.nodes),o=12.662/(this.body.nodeIndices.length+7.4147)+.0964822,o*=Math.min(n/600,r/600)}else{this.body.emitter.emit("_resizeNodes"),i=f0.getRange(this.body.nodes,t.nodes);var l=n/(1.1*Math.abs(i.maxX-i.minX)),h=r/(1.1*Math.abs(i.maxY-i.minY));o=l<=h?l:h}o>t.maxZoomLevel?o=t.maxZoomLevel:o1&&void 0!==arguments[1]?arguments[1]:{};if(void 0!==this.body.nodes[t]){var i={x:this.body.nodes[t].x,y:this.body.nodes[t].y};e.position=i,e.lockedOnNode=t,this.moveTo(e)}else console.error("Node: "+t+" cannot be found.")}},{key:"moveTo",value:function(t){if(void 0!==t){if(null!=t.offset){if(null!=t.offset.x){if(t.offset.x=+t.offset.x,!kJ(t.offset.x))throw new TypeError('The option "offset.x" has to be a finite number.')}else t.offset.x=0;if(null!=t.offset.y){if(t.offset.y=+t.offset.y,!kJ(t.offset.y))throw new TypeError('The option "offset.y" has to be a finite number.')}else t.offset.x=0}else t.offset={x:0,y:0};if(null!=t.position){if(null!=t.position.x){if(t.position.x=+t.position.x,!kJ(t.position.x))throw new TypeError('The option "position.x" has to be a finite number.')}else t.position.x=0;if(null!=t.position.y){if(t.position.y=+t.position.y,!kJ(t.position.y))throw new TypeError('The option "position.y" has to be a finite number.')}else t.position.x=0}else t.position=this.getViewPosition();if(null!=t.scale){if(t.scale=+t.scale,!(t.scale>0))throw new TypeError('The option "scale" has to be a number greater than zero.')}else t.scale=this.body.view.scale;void 0===t.animation&&(t.animation={duration:0}),!1===t.animation&&(t.animation={duration:0}),!0===t.animation&&(t.animation={}),void 0===t.animation.duration&&(t.animation.duration=1e3),void 0===t.animation.easingFunction&&(t.animation.easingFunction="easeInOutQuad"),this.animateView(t)}else t={}}},{key:"animateView",value:function(t){if(void 0!==t){this.animationEasingFunction=t.animation.easingFunction,this.releaseNode(),!0===t.locked&&(this.lockedOnNodeId=t.lockedOnNode,this.lockedOnNodeOffset=t.offset),0!=this.easingTime&&this._transitionRedraw(!0),this.sourceScale=this.body.view.scale,this.sourceTranslation=this.body.view.translation,this.targetScale=t.scale,this.body.view.scale=this.targetScale;var e,i,o=this.canvas.DOMtoCanvas({x:.5*this.canvas.frame.canvas.clientWidth,y:.5*this.canvas.frame.canvas.clientHeight}),n=o.x-t.position.x,r=o.y-t.position.y;if(this.targetTranslation={x:this.sourceTranslation.x+n*this.targetScale+t.offset.x,y:this.sourceTranslation.y+r*this.targetScale+t.offset.y},0===t.animation.duration)if(null!=this.lockedOnNodeId)this.viewFunction=VB(e=this._lockedRedraw).call(e,this),this.body.emitter.on("initRedraw",this.viewFunction);else this.body.view.scale=this.targetScale,this.body.view.translation=this.targetTranslation,this.body.emitter.emit("_requestRedraw");else this.animationSpeed=1/(60*t.animation.duration*.001)||1/60,this.animationEasingFunction=t.animation.easingFunction,this.viewFunction=VB(i=this._transitionRedraw).call(i,this),this.body.emitter.on("initRedraw",this.viewFunction),this.body.emitter.emit("_startRendering")}}},{key:"_lockedRedraw",value:function(){var t=this.body.nodes[this.lockedOnNodeId].x,e=this.body.nodes[this.lockedOnNodeId].y,i=this.canvas.DOMtoCanvas({x:.5*this.canvas.frame.canvas.clientWidth,y:.5*this.canvas.frame.canvas.clientHeight}),o=i.x-t,n=i.y-e,r=this.body.view.translation,s={x:r.x+o*this.body.view.scale+this.lockedOnNodeOffset.x,y:r.y+n*this.body.view.scale+this.lockedOnNodeOffset.y};this.body.view.translation=s}},{key:"releaseNode",value:function(){void 0!==this.lockedOnNodeId&&void 0!==this.viewFunction&&(this.body.emitter.off("initRedraw",this.viewFunction),this.lockedOnNodeId=void 0,this.lockedOnNodeOffset=void 0)}},{key:"_transitionRedraw",value:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];this.easingTime+=this.animationSpeed,this.easingTime=!0===t?1:this.easingTime;var e=Xq[this.animationEasingFunction](this.easingTime);if(this.body.view.scale=this.sourceScale+(this.targetScale-this.sourceScale)*e,this.body.view.translation={x:this.sourceTranslation.x+(this.targetTranslation.x-this.sourceTranslation.x)*e,y:this.sourceTranslation.y+(this.targetTranslation.y-this.sourceTranslation.y)*e},this.easingTime>=1){var i;if(this.body.emitter.off("initRedraw",this.viewFunction),this.easingTime=0,null!=this.lockedOnNodeId)this.viewFunction=VB(i=this._lockedRedraw).call(i,this),this.body.emitter.on("initRedraw",this.viewFunction);this.body.emitter.emit("animationFinished")}}},{key:"getScale",value:function(){return this.body.view.scale}},{key:"getViewPosition",value:function(){return this.canvas.DOMtoCanvas({x:.5*this.canvas.frame.canvas.clientWidth,y:.5*this.canvas.frame.canvas.clientHeight})}}]),t}();function k0(t){var e,i=t&&t.preventDefault||!1,o=t&&t.container||window,n={},r={keydown:{},keyup:{}},s={};for(e=97;e<=122;e++)s[String.fromCharCode(e)]={code:e-97+65,shift:!1};for(e=65;e<=90;e++)s[String.fromCharCode(e)]={code:e,shift:!0};for(e=0;e<=9;e++)s[""+e]={code:48+e,shift:!1};for(e=1;e<=12;e++)s["F"+e]={code:111+e,shift:!1};for(e=0;e<=9;e++)s["num"+e]={code:96+e,shift:!1};s["num*"]={code:106,shift:!1},s["num+"]={code:107,shift:!1},s["num-"]={code:109,shift:!1},s["num/"]={code:111,shift:!1},s["num."]={code:110,shift:!1},s.left={code:37,shift:!1},s.up={code:38,shift:!1},s.right={code:39,shift:!1},s.down={code:40,shift:!1},s.space={code:32,shift:!1},s.enter={code:13,shift:!1},s.shift={code:16,shift:void 0},s.esc={code:27,shift:!1},s.backspace={code:8,shift:!1},s.tab={code:9,shift:!1},s.ctrl={code:17,shift:!1},s.alt={code:18,shift:!1},s.delete={code:46,shift:!1},s.pageup={code:33,shift:!1},s.pagedown={code:34,shift:!1},s["="]={code:187,shift:!1},s["-"]={code:189,shift:!1},s["]"]={code:221,shift:!1},s["["]={code:219,shift:!1};var a=function(t){h(t,"keydown")},l=function(t){h(t,"keyup")},h=function(t,e){if(void 0!==r[e][t.keyCode]){for(var o=r[e][t.keyCode],n=0;n700&&(this.body.emitter.emit("fit",{duration:700}),this.touchTime=(new Date).valueOf())}},{key:"_stopMovement",value:function(){for(var t in this.boundFunctions)Object.prototype.hasOwnProperty.call(this.boundFunctions,t)&&(this.body.emitter.off("initRedraw",this.boundFunctions[t]),this.body.emitter.emit("_stopRendering"));this.boundFunctions={}}},{key:"_moveUp",value:function(){this.body.view.translation.y+=this.options.keyboard.speed.y}},{key:"_moveDown",value:function(){this.body.view.translation.y-=this.options.keyboard.speed.y}},{key:"_moveLeft",value:function(){this.body.view.translation.x+=this.options.keyboard.speed.x}},{key:"_moveRight",value:function(){this.body.view.translation.x-=this.options.keyboard.speed.x}},{key:"_zoomIn",value:function(){var t=this.body.view.scale,e=this.body.view.scale*(1+this.options.keyboard.speed.zoom),i=this.body.view.translation,o=e/t,n=(1-o)*this.canvas.canvasViewCenter.x+i.x*o,r=(1-o)*this.canvas.canvasViewCenter.y+i.y*o;this.body.view.scale=e,this.body.view.translation={x:n,y:r},this.body.emitter.emit("zoom",{direction:"+",scale:this.body.view.scale,pointer:null})}},{key:"_zoomOut",value:function(){var t=this.body.view.scale,e=this.body.view.scale/(1+this.options.keyboard.speed.zoom),i=this.body.view.translation,o=e/t,n=(1-o)*this.canvas.canvasViewCenter.x+i.x*o,r=(1-o)*this.canvas.canvasViewCenter.y+i.y*o;this.body.view.scale=e,this.body.view.translation={x:n,y:r},this.body.emitter.emit("zoom",{direction:"-",scale:this.body.view.scale,pointer:null})}},{key:"configureKeyboardBindings",value:function(){var t,e,i,o,n,r,s,a,l,h,c,d,u,f,p,v,g,y,m,b,w,A,E,k,C=this;(void 0!==this.keycharm&&this.keycharm.destroy(),!0===this.options.keyboard.enabled)&&(!0===this.options.keyboard.bindToWindow?this.keycharm=k0({container:window,preventDefault:!0}):this.keycharm=k0({container:this.canvas.frame,preventDefault:!0}),this.keycharm.reset(),!0===this.activated&&(VB(t=this.keycharm).call(t,"up",(function(){C.bindToRedraw("_moveUp")}),"keydown"),VB(e=this.keycharm).call(e,"down",(function(){C.bindToRedraw("_moveDown")}),"keydown"),VB(i=this.keycharm).call(i,"left",(function(){C.bindToRedraw("_moveLeft")}),"keydown"),VB(o=this.keycharm).call(o,"right",(function(){C.bindToRedraw("_moveRight")}),"keydown"),VB(n=this.keycharm).call(n,"=",(function(){C.bindToRedraw("_zoomIn")}),"keydown"),VB(r=this.keycharm).call(r,"num+",(function(){C.bindToRedraw("_zoomIn")}),"keydown"),VB(s=this.keycharm).call(s,"num-",(function(){C.bindToRedraw("_zoomOut")}),"keydown"),VB(a=this.keycharm).call(a,"-",(function(){C.bindToRedraw("_zoomOut")}),"keydown"),VB(l=this.keycharm).call(l,"[",(function(){C.bindToRedraw("_zoomOut")}),"keydown"),VB(h=this.keycharm).call(h,"]",(function(){C.bindToRedraw("_zoomIn")}),"keydown"),VB(c=this.keycharm).call(c,"pageup",(function(){C.bindToRedraw("_zoomIn")}),"keydown"),VB(d=this.keycharm).call(d,"pagedown",(function(){C.bindToRedraw("_zoomOut")}),"keydown"),VB(u=this.keycharm).call(u,"up",(function(){C.unbindFromRedraw("_moveUp")}),"keyup"),VB(f=this.keycharm).call(f,"down",(function(){C.unbindFromRedraw("_moveDown")}),"keyup"),VB(p=this.keycharm).call(p,"left",(function(){C.unbindFromRedraw("_moveLeft")}),"keyup"),VB(v=this.keycharm).call(v,"right",(function(){C.unbindFromRedraw("_moveRight")}),"keyup"),VB(g=this.keycharm).call(g,"=",(function(){C.unbindFromRedraw("_zoomIn")}),"keyup"),VB(y=this.keycharm).call(y,"num+",(function(){C.unbindFromRedraw("_zoomIn")}),"keyup"),VB(m=this.keycharm).call(m,"num-",(function(){C.unbindFromRedraw("_zoomOut")}),"keyup"),VB(b=this.keycharm).call(b,"-",(function(){C.unbindFromRedraw("_zoomOut")}),"keyup"),VB(w=this.keycharm).call(w,"[",(function(){C.unbindFromRedraw("_zoomOut")}),"keyup"),VB(A=this.keycharm).call(A,"]",(function(){C.unbindFromRedraw("_zoomIn")}),"keyup"),VB(E=this.keycharm).call(E,"pageup",(function(){C.unbindFromRedraw("_zoomIn")}),"keyup"),VB(k=this.keycharm).call(k,"pagedown",(function(){C.unbindFromRedraw("_zoomOut")}),"keyup")))}}]),t}();function x0(t,e){var i=void 0!==lH&&uN(t)||t["@@iterator"];if(!i){if(EH(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return S0(t,e);var o=vH(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===o&&t.constructor&&(o=t.constructor.name);if("Map"===o||"Set"===o)return GT(t);if("Arguments"===o||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(o))return S0(t,e)}(t))||e){i&&(t=i);var o=0,n=function(){};return{s:n,n:function(){return o>=t.length?{done:!0}:{done:!1,value:t[o++]}},e:function(t){throw t},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function S0(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,o=new Array(e);i50&&(this.drag.pointer=this.getPointer(t.center),this.drag.pinched=!1,this.pinch.scale=this.body.view.scale,this.touchTime=(new Date).valueOf())}},{key:"onTap",value:function(t){var e=this.getPointer(t.center),i=this.selectionHandler.options.multiselect&&(t.changedPointers[0].ctrlKey||t.changedPointers[0].metaKey);this.checkSelectionChanges(e,i),this.selectionHandler.commitAndEmit(e,t),this.selectionHandler.generateClickEvent("click",t,e)}},{key:"onDoubleTap",value:function(t){var e=this.getPointer(t.center);this.selectionHandler.generateClickEvent("doubleClick",t,e)}},{key:"onHold",value:function(t){var e=this.getPointer(t.center),i=this.selectionHandler.options.multiselect;this.checkSelectionChanges(e,i),this.selectionHandler.commitAndEmit(e,t),this.selectionHandler.generateClickEvent("click",t,e),this.selectionHandler.generateClickEvent("hold",t,e)}},{key:"onRelease",value:function(t){if((new Date).valueOf()-this.touchTime>10){var e=this.getPointer(t.center);this.selectionHandler.generateClickEvent("release",t,e),this.touchTime=(new Date).valueOf()}}},{key:"onContext",value:function(t){var e=this.getPointer({x:t.clientX,y:t.clientY});this.selectionHandler.generateClickEvent("oncontext",t,e)}},{key:"checkSelectionChanges",value:function(t){!0===(arguments.length>1&&void 0!==arguments[1]&&arguments[1])?this.selectionHandler.selectAdditionalOnPoint(t):this.selectionHandler.selectOnPoint(t)}},{key:"_determineDifference",value:function(t,e){var i=function(t,e){for(var i=[],o=0;o=n.minX&&i.x<=n.maxX&&i.y>=n.minY&&i.y<=n.maxY}));ZH(r).call(r,(function(t){return e.selectionHandler.selectObject(e.body.nodes[t])}));var s=this.getPointer(t.center);this.selectionHandler.commitAndEmit(s,t),this.selectionHandler.generateClickEvent("dragEnd",t,this.getPointer(t.center),void 0,!0),this.body.emitter.emit("_requestRedraw")}else{var a=this.drag.selection;a&&a.length?(ZH(a).call(a,(function(t){t.node.options.fixed.x=t.xFixed,t.node.options.fixed.y=t.yFixed})),this.selectionHandler.generateClickEvent("dragEnd",t,this.getPointer(t.center)),this.body.emitter.emit("startSimulation")):(this.selectionHandler.generateClickEvent("dragEnd",t,this.getPointer(t.center),void 0,!0),this.body.emitter.emit("_requestRedraw"))}}},{key:"onPinch",value:function(t){var e=this.getPointer(t.center);this.drag.pinched=!0,void 0===this.pinch.scale&&(this.pinch.scale=1);var i=this.pinch.scale*t.scale;this.zoom(i,e)}},{key:"zoom",value:function(t,e){if(!0===this.options.zoomView){var i=this.body.view.scale;t<1e-5&&(t=1e-5),t>10&&(t=10);var o=void 0;void 0!==this.drag&&!0===this.drag.dragging&&(o=this.canvas.DOMtoCanvas(this.drag.pointer));var n=this.body.view.translation,r=t/i,s=(1-r)*e.x+n.x*r,a=(1-r)*e.y+n.y*r;if(this.body.view.scale=t,this.body.view.translation={x:s,y:a},null!=o){var l=this.canvas.canvasToDOM(o);this.drag.pointer.x=l.x,this.drag.pointer.y=l.y}this.body.emitter.emit("_requestRedraw"),i0&&(this.popupObj=h[c[c.length-1]],r=!0)}if(void 0===this.popupObj&&!1===r){for(var u,f=this.body.edgeIndices,p=this.body.edges,v=[],g=0;g0&&(this.popupObj=p[v[v.length-1]],s="edge")}void 0!==this.popupObj?this.popupObj.id!==n&&(void 0===this.popup&&(this.popup=new dY(this.canvas.frame)),this.popup.popupTargetType=s,this.popup.popupTargetId=this.popupObj.id,this.popup.setPosition(t.x+3,t.y-5),this.popup.setText(this.popupObj.getTitle()),this.popup.show(),this.body.emitter.emit("showPopup",this.popupObj.id)):void 0!==this.popup&&(this.popup.hide(),this.body.emitter.emit("hidePopup"))}},{key:"_checkHidePopup",value:function(t){var e=this.selectionHandler._pointerToPositionObject(t),i=!1;if("node"===this.popup.popupTargetType){if(void 0!==this.body.nodes[this.popup.popupTargetId]&&!0===(i=this.body.nodes[this.popup.popupTargetId].isOverlappingWith(e))){var o=this.selectionHandler.getNodeAt(t);i=void 0!==o&&o.id===this.popup.popupTargetId}}else void 0===this.selectionHandler.getNodeAt(t)&&void 0!==this.body.edges[this.popup.popupTargetId]&&(i=this.body.edges[this.popup.popupTargetId].isOverlappingWith(e));!1===i&&(this.popupObj=void 0,this.popup.hide(),this.body.emitter.emit("hidePopup"))}}]),t}();JZ("Set",(function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}}),yJ);var M0=nM(oO.Set),O0=mM,D0=_Z,R0=gZ.getWeakData,B0=zZ,z0=nR,P0=qM,F0=iO,T0=DZ,N0=tD,j0=Qz.set,U0=Qz.getterFor,L0=zj.find,Q0=zj.findIndex,H0=O0([].splice),V0=0,W0=function(t){return t.frozen||(t.frozen=new G0)},G0=function(){this.entries=[]},K0=function(t,e){return L0(t.entries,(function(t){return t[0]===e}))};G0.prototype={get:function(t){var e=K0(this,t);if(e)return e[1]},has:function(t){return!!K0(this,t)},set:function(t,e){var i=K0(this,t);i?i[1]=e:this.entries.push([t,e])},delete:function(t){var e=Q0(this.entries,(function(e){return e[0]===t}));return~e&&H0(this.entries,e,1),!!~e}};var q0,Y0={getConstructor:function(t,e,i,o){var n=t((function(t,n){B0(t,r),j0(t,{type:e,id:V0++,frozen:void 0}),P0(n)||T0(n,t[o],{that:t,AS_ENTRIES:i})})),r=n.prototype,s=U0(e),a=function(t,e,i){var o=s(t),n=R0(z0(e),!0);return!0===n?W0(o).set(e,i):n[o.id]=i,t};return D0(r,{delete:function(t){var e=s(this);if(!F0(t))return!1;var i=R0(t);return!0===i?W0(e).delete(t):i&&N0(i,e.id)&&delete i[e.id]},has:function(t){var e=s(this);if(!F0(t))return!1;var i=R0(t);return!0===i?W0(e).has(t):i&&N0(i,e.id)}}),D0(r,i?{get:function(t){var e=s(this);if(F0(t)){var i=R0(t);return!0===i?W0(e).get(t):i?i[e.id]:void 0}},set:function(t,e){return a(this,t,e)}}:{add:function(t){return a(this,t,!0)}}),n}},Z0=tZ,J0=sM,X0=mM,_0=_Z,$0=gZ,t1=JZ,e1=Y0,i1=iO,o1=Qz.enforce,n1=aM,r1=Cz,s1=Object,a1=Array.isArray,l1=s1.isExtensible,h1=s1.isFrozen,c1=s1.isSealed,d1=s1.freeze,u1=s1.seal,f1={},p1={},v1=!J0.ActiveXObject&&"ActiveXObject"in J0,g1=function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}},y1=t1("WeakMap",g1,e1),m1=y1.prototype,b1=X0(m1.set);if(r1)if(v1){q0=e1.getConstructor(g1,"WeakMap",!0),$0.enable();var w1=X0(m1.delete),A1=X0(m1.has),E1=X0(m1.get);_0(m1,{delete:function(t){if(i1(t)&&!l1(t)){var e=o1(this);return e.frozen||(e.frozen=new q0),w1(this,t)||e.frozen.delete(t)}return w1(this,t)},has:function(t){if(i1(t)&&!l1(t)){var e=o1(this);return e.frozen||(e.frozen=new q0),A1(this,t)||e.frozen.has(t)}return A1(this,t)},get:function(t){if(i1(t)&&!l1(t)){var e=o1(this);return e.frozen||(e.frozen=new q0),A1(this,t)?E1(this,t):e.frozen.get(t)}return E1(this,t)},set:function(t,e){if(i1(t)&&!l1(t)){var i=o1(this);i.frozen||(i.frozen=new q0),A1(this,t)?b1(this,t,e):i.frozen.set(t,e)}else b1(this,t,e);return this}})}else Z0&&n1((function(){var t=d1([]);return b1(new y1,t,1),!h1(t)}))&&_0(m1,{set:function(t,e){var i;return a1(t)&&(h1(t)?i=f1:c1(t)&&(i=p1)),b1(this,t,e),i===f1&&d1(t),i===p1&&u1(t),this}});var k1,C1,x1,S1,I1,M1=nM(oO.WeakMap);function O1(t,e,i,o){if("a"===i&&!o)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!o:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===i?o:"a"===i?o.call(t):o?o.value:e.get(t)}function D1(t,e,i,o,n){if("function"==typeof e?t!==e||!n:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return e.set(t,i),i}function R1(t,e){var i=void 0!==lH&&uN(t)||t["@@iterator"];if(!i){if(EH(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return B1(t,e);var o=vH(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===o&&t.constructor&&(o=t.constructor.name);if("Map"===o||"Set"===o)return GT(t);if("Arguments"===o||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(o))return B1(t,e)}(t))||e){i&&(t=i);var o=0,n=function(){};return{s:n,n:function(){return o>=t.length?{done:!0}:{done:!1,value:t[o++]}},e:function(t){throw t},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function B1(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,o=new Array(e);i0&&void 0!==arguments[0]?arguments[0]:function(){};fN(this,t),x1.set(this,new P1),S1.set(this,new P1),I1.set(this,void 0),D1(this,I1,e)}return mQ(t,[{key:"sizeNodes",get:function(){return O1(this,x1,"f").size}},{key:"sizeEdges",get:function(){return O1(this,S1,"f").size}},{key:"getNodes",value:function(){return O1(this,x1,"f").getSelection()}},{key:"getEdges",value:function(){return O1(this,S1,"f").getSelection()}},{key:"addNodes",value:function(){var t;(t=O1(this,x1,"f")).add.apply(t,arguments)}},{key:"addEdges",value:function(){var t;(t=O1(this,S1,"f")).add.apply(t,arguments)}},{key:"deleteNodes",value:function(t){O1(this,x1,"f").delete(t)}},{key:"deleteEdges",value:function(t){O1(this,S1,"f").delete(t)}},{key:"clear",value:function(){O1(this,x1,"f").clear(),O1(this,S1,"f").clear()}},{key:"commit",value:function(){for(var t,e,i={nodes:O1(this,x1,"f").commit(),edges:O1(this,S1,"f").commit()},o=arguments.length,n=new Array(o),r=0;r=t.length?{done:!0}:{done:!1,value:t[o++]}},e:function(t){throw t},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function N1(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,o=new Array(e);i4&&void 0!==arguments[4]&&arguments[4],r=this._initBaseEvent(e,i);if(!0===n)r.nodes=[],r.edges=[];else{var s=this.getSelection();r.nodes=s.nodes,r.edges=s.edges}void 0!==o&&(r.previousSelection=o),"click"==t&&(r.items=this.getClickedItems(i)),void 0!==e.controlEdge&&(r.controlEdge=e.controlEdge),this.body.emitter.emit(t,r)}},{key:"selectObject",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.options.selectConnectedEdges;if(void 0!==t){if(t instanceof X_){var i;if(!0===e)(i=this._selectionAccumulator).addEdges.apply(i,aH(t.edges));this._selectionAccumulator.addNodes(t)}else this._selectionAccumulator.addEdges(t);return!0}return!1}},{key:"deselectObject",value:function(t){!0===t.isSelected()&&(t.selected=!1,this._removeFromSelection(t))}},{key:"_getAllNodesOverlappingWith",value:function(t){for(var e=[],i=this.body.nodes,o=0;o1&&void 0!==arguments[1])||arguments[1],i=this._pointerToPositionObject(t),o=this._getAllNodesOverlappingWith(i);return o.length>0?!0===e?this.body.nodes[o[o.length-1]]:o[o.length-1]:void 0}},{key:"_getEdgesOverlappingWith",value:function(t,e){for(var i=this.body.edges,o=0;o1&&void 0!==arguments[1])||arguments[1],i=this.canvas.DOMtoCanvas(t),o=10,n=null,r=this.body.edges,s=0;s0&&(this.generateClickEvent("deselectEdge",e,t,n),i=!0),o.nodes.deleted.length>0&&(this.generateClickEvent("deselectNode",e,t,n),i=!0),o.nodes.added.length>0&&(this.generateClickEvent("selectNode",e,t),i=!0),o.edges.added.length>0&&(this.generateClickEvent("selectEdge",e,t),i=!0),!0===i&&this.generateClickEvent("select",e,t)}},{key:"getSelection",value:function(){return{nodes:this.getSelectedNodeIds(),edges:this.getSelectedEdgeIds()}}},{key:"getSelectedNodes",value:function(){return this._selectionAccumulator.getNodes()}},{key:"getSelectedEdges",value:function(){return this._selectionAccumulator.getEdges()}},{key:"getSelectedNodeIds",value:function(){var t;return OH(t=this._selectionAccumulator.getNodes()).call(t,(function(t){return t.id}))}},{key:"getSelectedEdgeIds",value:function(){var t;return OH(t=this._selectionAccumulator.getEdges()).call(t,(function(t){return t.id}))}},{key:"setSelection",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!t||!t.nodes&&!t.edges)throw new TypeError("Selection must be an object with nodes and/or edges properties");if((e.unselectAll||void 0===e.unselectAll)&&this.unselectAll(),t.nodes){var i,o=T1(t.nodes);try{for(o.s();!(i=o.n()).done;){var n=i.value,r=this.body.nodes[n];if(!r)throw new RangeError('Node with id "'+n+'" not found');this.selectObject(r,e.highlightEdges)}}catch(t){o.e(t)}finally{o.f()}}if(t.edges){var s,a=T1(t.edges);try{for(a.s();!(s=a.n()).done;){var l=s.value,h=this.body.edges[l];if(!h)throw new RangeError('Edge with id "'+l+'" not found');this.selectObject(h)}}catch(t){a.e(t)}finally{a.f()}}this.body.emitter.emit("_requestRedraw"),this._selectionAccumulator.commit()}},{key:"selectNodes",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(!t||void 0===t.length)throw"Selection must be an array with ids";this.setSelection({nodes:t},{highlightEdges:e})}},{key:"selectEdges",value:function(t){if(!t||void 0===t.length)throw"Selection must be an array with ids";this.setSelection({edges:t})}},{key:"updateSelection",value:function(){for(var t in this._selectionAccumulator.getNodes())Object.prototype.hasOwnProperty.call(this.body.nodes,t.id)||this._selectionAccumulator.deleteNodes(t);for(var e in this._selectionAccumulator.getEdges())Object.prototype.hasOwnProperty.call(this.body.edges,e.id)||this._selectionAccumulator.deleteEdges(e)}},{key:"getClickedItems",value:function(t){for(var e=this.canvas.DOMtoCanvas(t),i=[],o=this.body.nodeIndices,n=this.body.nodes,r=o.length-1;r>=0;r--){var s=n[o[r]].getItemsOnPoint(e);i.push.apply(i,s)}for(var a=this.body.edgeIndices,l=this.body.edges,h=a.length-1;h>=0;h--){var c=l[a[h]].getItemsOnPoint(e);i.push.apply(i,c)}return i}}]),t}(),U1=sj,L1=Math.floor,Q1=function(t,e){var i=t.length,o=L1(i/2);return i<8?H1(t,e):V1(t,Q1(U1(t,0,o),e),Q1(U1(t,o),e),e)},H1=function(t,e){for(var i,o,n=t.length,r=1;r0;)t[o]=t[--o];o!==r++&&(t[o]=i)}return t},V1=function(t,e,i,o){for(var n=e.length,r=i.length,s=0,a=0;s3)){if(a2)return!0;if(h2)return h2<603;var t,e,i,o,n="";for(t=65;t<76;t++){switch(e=String.fromCharCode(t),t){case 66:case 69:case 70:case 72:i=3;break;case 68:case 71:i=4;break;default:i=2}for(o=0;o<47;o++)c2.push({k:e+o,v:i})}for(c2.sort((function(t,e){return e.v-t.v})),o=0;oi2(i)?1:-1}}(t)),i=t2(n),o=0;o=0:a>l;l+=h)l in s&&(n=i(n,s[l],l,r));return n}},O2={left:M2(!1),right:M2(!0)},D2="process"===EM(sM.process),R2=O2.left;DR({target:"Array",proto:!0,forced:!D2&&yO>79&&yO<83||!jH("reduce")},{reduce:function(t){var e=arguments.length;return R2(this,t,e,e>1?arguments[1]:void 0)}});var B2=TB("Array").reduce,z2=hO,P2=B2,F2=Array.prototype,T2=function(t){var e=t.reduce;return t===F2||z2(F2,t)&&e===F2.reduce?P2:e},N2=nM(T2);function j2(t){var e=function(){if("undefined"==typeof Reflect||!e_)return!1;if(e_.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(e_(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,o=h_(t);if(e){var n=h_(this).constructor;i=e_(o,arguments,n)}else i=o.apply(this,arguments);return a_(this,i)}}var U2=function(){function t(){fN(this,t)}return mQ(t,[{key:"abstract",value:function(){throw new Error("Can't instantiate abstract class!")}},{key:"fake_use",value:function(){}},{key:"curveType",value:function(){return this.abstract()}},{key:"getPosition",value:function(t){return this.fake_use(t),this.abstract()}},{key:"setPosition",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0;this.fake_use(t,e,i),this.abstract()}},{key:"getTreeSize",value:function(t){return this.fake_use(t),this.abstract()}},{key:"sort",value:function(t){this.fake_use(t),this.abstract()}},{key:"fix",value:function(t,e){this.fake_use(t,e),this.abstract()}},{key:"shift",value:function(t,e){this.fake_use(t,e),this.abstract()}}]),t}(),L2=function(t){s_(i,t);var e=j2(i);function i(t){var o;return fN(this,i),(o=e.call(this)).layout=t,o}return mQ(i,[{key:"curveType",value:function(){return"horizontal"}},{key:"getPosition",value:function(t){return t.x}},{key:"setPosition",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0;void 0!==i&&this.layout.hierarchical.addToOrdering(t,i),t.x=e}},{key:"getTreeSize",value:function(t){var e=this.layout.hierarchical.getTreeSize(this.layout.body.nodes,t);return{min:e.min_x,max:e.max_x}}},{key:"sort",value:function(t){E2(t).call(t,(function(t,e){return t.x-e.x}))}},{key:"fix",value:function(t,e){t.y=this.layout.options.hierarchical.levelSeparation*e,t.options.fixed.y=!0}},{key:"shift",value:function(t,e){this.layout.body.nodes[t].x+=e}}]),i}(U2),Q2=function(t){s_(i,t);var e=j2(i);function i(t){var o;return fN(this,i),(o=e.call(this)).layout=t,o}return mQ(i,[{key:"curveType",value:function(){return"vertical"}},{key:"getPosition",value:function(t){return t.y}},{key:"setPosition",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0;void 0!==i&&this.layout.hierarchical.addToOrdering(t,i),t.y=e}},{key:"getTreeSize",value:function(t){var e=this.layout.hierarchical.getTreeSize(this.layout.body.nodes,t);return{min:e.min_y,max:e.max_y}}},{key:"sort",value:function(t){E2(t).call(t,(function(t,e){return t.y-e.y}))}},{key:"fix",value:function(t,e){t.x=this.layout.options.hierarchical.levelSeparation*e,t.options.fixed.x=!0}},{key:"shift",value:function(t,e){this.layout.body.nodes[t].y+=e}}]),i}(U2),H2=zj.every;DR({target:"Array",proto:!0,forced:!jH("every")},{every:function(t){return H2(this,t,arguments.length>1?arguments[1]:void 0)}});var V2=TB("Array").every,W2=hO,G2=V2,K2=Array.prototype,q2=function(t){var e=t.every;return t===K2||W2(K2,t)&&e===K2.every?G2:e},Y2=nM(q2);function Z2(t,e){var i=void 0!==lH&&uN(t)||t["@@iterator"];if(!i){if(EH(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return J2(t,e);var o=vH(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===o&&t.constructor&&(o=t.constructor.name);if("Map"===o||"Set"===o)return GT(t);if("Arguments"===o||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(o))return J2(t,e)}(t))||e){i&&(t=i);var o=0,n=function(){};return{s:n,n:function(){return o>=t.length?{done:!0}:{done:!1,value:t[o++]}},e:function(t){throw t},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function J2(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,o=new Array(e);i=e[o])&&(e[o]=e[i]+1)})),e}function _2(t,e,i,o){var n,r,s=WW(null),a=N2(n=aH(RX(o).call(o))).call(n,(function(t,e){return t+1+e.edges.length}),0),l=i+"Id",h="to"===i?1:-1,c=Z2(o);try{var d,u=function(){var n=sH(r.value,2),c=n[0],d=n[1];if(!o.has(c)||!t(d))return 0;s[c]=0;for(var u,f,p=[d],v=0,g=function(){var t,n;if(!o.has(c))return 0;var r=s[u.id]+h;if(ZH(t=aW(n=u.edges).call(n,(function(t){return t.connected&&t.to!==t.from&&t[i]!==u&&o.has(t.toId)&&o.has(t.fromId)}))).call(t,(function(t){var o=t[l],n=s[o];(null==n||e(r,n))&&(s[o]=r,p.push(t[i]))})),v>a)return{v:{v:X2(o,s)}};++v};u=p.pop();)if(0!==(f=g())&&f)return f.v};for(c.s();!(r=c.n()).done;)if(0!==(d=u())&&d)return d.v}catch(t){c.e(t)}finally{c.f()}return s}var $2=function(){function t(){fN(this,t),this.childrenReference={},this.parentReference={},this.trees={},this.distributionOrdering={},this.levels={},this.distributionIndex={},this.isTree=!1,this.treeIndex=-1}return mQ(t,[{key:"addRelation",value:function(t,e){void 0===this.childrenReference[t]&&(this.childrenReference[t]=[]),this.childrenReference[t].push(e),void 0===this.parentReference[e]&&(this.parentReference[e]=[]),this.parentReference[e].push(t)}},{key:"checkIfTree",value:function(){for(var t in this.parentReference)if(this.parentReference[t].length>1)return void(this.isTree=!1);this.isTree=!0}},{key:"numTrees",value:function(){return this.treeIndex+1}},{key:"setTreeIndex",value:function(t,e){void 0!==e&&void 0===this.trees[t.id]&&(this.trees[t.id]=e,this.treeIndex=Math.max(e,this.treeIndex))}},{key:"ensureLevel",value:function(t){void 0===this.levels[t]&&(this.levels[t]=0)}},{key:"getMaxLevel",value:function(t){var e=this,i={};return function t(o){if(void 0!==i[o])return i[o];var n=e.levels[o];if(e.childrenReference[o]){var r=e.childrenReference[o];if(r.length>0)for(var s=0;s0&&(i.levelSeparation*=-1):i.levelSeparation<0&&(i.levelSeparation*=-1),this.setDirectionStrategy(),this.body.emitter.emit("_resetHierarchicalLayout"),this.adaptAllOptionsForHierarchicalLayout(e);if(!0===o)return this.body.emitter.emit("refresh"),Tq(e,this.optionsBackup)}return e}},{key:"_resetRNG",value:function(t){this.initialRandomSeed=t,this._rng=Eq(this.initialRandomSeed)}},{key:"adaptAllOptionsForHierarchicalLayout",value:function(t){if(!0===this.options.hierarchical.enabled){var e=this.optionsBackup.physics;void 0===t.physics||!0===t.physics?(t.physics={enabled:void 0===e.enabled||e.enabled,solver:"hierarchicalRepulsion"},e.enabled=void 0===e.enabled||e.enabled,e.solver=e.solver||"barnesHut"):"object"===pQ(t.physics)?(e.enabled=void 0===t.physics.enabled||t.physics.enabled,e.solver=t.physics.solver||"barnesHut",t.physics.solver="hierarchicalRepulsion"):!1!==t.physics&&(e.solver="barnesHut",t.physics={solver:"hierarchicalRepulsion"});var i=this.direction.curveType();if(void 0===t.edges)this.optionsBackup.edges={smooth:{enabled:!0,type:"dynamic"}},t.edges={smooth:!1};else if(void 0===t.edges.smooth)this.optionsBackup.edges={smooth:{enabled:!0,type:"dynamic"}},t.edges.smooth=!1;else if("boolean"==typeof t.edges.smooth)this.optionsBackup.edges={smooth:t.edges.smooth},t.edges.smooth={enabled:t.edges.smooth,type:i};else{var o=t.edges.smooth;void 0!==o.type&&"dynamic"!==o.type&&(i=o.type),this.optionsBackup.edges={smooth:{enabled:void 0===o.enabled||o.enabled,type:void 0===o.type?"dynamic":o.type,roundness:void 0===o.roundness?.5:o.roundness,forceDirection:void 0!==o.forceDirection&&o.forceDirection}},t.edges.smooth={enabled:void 0===o.enabled||o.enabled,type:i,roundness:void 0===o.roundness?.5:o.roundness,forceDirection:void 0!==o.forceDirection&&o.forceDirection}}this.body.emitter.emit("_forceDisableDynamicCurves",i)}return t}},{key:"positionInitially",value:function(t){if(!0!==this.options.hierarchical.enabled){this._resetRNG(this.initialRandomSeed);for(var e=t.length+50,i=0;in){for(var s=t.length;t.length>n&&o<=10;){o+=1;var a=t.length;if(o%3==0?this.body.modules.clustering.clusterBridges(r):this.body.modules.clustering.clusterOutliers(r),a==t.length&&o%3!=0)return this._declusterAll(),this.body.emitter.emit("_layoutFailed"),void console.info("This network could not be positioned by this version of the improved layout algorithm. Please disable improvedLayout for better performance.")}this.body.modules.kamadaKawai.setOptions({springLength:Math.max(150,2*s)})}o>10&&console.info("The clustering didn't succeed within the amount of interations allowed, progressing with partial result."),this.body.modules.kamadaKawai.solve(t,this.body.edgeIndices,!0),this._shiftToCenter();for(var l=0;l0){var t,e,i=!1,o=!1;for(e in this.lastNodeOnLevel={},this.hierarchical=new $2,this.body.nodes)Object.prototype.hasOwnProperty.call(this.body.nodes,e)&&(void 0!==(t=this.body.nodes[e]).options.level?(i=!0,this.hierarchical.levels[e]=t.options.level):o=!0);if(!0===o&&!0===i)throw new Error("To use the hierarchical layout, nodes require either no predefined levels or levels have to be defined for all nodes.");if(!0===o){var n=this.options.hierarchical.sortMethod;"hubsize"===n?this._determineLevelsByHubsize():"directed"===n?this._determineLevelsDirected():"custom"===n&&this._determineLevelsCustomCallback()}for(var r in this.body.nodes)Object.prototype.hasOwnProperty.call(this.body.nodes,r)&&this.hierarchical.ensureLevel(r);var s=this._getDistribution();this._generateMap(),this._placeNodesByHierarchy(s),this._condenseHierarchy(),this._shiftToCenter()}}},{key:"_condenseHierarchy",value:function(){var t=this,e=!1,i={},o=function(e,i){var o=t.hierarchical.trees;for(var n in o)Object.prototype.hasOwnProperty.call(o,n)&&o[n]===e&&t.direction.shift(n,i)},n=function(){for(var e=[],i=0;i0)for(var r=0;r1&&void 0!==arguments[1]?arguments[1]:1e9,o=1e9,n=1e9,r=1e9,s=-1e9;for(var a in e)if(Object.prototype.hasOwnProperty.call(e,a)){var l=t.body.nodes[a],h=t.hierarchical.levels[l.id],c=t.direction.getPosition(l),d=sH(t._getSpaceAroundNode(l,e),2),u=d[0],f=d[1];o=Math.min(u,o),n=Math.min(f,n),h<=i&&(r=Math.min(c,r),s=Math.max(c,s))}return[r,s,o,n]},a=function(e,i,o){for(var n=t.hierarchical,r=0;r1)for(var l=0;l2&&void 0!==arguments[2]&&arguments[2],a=t.direction.getPosition(i),l=t.direction.getPosition(o),h=Math.abs(l-a),c=t.options.hierarchical.nodeSpacing;if(h>c){var d={},u={};r(i,d),r(o,u);var f=function(e,i){var o=t.hierarchical.getMaxLevel(e.id),n=t.hierarchical.getMaxLevel(i.id);return Math.min(o,n)}(i,o),p=s(d,f),v=s(u,f),g=p[1],y=v[0],m=v[2];if(Math.abs(g-y)>c){var b=g-y+c;b<-m+c&&(b=-m+c),b<0&&(t._shiftBlock(o.id,b),e=!0,!0===n&&t._centerParent(o))}}},h=function(o,n){for(var a=n.id,l=n.edges,h=t.hierarchical.levels[n.id],c=t.options.hierarchical.levelSeparation*t.options.hierarchical.levelSeparation,d={},u=[],f=0;f0?f=Math.min(u,d-t.options.hierarchical.nodeSpacing):u<0&&(f=-Math.min(-u,c-t.options.hierarchical.nodeSpacing)),0!=f&&(t._shiftBlock(n.id,f),e=!0)}(b),function(i){var o=t.direction.getPosition(n),r=sH(t._getSpaceAroundNode(n),2),s=r[0],a=r[1],l=i-o,h=o;l>0?h=Math.min(o+(a-t.options.hierarchical.nodeSpacing),i):l<0&&(h=Math.max(o-(s-t.options.hierarchical.nodeSpacing),i)),h!==o&&(t.direction.setPosition(n,h),e=!0)}(b=m(o,l))};!0===this.options.hierarchical.blockShifting&&(function(i){var o=t.hierarchical.getLevels();o=rV(o).call(o);for(var n=0;n0&&Math.abs(d)0&&(l=this.direction.getPosition(o[r-1])+a),this.direction.setPosition(s,l,e),this._validatePositionAndContinue(s,e,l),n++}}}}},{key:"_placeBranchNodes",value:function(t,e){var i,o=this.hierarchical.childrenReference[t];if(void 0!==o){for(var n=[],r=0;re&&void 0===this.positionedNodes[a.id]))return;var h=this.options.hierarchical.nodeSpacing,c=void 0;c=0===s?this.direction.getPosition(this.body.nodes[t]):this.direction.getPosition(n[s-1])+h,this.direction.setPosition(a,c,l),this._validatePositionAndContinue(a,l,c)}var d=this._getCenterPosition(n);this.direction.setPosition(this.body.nodes[t],d,e)}}},{key:"_validatePositionAndContinue",value:function(t,e,i){if(this.hierarchical.isTree){if(void 0!==this.lastNodeOnLevel[e]){var o=this.direction.getPosition(this.body.nodes[this.lastNodeOnLevel[e]]);if(i-ot}),"from",t)}(i),this.hierarchical.setMinLevelToZero(this.body.nodes)}},{key:"_generateMap",value:function(){var t=this;this._crawlNetwork((function(e,i){t.hierarchical.levels[i.id]>t.hierarchical.levels[e.id]&&t.hierarchical.addRelation(e.id,i.id)})),this.hierarchical.checkIfTree()}},{key:"_crawlNetwork",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:function(){},i=arguments.length>1?arguments[1]:void 0,o={},n=function i(n,r){if(void 0===o[n.id]){var s;t.hierarchical.setTreeIndex(n,r),o[n.id]=!0;for(var a=t._getActiveEdges(n),l=0;l=t.length?{done:!0}:{done:!1,value:t[o++]}},e:function(t){throw t},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function i3(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,o=new Array(e);i0&&!1!==this.options.deleteNode||0===i&&!1!==this.options.deleteEdge)&&(!0===s&&this._createSeperator(4),this._createDeleteButton(r)),this._bindElementEvents(this.closeDiv,VB(t=this.toggleEditMode).call(t,this)),this._temporaryBindEvent("select",VB(e=this.showManipulatorToolbar).call(e,this))}this.body.emitter.emit("_redraw")}},{key:"addNodeMode",value:function(){var t;if(!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="addNode",!0===this.guiEnabled){var e,i=this.options.locales[this.options.locale];this.manipulationDOM={},this._createBackButton(i),this._createSeperator(),this._createDescription(i.addDescription||this.options.locales.en.addDescription),this._bindElementEvents(this.closeDiv,VB(e=this.toggleEditMode).call(e,this))}this._temporaryBindEvent("click",VB(t=this._performAddNode).call(t,this))}},{key:"editNode",value:function(){var t=this;!0!==this.editMode&&this.enableEditMode(),this._clean();var e=this.selectionHandler.getSelectedNodes()[0];if(void 0!==e){if(this.inMode="editNode","function"!=typeof this.options.editNode)throw new Error("No function has been configured to handle the editing of nodes.");if(!0!==e.isCluster){var i=Tq({},e.options,!1);if(i.x=e.x,i.y=e.y,2!==this.options.editNode.length)throw new Error("The function for edit does not support two arguments (data, callback)");this.options.editNode(i,(function(e){null!=e&&"editNode"===t.inMode&&t.body.data.nodes.getDataSet().update(e),t.showManipulatorToolbar()}))}else alert(this.options.locales[this.options.locale].editClusterError||this.options.locales.en.editClusterError)}else this.showManipulatorToolbar()}},{key:"addEdgeMode",value:function(){var t,e,i,o,n;if(!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="addEdge",!0===this.guiEnabled){var r,s=this.options.locales[this.options.locale];this.manipulationDOM={},this._createBackButton(s),this._createSeperator(),this._createDescription(s.edgeDescription||this.options.locales.en.edgeDescription),this._bindElementEvents(this.closeDiv,VB(r=this.toggleEditMode).call(r,this))}this._temporaryBindUI("onTouch",VB(t=this._handleConnect).call(t,this)),this._temporaryBindUI("onDragEnd",VB(e=this._finishConnect).call(e,this)),this._temporaryBindUI("onDrag",VB(i=this._dragControlNode).call(i,this)),this._temporaryBindUI("onRelease",VB(o=this._finishConnect).call(o,this)),this._temporaryBindUI("onDragStart",VB(n=this._dragStartEdge).call(n,this)),this._temporaryBindUI("onHold",(function(){}))}},{key:"editEdgeMode",value:function(){if(!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="editEdge","object"!==pQ(this.options.editEdge)||"function"!=typeof this.options.editEdge.editWithoutDrag||(this.edgeBeingEditedId=this.selectionHandler.getSelectedEdgeIds()[0],void 0===this.edgeBeingEditedId)){if(!0===this.guiEnabled){var t,e=this.options.locales[this.options.locale];this.manipulationDOM={},this._createBackButton(e),this._createSeperator(),this._createDescription(e.editEdgeDescription||this.options.locales.en.editEdgeDescription),this._bindElementEvents(this.closeDiv,VB(t=this.toggleEditMode).call(t,this))}if(this.edgeBeingEditedId=this.selectionHandler.getSelectedEdgeIds()[0],void 0!==this.edgeBeingEditedId){var i,o,n,r,s=this.body.edges[this.edgeBeingEditedId],a=this._getNewTargetNode(s.from.x,s.from.y),l=this._getNewTargetNode(s.to.x,s.to.y);this.temporaryIds.nodes.push(a.id),this.temporaryIds.nodes.push(l.id),this.body.nodes[a.id]=a,this.body.nodeIndices.push(a.id),this.body.nodes[l.id]=l,this.body.nodeIndices.push(l.id),this._temporaryBindUI("onTouch",VB(i=this._controlNodeTouch).call(i,this)),this._temporaryBindUI("onTap",(function(){})),this._temporaryBindUI("onHold",(function(){})),this._temporaryBindUI("onDragStart",VB(o=this._controlNodeDragStart).call(o,this)),this._temporaryBindUI("onDrag",VB(n=this._controlNodeDrag).call(n,this)),this._temporaryBindUI("onDragEnd",VB(r=this._controlNodeDragEnd).call(r,this)),this._temporaryBindUI("onMouseMove",(function(){})),this._temporaryBindEvent("beforeDrawing",(function(t){var e=s.edgeType.findBorderPositions(t);!1===a.selected&&(a.x=e.from.x,a.y=e.from.y),!1===l.selected&&(l.x=e.to.x,l.y=e.to.y)})),this.body.emitter.emit("_redraw")}else this.showManipulatorToolbar()}else{var h=this.body.edges[this.edgeBeingEditedId];this._performEditEdge(h.from.id,h.to.id)}}},{key:"deleteSelected",value:function(){var t=this;!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="delete";var e=this.selectionHandler.getSelectedNodeIds(),i=this.selectionHandler.getSelectedEdgeIds(),o=void 0;if(e.length>0){for(var n=0;n0&&"function"==typeof this.options.deleteEdge&&(o=this.options.deleteEdge);if("function"==typeof o){var r={nodes:e,edges:i};if(2!==o.length)throw new Error("The function for delete does not support two arguments (data, callback)");o(r,(function(e){null!=e&&"delete"===t.inMode?(t.body.data.edges.getDataSet().remove(e.edges),t.body.data.nodes.getDataSet().remove(e.nodes),t.body.emitter.emit("startSimulation"),t.showManipulatorToolbar()):(t.body.emitter.emit("startSimulation"),t.showManipulatorToolbar())}))}else this.body.data.edges.getDataSet().remove(i),this.body.data.nodes.getDataSet().remove(e),this.body.emitter.emit("startSimulation"),this.showManipulatorToolbar()}},{key:"_setup",value:function(){!0===this.options.enabled?(this.guiEnabled=!0,this._createWrappers(),!1===this.editMode?this._createEditButton():this.showManipulatorToolbar()):(this._removeManipulationDOM(),this.guiEnabled=!1)}},{key:"_createWrappers",value:function(){var t,e;(void 0===this.manipulationDiv&&(this.manipulationDiv=document.createElement("div"),this.manipulationDiv.className="vis-manipulation",!0===this.editMode?this.manipulationDiv.style.display="block":this.manipulationDiv.style.display="none",this.canvas.frame.appendChild(this.manipulationDiv)),void 0===this.editModeDiv&&(this.editModeDiv=document.createElement("div"),this.editModeDiv.className="vis-edit-mode",!0===this.editMode?this.editModeDiv.style.display="none":this.editModeDiv.style.display="block",this.canvas.frame.appendChild(this.editModeDiv)),void 0===this.closeDiv)&&(this.closeDiv=document.createElement("button"),this.closeDiv.className="vis-close",this.closeDiv.setAttribute("aria-label",null!==(t=null===(e=this.options.locales[this.options.locale])||void 0===e?void 0:e.close)&&void 0!==t?t:this.options.locales.en.close),this.closeDiv.style.display=this.manipulationDiv.style.display,this.canvas.frame.appendChild(this.closeDiv))}},{key:"_getNewTargetNode",value:function(t,e){var i=Tq({},this.options.controlNodeStyle);i.id="targetNode"+u0(),i.hidden=!1,i.physics=!1,i.x=t,i.y=e;var o=this.body.functions.createNode(i);return o.shape.boundingBox={left:t,right:t,top:e,bottom:e},o}},{key:"_createEditButton",value:function(){var t;this._clean(),this.manipulationDOM={},Oq(this.editModeDiv);var e=this.options.locales[this.options.locale],i=this._createButton("editMode","vis-edit vis-edit-mode",e.edit||this.options.locales.en.edit);this.editModeDiv.appendChild(i),this._bindElementEvents(i,VB(t=this.toggleEditMode).call(t,this))}},{key:"_clean",value:function(){this.inMode=!1,!0===this.guiEnabled&&(Oq(this.editModeDiv),Oq(this.manipulationDiv),this._cleanupDOMEventListeners()),this._cleanupTemporaryNodesAndEdges(),this._unbindTemporaryUIs(),this._unbindTemporaryEvents(),this.body.emitter.emit("restorePhysics")}},{key:"_cleanupDOMEventListeners",value:function(){var t,e,i=e3(IV(t=this._domEventListenerCleanupQueue).call(t,0));try{for(i.s();!(e=i.n()).done;){(0,e.value)()}}catch(t){i.e(t)}finally{i.f()}}},{key:"_removeManipulationDOM",value:function(){this._clean(),Oq(this.manipulationDiv),Oq(this.editModeDiv),Oq(this.closeDiv),this.manipulationDiv&&this.canvas.frame.removeChild(this.manipulationDiv),this.editModeDiv&&this.canvas.frame.removeChild(this.editModeDiv),this.closeDiv&&this.canvas.frame.removeChild(this.closeDiv),this.manipulationDiv=void 0,this.editModeDiv=void 0,this.closeDiv=void 0}},{key:"_createSeperator",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1;this.manipulationDOM["seperatorLineDiv"+t]=document.createElement("div"),this.manipulationDOM["seperatorLineDiv"+t].className="vis-separator-line",this.manipulationDiv.appendChild(this.manipulationDOM["seperatorLineDiv"+t])}},{key:"_createAddNodeButton",value:function(t){var e,i=this._createButton("addNode","vis-add",t.addNode||this.options.locales.en.addNode);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,VB(e=this.addNodeMode).call(e,this))}},{key:"_createAddEdgeButton",value:function(t){var e,i=this._createButton("addEdge","vis-connect",t.addEdge||this.options.locales.en.addEdge);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,VB(e=this.addEdgeMode).call(e,this))}},{key:"_createEditNodeButton",value:function(t){var e,i=this._createButton("editNode","vis-edit",t.editNode||this.options.locales.en.editNode);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,VB(e=this.editNode).call(e,this))}},{key:"_createEditEdgeButton",value:function(t){var e,i=this._createButton("editEdge","vis-edit",t.editEdge||this.options.locales.en.editEdge);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,VB(e=this.editEdgeMode).call(e,this))}},{key:"_createDeleteButton",value:function(t){var e,i;i=this.options.rtl?"vis-delete-rtl":"vis-delete";var o=this._createButton("delete",i,t.del||this.options.locales.en.del);this.manipulationDiv.appendChild(o),this._bindElementEvents(o,VB(e=this.deleteSelected).call(e,this))}},{key:"_createBackButton",value:function(t){var e,i=this._createButton("back","vis-back",t.back||this.options.locales.en.back);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,VB(e=this.showManipulatorToolbar).call(e,this))}},{key:"_createButton",value:function(t,e,i){var o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"vis-label";return this.manipulationDOM[t+"Div"]=document.createElement("button"),this.manipulationDOM[t+"Div"].className="vis-button "+e,this.manipulationDOM[t+"Label"]=document.createElement("div"),this.manipulationDOM[t+"Label"].className=o,this.manipulationDOM[t+"Label"].innerText=i,this.manipulationDOM[t+"Div"].appendChild(this.manipulationDOM[t+"Label"]),this.manipulationDOM[t+"Div"]}},{key:"_createDescription",value:function(t){this.manipulationDOM.descriptionLabel=document.createElement("div"),this.manipulationDOM.descriptionLabel.className="vis-none",this.manipulationDOM.descriptionLabel.innerText=t,this.manipulationDiv.appendChild(this.manipulationDOM.descriptionLabel)}},{key:"_temporaryBindEvent",value:function(t,e){this.temporaryEventFunctions.push({event:t,boundFunction:e}),this.body.emitter.on(t,e)}},{key:"_temporaryBindUI",value:function(t,e){if(void 0===this.body.eventListeners[t])throw new Error("This UI function does not exist. Typo? You tried: "+t+" possible are: "+YW(BH(this.body.eventListeners)));this.temporaryUIFunctions[t]=this.body.eventListeners[t],this.body.eventListeners[t]=e}},{key:"_unbindTemporaryUIs",value:function(){for(var t in this.temporaryUIFunctions)Object.prototype.hasOwnProperty.call(this.temporaryUIFunctions,t)&&(this.body.eventListeners[t]=this.temporaryUIFunctions[t],delete this.temporaryUIFunctions[t]);this.temporaryUIFunctions={}}},{key:"_unbindTemporaryEvents",value:function(){for(var t=0;t=0;s--)if(n[s]!==this.selectedControlNode.id){r=this.body.nodes[n[s]];break}if(void 0!==r&&void 0!==this.selectedControlNode)if(!0===r.isCluster)alert(this.options.locales[this.options.locale].createEdgeError||this.options.locales.en.createEdgeError);else{var a=this.body.nodes[this.temporaryIds.nodes[0]];this.selectedControlNode.id===a.id?this._performEditEdge(r.id,o.to.id):this._performEditEdge(o.from.id,r.id)}else o.updateEdgeType(),this.body.emitter.emit("restorePhysics");this.body.emitter.emit("_redraw")}}},{key:"_handleConnect",value:function(t){if((new Date).valueOf()-this.touchTime>100){this.lastTouch=this.body.functions.getPointer(t.center),this.lastTouch.translation=AB({},this.body.view.translation),this.interactionHandler.drag.pointer=this.lastTouch,this.interactionHandler.drag.translation=this.lastTouch.translation;var e=this.lastTouch,i=this.selectionHandler.getNodeAt(e);if(void 0!==i)if(!0===i.isCluster)alert(this.options.locales[this.options.locale].createEdgeError||this.options.locales.en.createEdgeError);else{var o=this._getNewTargetNode(i.x,i.y);this.body.nodes[o.id]=o,this.body.nodeIndices.push(o.id);var n=this.body.functions.createEdge({id:"connectionEdge"+u0(),from:i.id,to:o.id,physics:!1,smooth:{enabled:!0,type:"continuous",roundness:.5}});this.body.edges[n.id]=n,this.body.edgeIndices.push(n.id),this.temporaryIds.nodes.push(o.id),this.temporaryIds.edges.push(n.id)}this.touchTime=(new Date).valueOf()}}},{key:"_dragControlNode",value:function(t){var e=this.body.functions.getPointer(t.center),i=this.selectionHandler._pointerToPositionObject(e),o=void 0;void 0!==this.temporaryIds.edges[0]&&(o=this.body.edges[this.temporaryIds.edges[0]].fromId);for(var n=this.selectionHandler._getAllNodesOverlappingWith(i),r=void 0,s=n.length-1;s>=0;s--){var a;if(-1===LW(a=this.temporaryIds.nodes).call(a,n[s])){r=this.body.nodes[n[s]];break}}if(t.controlEdge={from:o,to:r?r.id:void 0},this.selectionHandler.generateClickEvent("controlNodeDragging",t,e),void 0!==this.temporaryIds.nodes[0]){var l=this.body.nodes[this.temporaryIds.nodes[0]];l.x=this.canvas._XconvertDOMtoCanvas(e.x),l.y=this.canvas._YconvertDOMtoCanvas(e.y),this.body.emitter.emit("_redraw")}else this.interactionHandler.onDrag(t)}},{key:"_finishConnect",value:function(t){var e=this.body.functions.getPointer(t.center),i=this.selectionHandler._pointerToPositionObject(e),o=void 0;void 0!==this.temporaryIds.edges[0]&&(o=this.body.edges[this.temporaryIds.edges[0]].fromId);for(var n=this.selectionHandler._getAllNodesOverlappingWith(i),r=void 0,s=n.length-1;s>=0;s--){var a;if(-1===LW(a=this.temporaryIds.nodes).call(a,n[s])){r=this.body.nodes[n[s]];break}}this._cleanupTemporaryNodesAndEdges(),void 0!==r&&(!0===r.isCluster?alert(this.options.locales[this.options.locale].createEdgeError||this.options.locales.en.createEdgeError):void 0!==this.body.nodes[o]&&void 0!==this.body.nodes[r.id]&&this._performAddEdge(o,r.id)),t.controlEdge={from:o,to:r?r.id:void 0},this.selectionHandler.generateClickEvent("controlNodeDragEnd",t,e),this.body.emitter.emit("_redraw")}},{key:"_dragStartEdge",value:function(t){var e=this.lastTouch;this.selectionHandler.generateClickEvent("dragStart",t,e,void 0,!0)}},{key:"_performAddNode",value:function(t){var e=this,i={id:u0(),x:t.pointer.canvas.x,y:t.pointer.canvas.y,label:"new"};if("function"==typeof this.options.addNode){if(2!==this.options.addNode.length)throw this.showManipulatorToolbar(),new Error("The function for add does not support two arguments (data,callback)");this.options.addNode(i,(function(t){null!=t&&"addNode"===e.inMode&&e.body.data.nodes.getDataSet().add(t),e.showManipulatorToolbar()}))}else this.body.data.nodes.getDataSet().add(i),this.showManipulatorToolbar()}},{key:"_performAddEdge",value:function(t,e){var i=this,o={from:t,to:e};if("function"==typeof this.options.addEdge){if(2!==this.options.addEdge.length)throw new Error("The function for connect does not support two arguments (data,callback)");this.options.addEdge(o,(function(t){null!=t&&"addEdge"===i.inMode&&(i.body.data.edges.getDataSet().add(t),i.selectionHandler.unselectAll(),i.showManipulatorToolbar())}))}else this.body.data.edges.getDataSet().add(o),this.selectionHandler.unselectAll(),this.showManipulatorToolbar()}},{key:"_performEditEdge",value:function(t,e){var i=this,o={id:this.edgeBeingEditedId,from:t,to:e,label:this.body.data.edges.get(this.edgeBeingEditedId).label},n=this.options.editEdge;if("object"===pQ(n)&&(n=n.editWithoutDrag),"function"==typeof n){if(2!==n.length)throw new Error("The function for edit does not support two arguments (data, callback)");n(o,(function(t){null==t||"editEdge"!==i.inMode?(i.body.edges[o.id].updateEdgeType(),i.body.emitter.emit("_redraw"),i.showManipulatorToolbar()):(i.body.data.edges.getDataSet().update(t),i.selectionHandler.unselectAll(),i.showManipulatorToolbar())}))}else this.body.data.edges.getDataSet().update(o),this.selectionHandler.unselectAll(),this.showManipulatorToolbar()}}]),t}(),n3="string",r3="boolean",s3="number",a3="array",l3="object",h3=["arrow","bar","box","circle","crow","curve","diamond","image","inv_curve","inv_triangle","triangle","vee"],c3={borderWidth:{number:s3},borderWidthSelected:{number:s3,undefined:"undefined"},brokenImage:{string:n3,undefined:"undefined"},chosen:{label:{boolean:r3,function:"function"},node:{boolean:r3,function:"function"},__type__:{object:l3,boolean:r3}},color:{border:{string:n3},background:{string:n3},highlight:{border:{string:n3},background:{string:n3},__type__:{object:l3,string:n3}},hover:{border:{string:n3},background:{string:n3},__type__:{object:l3,string:n3}},__type__:{object:l3,string:n3}},opacity:{number:s3,undefined:"undefined"},fixed:{x:{boolean:r3},y:{boolean:r3},__type__:{object:l3,boolean:r3}},font:{align:{string:n3},color:{string:n3},size:{number:s3},face:{string:n3},background:{string:n3},strokeWidth:{number:s3},strokeColor:{string:n3},vadjust:{number:s3},multi:{boolean:r3,string:n3},bold:{color:{string:n3},size:{number:s3},face:{string:n3},mod:{string:n3},vadjust:{number:s3},__type__:{object:l3,string:n3}},boldital:{color:{string:n3},size:{number:s3},face:{string:n3},mod:{string:n3},vadjust:{number:s3},__type__:{object:l3,string:n3}},ital:{color:{string:n3},size:{number:s3},face:{string:n3},mod:{string:n3},vadjust:{number:s3},__type__:{object:l3,string:n3}},mono:{color:{string:n3},size:{number:s3},face:{string:n3},mod:{string:n3},vadjust:{number:s3},__type__:{object:l3,string:n3}},__type__:{object:l3,string:n3}},group:{string:n3,number:s3,undefined:"undefined"},heightConstraint:{minimum:{number:s3},valign:{string:n3},__type__:{object:l3,boolean:r3,number:s3}},hidden:{boolean:r3},icon:{face:{string:n3},code:{string:n3},size:{number:s3},color:{string:n3},weight:{string:n3,number:s3},__type__:{object:l3}},id:{string:n3,number:s3},image:{selected:{string:n3,undefined:"undefined"},unselected:{string:n3,undefined:"undefined"},__type__:{object:l3,string:n3}},imagePadding:{top:{number:s3},right:{number:s3},bottom:{number:s3},left:{number:s3},__type__:{object:l3,number:s3}},label:{string:n3,undefined:"undefined"},labelHighlightBold:{boolean:r3},level:{number:s3,undefined:"undefined"},margin:{top:{number:s3},right:{number:s3},bottom:{number:s3},left:{number:s3},__type__:{object:l3,number:s3}},mass:{number:s3},physics:{boolean:r3},scaling:{min:{number:s3},max:{number:s3},label:{enabled:{boolean:r3},min:{number:s3},max:{number:s3},maxVisible:{number:s3},drawThreshold:{number:s3},__type__:{object:l3,boolean:r3}},customScalingFunction:{function:"function"},__type__:{object:l3}},shadow:{enabled:{boolean:r3},color:{string:n3},size:{number:s3},x:{number:s3},y:{number:s3},__type__:{object:l3,boolean:r3}},shape:{string:["custom","ellipse","circle","database","box","text","image","circularImage","diamond","dot","star","triangle","triangleDown","square","icon","hexagon"]},ctxRenderer:{function:"function"},shapeProperties:{borderDashes:{boolean:r3,array:a3},borderRadius:{number:s3},interpolation:{boolean:r3},useImageSize:{boolean:r3},useBorderWithImage:{boolean:r3},coordinateOrigin:{string:["center","top-left"]},__type__:{object:l3}},size:{number:s3},title:{string:n3,dom:"dom",undefined:"undefined"},value:{number:s3,undefined:"undefined"},widthConstraint:{minimum:{number:s3},maximum:{number:s3},__type__:{object:l3,boolean:r3,number:s3}},x:{number:s3},y:{number:s3},__type__:{object:l3}},d3={configure:{enabled:{boolean:r3},filter:{boolean:r3,string:n3,array:a3,function:"function"},container:{dom:"dom"},showButton:{boolean:r3},__type__:{object:l3,boolean:r3,string:n3,array:a3,function:"function"}},edges:{arrows:{to:{enabled:{boolean:r3},scaleFactor:{number:s3},type:{string:h3},imageHeight:{number:s3},imageWidth:{number:s3},src:{string:n3},__type__:{object:l3,boolean:r3}},middle:{enabled:{boolean:r3},scaleFactor:{number:s3},type:{string:h3},imageWidth:{number:s3},imageHeight:{number:s3},src:{string:n3},__type__:{object:l3,boolean:r3}},from:{enabled:{boolean:r3},scaleFactor:{number:s3},type:{string:h3},imageWidth:{number:s3},imageHeight:{number:s3},src:{string:n3},__type__:{object:l3,boolean:r3}},__type__:{string:["from","to","middle"],object:l3}},endPointOffset:{from:{number:s3},to:{number:s3},__type__:{object:l3,number:s3}},arrowStrikethrough:{boolean:r3},background:{enabled:{boolean:r3},color:{string:n3},size:{number:s3},dashes:{boolean:r3,array:a3},__type__:{object:l3,boolean:r3}},chosen:{label:{boolean:r3,function:"function"},edge:{boolean:r3,function:"function"},__type__:{object:l3,boolean:r3}},color:{color:{string:n3},highlight:{string:n3},hover:{string:n3},inherit:{string:["from","to","both"],boolean:r3},opacity:{number:s3},__type__:{object:l3,string:n3}},dashes:{boolean:r3,array:a3},font:{color:{string:n3},size:{number:s3},face:{string:n3},background:{string:n3},strokeWidth:{number:s3},strokeColor:{string:n3},align:{string:["horizontal","top","middle","bottom"]},vadjust:{number:s3},multi:{boolean:r3,string:n3},bold:{color:{string:n3},size:{number:s3},face:{string:n3},mod:{string:n3},vadjust:{number:s3},__type__:{object:l3,string:n3}},boldital:{color:{string:n3},size:{number:s3},face:{string:n3},mod:{string:n3},vadjust:{number:s3},__type__:{object:l3,string:n3}},ital:{color:{string:n3},size:{number:s3},face:{string:n3},mod:{string:n3},vadjust:{number:s3},__type__:{object:l3,string:n3}},mono:{color:{string:n3},size:{number:s3},face:{string:n3},mod:{string:n3},vadjust:{number:s3},__type__:{object:l3,string:n3}},__type__:{object:l3,string:n3}},hidden:{boolean:r3},hoverWidth:{function:"function",number:s3},label:{string:n3,undefined:"undefined"},labelHighlightBold:{boolean:r3},length:{number:s3,undefined:"undefined"},physics:{boolean:r3},scaling:{min:{number:s3},max:{number:s3},label:{enabled:{boolean:r3},min:{number:s3},max:{number:s3},maxVisible:{number:s3},drawThreshold:{number:s3},__type__:{object:l3,boolean:r3}},customScalingFunction:{function:"function"},__type__:{object:l3}},selectionWidth:{function:"function",number:s3},selfReferenceSize:{number:s3},selfReference:{size:{number:s3},angle:{number:s3},renderBehindTheNode:{boolean:r3},__type__:{object:l3}},shadow:{enabled:{boolean:r3},color:{string:n3},size:{number:s3},x:{number:s3},y:{number:s3},__type__:{object:l3,boolean:r3}},smooth:{enabled:{boolean:r3},type:{string:["dynamic","continuous","discrete","diagonalCross","straightCross","horizontal","vertical","curvedCW","curvedCCW","cubicBezier"]},roundness:{number:s3},forceDirection:{string:["horizontal","vertical","none"],boolean:r3},__type__:{object:l3,boolean:r3}},title:{string:n3,undefined:"undefined"},width:{number:s3},widthConstraint:{maximum:{number:s3},__type__:{object:l3,boolean:r3,number:s3}},value:{number:s3,undefined:"undefined"},__type__:{object:l3}},groups:{useDefaultGroups:{boolean:r3},__any__:c3,__type__:{object:l3}},interaction:{dragNodes:{boolean:r3},dragView:{boolean:r3},hideEdgesOnDrag:{boolean:r3},hideEdgesOnZoom:{boolean:r3},hideNodesOnDrag:{boolean:r3},hover:{boolean:r3},keyboard:{enabled:{boolean:r3},speed:{x:{number:s3},y:{number:s3},zoom:{number:s3},__type__:{object:l3}},bindToWindow:{boolean:r3},autoFocus:{boolean:r3},__type__:{object:l3,boolean:r3}},multiselect:{boolean:r3},navigationButtons:{boolean:r3},selectable:{boolean:r3},selectConnectedEdges:{boolean:r3},hoverConnectedEdges:{boolean:r3},tooltipDelay:{number:s3},zoomView:{boolean:r3},zoomSpeed:{number:s3},__type__:{object:l3}},layout:{randomSeed:{undefined:"undefined",number:s3,string:n3},improvedLayout:{boolean:r3},clusterThreshold:{number:s3},hierarchical:{enabled:{boolean:r3},levelSeparation:{number:s3},nodeSpacing:{number:s3},treeSpacing:{number:s3},blockShifting:{boolean:r3},edgeMinimization:{boolean:r3},parentCentralization:{boolean:r3},direction:{string:["UD","DU","LR","RL"]},sortMethod:{string:["hubsize","directed"]},shakeTowards:{string:["leaves","roots"]},__type__:{object:l3,boolean:r3}},__type__:{object:l3}},manipulation:{enabled:{boolean:r3},initiallyActive:{boolean:r3},addNode:{boolean:r3,function:"function"},addEdge:{boolean:r3,function:"function"},editNode:{function:"function"},editEdge:{editWithoutDrag:{function:"function"},__type__:{object:l3,boolean:r3,function:"function"}},deleteNode:{boolean:r3,function:"function"},deleteEdge:{boolean:r3,function:"function"},controlNodeStyle:c3,__type__:{object:l3,boolean:r3}},nodes:c3,physics:{enabled:{boolean:r3},barnesHut:{theta:{number:s3},gravitationalConstant:{number:s3},centralGravity:{number:s3},springLength:{number:s3},springConstant:{number:s3},damping:{number:s3},avoidOverlap:{number:s3},__type__:{object:l3}},forceAtlas2Based:{theta:{number:s3},gravitationalConstant:{number:s3},centralGravity:{number:s3},springLength:{number:s3},springConstant:{number:s3},damping:{number:s3},avoidOverlap:{number:s3},__type__:{object:l3}},repulsion:{centralGravity:{number:s3},springLength:{number:s3},springConstant:{number:s3},nodeDistance:{number:s3},damping:{number:s3},__type__:{object:l3}},hierarchicalRepulsion:{centralGravity:{number:s3},springLength:{number:s3},springConstant:{number:s3},nodeDistance:{number:s3},damping:{number:s3},avoidOverlap:{number:s3},__type__:{object:l3}},maxVelocity:{number:s3},minVelocity:{number:s3},solver:{string:["barnesHut","repulsion","hierarchicalRepulsion","forceAtlas2Based"]},stabilization:{enabled:{boolean:r3},iterations:{number:s3},updateInterval:{number:s3},onlyDynamicEdges:{boolean:r3},fit:{boolean:r3},__type__:{object:l3,boolean:r3}},timestep:{number:s3},adaptiveTimestep:{boolean:r3},wind:{x:{number:s3},y:{number:s3},__type__:{object:l3}},__type__:{object:l3,boolean:r3}},autoResize:{boolean:r3},clickToUse:{boolean:r3},locale:{string:n3},locales:{__any__:{any:"any"},__type__:{object:l3}},height:{string:n3},width:{string:n3},__type__:{object:l3}},u3={nodes:{borderWidth:[1,0,10,1],borderWidthSelected:[2,0,10,1],color:{border:["color","#2B7CE9"],background:["color","#97C2FC"],highlight:{border:["color","#2B7CE9"],background:["color","#D2E5FF"]},hover:{border:["color","#2B7CE9"],background:["color","#D2E5FF"]}},opacity:[0,0,1,.1],fixed:{x:!1,y:!1},font:{color:["color","#343434"],size:[14,0,100,1],face:["arial","verdana","tahoma"],background:["color","none"],strokeWidth:[0,0,50,1],strokeColor:["color","#ffffff"]},hidden:!1,labelHighlightBold:!0,physics:!0,scaling:{min:[10,0,200,1],max:[30,0,200,1],label:{enabled:!1,min:[14,0,200,1],max:[30,0,200,1],maxVisible:[30,0,200,1],drawThreshold:[5,0,20,1]}},shadow:{enabled:!1,color:"rgba(0,0,0,0.5)",size:[10,0,20,1],x:[5,-30,30,1],y:[5,-30,30,1]},shape:["ellipse","box","circle","database","diamond","dot","square","star","text","triangle","triangleDown","hexagon"],shapeProperties:{borderDashes:!1,borderRadius:[6,0,20,1],interpolation:!0,useImageSize:!1},size:[25,0,200,1]},edges:{arrows:{to:{enabled:!1,scaleFactor:[1,0,3,.05],type:"arrow"},middle:{enabled:!1,scaleFactor:[1,0,3,.05],type:"arrow"},from:{enabled:!1,scaleFactor:[1,0,3,.05],type:"arrow"}},endPointOffset:{from:[0,-10,10,1],to:[0,-10,10,1]},arrowStrikethrough:!0,color:{color:["color","#848484"],highlight:["color","#848484"],hover:["color","#848484"],inherit:["from","to","both",!0,!1],opacity:[1,0,1,.05]},dashes:!1,font:{color:["color","#343434"],size:[14,0,100,1],face:["arial","verdana","tahoma"],background:["color","none"],strokeWidth:[2,0,50,1],strokeColor:["color","#ffffff"],align:["horizontal","top","middle","bottom"]},hidden:!1,hoverWidth:[1.5,0,5,.1],labelHighlightBold:!0,physics:!0,scaling:{min:[1,0,100,1],max:[15,0,100,1],label:{enabled:!0,min:[14,0,200,1],max:[30,0,200,1],maxVisible:[30,0,200,1],drawThreshold:[5,0,20,1]}},selectionWidth:[1.5,0,5,.1],selfReferenceSize:[20,0,200,1],selfReference:{size:[20,0,200,1],angle:[Math.PI/2,-6*Math.PI,6*Math.PI,Math.PI/8],renderBehindTheNode:!0},shadow:{enabled:!1,color:"rgba(0,0,0,0.5)",size:[10,0,20,1],x:[5,-30,30,1],y:[5,-30,30,1]},smooth:{enabled:!0,type:["dynamic","continuous","discrete","diagonalCross","straightCross","horizontal","vertical","curvedCW","curvedCCW","cubicBezier"],forceDirection:["horizontal","vertical","none"],roundness:[.5,0,1,.05]},width:[1,0,30,1]},layout:{hierarchical:{enabled:!1,levelSeparation:[150,20,500,5],nodeSpacing:[100,20,500,5],treeSpacing:[200,20,500,5],blockShifting:!0,edgeMinimization:!0,parentCentralization:!0,direction:["UD","DU","LR","RL"],sortMethod:["hubsize","directed"],shakeTowards:["leaves","roots"]}},interaction:{dragNodes:!0,dragView:!0,hideEdgesOnDrag:!1,hideEdgesOnZoom:!1,hideNodesOnDrag:!1,hover:!1,keyboard:{enabled:!1,speed:{x:[10,0,40,1],y:[10,0,40,1],zoom:[.02,0,.1,.005]},bindToWindow:!0,autoFocus:!0},multiselect:!1,navigationButtons:!1,selectable:!0,selectConnectedEdges:!0,hoverConnectedEdges:!0,tooltipDelay:[300,0,1e3,25],zoomView:!0,zoomSpeed:[1,.1,2,.1]},manipulation:{enabled:!1,initiallyActive:!1},physics:{enabled:!0,barnesHut:{theta:[.5,.1,1,.05],gravitationalConstant:[-2e3,-3e4,0,50],centralGravity:[.3,0,10,.05],springLength:[95,0,500,5],springConstant:[.04,0,1.2,.005],damping:[.09,0,1,.01],avoidOverlap:[0,0,1,.01]},forceAtlas2Based:{theta:[.5,.1,1,.05],gravitationalConstant:[-50,-500,0,1],centralGravity:[.01,0,1,.005],springLength:[95,0,500,5],springConstant:[.08,0,1.2,.005],damping:[.4,0,1,.01],avoidOverlap:[0,0,1,.01]},repulsion:{centralGravity:[.2,0,10,.05],springLength:[200,0,500,5],springConstant:[.05,0,1.2,.005],nodeDistance:[100,0,500,5],damping:[.09,0,1,.01]},hierarchicalRepulsion:{centralGravity:[.2,0,10,.05],springLength:[100,0,500,5],springConstant:[.01,0,1.2,.005],nodeDistance:[120,0,500,5],damping:[.09,0,1,.01],avoidOverlap:[0,0,1,.01]},maxVelocity:[50,0,150,1],minVelocity:[.1,.01,.5,.01],solver:["barnesHut","forceAtlas2Based","repulsion","hierarchicalRepulsion"],timestep:[.5,.01,1,.01],wind:{x:[0,-10,10,.1],y:[0,-10,10,.1]}}},f3=function(t,e,i){var o;return!(!ZV(t).call(t,"physics")||!ZV(o=u3.physics.solver).call(o,e)||i.physics.solver===e||"wind"===e)},p3=function(){function t(){fN(this,t)}return mQ(t,[{key:"getDistances",value:function(t,e,i){for(var o={},n=t.edges,r=0;r2&&void 0!==arguments[2]&&arguments[2],o=this.distanceSolver.getDistances(this.body,t,e);this._createL_matrix(o),this._createK_matrix(o),this._createE_matrix();for(var n=0,r=Math.max(1e3,Math.min(10*this.body.nodeIndices.length,6e3)),s=1e9,a=0,l=0,h=0,c=0,d=0;s>.01&&n1&&d<5;){d+=1,this._moveNode(a,l,h);var f=sH(this._getEnergy(a),3);c=f[0],l=f[1],h=f[2]}}}},{key:"_getHighestEnergyNode",value:function(t){for(var e=this.body.nodeIndices,i=this.body.nodes,o=0,n=e[0],r=0,s=0,a=0;a{var e;let i=t;for(;i;){if(["hui-card-preview","hui-dialog-edit-card"].includes(i.localName))return!0;const t=i.getRootNode();i=null!==(e=i.parentElement)&&void 0!==e?e:t instanceof ShadowRoot?t.host:null}return!1};var m3={Controller:"data:image/png;base64,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",RoomStat:"data:image/png;base64,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",SmartPlug:"data:image/png;base64,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",TemperatureHumiditySensor:"data:image/png;base64,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",iTRV:"data:image/png;base64,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",UnderFloorHeating:"data:image/png;base64,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",HeatingActuator:"data:image/png;base64,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",DimmableLight:"data:image/png;base64,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",OnOffLight:"data:image/png;base64,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",LoadControl:"data:image/png;base64,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",Shutter:"data:image/png;base64,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",SmokeAlarmDevice:"data:image/png;base64,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",WaterLeakageSensor:"data:image/png;base64,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",MotionLightSensor:"data:image/png;base64,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",WindowDoorSensor:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAACgCAYAAACLz2ctAAAM/ElEQVR42u1dyZLkVhU990k5Z1V1G2jCCxPAwmEvDDt2DgMLDMEXsOdr4Bf4Cla2CYObJljAAhxe4HAQ4fYQrOxu2x1VykpJ77LQ9KSUsrq7lFKmdM6iu4asKuXT1R3OnQCCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIAiCIGogYz+AMAzlo/9+YhbzKVar9WjP4Xx9ZhfLiQ5eAN+7/0C+c+9Fs5hPb/V7Xvzui70cGEENmCO4CuW2Qvjxw89eU8Vr69XKKNQ3YnwIAE1Pp/o/0o9R+dw9yX2f656fq+JpXlv3Gvd/NP+cVRsJJAKAy6vL93/w/Zc+6Poe+l39obfefsf75Zu/iO//9W8/v3v37m/vvvBCDJjav29ETH5OakvHJ2LUaryNwuh3i+Xkg+z3Pu91ffb5//5wdnb2E1XA9z1MptPRaB9jDCa+B1XFcrl8C8Cv2nioj1IAMzx+/OWvp7Ppb9brM4gkb16kUMjJ587jqwKIQlUgovB9H2EYIwyDewDefOP1n9nbXI+NY2utQlVjVUB1RFY9ea8xgKm1GgOAPxmoBsxFzHib9N1vAPhSsQ+SS6MUJgTZqwSQyIrIVMS8+tbb73iL5SS+pRPiXoDJr0EVzpMxQNlTlAx1+lajcOAC6AiaD8BTaC5omfBlWkgk1YgQKBRGAKiY1MeJvnzysIU7Aa3ziXVUFEHxsA9eA9YFQYnCcb3mQgwSmSzEQVWV7FHr+rDyHHboh/brftR/XSQTyk4eAUqzcwxdm2BzPL6wa4bF0XiocB/EQU3iZDQ+YPnjJAIFRDQXOjc6xoGMhBFKdp9BiMER+SFJ0OGa4DLDKpmGFGYRWw4IYeO4Fw1ouje3tsYHlFzOcm0IST6upB8Knk6ZDGrRBRJjxhGEOEmOSj4p+TchnJNTUUf86AUe2Pr09CAeRxCSGlgRzX3AhAwuUzBSkcQoClr524T0lgHqxQTLzq1P/brU58sJaNll710f0PcXNMCnHnX3pfHcWy9OhFsrnO7P2kIjtqEBhRKYOt8YiQmuUfUKQFLfr6Bj3OxIkZoTU5xUGxpwVMUHN0TC48gF16icxKJqEYCg4ASrmjARGGn94AmMJwiRRmFQhxNU1uRSAI/MTzmMxqIEOlHw4InohN97PmJED+Kz0QmEUxI3fCLaeHtEQfaLxUFkhQoQY6JhslRcUxmWW4iwW5RADM0PNsdDAyAnnzMKhhEqg5Au2ZjKE6lORTQpk6ES0X5f0ex+E6xPZXbbyIQQozPBUpuBcBvRXDJ6X9zRRiaEUUh69tZiNLngpvvuar19XZEtW2JlPWBTmdygMyFac+/l5rztDVqReM56QDOipiTNhU1qKwO1UphA2riDe2LHkgnJJVD39Ibojj9YVMNQWIYUh5jjerOy4+ep1uXj6LodajLCiHpC5KnigXJgouUWQtIwIBHdUiruqfkCyaZaWSaDB0AEmJN6sxV7/M+//4OyQyL6eeVPn08Y0+DEtkecKonoMeWCpYWnTmk1254V2Fee3fTdDfzM/RtSTIn5/PNHlB72BXdn/bJMCCeqHaIUzo61HlCfKbuRyKCynZK54BZHI0pTrwc13dCDEP8YrG4+C+ZZGpRU8fDj/5wkB5E5/XUPXTGWRLq9ntEUI8jt/cFTLcdyBc792BW2ptccPAjpqRihHw2odYMpxWlGb17zk3CAJ7kSoaT1TDqPT1VzjZcJorV2R0sOtR3B7594l9Jo3vJoDmks3T/FuSuuad1sNgi3W9iKkpvNppjNZh3zc/2Z4J4rom0ahEjeC1IMJBJH2KqcoZysBrSxRRAEMMZguVyVhi3FUYyrIEBwtcHZ2Qqe73emAfuajOD3rf3cN2+MVzpoa+Od9kx74guMrLVYrVaAAMFVgDCK8u9NfB/n52eIwgiXVwHOz88ag5WhbKvw+y1IldLTvbneYnt9CVULz5tiuVxAxC/dACMFF3iKJngynSCOY2yuNvB8D+vZKnd5r6+v8dXjr7Fer3BxcQ5rbeIbdiAcfZ1nzzRMsRcuCJ4gCC5zpxy4RhA8wZ079+D7ZSE8NXqwZIJToVqvVzuzblbrFWbzGWxs86934wf2V5DqH0cmRDGfL2EtEMdbAEAYbjGfr9NoUU+6FskVIEnHEcc1oXwcxzDGwBhTErzDC+GoGtN3p41nfs5yuYIx5zDGIIpCqCK/GYOoxky9DpdiSeiXrAFLdxc1igxaA5pjKITM5MsYg2++eYSPH34EVVVj8pulLoGYbdDEidZ9usJlrcWXX3yB6+vrnBvMBK477m9EGtA2arPkBJbLVVqZkdffa761GpoPydcTrCOtS8GJCJbLNXzP2/H7uuMBR6QBTbr/ozjYpA3TGIMw3KrnTfXu3XuwNlJrrRpjJJ1pKRk3mG4VAQZSCLpYLkqc35iq8nvzAQuSOXnnV1dPsNkE4nkeRAy2240Y4+Hi4luOEFoBTMlXOsVUXObXZSm3Es2UmuEsWu4sEtbRmWAt5XujKIK1cRYPYjKZIopCxHEsnudBNZZiY1Kbjrl2ygMaYxCFIcIwxGK53Hnt1eUVxAgWi0XBAx7cDPdXku/375VbqFqcn7+AMAxxfR2kKaEZ7sxnsNbCWlXAE0CTTEirPuDhT97VgHEcw3geoiDA40dfYTabwngGajUXOM8YxFEMMR0WI8goeUCbPn0G1sbwfQ+TyXkeeMRxlB2+4weiXCxzQsZHRBBcBYitxcXFGeLYYrsNodbC8zzMF/P8NZeXT3Bx57yzVFxfLo3fiz+k1WFEmvclqMZpwi0pEy8W0yStcEbSDdNyWtUwqomGW61X2AQbPH70NabTCSYTHyITqFoEVwGstVgsFlgsF222noLlWDtZAXFywe73yuot+Z7NX5sXI7T2wGp3bY8p2bxYLjCbz7DdbhGGURp8CCaTCSbTCYDCHPfZMjlIATQilbZMbRAI4wQq8lxtnMfi/JSiXxT54Pl8Xl3HnWs992cOL4QyHgHcjYLrVlLX1f5JXg1jtU3mXnspSm2ikuqol040oGJEPmDJBGtqYs3OhPyy5ks+tqVl1qf39JcKE2orvrvK/454Qupug4g0CIM0z5GRYaxHxZFs7xzPrri9l+AKmjrBhxzSZLD5OKW6RqEBxa0xAADEDT0fUuIKq1LXoqbgdCwRaOqcD14D1hOexhG0qjAaRxC56XxIJHR/GrCkfEzlUqTE+5XaN53L5douDim/ZSZEa9JydVSMlkSw/aeWmnRUM6LLmZCqjyc7eeI64VRVhg4Hui+Db0wvay6t0XRaszWzPFm/XetLSXYHVI6ChtndlKRO6m3/PuEDlJBTAqHjaUxP8qF1o3ptgxm+aYQb0eZjOI5MiGDPokLXHzS186TbTc6TzxmVCS6iYKnJcuxJvVVI6BYroil/Y4uCtXFYoDZUwdQI6wnVA56SDzh4E5w0lbs0i9QInKl8f5cTpOI6UFAwGU0uWCr+XrUIoa44YVjFmNwT0hMPWLzXatWzNBQmKE3lQEdzmH5pGGkgousqYMpzZMgDsiS/pUyI1vB+piEokQOtaSHU2vFOx9oVLL3xySQp3XZJvhlPY7qWNJ405IUVgHdw/4/6b4TzAaWxL6TasGRromSWY3E+4EFuvDz1Xrl2hYamPCnJH60P6AYXZk8DellDtuUD0pfMdsWNaVvmjfvidKcANduklFlePdXGYGrAY+wLRkNWZM/X6bpxX3B7fr82ZDykVIx6GHPJOLhPV8QcJwtPv2wsrZl+vyX5TaVYWrsh8xCHRP3X74jeHrvidO9e4O40IiUwaXjVEfUF702/7fqGifbLOMD2SzFH7PjtaMBR7AuWp9I8UjMlgb7hYfwPgdrRTse6uVCh2Kjefi2WJhuyCRlRLlhrNV1dHlgdGkaYteggCBmFCX7W0iuCbZkdanvdGcVGHF4JZCvCRqYBxdmEuV9E0526Mphd9UdXEd2PBuyhJN/aRIxMtDuS7WbWIFnl6hlV9Q7lD7hrUweedpO+n8POBdD3/GVyX+385mxE3biOZK/ubDb98N//ehiHYSiTyeRWp2dMfh/sWAKdoj02ec+DX1Y4ny8sAGw2wR+/evzo254nUY24SYUiMTUHZxVQ3/N+DwDv/vkvBsmg6ed1SCWKYkRx7BljYGM7onjIILbWc7V91z7gSR/1e/cfyE/feP1W2u9P7z740Ww2fQUAVqvVorq3t+hlLhz1qml2v7cvuZ9pGWtt6XdVtyG525LQsDUpuyZ393CTJnOvxb1WYwxEsEm//v6PX3v1w8HTj+/dfyCbTWBefvmVW/2eTz/9xN5W+IgxdyQfkRbdbALz0vd+OMr3v5hP+UATBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQxPHh/6ndY8IEYh1QAAAAAElFTkSuQmCC",CFMT:"data:image/png;base64,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",PowerTagE:"data:image/png;base64,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",ButtonPanel:"data:image/png;base64,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",BoilerInterface:"data:image/png;base64,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"};const b3="data:image/svg+xml,"+encodeURIComponent(''),w3=Object.assign({},m3);const A3={autoResize:!0,height:"100%",nodes:{shape:"box",color:{background:"#edf2f8",border:"#c9d5e4",highlight:{background:"#dce9f8",border:"#5288bd"}},font:{size:14,face:"system-ui, sans-serif",color:"#26364a"},margin:{top:14,bottom:14,left:18,right:18},widthConstraint:{minimum:100,maximum:160},borderWidth:1,shapeProperties:{borderRadius:12}},groups:{Controller:{color:{background:"#dceee6",border:"#91bba7"}},RoomStat:{color:{background:"#eee6f2",border:"#c9b3d5"}},iTRV:{color:{background:"#f7eadc",border:"#d9bc98"}},SmartPlug:{color:{background:"#dceef0",border:"#94bec4"}},HeatingActuator:{color:{background:"#e1e9fa",border:"#aabce0"}},UnderFloorHeating:{color:{background:"#e1e9fa",border:"#aabce0"}},Shutter:{color:{background:"#e7ebef",border:"#b4bec9"}},OnOffLight:{color:{background:"#f5efd9",border:"#d6c68e"}},DimmableLight:{color:{background:"#f5efd9",border:"#d6c68e"}}},edges:{arrows:{to:{enabled:!0,scaleFactor:.45}},color:{color:"#8a9bac",highlight:"#5288bd",hover:"#5288bd",inherit:!1},smooth:{enabled:!0,type:"cubicBezier",forceDirection:"horizontal",roundness:.45},width:1.5,font:{align:"horizontal",color:"#66788a",size:11,face:"system-ui, sans-serif",strokeWidth:0}},interaction:{hover:!0,dragView:!0,dragNodes:!0,selectConnectedEdges:!0,zoomView:!0,keyboard:!1},physics:{enabled:!1}};const E3="data:image/svg+xml,"+encodeURIComponent('');async function k3(t,e,i){const o=i||(await t.callWS({type:"wiser/hubs"}))[0];if(!o)return;const[n,r]=await Promise.all([t.callWS({type:"config/entity_registry/list"}),t.callWS({type:"config/device_registry/list"})]),s=new Set(r.filter((t=>t.identifiers.some((([t,e])=>"wiser"===t&&e===o)))).map((t=>t.id))),a=n.filter((i=>{if("wiser"!==i.platform||!i.entity_id.startsWith("sensor."))return!1;const n=t.states[i.entity_id],a=null==n?void 0:n.attributes;if(!a||null==a.node_id||Number(a.node_id)!==e.id||void 0===a.displayed_signal_strength)return!1;if("Controller"!==e.group&&a.product_type!==e.group)return!1;const l=r.find((t=>t.id===i.device_id));return!!l&&(s.has(l.id)||null!=l.via_device_id&&s.has(l.via_device_id)||l.identifiers.some((([t,e])=>"wiser"===t&&e.startsWith(`${o} Wiser `))))}));return 1===a.length?a[0].entity_id:void 0}function C3(t,e){const i=t=>"number"==typeof t&&Number.isFinite(t);return 0===t&&0===e?{}:{rssi:i(t)?t:void 0,lqi:i(e)?e:void 0}}function x3(t,e="horizontal",i,o="none"){var n,r;const s=new Map,a=t.nodes.filter((t=>"Controller"===t.group)),l=(a.length?a:t.nodes.slice(0,1)).map((t=>t.id));l.forEach((t=>s.set(t,0)));for(let e=0;e"Area"!==t.group)),s=new Map(r.map((t=>[t.id,t]))),a=new Map,l=new Map;for(const e of r){const o=t.edges.find((t=>t.from===e.id&&s.has(t.to)&&i.has(t.to)&&i.has(e.id)&&i.get(t.to){var i;const o=c.get(t);if(o)return o;const n=null!==(i=a.get(t))&&void 0!==i?i:[],r=Math.max(e?115:65,4*d(s.get(t).label).length+30),l=Math.max(0,...n.map((t=>f(t).radius))),u=n.length?Math.max(r+l+h,n.length>1?(l+h/2)/Math.sin(Math.PI/n.length):0):0,p={radius:u+(n.length?l:r),orbit:u};return c.set(t,p),p},p=[],v=(t,e,i,n)=>{var r;p.push(Object.assign(Object.assign({},s.get(t)),{x:e,y:i}));const l=[...null!==(r=a.get(t))&&void 0!==r?r:[]],h=null==o?void 0:o[t],c=t=>{const e=null==o?void 0:o[t];if(e&&h)return((Math.atan2(e.y-h.y,e.x-h.x)-n)%(2*Math.PI)+2*Math.PI)%(2*Math.PI)};l.sort(((t,e)=>{const i=Number(a.has(e))-Number(a.has(t));if(i)return i;const o=c(t),n=c(e);return void 0!==o&&void 0!==n&&Math.abs(o-n)>1e-6?o-n:s.get(t).label.localeCompare(s.get(e).label)})),l.forEach(((o,r)=>{const s=n+2*r*Math.PI/l.length,a=f(t).orbit;v(o,e+Math.cos(s)*a,i+Math.sin(s)*a,s)}))},g=r.filter((t=>!l.has(t.id))).sort(((t,e)=>Number("Controller"===e.group)-Number("Controller"===t.group)||t.label.localeCompare(e.label)));let y=0;if(g.forEach(((t,e)=>{const i=f(t.id).radius,o=e?y+i+h:0;v(t.id,o,0,0),y=o+i})),e)for(const[t,e]of a){const i=p.find((e=>e.id===t)),o=(t,e=t.x,i=t.y)=>{const o=d(t.label),n=Math.max(40,4.5*o.length+12);return{left:e-n,right:e+n,top:i-42,bottom:i+72}},n=(t,e)=>t.lefte.left&&t.tope.top;for(const t of e.filter((t=>!a.has(t)))){const r=p.find((e=>e.id===t));if(!r.area_id)continue;const l=e.filter((t=>a.has(t)&&s.get(t).area_id===r.area_id)).map((t=>p.find((e=>e.id===t)))).sort(((t,e)=>Math.hypot(t.x-r.x,t.y-r.y)-Math.hypot(e.x-r.x,e.y-r.y)));let h=!1;for(const t of l){const e=Math.atan2(t.y-i.y,t.x-i.x),s=Math.max(150,(o(t).right-o(t).left+o(r).right-o(r).left)/2+20),l=[0,1,2,3].map((t=>({inward:s+90*t,side:65})));for(let t=1;t<5;t++)for(const e of[1,0,2])l.push({inward:s+90*e,side:65+130*t});for(const s of l){if(h)break;for(const l of[1,-1]){const c=s.inward,d=l*s.side,u=t.x-Math.cos(e)*c-Math.sin(e)*d,f=t.y-Math.sin(e)*c+Math.cos(e)*d,v=o(r,u,f);if(p.some((t=>t.id!==r.id&&("Controller"===t.group||a.has(t.id)||t.area_id===r.area_id)&&n(v,o(t)))))continue;const g=o(t),y={left:Math.min(v.left,g.left)-18,right:Math.max(v.right,g.right)+18,top:Math.min(v.top,g.top)-110,bottom:Math.max(v.bottom,g.bottom)+18};if(!n(y,o(i))){r.x=u,r.y=f,h=!0;break}}}if(h)break}}}for(const e of t.nodes.filter((t=>"Area"===t.group))){const t=p.filter((t=>{var i,o;return"Controller"!==t.group&&(null!==(i=t.area_id)&&void 0!==i?i:"")===(null!==(o=e.area_id)&&void 0!==o?o:"")}));p.push(Object.assign(Object.assign({},e),{x:t.length?(Math.min(...t.map((t=>t.x)))+Math.max(...t.map((t=>t.x))))/2:0,y:t.length?Math.min(...t.map((t=>t.y)))-110:0}))}return e&&u(p,new Set(a.keys())),{nodes:p,edges:t.edges.map((t=>Object.assign({},t)))}}(t,"area"===o,s,i);const h=new Map,c=Math.max(0,...s.values())+1;for(const e of t.nodes){if("Area"===e.group)continue;const t=null!==(n=s.get(e.id))&&void 0!==n?n:c;h.set(t,[...null!==(r=h.get(t))&&void 0!==r?r:[],e])}const f=[];for(const[n,r]of[...h].sort((([t],[e])=>t-e))){const s="vertical"===e?"x":"y";r.sort(((e,o)=>{var n,r;const a=e=>{var i,o,n;const r=null===(i=t.edges.find((t=>t.from===e)))||void 0===i?void 0:i.to;return null!==(n=null===(o=f.find((t=>t.id===r)))||void 0===o?void 0:o[s])&&void 0!==n?n:0},l=a(e.id)-a(o.id);if(l)return l;const h=null===(n=null==i?void 0:i[e.id])||void 0===n?void 0:n[s],c=null===(r=null==i?void 0:i[o.id])||void 0===r?void 0:r[s];return Number.isFinite(h)&&Number.isFinite(c)&&h!==c?h-c:e.label.localeCompare(o.label)})),r.forEach(((t,i)=>{let s=i-(r.length-1)/2;f.push(Object.assign(Object.assign({},t),{x:"vertical"===e?s*("area"===o?230:170):n*("area"===o?300:270),y:"vertical"===e?n*("area"===o?300:150):s*("area"===o?260:110)}))}))}for(const e of t.nodes.filter((t=>"Area"===t.group))){const t=f.filter((t=>{var i,o;return"Controller"!==t.group&&(null!==(i=t.area_id)&&void 0!==i?i:"")===(null!==(o=e.area_id)&&void 0!==o?o:"")}));f.push(Object.assign(Object.assign({},e),{x:t.length?(Math.min(...t.map((t=>t.x)))+Math.max(...t.map((t=>t.x))))/2:0,y:t.length?Math.min(...t.map((t=>t.y)))-110:0}))}return{nodes:f,edges:t.edges.map((t=>Object.assign({},t)))}}const S3=t=>{class i extends t{connectedCallback(){super.connectedCallback(),this.__checkSubscribed()}disconnectedCallback(){if(super.disconnectedCallback(),this.__unsubs){for(;this.__unsubs.length;){const t=this.__unsubs.pop();t instanceof Promise?t.then((t=>t())):null!=t&&t()}this.__unsubs=void 0}}updated(t){super.updated(t),t.has("hass")&&this.__checkSubscribed()}hassSubscribe(){return[]}__checkSubscribed(){void 0===this.__unsubs&&this.isConnected&&void 0!==this.hass&&(this.__unsubs=this.hassSubscribe())}}return e([Ut({attribute:!1})],i.prototype,"hass",void 0),i};var I3={"common.version":"Version","card.title":"Zigbee network","card.description":"An interactive map of your Wiser Zigbee network","card.hub":"Wiser Hub","card.devices_one":"{count} device","card.devices_other":"{count} devices","card.connections_one":"{count} connection","card.connections_other":"{count} connections","card.controls":"Network controls","card.fit":"Fit view","card.tidy":"Tidy layout","card.link_labels":"Link labels","card.save_layout":"Save layout","card.load_error":"Unable to load the network. Try refreshing.","card.updating":"Updating network…","card.empty":"No devices found","card.unknown_device":"Unknown device","card.hint":"Double-click to zoom in or out. Drag to rearrange. Tap a device for Zigbee details. Long-press for More info.","map.accessible_only":"Interactive Zigbee network map. Double-click a device or empty area to zoom in, and double-click again to zoom out. Drag to rearrange. Tap a device for Zigbee details. Long-press for More info.","map.accessible_list":"Interactive Zigbee network map. Device and connection details are available in the list below. Tap a device for Zigbee details. Long-press for More info.","map.accessible_details":"Interactive Zigbee network map. Tap a device for Zigbee details. Long-press for More info.","layout.storage_error":"Browser storage unavailable. Copy the layout into your card configuration.","layout.device_list":"All devices & connections","editor.auto_update":"Auto refresh","editor.show_device_list":"Show all devices & connections","editor.orientation":"Network view","editor.loading":"Loading Home Assistant controls…","signal.connected":"Connected","signal.online":"Online","signal.offline":"Offline","signal.no_signal":"No signal","signal.very_good":"Very good","signal.good":"Good","signal.poor":"Poor","zigbee.type":"Device type","zigbee.node":"Zigbee node ID","zigbee.parent":"Parent node ID","zigbee.channel":"Zigbee channel","zigbee.signal":"Signal quality","zigbee.device_rssi":"Device RSSI","zigbee.device_lqi":"Device LQI","zigbee.hub_rssi":"Hub RSSI","zigbee.hub_lqi":"Hub LQI","editor.map_height":"Map height","card.show_detailed_view":"Show detailed view","card.zoom_in":"Zoom in","card.zoom_out":"Zoom out","editor.group_by":"Group","card.unassigned_area":"Unassigned","editor.show_labels":"Show link labels","editor.link_status":"Link status","editor.links":"Links","editor.both":"Both","signal.medium":"Medium","layout.config_save_error":"Unable to save this card’s configuration. Use the card editor to save, or copy the layout YAML for a YAML dashboard.","editor.magnifier":"Magnifying glass","editor.lens_size":"Lens size","layout.copy_error":"Unable to copy the layout. Check clipboard permissions and try again.","panel.menu":"Toggle sidebar","panel.settings":"Panel settings","panel.description":"Customize this panel. Dashboard cards keep their own settings.","panel.editor_error":"Unable to open the editor. Close this dialog and try again.","panel.save_error":"Unable to save settings to Home Assistant. Please try again."};const M3={"en-US":I3,"en-GB":{"common.version":"Version","card.title":"Zigbee network","card.description":"An interactive map of your Wiser Zigbee network","card.hub":"Wiser Hub","card.devices_one":"{count} device","card.devices_other":"{count} devices","card.connections_one":"{count} connection","card.connections_other":"{count} connections","card.controls":"Network controls","card.fit":"Fit view","card.tidy":"Tidy layout","card.link_labels":"Link labels","card.save_layout":"Save layout","card.load_error":"Unable to load the network. Try refreshing.","card.updating":"Updating network…","card.empty":"No devices found","card.unknown_device":"Unknown device","card.hint":"Double-click to zoom in or out. Drag to rearrange. Tap a device for Zigbee details. Long-press for More info.","map.accessible_only":"Interactive Zigbee network map. Double-click a device or empty area to zoom in, and double-click again to zoom out. Drag to rearrange. Tap a device for Zigbee details. Long-press for More info.","map.accessible_list":"Interactive Zigbee network map. Device and connection details are available in the list below. Tap a device for Zigbee details. Long-press for More info.","map.accessible_details":"Interactive Zigbee network map. Tap a device for Zigbee details. Long-press for More info.","layout.storage_error":"Browser storage unavailable. Copy the layout into your card configuration.","layout.device_list":"All devices & connections","editor.auto_update":"Auto refresh","editor.show_device_list":"Show all devices & connections","editor.orientation":"Network view","editor.loading":"Loading Home Assistant controls…","signal.connected":"Connected","signal.online":"Online","signal.offline":"Offline","signal.no_signal":"No signal","signal.very_good":"Very good","signal.good":"Good","signal.poor":"Poor","zigbee.type":"Device type","zigbee.node":"Zigbee node ID","zigbee.parent":"Parent node ID","zigbee.channel":"Zigbee channel","zigbee.signal":"Signal quality","zigbee.device_rssi":"Device RSSI","zigbee.device_lqi":"Device LQI","zigbee.hub_rssi":"Hub RSSI","zigbee.hub_lqi":"Hub LQI","editor.map_height":"Map height","card.show_detailed_view":"Show detailed view","card.zoom_in":"Zoom in","card.zoom_out":"Zoom out","editor.group_by":"Group","card.unassigned_area":"Unassigned","editor.show_labels":"Show link labels","editor.link_status":"Link status","editor.links":"Links","editor.both":"Both","signal.medium":"Medium","layout.config_save_error":"Unable to save this card’s configuration. Use the card editor to save, or copy the layout YAML for a YAML dashboard.","editor.magnifier":"Magnifying glass","editor.lens_size":"Lens size","layout.copy_error":"Unable to copy the layout. Check clipboard permissions and try again.","panel.menu":"Toggle sidebar","panel.settings":"Panel settings","panel.description":"Customise this panel. Dashboard cards keep their own settings.","panel.editor_error":"Unable to open the editor. Close this dialogue and try again.","panel.save_error":"Unable to save settings to Home Assistant. Please try again."},de:{"common.version":"Version","card.title":"Zigbee-Netzwerk","card.description":"Eine interaktive Karte Ihres Wiser-Zigbee-Netzwerks","card.hub":"Wiser Hub","card.devices_one":"{count} Gerät","card.devices_other":"{count} Geräte","card.connections_one":"{count} Verbindung","card.connections_other":"{count} Verbindungen","card.controls":"Netzwerksteuerung","card.fit":"Ansicht einpassen","card.tidy":"Layout anordnen","card.link_labels":"Verbindungsbeschriftungen","card.save_layout":"Layout speichern","card.load_error":"Das Netzwerk konnte nicht geladen werden. Bitte aktualisieren.","card.updating":"Netzwerk wird aktualisiert…","card.empty":"Keine Geräte gefunden","card.unknown_device":"Unbekanntes Gerät","card.hint":"Zum Vergrößern oder Verkleinern doppelklicken. Zum Anordnen ziehen. Für Zigbee-Details auf ein Gerät tippen. Für weitere Informationen gedrückt halten.","map.accessible_only":"Interaktive Zigbee-Netzwerkkarte. Zum Vergrößern auf ein Gerät oder eine freie Stelle doppelklicken, zum Verkleinern erneut doppelklicken. Zum Anordnen ziehen. Für Zigbee-Details auf ein Gerät tippen. Für weitere Informationen gedrückt halten.","map.accessible_list":"Interaktive Zigbee-Netzwerkkarte. Geräte- und Verbindungsdetails stehen in der Liste darunter. Für Zigbee-Details auf ein Gerät tippen. Für weitere Informationen gedrückt halten.","map.accessible_details":"Interaktive Zigbee-Netzwerkkarte. Für Zigbee-Details auf ein Gerät tippen. Für weitere Informationen gedrückt halten.","layout.storage_error":"Browserspeicher nicht verfügbar. Kopieren Sie das Layout in Ihre Kartenkonfiguration.","layout.device_list":"Alle Geräte und Verbindungen","editor.auto_update":"Automatisch aktualisieren","editor.show_device_list":"Alle Geräte und Verbindungen anzeigen","editor.orientation":"Netzwerkansicht","editor.loading":"Home-Assistant-Steuerelemente werden geladen…","signal.connected":"Verbunden","signal.online":"Online","signal.offline":"Offline","signal.no_signal":"Kein Signal","signal.very_good":"Sehr gut","signal.good":"Gut","signal.poor":"Schwach","zigbee.type":"Gerätetyp","zigbee.node":"Zigbee-Knoten-ID","zigbee.parent":"Übergeordnete Knoten-ID","zigbee.channel":"Zigbee-Kanal","zigbee.signal":"Signalqualität","zigbee.device_rssi":"Geräte-RSSI","zigbee.device_lqi":"Geräte-LQI","zigbee.hub_rssi":"Hub-RSSI","zigbee.hub_lqi":"Hub-LQI","editor.map_height":"Kartenhöhe","card.show_detailed_view":"Detailansicht anzeigen","card.zoom_in":"Vergrößern","card.zoom_out":"Verkleinern","editor.group_by":"Gruppieren","card.unassigned_area":"Nicht zugewiesen","editor.show_labels":"Verbindungsbeschriftungen anzeigen","editor.link_status":"Verbindungsstatus","editor.links":"Verbindungen","editor.both":"Beides","signal.medium":"Mittel","layout.config_save_error":"Die Kartenkonfiguration konnte nicht gespeichert werden. Speichere im Karteneditor oder kopiere das Layout-YAML für ein YAML-Dashboard.","editor.magnifier":"Lupe","editor.lens_size":"Lupengröße","layout.copy_error":"Das Layout konnte nicht kopiert werden. Prüfe die Berechtigungen für die Zwischenablage und versuche es erneut.","panel.menu":"Seitenleiste umschalten","panel.settings":"Panel-Einstellungen","panel.description":"Dieses Panel anpassen. Dashboard-Karten behalten ihre eigenen Einstellungen.","panel.editor_error":"Der Editor konnte nicht geöffnet werden. Schließe den Dialog und versuche es erneut.","panel.save_error":"Einstellungen konnten nicht in Home Assistant gespeichert werden. Bitte versuche es erneut."},fr:{"common.version":"Version","card.title":"Réseau Zigbee","card.description":"Une carte interactive de votre réseau Zigbee Wiser","card.hub":"Hub Wiser","card.devices_one":"{count} appareil","card.devices_other":"{count} appareils","card.connections_one":"{count} connexion","card.connections_other":"{count} connexions","card.controls":"Commandes du réseau","card.fit":"Ajuster la vue","card.tidy":"Réorganiser la disposition","card.link_labels":"Libellés des connexions","card.save_layout":"Enregistrer la disposition","card.load_error":"Impossible de charger le réseau. Essayez de l’actualiser.","card.updating":"Actualisation du réseau…","card.empty":"Aucun appareil trouvé","card.unknown_device":"Appareil inconnu","card.hint":"Double-cliquez pour zoomer ou dézoomer. Faites glisser pour réorganiser. Appuyez sur un appareil pour afficher ses détails Zigbee. Maintenez-le enfoncé pour afficher Plus d’informations.","map.accessible_only":"Carte interactive du réseau Zigbee. Double-cliquez sur un appareil ou une zone vide pour zoomer, puis à nouveau pour dézoomer. Faites glisser pour réorganiser. Appuyez sur un appareil pour afficher ses détails Zigbee. Maintenez-le enfoncé pour afficher Plus d’informations.","map.accessible_list":"Carte interactive du réseau Zigbee. Les détails des appareils et des connexions figurent dans la liste ci-dessous. Appuyez sur un appareil pour afficher ses détails Zigbee. Maintenez-le enfoncé pour afficher Plus d’informations.","map.accessible_details":"Carte interactive du réseau Zigbee. Appuyez sur un appareil pour afficher ses détails Zigbee. Maintenez-le enfoncé pour afficher Plus d’informations.","layout.storage_error":"Stockage du navigateur indisponible. Copiez la disposition dans la configuration de votre carte.","layout.device_list":"Tous les appareils et connexions","editor.auto_update":"Actualisation automatique","editor.show_device_list":"Afficher tous les appareils et connexions","editor.orientation":"Vue du réseau","editor.loading":"Chargement des commandes Home Assistant…","signal.connected":"Connecté","signal.online":"En ligne","signal.offline":"Hors ligne","signal.no_signal":"Aucun signal","signal.very_good":"Très bon","signal.good":"Bon","signal.poor":"Faible","zigbee.type":"Type d’appareil","zigbee.node":"ID du nœud Zigbee","zigbee.parent":"ID du nœud parent","zigbee.channel":"Canal Zigbee","zigbee.signal":"Qualité du signal","zigbee.device_rssi":"RSSI de l’appareil","zigbee.device_lqi":"LQI de l’appareil","zigbee.hub_rssi":"RSSI du hub","zigbee.hub_lqi":"LQI du hub","editor.map_height":"Hauteur de la carte","card.show_detailed_view":"Afficher la vue détaillée","card.zoom_in":"Zoom avant","card.zoom_out":"Zoom arrière","editor.group_by":"Grouper","card.unassigned_area":"Non attribué","editor.show_labels":"Afficher les libellés des liaisons","editor.link_status":"État des liaisons","editor.links":"Liaisons","editor.both":"Les deux","signal.medium":"Moyenne","layout.config_save_error":"Impossible d’enregistrer la configuration de cette carte. Utilisez l’éditeur de carte ou copiez le YAML de disposition pour un tableau de bord YAML.","editor.magnifier":"Loupe","editor.lens_size":"Taille de la loupe","layout.copy_error":"Impossible de copier la disposition. Vérifiez les autorisations du presse-papiers et réessayez.","panel.menu":"Afficher ou masquer la barre latérale","panel.settings":"Paramètres du panneau","panel.description":"Personnalisez ce panneau. Les cartes du tableau de bord conservent leurs propres paramètres.","panel.editor_error":"Impossible d’ouvrir l’éditeur. Fermez cette boîte de dialogue et réessayez.","panel.save_error":"Impossible d’enregistrer les paramètres dans Home Assistant. Veuillez réessayer."}},O3={"panel.cancel":"ui.common.cancel","panel.retry":"ui.common.retry","common.copy":"ui.common.copy","common.copied":"ui.common.copied","common.saved":"ui.common.successfully_saved","editor.icons":"ui.panel.lovelace.editor.features.types.climate-preset-modes.style_list.icons","editor.pie":"ui.panel.lovelace.editor.card.energy-devices-graph.mode_options.pie","common.invalid_configuration":"ui.panel.lovelace.editor.condition-editor.visibility_status.invalid.headline","editor.none":"ui.common.none","editor.area":"ui.panel.lovelace.editor.card.area.name","common.refresh":"ui.common.refresh","common.close":"ui.common.close","common.save":"ui.common.save","common.title":"ui.panel.lovelace.editor.card.generic.title","common.loading":"ui.init.loading","editor.horizontal":"ui.panel.lovelace.editor.card.tile.content_layout_options.horizontal","editor.vertical":"ui.panel.lovelace.editor.card.tile.content_layout_options.vertical","signal.unknown":"state.default.unknown"},D3={"zigbee.type":"ui.panel.config.zha.visualization.device_type","card.unassigned_area":"ui.panel.config.automation.editor.unassigned","signal.medium":"ui.panel.config.matter.visualization.strength.medium","common.version":"ui.panel.config.zwave_js.visualization.version","card.empty":"ui.panel.config.zha.groups.no_devices_found","card.unknown_device":"ui.panel.config.integrations.config_entry.unknown_via_device","signal.connected":"ui.panel.config.serial.connected","signal.online":"ui.panel.config.zha.configuration_page.status_online","signal.offline":"ui.panel.config.zha.configuration_page.status_offline"};function R3(t){var e;const i=((null===(e=null==t?void 0:t.locale)||void 0===e?void 0:e.language)||(null==t?void 0:t.language)||("undefined"!=typeof document?document.documentElement.lang:"")||"en-US").replace(/_/g,"-").toLowerCase();return"en-gb"===i?"en-GB":"de"===i||i.startsWith("de-")?"de":"fr"===i||i.startsWith("fr-")?"fr":"en-US"}function B3(t,e,i={}){var o;const n=R3(e);let r;const s=O3[t]||D3[t];if(s){const i=null===(o=null==e?void 0:e.localize)||void 0===o?void 0:o.call(e,s);if(i&&i!==s&&(r=i),O3[t])return null!=r?r:""}return r||(r=M3[n][t]||I3[t]||t),r.replace(/\{(\w+)\}/g,((t,e)=>{var o;return String(null!==(o=i[e])&&void 0!==o?o:t)}))}function z3(t,e,i){const o=R3(i);return B3(`card.${t}_${"one"===new Intl.PluralRules(o).select(e)?"one":"other"}`,i,{count:new Intl.NumberFormat(o).format(e)})}function P3(t,e){if(!t)return B3("signal.connected",e);const i=t.match(/^([a-z\s_-]+?)(\s*\([\d.,]+%\))?$/i);if(!i)return t;const o={connected:"connected",online:"online",offline:"offline",nosignal:"no_signal",verygood:"very_good",good:"good",poor:"poor",medium:"medium",unknown:"unknown"}[i[1].replace(/[\s_-]/g,"").toLowerCase()];return o?B3(`signal.${o}`,e)+(i[2]||""):t}function F3(t,e){const i=t.match(/\(([\d.,]+)%\)\s*$/);if(!i)return P3(t,e);const o=Number(i[1].replace(",","."));return!Number.isFinite(o)||o<0||o>100?P3(t,e):new Intl.NumberFormat(R3(e),{style:"percent",maximumFractionDigits:1}).format(o/100)}function T3(t){for(const e of["ha-icon","ha-button","ha-icon-button","ha-tooltip","ha-expansion-panel","ha-button-toggle-group","ha-alert","ha-dropdown","ha-dropdown-item","ha-slider"])customElements.get(e)||customElements.whenDefined(e).then((()=>{t.isConnected&&t.requestUpdate()}))}class N3 extends Pt{constructor(){super(...arguments),this.hideHubSelector=!1,this._hubs=[],this._formReady=!!customElements.get("ha-form"),this.boundLayoutSaveHandler=this.save_layout.bind(this),this.computeLabel=t=>this.t("name"===t.name?"common.title":"hub"===t.name?"card.hub":"show_detailed_view"===t.name?"card.show_detailed_view":`editor.${t.name}`)}t(t){return B3(t,this.hass)}setConfig(t){var e;this._config=Object.assign(Object.assign({},t),{auto_update:null===(e=t.auto_update)||void 0===e||e}),this.loadNativeForm()}connectedCallback(){super.connectedCallback(),T3(this),window.addEventListener("wiser-zigbee-save-layout",this.boundLayoutSaveHandler)}disconnectedCallback(){window.removeEventListener("wiser-zigbee-save-layout",this.boundLayoutSaveHandler),super.disconnectedCallback()}updated(t){var e;t.has("hass")&&this.hass&&!t.get("hass")&&(e=this.hass,e.callWS({type:"wiser/hubs"})).then((t=>{this._hubs=t})).catch((()=>{this._hubs=[]}))}async loadNativeForm(){if(customElements.get("ha-form"))this._formReady=!0;else{if(this.loadingForm)return this.loadingForm;this.loadingForm=(async()=>{const t=(await window.loadCardHelpers()).createCardElement({type:"button"});await t.constructor.getConfigElement(),await customElements.whenDefined("ha-form"),this._formReady=!0})();try{await this.loadingForm}catch(t){this.loadingForm=void 0}}}render(){var t,e,i,o,n,r,s,a,l;if(!this.hass||!this._config)return X``;if(!this._formReady)return X`

${this.t("editor.loading")}

`;const h=[...new Set([...this._hubs,...this._config.hub?[this._config.hub]:[]])],c=Object.assign(Object.assign({},this._config),{hub:this._config.hub||this._hubs[0],name:null!==(t=this._config.name)&&void 0!==t?t:this.t("card.title"),show_detailed_view:!(null!==(e=this._config.map_only)&&void 0!==e&&e),map_height:null!==(i=this._config.map_height)&&void 0!==i?i:null,show_device_list:null===(o=this._config.show_device_list)||void 0===o||o,show_labels:null!==(n=this._config.show_labels)&&void 0!==n&&n,magnifier:null!==(r=this._config.magnifier)&&void 0!==r&&r}),d=[{name:"hub",required:!0,disabled:0===h.length,selector:{select:{options:h,mode:"dropdown"}}},{name:"name",selector:{text:{}}},{name:"map_height",selector:{number:{min:100,max:2e3,step:1,mode:"box",unit_of_measurement:"px"}}}],u=[{name:"show_labels",selector:{boolean:{}}},{name:"magnifier",selector:{boolean:{}}},{name:"auto_update",selector:{boolean:{}}},{name:"show_detailed_view",selector:{boolean:{}}},{name:"show_device_list",selector:{boolean:{}},disabled:!c.show_detailed_view}];return X` -1}var uZ=function(){function t(t,e){this.manager=t,this.set(e)}var e=t.prototype;return e.set=function(t){t===NY&&(t=this.compute()),TY&&this.manager.element.style&&VY[t]&&(this.manager.element.style[FY]=t),this.actions=t.toLowerCase().trim()},e.update=function(){this.set(this.manager.options.touchAction)},e.compute=function(){var t=[];return hZ(this.manager.recognizers,(function(e){cZ(e.options.enable,[e])&&(t=t.concat(e.getTouchAction()))})),function(t){if(dZ(t,UY))return UY;var e=dZ(t,QY),i=dZ(t,HY);return e&&i?UY:e||i?e?QY:HY:dZ(t,LY)?LY:jY}(t.join(" "))},e.preventDefaults=function(t){var e=t.srcEvent,i=t.offsetDirection;if(this.manager.session.prevented)e.preventDefault();else{var n=this.actions,o=dZ(n,UY)&&!VY[UY],r=dZ(n,HY)&&!VY[HY],s=dZ(n,QY)&&!VY[QY];if(o){var a=1===t.pointers.length,l=t.distance<2,h=t.deltaTime<250;if(a&&l&&h)return}if(!s||!r)return o||r&&i&oZ||s&&i&rZ?this.preventSrc(e):void 0}},e.preventSrc=function(t){this.manager.session.prevented=!0,t.preventDefault()},t}();function fZ(t,e){for(;t;){if(t===e)return!0;t=t.parentNode}return!1}function pZ(t){var e=t.length;if(1===e)return{x:RY(t[0].clientX),y:RY(t[0].clientY)};for(var i=0,n=0,o=0;o=BY(e)?t<0?tZ:eZ:e<0?iZ:nZ}function bZ(t,e,i){return{x:e/t||0,y:i/t||0}}function wZ(t,e){var i=t.session,n=e.pointers,o=n.length;i.firstInput||(i.firstInput=vZ(e)),o>1&&!i.firstMultiple?i.firstMultiple=vZ(e):1===o&&(i.firstMultiple=!1);var r=i.firstInput,s=i.firstMultiple,a=s?s.center:r.center,l=e.center=pZ(n);e.timeStamp=zY(),e.deltaTime=e.timeStamp-r.timeStamp,e.angle=yZ(a,l),e.distance=gZ(a,l),function(t,e){var i=e.center,n=t.offsetDelta||{},o=t.prevDelta||{},r=t.prevInput||{};e.eventType!==JY&&r.eventType!==XY||(o=t.prevDelta={x:r.deltaX||0,y:r.deltaY||0},n=t.offsetDelta={x:i.x,y:i.y}),e.deltaX=o.x+(i.x-n.x),e.deltaY=o.y+(i.y-n.y)}(i,e),e.offsetDirection=mZ(e.deltaX,e.deltaY);var h,c,d=bZ(e.deltaTime,e.deltaX,e.deltaY);e.overallVelocityX=d.x,e.overallVelocityY=d.y,e.overallVelocity=BY(d.x)>BY(d.y)?d.x:d.y,e.scale=s?(h=s.pointers,gZ((c=n)[0],c[1],lZ)/gZ(h[0],h[1],lZ)):1,e.rotation=s?function(t,e){return yZ(e[1],e[0],lZ)+yZ(t[1],t[0],lZ)}(s.pointers,n):0,e.maxPointers=i.prevInput?e.pointers.length>i.prevInput.maxPointers?e.pointers.length:i.prevInput.maxPointers:e.pointers.length,function(t,e){var i,n,o,r,s=t.lastInterval||e,a=e.timeStamp-s.timeStamp;if(e.eventType!==_Y&&(a>ZY||void 0===s.velocity)){var l=e.deltaX-s.deltaX,h=e.deltaY-s.deltaY,c=bZ(a,l,h);n=c.x,o=c.y,i=BY(c.x)>BY(c.y)?c.x:c.y,r=mZ(l,h),t.lastInterval=e}else i=s.velocity,n=s.velocityX,o=s.velocityY,r=s.direction;e.velocity=i,e.velocityX=n,e.velocityY=o,e.direction=r}(i,e);var u,f=t.element,p=e.srcEvent;fZ(u=p.composedPath?p.composedPath()[0]:p.path?p.path[0]:p.target,f)&&(f=u),e.target=f}function AZ(t,e,i){var n=i.pointers.length,o=i.changedPointers.length,r=e&JY&&n-o==0,s=e&(XY|_Y)&&n-o==0;i.isFirst=!!r,i.isFinal=!!s,r&&(t.session={}),i.eventType=e,wZ(t,i),t.emit("hammer.input",i),t.recognize(i),t.session.prevInput=i}function kZ(t){return t.trim().split(/\s+/g)}function EZ(t,e,i){hZ(kZ(e),(function(e){t.addEventListener(e,i,!1)}))}function CZ(t,e,i){hZ(kZ(e),(function(e){t.removeEventListener(e,i,!1)}))}function xZ(t){var e=t.ownerDocument||t;return e.defaultView||e.parentWindow||window}var IZ=function(){function t(t,e){var i=this;this.manager=t,this.callback=e,this.element=t.element,this.target=t.options.inputTarget,this.domHandler=function(e){cZ(t.options.enable,[t])&&i.handler(e)},this.init()}var e=t.prototype;return e.handler=function(){},e.init=function(){this.evEl&&EZ(this.element,this.evEl,this.domHandler),this.evTarget&&EZ(this.target,this.evTarget,this.domHandler),this.evWin&&EZ(xZ(this.element),this.evWin,this.domHandler)},e.destroy=function(){this.evEl&&CZ(this.element,this.evEl,this.domHandler),this.evTarget&&CZ(this.target,this.evTarget,this.domHandler),this.evWin&&CZ(xZ(this.element),this.evWin,this.domHandler)},t}();function SZ(t,e,i){if(t.indexOf&&!i)return t.indexOf(e);for(var n=0;ni[e]})):n.sort()),n}var FZ={touchstart:JY,touchmove:2,touchend:XY,touchcancel:_Y},TZ=function(t){function e(){var i;return e.prototype.evTarget="touchstart touchmove touchend touchcancel",(i=t.apply(this,arguments)||this).targetIds={},i}return xY(e,t),e.prototype.handler=function(t){var e=FZ[t.type],i=NZ.call(this,t,e);i&&this.callback(this.manager,e,{pointers:i[0],changedPointers:i[1],pointerType:qY,srcEvent:t})},e}(IZ);function NZ(t,e){var i,n,o=zZ(t.touches),r=this.targetIds;if(e&(2|JY)&&1===o.length)return r[o[0].identifier]=!0,[o,o];var s=zZ(t.changedTouches),a=[],l=this.target;if(n=o.filter((function(t){return fZ(t.target,l)})),e===JY)for(i=0;i-1&&n.splice(t,1)}),UZ)}}function HZ(t,e){t&JY?(this.primaryTouch=e.changedPointers[0].identifier,QZ.call(this,e)):t&(XY|_Y)&&QZ.call(this,e)}function VZ(t){for(var e=t.srcEvent.clientX,i=t.srcEvent.clientY,n=0;n-1&&this.requireFail.splice(e,1),this},e.hasRequireFailures=function(){return this.requireFail.length>0},e.canRecognizeWith=function(t){return!!this.simultaneous[t.id]},e.emit=function(t){var e=this,i=this.state;function n(i){e.manager.emit(i,t)}i<8&&n(e.options.event+ZZ(i)),n(e.options.event),t.additionalEvent&&n(t.additionalEvent),i>=8&&n(e.options.event+ZZ(i))},e.tryEmit=function(t){if(this.canEmit())return this.emit(t);this.state=KZ},e.canEmit=function(){for(var t=0;te.threshold&&o&e.direction},i.attrTest=function(t){return _Z.prototype.attrTest.call(this,t)&&(2&this.state||!(2&this.state)&&this.directionTest(t))},i.emit=function(e){this.pX=e.deltaX,this.pY=e.deltaY;var i=$Z(e.direction);i&&(e.additionalEvent=this.options.event+i),t.prototype.emit.call(this,e)},e}(_Z),eJ=function(t){function e(e){return void 0===e&&(e={}),t.call(this,CY({event:"swipe",threshold:10,velocity:.3,direction:oZ|rZ,pointers:1},e))||this}xY(e,t);var i=e.prototype;return i.getTouchAction=function(){return tJ.prototype.getTouchAction.call(this)},i.attrTest=function(e){var i,n=this.options.direction;return n&(oZ|rZ)?i=e.overallVelocity:n&oZ?i=e.overallVelocityX:n&rZ&&(i=e.overallVelocityY),t.prototype.attrTest.call(this,e)&&n&e.offsetDirection&&e.distance>this.options.threshold&&e.maxPointers===this.options.pointers&&BY(i)>this.options.velocity&&e.eventType&XY},i.emit=function(t){var e=$Z(t.offsetDirection);e&&this.manager.emit(this.options.event+e,t),this.manager.emit(this.options.event,t)},e}(_Z),iJ=function(t){function e(e){return void 0===e&&(e={}),t.call(this,CY({event:"pinch",threshold:0,pointers:2},e))||this}xY(e,t);var i=e.prototype;return i.getTouchAction=function(){return[UY]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.scale-1)>this.options.threshold||2&this.state)},i.emit=function(e){if(1!==e.scale){var i=e.scale<1?"in":"out";e.additionalEvent=this.options.event+i}t.prototype.emit.call(this,e)},e}(_Z),nJ=function(t){function e(e){return void 0===e&&(e={}),t.call(this,CY({event:"rotate",threshold:0,pointers:2},e))||this}xY(e,t);var i=e.prototype;return i.getTouchAction=function(){return[UY]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.rotation)>this.options.threshold||2&this.state)},e}(_Z),oJ=function(t){function e(e){var i;return void 0===e&&(e={}),(i=t.call(this,CY({event:"press",pointers:1,time:251,threshold:9},e))||this)._timer=null,i._input=null,i}xY(e,t);var i=e.prototype;return i.getTouchAction=function(){return[jY]},i.process=function(t){var e=this,i=this.options,n=t.pointers.length===i.pointers,o=t.distancei.time;if(this._input=t,!o||!n||t.eventType&(XY|_Y)&&!r)this.reset();else if(t.eventType&JY)this.reset(),this._timer=setTimeout((function(){e.state=8,e.tryEmit()}),i.time);else if(t.eventType&XY)return 8;return KZ},i.reset=function(){clearTimeout(this._timer)},i.emit=function(t){8===this.state&&(t&&t.eventType&XY?this.manager.emit(this.options.event+"up",t):(this._input.timeStamp=zY(),this.manager.emit(this.options.event,this._input)))},e}(JZ),rJ={domEvents:!1,touchAction:NY,enable:!0,inputTarget:null,inputClass:null,cssProps:{userSelect:"none",touchSelect:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}},sJ=[[nJ,{enable:!1}],[iJ,{enable:!1},["rotate"]],[eJ,{direction:oZ}],[tJ,{direction:oZ},["swipe"]],[XZ],[XZ,{event:"doubletap",taps:2},["tap"]],[oJ]];function aJ(t,e){var i,n=t.element;n.style&&(hZ(t.options.cssProps,(function(o,r){i=PY(n.style,r),e?(t.oldCssProps[i]=n.style[i],n.style[i]=o):n.style[i]=t.oldCssProps[i]||""})),e||(t.oldCssProps={}))}var lJ=function(){function t(t,e){var i,n=this;this.options=MY({},rJ,e||{}),this.options.inputTarget=this.options.inputTarget||t,this.handlers={},this.session={},this.recognizers=[],this.oldCssProps={},this.element=t,this.input=new((i=this).options.inputClass||(GY?BZ:KY?TZ:WY?WZ:LZ))(i,AZ),this.touchAction=new uZ(this,this.options.touchAction),aJ(this,!0),hZ(this.options.recognizers,(function(t){var e=n.add(new t[0](t[1]));t[2]&&e.recognizeWith(t[2]),t[3]&&e.requireFailure(t[3])}),this)}var e=t.prototype;return e.set=function(t){return MY(this.options,t),t.touchAction&&this.touchAction.update(),t.inputTarget&&(this.input.destroy(),this.input.target=t.inputTarget,this.input.init()),this},e.stop=function(t){this.session.stopped=t?2:1},e.recognize=function(t){var e=this.session;if(!e.stopped){var i;this.touchAction.preventDefaults(t);var n=this.recognizers,o=e.curRecognizer;(!o||o&&8&o.state)&&(e.curRecognizer=null,o=null);for(var r=0;r\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",o=window.console&&(window.console.warn||window.console.log);return o&&o.call(window.console,n,i),t.apply(this,arguments)}}var fJ=uJ((function(t,e,i){for(var n=Object.keys(e),o=0;o=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function wJ(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i>>0,t=(o*=t)>>>0,t+=4294967296*(o-=t)}return 2.3283064365386963e-10*(t>>>0)}}(),e=t(" "),i=t(" "),n=t(" "),o=0;o2&&void 0!==arguments[2]&&arguments[2];for(var n in t)if(void 0!==e[n])if(null===e[n]||"object"!==fW(e[n]))RJ(t,e,n,i);else{var o=t[n],r=e[n];DJ(o)&&DJ(r)&&BJ(o,r,i)}}function zJ(t,e,i){var n=arguments.length>3&&void 0!==arguments[3]&&arguments[3];if(AG(i))throw new TypeError("Arrays are not supported by deepExtend");for(var o=0;o3&&void 0!==arguments[3]&&arguments[3];if(AG(i))throw new TypeError("Arrays are not supported by deepExtend");for(var o in i)if(Object.prototype.hasOwnProperty.call(i,o)&&!YK(t).call(t,o))if(i[o]&&i[o].constructor===Object)void 0===e[o]&&(e[o]={}),e[o].constructor===Object?FJ(e[o],i[o]):RJ(e,i,o,n);else if(AG(i[o])){e[o]=[];for(var r=0;r2&&void 0!==arguments[2]&&arguments[2],n=arguments.length>3&&void 0!==arguments[3]&&arguments[3];for(var o in e)if(Object.prototype.hasOwnProperty.call(e,o)||!0===i)if("object"===fW(e[o])&&null!==e[o]&&$K(e[o])===Object.prototype)void 0===t[o]?t[o]=FJ({},e[o],i):"object"===fW(t[o])&&null!==t[o]&&$K(t[o])===Object.prototype?FJ(t[o],e[o],i):RJ(t,e,o,n);else if(AG(e[o])){var r;t[o]=pG(r=e[o]).call(r)}else RJ(t,e,o,n);return t}function TJ(t,e){var i;return fG(i=[]).call(i,sG(t),[e])}function NJ(t){return t.getBoundingClientRect().top}function jJ(t,e){if(AG(t))for(var i=t.length,n=0;n3&&void 0!==arguments[3]?arguments[3]:{},o=function(t){return null!=t},r=function(t){return null!==t&&"object"===fW(t)};if(!r(t))throw new Error("Parameter mergeTarget must be an object");if(!r(e))throw new Error("Parameter options must be an object");if(!o(i))throw new Error("Parameter option must have a value");if(!r(n))throw new Error("Parameter globalOptions must be an object");var s=e[i],a=r(n)&&!function(t){for(var e in t)if(Object.prototype.hasOwnProperty.call(t,e))return!1;return!0}(n),l=a?n[i]:void 0,h=l?l.enabled:void 0;if(void 0!==s){if("boolean"==typeof s)return r(t[i])||(t[i]={}),void(t[i].enabled=s);if(null===s&&!r(t[i])){if(!o(l))return;t[i]=Vq(l)}if(r(s)){var c=!0;void 0!==s.enabled?c=s.enabled:void 0!==h&&(c=l.enabled),function(t,e,i){r(t[i])||(t[i]={});var n=e[i],o=t[i];for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(o[s]=n[s])}(t,e,i),t[i].enabled=c}}}var JJ={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return t*(2-t)},easeInOutQuad:function(t){return t<.5?2*t*t:(4-2*t)*t-1},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return--t*t*t+1},easeInOutCubic:function(t){return t<.5?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return 1- --t*t*t*t},easeInOutQuart:function(t){return t<.5?8*t*t*t*t:1-8*--t*t*t*t},easeInQuint:function(t){return t*t*t*t*t},easeOutQuint:function(t){return 1+--t*t*t*t*t},easeInOutQuint:function(t){return t<.5?16*t*t*t*t*t:1+16*--t*t*t*t*t}};function XJ(t,e){var i;AG(e)||(e=[e]);var n,o=bJ(t);try{for(o.s();!(n=o.n()).done;){var r=n.value;if(r){i=r[e[0]];for(var s=1;s0&&void 0!==arguments[0]?arguments[0]:1;uU(this,t),this.pixelRatio=e,this.generated=!1,this.centerCoordinates={x:144.5,y:144.5},this.r=289*.49,this.color={r:255,g:255,b:255,a:1},this.hueCircle=void 0,this.initialColor={r:255,g:255,b:255,a:1},this.previousColor=void 0,this.applied=!1,this.updateCallback=function(){},this.closeCallback=function(){},this._create()}return yW(t,[{key:"insertTo",value:function(t){void 0!==this.hammer&&(this.hammer.destroy(),this.hammer=void 0),this.container=t,this.container.appendChild(this.frame),this._bindHammer(),this._setSize()}},{key:"setUpdateCallback",value:function(t){if("function"!=typeof t)throw new Error("Function attempted to set as colorPicker update callback is not a function.");this.updateCallback=t}},{key:"setCloseCallback",value:function(t){if("function"!=typeof t)throw new Error("Function attempted to set as colorPicker closing callback is not a function.");this.closeCallback=t}},{key:"_isColorString",value:function(t){if("string"==typeof t)return _J[t]}},{key:"setColor",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if("none"!==t){var i,n=this._isColorString(t);if(void 0!==n&&(t=n),!0===OJ(t)){if(!0===qJ(t)){var o=t.substr(4).substr(0,t.length-5).split(",");i={r:o[0],g:o[1],b:o[2],a:1}}else if(!0===function(t){return SJ.test(t)}(t)){var r=t.substr(5).substr(0,t.length-6).split(",");i={r:r[0],g:r[1],b:r[2],a:r[3]}}else if(!0===KJ(t)){var s=LJ(t);i={r:s.r,g:s.g,b:s.b,a:1}}}else if(t instanceof Object&&void 0!==t.r&&void 0!==t.g&&void 0!==t.b){var a=void 0!==t.a?t.a:"1.0";i={r:t.r,g:t.g,b:t.b,a:a}}if(void 0===i)throw new Error("Unknown color passed to the colorPicker. Supported are strings: rgb, hex, rgba. Object: rgb ({r:r,g:g,b:b,[a:a]}). Supplied: "+qq(t));this._setColor(i,e)}}},{key:"show",value:function(){void 0!==this.closeCallback&&(this.closeCallback(),this.closeCallback=void 0),this.applied=!1,this.frame.style.display="block",this._generateHueCircle()}},{key:"_hide",value:function(){var t=this;!0===(!(arguments.length>0&&void 0!==arguments[0])||arguments[0])&&(this.previousColor=wF({},this.color)),!0===this.applied&&this.updateCallback(this.initialColor),this.frame.style.display="none",uY((function(){void 0!==t.closeCallback&&(t.closeCallback(),t.closeCallback=void 0)}),0)}},{key:"_save",value:function(){this.updateCallback(this.color),this.applied=!1,this._hide()}},{key:"_apply",value:function(){this.applied=!0,this.updateCallback(this.color),this._updatePicker(this.color)}},{key:"_loadLast",value:function(){void 0!==this.previousColor?this.setColor(this.previousColor,!1):alert("There is no last color to load...")}},{key:"_setColor",value:function(t){!0===(!(arguments.length>1&&void 0!==arguments[1])||arguments[1])&&(this.initialColor=wF({},t)),this.color=t;var e=VJ(t.r,t.g,t.b),i=2*Math.PI,n=this.r*e.s,o=this.centerCoordinates.x+n*Math.sin(i*e.h),r=this.centerCoordinates.y+n*Math.cos(i*e.h);this.colorPickerSelector.style.left=o-.5*this.colorPickerSelector.clientWidth+"px",this.colorPickerSelector.style.top=r-.5*this.colorPickerSelector.clientHeight+"px",this._updatePicker(t)}},{key:"_setOpacity",value:function(t){this.color.a=t/100,this._updatePicker(this.color)}},{key:"_setBrightness",value:function(t){var e=VJ(this.color.r,this.color.g,this.color.b);e.v=t/100;var i=WJ(e.h,e.s,e.v);i.a=this.color.a,this.color=i,this._updatePicker()}},{key:"_updatePicker",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.color,e=VJ(t.r,t.g,t.b),i=this.colorPickerCanvas.getContext("2d");void 0===this.pixelRation&&(this.pixelRatio=(window.devicePixelRatio||1)/(i.webkitBackingStorePixelRatio||i.mozBackingStorePixelRatio||i.msBackingStorePixelRatio||i.oBackingStorePixelRatio||i.backingStorePixelRatio||1)),i.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var n=this.colorPickerCanvas.clientWidth,o=this.colorPickerCanvas.clientHeight;i.clearRect(0,0,n,o),i.putImageData(this.hueCircle,0,0),i.fillStyle="rgba(0,0,0,"+(1-e.v)+")",i.circle(this.centerCoordinates.x,this.centerCoordinates.y,this.r),EY(i).call(i),this.brightnessRange.value=100*e.v,this.opacityRange.value=100*t.a,this.initialColorDiv.style.backgroundColor="rgba("+this.initialColor.r+","+this.initialColor.g+","+this.initialColor.b+","+this.initialColor.a+")",this.newColorDiv.style.backgroundColor="rgba("+this.color.r+","+this.color.g+","+this.color.b+","+this.color.a+")"}},{key:"_setSize",value:function(){this.colorPickerCanvas.style.width="100%",this.colorPickerCanvas.style.height="100%",this.colorPickerCanvas.width=289*this.pixelRatio,this.colorPickerCanvas.height=289*this.pixelRatio}},{key:"_create",value:function(){var t,e,i,n;if(this.frame=document.createElement("div"),this.frame.className="vis-color-picker",this.colorPickerDiv=document.createElement("div"),this.colorPickerSelector=document.createElement("div"),this.colorPickerSelector.className="vis-selector",this.colorPickerDiv.appendChild(this.colorPickerSelector),this.colorPickerCanvas=document.createElement("canvas"),this.colorPickerDiv.appendChild(this.colorPickerCanvas),this.colorPickerCanvas.getContext){var o=this.colorPickerCanvas.getContext("2d");this.pixelRatio=(window.devicePixelRatio||1)/(o.webkitBackingStorePixelRatio||o.mozBackingStorePixelRatio||o.msBackingStorePixelRatio||o.oBackingStorePixelRatio||o.backingStorePixelRatio||1),this.colorPickerCanvas.getContext("2d").setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0)}else{var r=document.createElement("DIV");r.style.color="red",r.style.fontWeight="bold",r.style.padding="10px",r.innerText="Error: your browser does not support HTML canvas",this.colorPickerCanvas.appendChild(r)}this.colorPickerDiv.className="vis-color",this.opacityDiv=document.createElement("div"),this.opacityDiv.className="vis-opacity",this.brightnessDiv=document.createElement("div"),this.brightnessDiv.className="vis-brightness",this.arrowDiv=document.createElement("div"),this.arrowDiv.className="vis-arrow",this.opacityRange=document.createElement("input");try{this.opacityRange.type="range",this.opacityRange.min="0",this.opacityRange.max="100"}catch(t){}this.opacityRange.value="100",this.opacityRange.className="vis-range",this.brightnessRange=document.createElement("input");try{this.brightnessRange.type="range",this.brightnessRange.min="0",this.brightnessRange.max="100"}catch(t){}this.brightnessRange.value="100",this.brightnessRange.className="vis-range",this.opacityDiv.appendChild(this.opacityRange),this.brightnessDiv.appendChild(this.brightnessRange);var s=this;this.opacityRange.onchange=function(){s._setOpacity(this.value)},this.opacityRange.oninput=function(){s._setOpacity(this.value)},this.brightnessRange.onchange=function(){s._setBrightness(this.value)},this.brightnessRange.oninput=function(){s._setBrightness(this.value)},this.brightnessLabel=document.createElement("div"),this.brightnessLabel.className="vis-label vis-brightness",this.brightnessLabel.innerText="brightness:",this.opacityLabel=document.createElement("div"),this.opacityLabel.className="vis-label vis-opacity",this.opacityLabel.innerText="opacity:",this.newColorDiv=document.createElement("div"),this.newColorDiv.className="vis-new-color",this.newColorDiv.innerText="new",this.initialColorDiv=document.createElement("div"),this.initialColorDiv.className="vis-initial-color",this.initialColorDiv.innerText="initial",this.cancelButton=document.createElement("div"),this.cancelButton.className="vis-button vis-cancel",this.cancelButton.innerText="cancel",this.cancelButton.onclick=HF(t=this._hide).call(t,this,!1),this.applyButton=document.createElement("div"),this.applyButton.className="vis-button vis-apply",this.applyButton.innerText="apply",this.applyButton.onclick=HF(e=this._apply).call(e,this),this.saveButton=document.createElement("div"),this.saveButton.className="vis-button vis-save",this.saveButton.innerText="save",this.saveButton.onclick=HF(i=this._save).call(i,this),this.loadButton=document.createElement("div"),this.loadButton.className="vis-button vis-load",this.loadButton.innerText="load last",this.loadButton.onclick=HF(n=this._loadLast).call(n,this),this.frame.appendChild(this.colorPickerDiv),this.frame.appendChild(this.arrowDiv),this.frame.appendChild(this.brightnessLabel),this.frame.appendChild(this.brightnessDiv),this.frame.appendChild(this.opacityLabel),this.frame.appendChild(this.opacityDiv),this.frame.appendChild(this.newColorDiv),this.frame.appendChild(this.initialColorDiv),this.frame.appendChild(this.cancelButton),this.frame.appendChild(this.applyButton),this.frame.appendChild(this.saveButton),this.frame.appendChild(this.loadButton)}},{key:"_bindHammer",value:function(){var t=this;this.drag={},this.pinch={},this.hammer=new kJ(this.colorPickerCanvas),this.hammer.get("pinch").set({enable:!0}),this.hammer.on("hammer.input",(function(e){e.isFirst&&t._moveSelector(e)})),this.hammer.on("tap",(function(e){t._moveSelector(e)})),this.hammer.on("panstart",(function(e){t._moveSelector(e)})),this.hammer.on("panmove",(function(e){t._moveSelector(e)})),this.hammer.on("panend",(function(e){t._moveSelector(e)}))}},{key:"_generateHueCircle",value:function(){if(!1===this.generated){var t=this.colorPickerCanvas.getContext("2d");void 0===this.pixelRation&&(this.pixelRatio=(window.devicePixelRatio||1)/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1)),t.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var e,i,n,o,r=this.colorPickerCanvas.clientWidth,s=this.colorPickerCanvas.clientHeight;t.clearRect(0,0,r,s),this.centerCoordinates={x:.5*r,y:.5*s},this.r=.49*r;var a,l=2*Math.PI/360,h=1/360,c=1/this.r;for(n=0;n<360;n++)for(o=0;o3&&void 0!==arguments[3]?arguments[3]:1,r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:function(){return!1};uU(this,t),this.parent=e,this.changedOptions=[],this.container=i,this.allowCreation=!1,this.hideOption=r,this.options={},this.initialized=!1,this.popupCounter=0,this.defaultOptions={enabled:!1,filter:!0,container:void 0,showButton:!0},wF(this.options,this.defaultOptions),this.configureOptions=n,this.moduleOptions={},this.domElements=[],this.popupDiv={},this.popupLimit=5,this.popupHistory={},this.colorPicker=new $J(o),this.wrapper=void 0}return yW(t,[{key:"setOptions",value:function(t){if(void 0!==t){this.popupHistory={},this._removePopup();var e=!0;if("string"==typeof t)this.options.filter=t;else if(AG(t))this.options.filter=t.join();else if("object"===fW(t)){if(null==t)throw new TypeError("options cannot be null");void 0!==t.container&&(this.options.container=t.container),void 0!==sq(t)&&(this.options.filter=sq(t)),void 0!==t.showButton&&(this.options.showButton=t.showButton),void 0!==t.enabled&&(e=t.enabled)}else"boolean"==typeof t?(this.options.filter=!0,e=t):"function"==typeof t&&(this.options.filter=t,e=!0);!1===sq(this.options)&&(e=!1),this.options.enabled=e}this._clean()}},{key:"setModuleOptions",value:function(t){this.moduleOptions=t,!0===this.options.enabled&&(this._clean(),void 0!==this.options.container&&(this.container=this.options.container),this._create())}},{key:"_create",value:function(){this._clean(),this.changedOptions=[];var t=sq(this.options),e=0,i=!1;for(var n in this.configureOptions)Object.prototype.hasOwnProperty.call(this.configureOptions,n)&&(this.allowCreation=!1,i=!1,"function"==typeof t?i=(i=t(n,[]))||this._handleObject(this.configureOptions[n],[n],!0):!0!==t&&-1===Lq(t).call(t,n)||(i=!0),!1!==i&&(this.allowCreation=!0,e>0&&this._makeItem([]),this._makeHeader(n),this._handleObject(this.configureOptions[n],[n])),e++);this._makeButton(),this._push()}},{key:"_push",value:function(){this.wrapper=document.createElement("div"),this.wrapper.className="vis-configuration-wrapper",this.container.appendChild(this.wrapper);for(var t=0;t1?i-1:0),o=1;o2&&void 0!==arguments[2]&&arguments[2],n=document.createElement("div");if(n.className="vis-configuration vis-config-label vis-config-s"+e.length,!0===i){for(;n.firstChild;)n.removeChild(n.firstChild);n.appendChild(tX("i","b",t))}else n.innerText=t+":";return n}},{key:"_makeDropdown",value:function(t,e,i){var n=document.createElement("select");n.className="vis-configuration vis-config-select";var o=0;void 0!==e&&-1!==Lq(t).call(t,e)&&(o=Lq(t).call(t,e));for(var r=0;rr&&1!==r&&(a.max=Math.ceil(e*c),h=a.max,l="range increased"),a.value=e}else a.value=n;var d=document.createElement("input");d.className="vis-configuration vis-config-rangeinput",d.value=a.value;var u=this;a.onchange=function(){d.value=this.value,u._update(Number(this.value),i)},a.oninput=function(){d.value=this.value};var f=this._makeLabel(i[i.length-1],i),p=this._makeItem(i,f,a,d);""!==l&&this.popupHistory[p]!==h&&(this.popupHistory[p]=h,this._setupPopup(l,p))}},{key:"_makeButton",value:function(){var t=this;if(!0===this.options.showButton){var e=document.createElement("div");e.className="vis-configuration vis-config-button",e.innerText="generate options",e.onclick=function(){t._printOptions()},e.onmouseover=function(){e.className="vis-configuration vis-config-button hover"},e.onmouseout=function(){e.className="vis-configuration vis-config-button"},this.optionsContainer=document.createElement("div"),this.optionsContainer.className="vis-configuration vis-config-option-container",this.domElements.push(this.optionsContainer),this.domElements.push(e)}}},{key:"_setupPopup",value:function(t,e){var i=this;if(!0===this.initialized&&!0===this.allowCreation&&this.popupCounter1&&void 0!==arguments[1]?arguments[1]:[],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=!1,o=sq(this.options),r=!1;for(var s in t)if(Object.prototype.hasOwnProperty.call(t,s)){n=!0;var a=t[s],l=TJ(e,s);if("function"==typeof o&&!1===(n=o(s,e))&&!AG(a)&&"string"!=typeof a&&"boolean"!=typeof a&&a instanceof Object&&(this.allowCreation=!1,n=this._handleObject(a,l,!0),this.allowCreation=!1===i),!1!==n){r=!0;var h=this._getValue(l);if(AG(a))this._handleArray(a,h,l);else if("string"==typeof a)this._makeTextInput(a,h,l);else if("boolean"==typeof a)this._makeCheckbox(a,h,l);else if(a instanceof Object){if(!this.hideOption(e,s,this.moduleOptions))if(void 0!==a.enabled){var c=TJ(l,"enabled"),d=this._getValue(c);if(!0===d){var u=this._makeLabel(s,l,!0);this._makeItem(l,u),r=this._handleObject(a,l)||r}else this._makeCheckbox(a,d,l)}else{var f=this._makeLabel(s,l,!0);this._makeItem(l,f),r=this._handleObject(a,l)||r}}else console.error("dont know how to handle",a,s,l)}}return r}},{key:"_handleArray",value:function(t,e,i){"string"==typeof t[0]&&"color"===t[0]?(this._makeColorField(t,e,i),t[1]!==e&&this.changedOptions.push({path:i,value:e})):"string"==typeof t[0]?(this._makeDropdown(t,e,i),t[0]!==e&&this.changedOptions.push({path:i,value:e})):"number"==typeof t[0]&&(this._makeRange(t,e,i),t[0]!==e&&this.changedOptions.push({path:i,value:Number(e)}))}},{key:"_update",value:function(t,e){var i=this._constructOptions(t,e);this.parent.body&&this.parent.body.emitter&&this.parent.body.emitter.emit&&this.parent.body.emitter.emit("configChange",i),this.initialized=!0,this.parent.setOptions(i)}},{key:"_constructOptions",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},n=i;t="false"!==(t="true"===t||t)&&t;for(var o=0;oo-this.padding&&(a=!0),r=a?this.x-i:this.x,s=l?this.y-e:this.y}else(s=this.y-e)+e+this.padding>n&&(s=n-e-this.padding),so&&(r=o-i-this.padding),rs.distance?" in "+t.printLocation(r.path,e,"")+"Perhaps it was misplaced? Matching option found at: "+t.printLocation(s.path,s.closestMatch,""):r.distance<=8?'. Did you mean "'+r.closestMatch+'"?'+t.printLocation(r.path,e):". Did you mean one of these: "+t.print(RG(i))+t.printLocation(n,e),console.error('%cUnknown option detected: "'+e+'"'+o,rX),oX=!0}},{key:"findInOptions",value:function(e,i,n){var o,r=arguments.length>3&&void 0!==arguments[3]&&arguments[3],s=1e9,a="",l=[],h=e.toLowerCase(),c=void 0;for(var d in i){var u=void 0;if(void 0!==i[d].__type__&&!0===r){var f=t.findInOptions(e,i[d],TJ(n,d));s>f.distance&&(a=f.closestMatch,l=f.path,s=f.distance,c=f.indexMatch)}else{var p;-1!==Lq(p=d.toLowerCase()).call(p,h)&&(c=d),s>(u=t.levenshteinDistance(e,d))&&(a=d,l=pG(o=n).call(o),s=u)}}return{closestMatch:a,path:l,distance:s,indexMatch:c}}},{key:"printLocation",value:function(t,e){for(var i="\n\n"+(arguments.length>2&&void 0!==arguments[2]?arguments[2]:"Problem value found at: \n")+"options = {\n",n=0;n":!0,"--":!0},mX="",bX=0,wX="",AX="",kX=gX.NULL;function EX(){bX++,wX=mX.charAt(bX)}function CX(){return mX.charAt(bX+1)}function xX(t){var e=t.charCodeAt(0);return e<47?35===e||46===e:e<59?e>47:e<91?e>64:e<96?95===e:e<123&&e>96}function IX(t,e){if(t||(t={}),e)for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function SX(t,e,i){for(var n=e.split("."),o=t;n.length;){var r=n.shift();n.length?(o[r]||(o[r]={}),o=o[r]):o[r]=i}}function MX(t,e){for(var i,n,o=null,r=[t],s=t;s.parent;)r.push(s.parent),s=s.parent;if(s.nodes)for(i=0,n=s.nodes.length;i=0;i--){var a,l=r[i];l.nodes||(l.nodes=[]),-1===Lq(a=l.nodes).call(a,o)&&l.nodes.push(o)}e.attr&&(o.attr=IX(o.attr,e.attr))}function OX(t,e){if(t.edges||(t.edges=[]),t.edges.push(e),t.edge){var i=IX({},t.edge);e.attr=IX(i,e.attr)}}function DX(t,e,i,n,o){var r={from:e,to:i,type:n};return t.edge&&(r.attr=IX({},t.edge)),r.attr=IX(r.attr||{},o),null!=o&&o.hasOwnProperty("arrows")&&null!=o.arrows&&(r.arrows={to:{enabled:!0,type:o.arrows.type}},o.arrows=null),r}function RX(){for(kX=gX.NULL,AX="";" "===wX||"\t"===wX||"\n"===wX||"\r"===wX;)EX();do{var t=!1;if("#"===wX){for(var e=bX-1;" "===mX.charAt(e)||"\t"===mX.charAt(e);)e--;if("\n"===mX.charAt(e)||""===mX.charAt(e)){for(;""!=wX&&"\n"!=wX;)EX();t=!0}}if("/"===wX&&"/"===CX()){for(;""!=wX&&"\n"!=wX;)EX();t=!0}if("/"===wX&&"*"===CX()){for(;""!=wX;){if("*"===wX&&"/"===CX()){EX(),EX();break}EX()}t=!0}for(;" "===wX||"\t"===wX||"\n"===wX||"\r"===wX;)EX()}while(t);if(""!==wX){var i=wX+CX();if(yX[i])return kX=gX.DELIMITER,AX=i,EX(),void EX();if(yX[wX])return kX=gX.DELIMITER,AX=wX,void EX();if(xX(wX)||"-"===wX){for(AX+=wX,EX();xX(wX);)AX+=wX,EX();return"false"===AX?AX=!1:"true"===AX?AX=!0:isNaN(Number(AX))||(AX=Number(AX)),void(kX=gX.IDENTIFIER)}if('"'===wX){for(EX();""!=wX&&('"'!=wX||'"'===wX&&'"'===CX());)'"'===wX?(AX+=wX,EX()):"\\"===wX&&"n"===CX()?(AX+="\n",EX()):AX+=wX,EX();if('"'!=wX)throw NX('End of string " expected');return EX(),void(kX=gX.IDENTIFIER)}for(kX=gX.UNKNOWN;""!=wX;)AX+=wX,EX();throw new SyntaxError('Syntax error in part "'+jX(AX,30)+'"')}kX=gX.DELIMITER}function BX(t){for(;""!==AX&&"}"!=AX;)zX(t),";"===AX&&RX()}function zX(t){var e=PX(t);if(e)FX(t,e);else{var i=function(t){if("node"===AX)return RX(),t.node=TX(),"node";if("edge"===AX)return RX(),t.edge=TX(),"edge";if("graph"===AX)return RX(),t.graph=TX(),"graph";return null}(t);if(!i){if(kX!=gX.IDENTIFIER)throw NX("Identifier expected");var n=AX;if(RX(),"="===AX){if(RX(),kX!=gX.IDENTIFIER)throw NX("Identifier expected");t[n]=AX,RX()}else!function(t,e){var i={id:e},n=TX();n&&(i.attr=n);MX(t,i),FX(t,e)}(t,n)}}}function PX(t){var e=null;if("subgraph"===AX&&((e={}).type="subgraph",RX(),kX===gX.IDENTIFIER&&(e.id=AX,RX())),"{"===AX){if(RX(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,BX(e),"}"!=AX)throw NX("Angle bracket } expected");RX(),delete e.node,delete e.edge,delete e.graph,delete e.parent,t.subgraphs||(t.subgraphs=[]),t.subgraphs.push(e)}return e}function FX(t,e){for(;"->"===AX||"--"===AX;){var i,n=AX;RX();var o=PX(t);if(o)i=o;else{if(kX!=gX.IDENTIFIER)throw NX("Identifier or subgraph expected");MX(t,{id:i=AX}),RX()}OX(t,DX(t,e,i,n,TX())),e=i}}function TX(){for(var t,e,i=null,n={dashed:!0,solid:!1,dotted:[1,5]},o={dot:"circle",box:"box",crow:"crow",curve:"curve",icurve:"inv_curve",normal:"triangle",inv:"inv_triangle",diamond:"diamond",tee:"bar",vee:"vee"},r=new Array,s=new Array;"["===AX;){for(RX(),i={};""!==AX&&"]"!=AX;){if(kX!=gX.IDENTIFIER)throw NX("Attribute name expected");var a=AX;if(RX(),"="!=AX)throw NX("Equal sign = expected");if(RX(),kX!=gX.IDENTIFIER)throw NX("Attribute value expected");var l=AX;"style"===a&&(l=n[l]),"arrowhead"===a&&(a="arrows",l={to:{enabled:!0,type:o[l]}}),"arrowtail"===a&&(a="arrows",l={from:{enabled:!0,type:o[l]}}),r.push({attr:i,name:a,value:l}),s.push(a),RX(),","==AX&&RX()}if("]"!=AX)throw NX("Bracket ] expected");RX()}if(YK(s).call(s,"dir")){var h={arrows:{}};for(t=0;t"===t.type&&(e.arrows="to"),e};YG(o=i.edges).call(o,(function(t){var e,i,o,s,a,l,h;(e=t.from instanceof Object?t.from.nodes:{id:t.from},i=t.to instanceof Object?t.to.nodes:{id:t.to},t.from instanceof Object&&t.from.edges)&&YG(o=t.from.edges).call(o,(function(t){var e=r(t);n.edges.push(e)}));(a=i,l=function(e,i){var o=DX(n,e.id,i.id,t.type,t.attr),s=r(o);n.edges.push(s)},AG(s=e)?YG(s).call(s,(function(t){AG(a)?YG(a).call(a,(function(e){l(t,e)})):l(t,a)})):AG(a)?YG(a).call(a,(function(t){l(s,t)})):l(s,a),t.to instanceof Object&&t.to.edges)&&YG(h=t.to.edges).call(h,(function(t){var e=r(t);n.edges.push(e)}))}))}return i.attr&&(n.options=i.attr),n}var HX=Object.freeze({__proto__:null,cn:{addDescription:"单击空白处放置新节点。",addEdge:"添加连接线",addNode:"添加节点",back:"返回",close:"關閉",createEdgeError:"无法将连接线连接到群集。",del:"删除选定",deleteClusterError:"无法删除群集。",edgeDescription:"单击某个节点并将该连接线拖动到另一个节点以连接它们。",edit:"编辑",editClusterError:"无法编辑群集。",editEdge:"编辑连接线",editEdgeDescription:"单击控制节点并将它们拖到节点上连接。",editNode:"编辑节点"},cs:{addDescription:"Kluknutím do prázdného prostoru můžete přidat nový vrchol.",addEdge:"Přidat hranu",addNode:"Přidat vrchol",back:"Zpět",close:"Zavřít",createEdgeError:"Nelze připojit hranu ke shluku.",del:"Smazat výběr",deleteClusterError:"Nelze mazat shluky.",edgeDescription:"Přetažením z jednoho vrcholu do druhého můžete spojit tyto vrcholy novou hranou.",edit:"Upravit",editClusterError:"Nelze upravovat shluky.",editEdge:"Upravit hranu",editEdgeDescription:"Přetažením kontrolního vrcholu hrany ji můžete připojit k jinému vrcholu.",editNode:"Upravit vrchol"},de:{addDescription:"Klicke auf eine freie Stelle, um einen neuen Knoten zu plazieren.",addEdge:"Kante hinzufügen",addNode:"Knoten hinzufügen",back:"Zurück",close:"Schließen",createEdgeError:"Es ist nicht möglich, Kanten mit Clustern zu verbinden.",del:"Lösche Auswahl",deleteClusterError:"Cluster können nicht gelöscht werden.",edgeDescription:"Klicke auf einen Knoten und ziehe die Kante zu einem anderen Knoten, um diese zu verbinden.",edit:"Editieren",editClusterError:"Cluster können nicht editiert werden.",editEdge:"Kante editieren",editEdgeDescription:"Klicke auf die Verbindungspunkte und ziehe diese auf einen Knoten, um sie zu verbinden.",editNode:"Knoten editieren"},en:{addDescription:"Click in an empty space to place a new node.",addEdge:"Add Edge",addNode:"Add Node",back:"Back",close:"Close",createEdgeError:"Cannot link edges to a cluster.",del:"Delete selected",deleteClusterError:"Clusters cannot be deleted.",edgeDescription:"Click on a node and drag the edge to another node to connect them.",edit:"Edit",editClusterError:"Clusters cannot be edited.",editEdge:"Edit Edge",editEdgeDescription:"Click on the control points and drag them to a node to connect to it.",editNode:"Edit Node"},es:{addDescription:"Haga clic en un lugar vacío para colocar un nuevo nodo.",addEdge:"Añadir arista",addNode:"Añadir nodo",back:"Atrás",close:"Cerrar",createEdgeError:"No se puede conectar una arista a un grupo.",del:"Eliminar selección",deleteClusterError:"No es posible eliminar grupos.",edgeDescription:"Haga clic en un nodo y arrastre la arista hacia otro nodo para conectarlos.",edit:"Editar",editClusterError:"No es posible editar grupos.",editEdge:"Editar arista",editEdgeDescription:"Haga clic en un punto de control y arrastrelo a un nodo para conectarlo.",editNode:"Editar nodo"},fr:{addDescription:"Cliquez dans un endroit vide pour placer un nœud.",addEdge:"Ajouter un lien",addNode:"Ajouter un nœud",back:"Retour",close:"Fermer",createEdgeError:"Impossible de créer un lien vers un cluster.",del:"Effacer la sélection",deleteClusterError:"Les clusters ne peuvent pas être effacés.",edgeDescription:"Cliquez sur un nœud et glissez le lien vers un autre nœud pour les connecter.",edit:"Éditer",editClusterError:"Les clusters ne peuvent pas être édités.",editEdge:"Éditer le lien",editEdgeDescription:"Cliquez sur les points de contrôle et glissez-les pour connecter un nœud.",editNode:"Éditer le nœud"},it:{addDescription:"Clicca per aggiungere un nuovo nodo",addEdge:"Aggiungi un vertice",addNode:"Aggiungi un nodo",back:"Indietro",close:"Chiudere",createEdgeError:"Non si possono collegare vertici ad un cluster",del:"Cancella la selezione",deleteClusterError:"I cluster non possono essere cancellati",edgeDescription:"Clicca su un nodo e trascinalo ad un altro nodo per connetterli.",edit:"Modifica",editClusterError:"I clusters non possono essere modificati.",editEdge:"Modifica il vertice",editEdgeDescription:"Clicca sui Punti di controllo e trascinali ad un nodo per connetterli.",editNode:"Modifica il nodo"},nl:{addDescription:"Klik op een leeg gebied om een nieuwe node te maken.",addEdge:"Link toevoegen",addNode:"Node toevoegen",back:"Terug",close:"Sluiten",createEdgeError:"Kan geen link maken naar een cluster.",del:"Selectie verwijderen",deleteClusterError:"Clusters kunnen niet worden verwijderd.",edgeDescription:"Klik op een node en sleep de link naar een andere node om ze te verbinden.",edit:"Wijzigen",editClusterError:"Clusters kunnen niet worden aangepast.",editEdge:"Link wijzigen",editEdgeDescription:"Klik op de verbindingspunten en sleep ze naar een node om daarmee te verbinden.",editNode:"Node wijzigen"},pt:{addDescription:"Clique em um espaço em branco para adicionar um novo nó",addEdge:"Adicionar aresta",addNode:"Adicionar nó",back:"Voltar",close:"Fechar",createEdgeError:"Não foi possível linkar arestas a um cluster.",del:"Remover selecionado",deleteClusterError:"Clusters não puderam ser removidos.",edgeDescription:"Clique em um nó e arraste a aresta até outro nó para conectá-los",edit:"Editar",editClusterError:"Clusters não puderam ser editados.",editEdge:"Editar aresta",editEdgeDescription:"Clique nos pontos de controle e os arraste para um nó para conectá-los",editNode:"Editar nó"},ru:{addDescription:"Кликните в свободное место, чтобы добавить новый узел.",addEdge:"Добавить ребро",addNode:"Добавить узел",back:"Назад",close:"Закрывать",createEdgeError:"Невозможно соединить ребра в кластер.",del:"Удалить выбранное",deleteClusterError:"Кластеры не могут быть удалены",edgeDescription:"Кликните на узел и протяните ребро к другому узлу, чтобы соединить их.",edit:"Редактировать",editClusterError:"Кластеры недоступны для редактирования.",editEdge:"Редактировать ребро",editEdgeDescription:"Кликните на контрольные точки и перетащите их в узел, чтобы подключиться к нему.",editNode:"Редактировать узел"},uk:{addDescription:"Kлікніть на вільне місце, щоб додати новий вузол.",addEdge:"Додати край",addNode:"Додати вузол",back:"Назад",close:"Закрити",createEdgeError:"Не можливо об'єднати краї в групу.",del:"Видалити обране",deleteClusterError:"Групи не можуть бути видалені.",edgeDescription:"Клікніть на вузол і перетягніть край до іншого вузла, щоб їх з'єднати.",edit:"Редагувати",editClusterError:"Групи недоступні для редагування.",editEdge:"Редагувати край",editEdgeDescription:"Клікніть на контрольні точки і перетягніть їх у вузол, щоб підключитися до нього.",editNode:"Редагувати вузол"}});var VX=function(){function t(){uU(this,t),this.NUM_ITERATIONS=4,this.image=new Image,this.canvas=document.createElement("canvas")}return yW(t,[{key:"init",value:function(){if(!this.initialized()){this.src=this.image.src;var t=this.image.width,e=this.image.height;this.width=t,this.height=e;var i=Math.floor(e/2),n=Math.floor(e/4),o=Math.floor(e/8),r=Math.floor(e/16),s=Math.floor(t/2),a=Math.floor(t/4),l=Math.floor(t/8),h=Math.floor(t/16);this.canvas.width=3*a,this.canvas.height=i,this.coordinates=[[0,0,s,i],[s,0,a,n],[s,n,l,o],[5*l,n,h,r]],this._fillMipMap()}}},{key:"initialized",value:function(){return void 0!==this.coordinates}},{key:"_fillMipMap",value:function(){var t=this.canvas.getContext("2d"),e=this.coordinates[0];t.drawImage(this.image,e[0],e[1],e[2],e[3]);for(var i=1;i2){e*=.5;for(var s=0;e>2&&s=this.NUM_ITERATIONS&&(s=this.NUM_ITERATIONS-1);var a=this.coordinates[s];t.drawImage(this.canvas,a[0],a[1],a[2],a[3],i,n,o,r)}else t.drawImage(this.image,i,n,o,r)}}]),t}(),WX=function(){function t(e){uU(this,t),this.images={},this.imageBroken={},this.callback=e}return yW(t,[{key:"_tryloadBrokenUrl",value:function(t,e,i){void 0!==t&&void 0!==i&&(void 0!==e?(i.image.onerror=function(){console.error("Could not load brokenImage:",e)},i.image.src=e):console.warn("No broken url image defined"))}},{key:"_redrawWithImage",value:function(t){this.callback&&this.callback(t)}},{key:"load",value:function(t,e){var i=this,n=this.images[t];if(n)return n;var o=new VX;return this.images[t]=o,o.image.onload=function(){i._fixImageCoordinates(o.image),o.init(),i._redrawWithImage(o)},o.image.onerror=function(){console.error("Could not load image:",t),i._tryloadBrokenUrl(t,e,o)},o.image.src=t,o}},{key:"_fixImageCoordinates",value:function(t){0===t.width&&(document.body.appendChild(t),t.width=t.offsetWidth,t.height=t.offsetHeight,document.body.removeChild(t))}}]),t}(),GX={exports:{}},KX=sR((function(){if("function"==typeof ArrayBuffer){var t=new ArrayBuffer(8);Object.isExtensible(t)&&Object.defineProperty(t,"a",{value:8})}})),qX=sR,YX=eB,ZX=AR,JX=KX,XX=Object.isExtensible,_X=qX((function(){XX(1)}))||JX?function(t){return!!YX(t)&&((!JX||"ArrayBuffer"!==ZX(t))&&(!XX||XX(t)))}:XX,$X=!sR((function(){return Object.isExtensible(Object.preventExtensions({}))})),t_=OP,e_=yR,i_=YP,n_=eB,o_=$B,r_=_z.f,s_=JU,a_=$U,l_=_X,h_=$X,c_=!1,d_=oz("meta"),u_=0,f_=function(t){r_(t,d_,{value:{objectID:"O"+u_++,weakData:{}}})},p_=GX.exports={enable:function(){p_.enable=function(){},c_=!0;var t=s_.f,e=e_([].splice),i={};i[d_]=1,t(i).length&&(s_.f=function(i){for(var n=t(i),o=0,r=n.length;or;r++)if((a=y(t[r]))&&k_(M_,a))return a;return new S_(!1)}n=E_(t,o)}for(l=u?t.next:n.next;!(h=y_(l,n)).done;){try{a=y(h.value)}catch(t){x_(n,"throw",t)}if("object"==typeof a&&a&&k_(M_,a))return a}return new S_(!1)},D_=lB,R_=TypeError,B_=function(t,e){if(D_(e,t))return t;throw new R_("Incorrect invocation")},z_=OP,P_=rR,F_=v_,T_=sR,N_=yP,j_=O_,L_=B_,U_=MR,Q_=eB,H_=KR,V_=YN,W_=_z.f,G_=BQ.forEach,K_=DR,q_=UT.set,Y_=UT.getterFor,Z_=function(t,e,i){var n,o=-1!==t.indexOf("Map"),r=-1!==t.indexOf("Weak"),s=o?"set":"add",a=P_[t],l=a&&a.prototype,h={};if(K_&&U_(a)&&(r||l.forEach&&!T_((function(){(new a).entries().next()})))){var c=(n=e((function(e,i){q_(L_(e,c),{type:t,collection:new a}),H_(i)||j_(i,e[s],{that:e,AS_ENTRIES:o})}))).prototype,d=Y_(t);G_(["add","clear","delete","forEach","get","has","set","keys","values","entries"],(function(t){var e="add"===t||"set"===t;!(t in l)||r&&"clear"===t||N_(c,t,(function(i,n){var o=d(this).collection;if(!e&&r&&!Q_(i))return"get"===t&&void 0;var s=o[t](0===i?0:i,n);return e?this:s}))})),r||W_(c,"size",{configurable:!0,get:function(){return d(this).collection.size}})}else n=i.getConstructor(e,t,o,s),F_.enable();return V_(n,t,!1,!0),h[t]=n,z_({global:!0,forced:!0},h),r||i.setStrong(n,t,o),n},J_=ON,X_=function(t,e,i){for(var n in e)i&&i.unsafe&&t[n]?t[n]=e[n]:J_(t,n,e[n],i);return t},__=aB,$_=uQ,t$=DR,e$=fz("species"),i$=mN,n$=uQ,o$=X_,r$=Xz,s$=B_,a$=KR,l$=O_,h$=xj,c$=Ij,d$=function(t){var e=__(t);t$&&e&&!e[e$]&&$_(e,e$,{configurable:!0,get:function(){return this}})},u$=DR,f$=v_.fastKey,p$=UT.set,v$=UT.getterFor,g$={getConstructor:function(t,e,i,n){var o=t((function(t,o){s$(t,r),p$(t,{type:e,index:i$(null),first:void 0,last:void 0,size:0}),u$||(t.size=0),a$(o)||l$(o,t[n],{that:t,AS_ENTRIES:i})})),r=o.prototype,s=v$(e),a=function(t,e,i){var n,o,r=s(t),a=l(t,e);return a?a.value=i:(r.last=a={index:o=f$(e,!0),key:e,value:i,previous:n=r.last,next:void 0,removed:!1},r.first||(r.first=a),n&&(n.next=a),u$?r.size++:t.size++,"F"!==o&&(r.index[o]=a)),t},l=function(t,e){var i,n=s(t),o=f$(e);if("F"!==o)return n.index[o];for(i=n.first;i;i=i.next)if(i.key===e)return i};return o$(r,{clear:function(){for(var t=s(this),e=t.index,i=t.first;i;)i.removed=!0,i.previous&&(i.previous=i.previous.next=void 0),delete e[i.index],i=i.next;t.first=t.last=void 0,u$?t.size=0:this.size=0},delete:function(t){var e=this,i=s(e),n=l(e,t);if(n){var o=n.next,r=n.previous;delete i.index[n.index],n.removed=!0,r&&(r.next=o),o&&(o.previous=r),i.first===n&&(i.first=o),i.last===n&&(i.last=r),u$?i.size--:e.size--}return!!n},forEach:function(t){for(var e,i=s(this),n=r$(t,arguments.length>1?arguments[1]:void 0);e=e?e.next:i.first;)for(n(e.value,e.key,this);e&&e.removed;)e=e.previous},has:function(t){return!!l(this,t)}}),o$(r,i?{get:function(t){var e=l(this,t);return e&&e.value},set:function(t,e){return a(this,0===t?0:t,e)}}:{add:function(t){return a(this,t=0===t?0:t,t)}}),u$&&n$(r,"size",{configurable:!0,get:function(){return s(this).size}}),o},setStrong:function(t,e,i){var n=e+" Iterator",o=v$(e),r=v$(n);h$(t,e,(function(t,e){p$(this,{type:n,target:t,state:o(t),kind:e,last:void 0})}),(function(){for(var t=r(this),e=t.kind,i=t.last;i&&i.removed;)i=i.previous;return t.target&&(t.last=i=i?i.next:t.state.first)?c$("keys"===e?i.key:"values"===e?i.value:[i.key,i.value],!1):(t.target=void 0,c$(void 0,!0))}),i?"entries":"values",!i,!0),d$(e)}};Z_("Map",(function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}}),g$);var y$=nR(iB.Map),m$=function(){function t(){uU(this,t),this.clear(),this._defaultIndex=0,this._groupIndex=0,this._defaultGroups=[{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"},hover:{border:"#2B7CE9",background:"#D2E5FF"}},{border:"#FFA500",background:"#FFFF00",highlight:{border:"#FFA500",background:"#FFFFA3"},hover:{border:"#FFA500",background:"#FFFFA3"}},{border:"#FA0A10",background:"#FB7E81",highlight:{border:"#FA0A10",background:"#FFAFB1"},hover:{border:"#FA0A10",background:"#FFAFB1"}},{border:"#41A906",background:"#7BE141",highlight:{border:"#41A906",background:"#A1EC76"},hover:{border:"#41A906",background:"#A1EC76"}},{border:"#E129F0",background:"#EB7DF4",highlight:{border:"#E129F0",background:"#F0B3F5"},hover:{border:"#E129F0",background:"#F0B3F5"}},{border:"#7C29F0",background:"#AD85E4",highlight:{border:"#7C29F0",background:"#D3BDF0"},hover:{border:"#7C29F0",background:"#D3BDF0"}},{border:"#C37F00",background:"#FFA807",highlight:{border:"#C37F00",background:"#FFCA66"},hover:{border:"#C37F00",background:"#FFCA66"}},{border:"#4220FB",background:"#6E6EFD",highlight:{border:"#4220FB",background:"#9B9BFD"},hover:{border:"#4220FB",background:"#9B9BFD"}},{border:"#FD5A77",background:"#FFC0CB",highlight:{border:"#FD5A77",background:"#FFD1D9"},hover:{border:"#FD5A77",background:"#FFD1D9"}},{border:"#4AD63A",background:"#C2FABC",highlight:{border:"#4AD63A",background:"#E6FFE3"},hover:{border:"#4AD63A",background:"#E6FFE3"}},{border:"#990000",background:"#EE0000",highlight:{border:"#BB0000",background:"#FF3333"},hover:{border:"#BB0000",background:"#FF3333"}},{border:"#FF6000",background:"#FF6000",highlight:{border:"#FF6000",background:"#FF6000"},hover:{border:"#FF6000",background:"#FF6000"}},{border:"#97C2FC",background:"#2B7CE9",highlight:{border:"#D2E5FF",background:"#2B7CE9"},hover:{border:"#D2E5FF",background:"#2B7CE9"}},{border:"#399605",background:"#255C03",highlight:{border:"#399605",background:"#255C03"},hover:{border:"#399605",background:"#255C03"}},{border:"#B70054",background:"#FF007E",highlight:{border:"#B70054",background:"#FF007E"},hover:{border:"#B70054",background:"#FF007E"}},{border:"#AD85E4",background:"#7C29F0",highlight:{border:"#D3BDF0",background:"#7C29F0"},hover:{border:"#D3BDF0",background:"#7C29F0"}},{border:"#4557FA",background:"#000EA1",highlight:{border:"#6E6EFD",background:"#000EA1"},hover:{border:"#6E6EFD",background:"#000EA1"}},{border:"#FFC0CB",background:"#FD5A77",highlight:{border:"#FFD1D9",background:"#FD5A77"},hover:{border:"#FFD1D9",background:"#FD5A77"}},{border:"#C2FABC",background:"#74D66A",highlight:{border:"#E6FFE3",background:"#74D66A"},hover:{border:"#E6FFE3",background:"#74D66A"}},{border:"#EE0000",background:"#990000",highlight:{border:"#FF3333",background:"#BB0000"},hover:{border:"#FF3333",background:"#BB0000"}}],this.options={},this.defaultOptions={useDefaultGroups:!0},wF(this.options,this.defaultOptions)}return yW(t,[{key:"setOptions",value:function(t){var e=["useDefaultGroups"];if(void 0!==t)for(var i in t)if(Object.prototype.hasOwnProperty.call(t,i)&&-1===Lq(e).call(e,i)){var n=t[i];this.add(i,n)}}},{key:"clear",value:function(){this._groups=new y$,this._groupNames=[]}},{key:"get",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=this._groups.get(t);if(void 0===i&&e)if(!1===this.options.useDefaultGroups&&this._groupNames.length>0){var n=this._groupIndex%this._groupNames.length;++this._groupIndex,(i={}).color=this._groups.get(this._groupNames[n]),this._groups.set(t,i)}else{var o=this._defaultIndex%this._defaultGroups.length;this._defaultIndex++,(i={}).color=this._defaultGroups[o],this._groups.set(t,i)}return i}},{key:"add",value:function(t,e){return this._groups.has(t)||this._groupNames.push(t),this._groups.set(t,e),e}}]),t}();OP({target:"Number",stat:!0},{isNaN:function(t){return t!=t}});var b$=nR(iB.Number.isNaN),w$=rR.isFinite,A$=Number.isFinite||function(t){return"number"==typeof t&&w$(t)};OP({target:"Number",stat:!0},{isFinite:A$});var k$=nR(iB.Number.isFinite),E$=BQ.some;OP({target:"Array",proto:!0,forced:!NG("some")},{some:function(t){return E$(this,t,arguments.length>1?arguments[1]:void 0)}});var C$=FF("Array").some,x$=lB,I$=C$,S$=Array.prototype,M$=function(t){var e=t.some;return t===S$||x$(S$,t)&&e===S$.some?I$:e},O$=nR(M$),D$=nR(iB.Object.getOwnPropertySymbols),R$={exports:{}},B$=OP,z$=sR,P$=_R,F$=OR.f,T$=DR;B$({target:"Object",stat:!0,forced:!T$||z$((function(){F$(1)})),sham:!T$},{getOwnPropertyDescriptor:function(t,e){return F$(P$(t),e)}});var N$=iB.Object,j$=R$.exports=function(t,e){return N$.getOwnPropertyDescriptor(t,e)};N$.getOwnPropertyDescriptor.sham&&(j$.sham=!0);var L$=R$.exports,U$=nR(L$),Q$=wG,H$=_R,V$=OR,W$=uL;OP({target:"Object",stat:!0,sham:!DR},{getOwnPropertyDescriptors:function(t){for(var e,i,n=H$(t),o=V$.f,r=Q$(n),s={},a=0;r.length>a;)void 0!==(i=o(n,e=r[a++]))&&W$(s,e,i);return s}});var G$=nR(iB.Object.getOwnPropertyDescriptors),K$={exports:{}},q$=OP,Y$=DR,Z$=qT.f;q$({target:"Object",stat:!0,forced:Object.defineProperties!==Z$,sham:!Y$},{defineProperties:Z$});var J$=iB.Object,X$=K$.exports=function(t,e){return J$.defineProperties(t,e)};J$.defineProperties.sham&&(X$.sham=!0);var _$=nR(K$.exports),$$=nR(bU);function t0(t,e,i){return(e=vW(e))in t?wU(t,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[e]=i,t}var e0=rR,i0=sR,n0=dT,o0=vq.trim,r0=aq,s0=yR("".charAt),a0=e0.parseFloat,l0=e0.Symbol,h0=l0&&l0.iterator,c0=1/a0(r0+"-0")!=-1/0||h0&&!i0((function(){a0(Object(h0))}))?function(t){var e=o0(n0(t)),i=a0(e);return 0===i&&"-"===s0(e,0)?-0:i}:a0;OP({global:!0,forced:parseFloat!==c0},{parseFloat:c0});var d0=nR(iB.parseFloat),u0=OP,f0=sR,p0=$U.f;u0({target:"Object",stat:!0,forced:f0((function(){return!Object.getOwnPropertyNames(1)}))},{getOwnPropertyNames:p0});var v0=iB.Object,g0=function(t){return v0.getOwnPropertyNames(t)},y0=nR(g0);function m0(t,e){var i=["node","edge","label"],n=!0,o=XJ(e,"chosen");if("boolean"==typeof o)n=o;else if("object"===fW(o)){if(-1===Lq(i).call(i,t))throw new Error("choosify: subOption '"+t+"' should be one of '"+i.join("', '")+"'");var r=XJ(e,["chosen",t]);"boolean"!=typeof r&&"function"!=typeof r||(n=r)}return n}function b0(t,e,i){if(t.width<=0||t.height<=0)return!1;if(void 0!==i){var n={x:e.x-i.x,y:e.y-i.y};if(0!==i.angle){var o=-i.angle;e={x:Math.cos(o)*n.x-Math.sin(o)*n.y,y:Math.sin(o)*n.x+Math.cos(o)*n.y}}else e=n}var r=t.x+t.width,s=t.y+t.width;return t.lefte.x&&t.tope.y}function w0(t){return"string"==typeof t&&""!==t}function A0(t,e,i,n){var o=n.x,r=n.y;if("function"==typeof n.distanceToBorder){var s=n.distanceToBorder(t,e),a=Math.sin(e)*s,l=Math.cos(e)*s;l===s?(o+=s,r=n.y):a===s?(o=n.x,r-=s):(o+=l,r-=a)}else n.shape.width>n.shape.height?(o=n.x+.5*n.shape.width,r=n.y-i):(o=n.x+i,r=n.y-.5*n.shape.height);return{x:o,y:r}}var k0=FF("Array").values,E0=lT,C0=$B,x0=lB,I0=k0,S0=Array.prototype,M0={DOMTokenList:!0,NodeList:!0},O0=function(t){var e=t.values;return t===S0||x0(S0,t)&&e===S0.values||C0(M0,E0(t))?I0:e},D0=nR(O0),R0=function(){function t(e){uU(this,t),this.measureText=e,this.current=0,this.width=0,this.height=0,this.lines=[]}return yW(t,[{key:"_add",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"normal";void 0===this.lines[t]&&(this.lines[t]={width:0,height:0,blocks:[]});var n=e;void 0!==e&&""!==e||(n=" ");var o=this.measureText(n,i),r=wF({},D0(o));r.text=e,r.width=o.width,r.mod=i,void 0!==e&&""!==e||(r.width=0),this.lines[t].blocks.push(r),this.lines[t].width+=r.width}},{key:"curWidth",value:function(){var t=this.lines[this.current];return void 0===t?0:t.width}},{key:"append",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"normal";this._add(this.current,t,e)}},{key:"newLine",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"normal";this._add(this.current,t,e),this.current++}},{key:"determineLineHeights",value:function(){for(var t=0;tt&&(t=n.width),e+=n.height}this.width=t,this.height=e}},{key:"removeEmptyBlocks",value:function(){for(var t=[],e=0;e"://,""://,""://,"":/<\/b>/,"":/<\/i>/,"":/<\/code>/,"*":/\*/,_:/_/,"`":/`/,afterBold:/[^*]/,afterItal:/[^_]/,afterMono:/[^`]/},z0=function(){function t(e){uU(this,t),this.text=e,this.bold=!1,this.ital=!1,this.mono=!1,this.spacing=!1,this.position=0,this.buffer="",this.modStack=[],this.blocks=[]}return yW(t,[{key:"mod",value:function(){return 0===this.modStack.length?"normal":this.modStack[0]}},{key:"modName",value:function(){return 0===this.modStack.length?"normal":"mono"===this.modStack[0]?"mono":this.bold&&this.ital?"boldital":this.bold?"bold":this.ital?"ital":void 0}},{key:"emitBlock",value:function(){this.spacing&&(this.add(" "),this.spacing=!1),this.buffer.length>0&&(this.blocks.push({text:this.buffer,mod:this.modName()}),this.buffer="")}},{key:"add",value:function(t){" "===t&&(this.spacing=!0),this.spacing&&(this.buffer+=" ",this.spacing=!1)," "!=t&&(this.buffer+=t)}},{key:"parseWS",value:function(t){return!!/[ \t]/.test(t)&&(this.mono?this.add(t):this.spacing=!0,!0)}},{key:"setTag",value:function(t){this.emitBlock(),this[t]=!0,this.modStack.unshift(t)}},{key:"unsetTag",value:function(t){this.emitBlock(),this[t]=!1,this.modStack.shift()}},{key:"parseStartTag",value:function(t,e){return!(this.mono||this[t]||!this.match(e))&&(this.setTag(t),!0)}},{key:"match",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=rG(this.prepareRegExp(t),2),n=i[0],o=i[1],r=n.test(this.text.substr(this.position,o));return r&&e&&(this.position+=o-1),r}},{key:"parseEndTag",value:function(t,e,i){var n=this.mod()===t;return!(!(n="mono"===t?n&&this.mono:n&&!this.mono)||!this.match(e))&&(void 0!==i?(this.position===this.text.length-1||this.match(i,!1))&&this.unsetTag(t):this.unsetTag(t),!0)}},{key:"replace",value:function(t,e){return!!this.match(t)&&(this.add(e),this.position+=length-1,!0)}},{key:"prepareRegExp",value:function(t){var e,i;if(t instanceof RegExp)i=t,e=1;else{var n=B0[t];i=void 0!==n?n:new RegExp(t),e=t.length}return[i,e]}}]),t}(),P0=function(){function t(e,i,n,o){var r=this;uU(this,t),this.ctx=e,this.parent=i,this.selected=n,this.hover=o;this.lines=new R0((function(t,i){if(void 0===t)return 0;var s=r.parent.getFormattingValues(e,n,o,i),a=0;""!==t&&(a=r.ctx.measureText(t).width);return{width:a,values:s}}))}return yW(t,[{key:"process",value:function(t){if(!w0(t))return this.lines.finalize();var e=this.parent.fontOptions;t=(t=t.replace(/\r\n/g,"\n")).replace(/\r/g,"\n");var i=String(t).split("\n"),n=i.length;if(e.multi)for(var o=0;o0)for(var s=0;s0)for(var u=0;u")||e.parseStartTag("ital","")||e.parseStartTag("mono","")||e.parseEndTag("bold","")||e.parseEndTag("ital","")||e.parseEndTag("mono",""))||i(n)||e.add(n),e.position++}return e.emitBlock(),e.blocks}},{key:"splitMarkdownBlocks",value:function(t){for(var e=this,i=new z0(t),n=!0,o=function(t){return!!/\\/.test(t)&&(i.positionthis.parent.fontOptions.maxWdt}},{key:"getLongestFit",value:function(t){for(var e="",i=0;i1&&void 0!==arguments[1]?arguments[1]:"normal",i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];this.parent.getFormattingValues(this.ctx,this.selected,this.hover,e);for(var n=(t=(t=t.replace(/^( +)/g,"$1\r")).replace(/([^\r][^ ]*)( +)/g,"$1\r$2\r")).split("\r");n.length>0;){var o=this.getLongestFit(n);if(0===o){var r=n[0],s=this.getLongestFitWord(r);this.lines.newLine(pG(r).call(r,0,s),e),n[0]=pG(r).call(r,s)}else{var a=o;" "===n[o-1]?o--:" "===n[a]&&a++;var l=pG(n).call(n,0,o).join("");o==n.length&&i?this.lines.append(l,e):this.lines.newLine(l,e),n=pG(n).call(n,a)}}}}]),t}(),F0=["bold","ital","boldital","mono"],T0=function(){function t(e,i){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];uU(this,t),this.body=e,this.pointToSelf=!1,this.baseSize=void 0,this.fontOptions={},this.setOptions(i),this.size={top:0,left:0,width:0,height:0,yLine:0},this.isEdgeLabel=n}return yW(t,[{key:"setOptions",value:function(t){if(this.elementOptions=t,this.initFontOptions(t.font),w0(t.label)?this.labelDirty=!0:t.label=void 0,void 0!==t.font&&null!==t.font)if("string"==typeof t.font)this.baseSize=this.fontOptions.size;else if("object"===fW(t.font)){var e=t.font.size;void 0!==e&&(this.baseSize=e)}}},{key:"initFontOptions",value:function(e){var i=this;jJ(F0,(function(t){i.fontOptions[t]={}})),t.parseFontString(this.fontOptions,e)?this.fontOptions.vadjust=0:jJ(e,(function(t,e){null!=t&&"object"!==fW(t)&&(i.fontOptions[e]=t)}))}},{key:"constrain",value:function(t){var e={constrainWidth:!1,maxWdt:-1,minWdt:-1,constrainHeight:!1,minHgt:-1,valign:"middle"},i=XJ(t,"widthConstraint");if("number"==typeof i)e.maxWdt=Number(i),e.minWdt=Number(i);else if("object"===fW(i)){var n=XJ(t,["widthConstraint","maximum"]);"number"==typeof n&&(e.maxWdt=Number(n));var o=XJ(t,["widthConstraint","minimum"]);"number"==typeof o&&(e.minWdt=Number(o))}var r=XJ(t,"heightConstraint");if("number"==typeof r)e.minHgt=Number(r);else if("object"===fW(r)){var s=XJ(t,["heightConstraint","minimum"]);"number"==typeof s&&(e.minHgt=Number(s));var a=XJ(t,["heightConstraint","valign"]);"string"==typeof a&&("top"!==a&&"bottom"!==a||(e.valign=a))}return e}},{key:"update",value:function(t,e){this.setOptions(t,!0),this.propagateFonts(e),FJ(this.fontOptions,this.constrain(e)),this.fontOptions.chooser=m0("label",e)}},{key:"adjustSizes",value:function(t){var e=t?t.right+t.left:0;this.fontOptions.constrainWidth&&(this.fontOptions.maxWdt-=e,this.fontOptions.minWdt-=e);var i=t?t.top+t.bottom:0;this.fontOptions.constrainHeight&&(this.fontOptions.minHgt-=i)}},{key:"addFontOptionsToPile",value:function(t,e){for(var i=0;i5&&void 0!==arguments[5]?arguments[5]:"middle";if(void 0!==this.elementOptions.label){var s=this.fontOptions.size*this.body.view.scale;this.elementOptions.label&&s=this.elementOptions.scaling.label.maxVisible&&(s=Number(this.elementOptions.scaling.label.maxVisible)/this.body.view.scale),this.calculateLabelSize(t,n,o,e,i,r),this._drawBackground(t),this._drawText(t,e,this.size.yLine,r,s))}}},{key:"_drawBackground",value:function(t){if(void 0!==this.fontOptions.background&&"none"!==this.fontOptions.background){t.fillStyle=this.fontOptions.background;var e=this.getSize();t.fillRect(e.left,e.top,e.width,e.height)}}},{key:"_drawText",value:function(t,e,i){var n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"middle",o=arguments.length>4?arguments[4]:void 0,r=rG(this._setAlignment(t,e,i,n),2);e=r[0],i=r[1],t.textAlign="left",e-=this.size.width/2,this.fontOptions.valign&&this.size.height>this.size.labelHeight&&("top"===this.fontOptions.valign&&(i-=(this.size.height-this.size.labelHeight)/2),"bottom"===this.fontOptions.valign&&(i+=(this.size.height-this.size.labelHeight)/2));for(var s=0;s0&&(t.lineWidth=c.strokeWidth,t.strokeStyle=f,t.lineJoin="round"),t.fillStyle=u,c.strokeWidth>0&&t.strokeText(c.text,e+l,i+c.vadjust),t.fillText(c.text,e+l,i+c.vadjust),l+=c.width}i+=a.height}}}},{key:"_setAlignment",value:function(t,e,i,n){if(this.isEdgeLabel&&"horizontal"!==this.fontOptions.align&&!1===this.pointToSelf){e=0,i=0;"top"===this.fontOptions.align?(t.textBaseline="alphabetic",i-=4):"bottom"===this.fontOptions.align?(t.textBaseline="hanging",i+=4):t.textBaseline="middle"}else t.textBaseline=n;return[e,i]}},{key:"_getColor",value:function(t,e,i){var n=t||"#000000",o=i||"#ffffff";if(e<=this.elementOptions.scaling.label.drawThreshold){var r=Math.max(0,Math.min(1,1-(this.elementOptions.scaling.label.drawThreshold-e)));n=UJ(n,r),o=UJ(o,r)}return[n,o]}},{key:"getTextSize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return this._processLabel(t,e,i),{width:this.size.width,height:this.size.height,lineCount:this.lineCount}}},{key:"getSize",value:function(){var t=this.size.left,e=this.size.top-1;if(this.isEdgeLabel){var i=.5*-this.size.width;switch(this.fontOptions.align){case"middle":t=i,e=.5*-this.size.height;break;case"top":t=i,e=-(this.size.height+2);break;case"bottom":t=i,e=2}}return{left:t,top:e,width:this.size.width,height:this.size.height}}},{key:"calculateLabelSize",value:function(t,e,i){var n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,o=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,r=arguments.length>5&&void 0!==arguments[5]?arguments[5]:"middle";this._processLabel(t,e,i),this.size.left=n-.5*this.size.width,this.size.top=o-.5*this.size.height,this.size.yLine=o+.5*(1-this.lineCount)*this.fontOptions.size,"hanging"===r&&(this.size.top+=.5*this.fontOptions.size,this.size.top+=4,this.size.yLine+=4)}},{key:"getFormattingValues",value:function(t,e,i,n){var o=function(t,e,i){return"normal"===e?"mod"===i?"":t[i]:void 0!==t[e][i]?t[e][i]:t[i]},r={color:o(this.fontOptions,n,"color"),size:o(this.fontOptions,n,"size"),face:o(this.fontOptions,n,"face"),mod:o(this.fontOptions,n,"mod"),vadjust:o(this.fontOptions,n,"vadjust"),strokeWidth:this.fontOptions.strokeWidth,strokeColor:this.fontOptions.strokeColor};(e||i)&&("normal"===n&&!0===this.fontOptions.chooser&&this.elementOptions.labelHighlightBold?r.mod="bold":"function"==typeof this.fontOptions.chooser&&this.fontOptions.chooser(r,this.elementOptions.id,e,i));var s="";return void 0!==r.mod&&""!==r.mod&&(s+=r.mod+" "),s+=r.size+"px "+r.face,t.font=s.replace(/"/g,""),r.font=t.font,r.height=r.size,r}},{key:"differentState",value:function(t,e){return t!==this.selectedState||e!==this.hoverState}},{key:"_processLabelText",value:function(t,e,i,n){return new P0(t,this,e,i).process(n)}},{key:"_processLabel",value:function(t,e,i){if(!1!==this.labelDirty||this.differentState(e,i)){var n=this._processLabelText(t,e,i,this.elementOptions.label);this.fontOptions.minWdt>0&&n.width0&&n.height0&&(this.enableBorderDashes(t,e),t.stroke(),this.disableBorderDashes(t,e)),t.restore()}},{key:"performFill",value:function(t,e){t.save(),t.fillStyle=e.color,this.enableShadow(t,e),EY(t).call(t),this.disableShadow(t,e),t.restore(),this.performStroke(t,e)}},{key:"_addBoundingBoxMargin",value:function(t){this.boundingBox.left-=t,this.boundingBox.top-=t,this.boundingBox.bottom+=t,this.boundingBox.right+=t}},{key:"_updateBoundingBox",value:function(t,e,i,n,o){void 0!==i&&this.resize(i,n,o),this.left=t-this.width/2,this.top=e-this.height/2,this.boundingBox.left=this.left,this.boundingBox.top=this.top,this.boundingBox.bottom=this.top+this.height,this.boundingBox.right=this.left+this.width}},{key:"updateBoundingBox",value:function(t,e,i,n,o){this._updateBoundingBox(t,e,i,n,o)}},{key:"getDimensionsFromLabel",value:function(t,e,i){this.textSize=this.labelModule.getTextSize(t,e,i);var n=this.textSize.width,o=this.textSize.height;return 0===n&&(n=14,o=14),{width:n,height:o}}}]),t}();function c1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var d1=function(t){r1(i,t);var e=c1(i);function i(t,n,o){var r;return uU(this,i),(r=e.call(this,t,n,o))._setMargins(o),r}return yW(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(this.needsRefresh(e,i)){var n=this.getDimensionsFromLabel(t,e,i);this.width=n.width+this.margin.right+this.margin.left,this.height=n.height+this.margin.top+this.margin.bottom,this.radius=this.width/2}}},{key:"draw",value:function(t,e,i,n,o,r){this.resize(t,n,o),this.left=e-this.width/2,this.top=i-this.height/2,this.initContextForDraw(t,r),WF(t,this.left,this.top,this.width,this.height,r.borderRadius),this.performFill(t,r),this.updateBoundingBox(e,i,t,n,o),this.labelModule.draw(t,this.left+this.textSize.width/2+this.margin.left,this.top+this.textSize.height/2+this.margin.top,n,o)}},{key:"updateBoundingBox",value:function(t,e,i,n,o){this._updateBoundingBox(t,e,i,n,o);var r=this.options.shapeProperties.borderRadius;this._addBoundingBoxMargin(r)}},{key:"distanceToBorder",value:function(t,e){t&&this.resize(t);var i=this.options.borderWidth;return Math.min(Math.abs(this.width/2/Math.cos(e)),Math.abs(this.height/2/Math.sin(e)))+i}}]),i}(h1);function u1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var f1=function(t){r1(i,t);var e=u1(i);function i(t,n,o){var r;return uU(this,i),(r=e.call(this,t,n,o)).labelOffset=0,r.selected=!1,r}return yW(i,[{key:"setOptions",value:function(t,e,i){this.options=t,void 0===e&&void 0===i||this.setImages(e,i)}},{key:"setImages",value:function(t,e){e&&this.selected?(this.imageObj=e,this.imageObjAlt=t):(this.imageObj=t,this.imageObjAlt=e)}},{key:"switchImages",value:function(t){var e=t&&!this.selected||!t&&this.selected;if(this.selected=t,void 0!==this.imageObjAlt&&e){var i=this.imageObj;this.imageObj=this.imageObjAlt,this.imageObjAlt=i}}},{key:"_getImagePadding",value:function(){var t={top:0,right:0,bottom:0,left:0};if(this.options.imagePadding){var e=this.options.imagePadding;"object"==fW(e)?(t.top=e.top,t.right=e.right,t.bottom=e.bottom,t.left=e.left):(t.top=e,t.right=e,t.bottom=e,t.left=e)}return t}},{key:"_resizeImage",value:function(){var t,e;if(!1===this.options.shapeProperties.useImageSize){var i=1,n=1;this.imageObj.width&&this.imageObj.height&&(this.imageObj.width>this.imageObj.height?i=this.imageObj.width/this.imageObj.height:n=this.imageObj.height/this.imageObj.width),t=2*this.options.size*i,e=2*this.options.size*n}else{var o=this._getImagePadding();t=this.imageObj.width+o.left+o.right,e=this.imageObj.height+o.top+o.bottom}this.width=t,this.height=e,this.radius=.5*this.width}},{key:"_drawRawCircle",value:function(t,e,i,n){this.initContextForDraw(t,n),VF(t,e,i,n.size),this.performFill(t,n)}},{key:"_drawImageAtPosition",value:function(t,e){if(0!=this.imageObj.width){t.globalAlpha=void 0!==e.opacity?e.opacity:1,this.enableShadow(t,e);var i=1;!0===this.options.shapeProperties.interpolation&&(i=this.imageObj.width/this.width/this.body.view.scale);var n=this._getImagePadding(),o=this.left+n.left,r=this.top+n.top,s=this.width-n.left-n.right,a=this.height-n.top-n.bottom;this.imageObj.drawImageAtPosition(t,i,o,r,s,a),this.disableShadow(t,e)}}},{key:"_drawImageLabel",value:function(t,e,i,n,o){var r=0;if(void 0!==this.height){r=.5*this.height;var s=this.labelModule.getTextSize(t,n,o);s.lineCount>=1&&(r+=s.height/2)}var a=i+r;this.options.label&&(this.labelOffset=r),this.labelModule.draw(t,e,a,n,o,"hanging")}}]),i}(h1);function p1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var v1=function(t){r1(i,t);var e=p1(i);function i(t,n,o){var r;return uU(this,i),(r=e.call(this,t,n,o))._setMargins(o),r}return yW(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(this.needsRefresh(e,i)){var n=this.getDimensionsFromLabel(t,e,i),o=Math.max(n.width+this.margin.right+this.margin.left,n.height+this.margin.top+this.margin.bottom);this.options.size=o/2,this.width=o,this.height=o,this.radius=this.width/2}}},{key:"draw",value:function(t,e,i,n,o,r){this.resize(t,n,o),this.left=e-this.width/2,this.top=i-this.height/2,this._drawRawCircle(t,e,i,r),this.updateBoundingBox(e,i),this.labelModule.draw(t,this.left+this.textSize.width/2+this.margin.left,i,n,o)}},{key:"updateBoundingBox",value:function(t,e){this.boundingBox.top=e-this.options.size,this.boundingBox.left=t-this.options.size,this.boundingBox.right=t+this.options.size,this.boundingBox.bottom=e+this.options.size}},{key:"distanceToBorder",value:function(t){return t&&this.resize(t),.5*this.width}}]),i}(f1);function g1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var y1=function(t){r1(i,t);var e=g1(i);function i(t,n,o,r,s){var a;return uU(this,i),(a=e.call(this,t,n,o)).setImages(r,s),a}return yW(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(void 0===this.imageObj.src||void 0===this.imageObj.width||void 0===this.imageObj.height){var n=2*this.options.size;return this.width=n,this.height=n,void(this.radius=.5*this.width)}this.needsRefresh(e,i)&&this._resizeImage()}},{key:"draw",value:function(t,e,i,n,o,r){this.switchImages(n),this.resize();var s=e,a=i;"top-left"===this.options.shapeProperties.coordinateOrigin?(this.left=e,this.top=i,s+=this.width/2,a+=this.height/2):(this.left=e-this.width/2,this.top=i-this.height/2),this._drawRawCircle(t,s,a,r),t.save(),t.clip(),this._drawImageAtPosition(t,r),t.restore(),this._drawImageLabel(t,s,a,n,o),this.updateBoundingBox(e,i)}},{key:"updateBoundingBox",value:function(t,e){"top-left"===this.options.shapeProperties.coordinateOrigin?(this.boundingBox.top=e,this.boundingBox.left=t,this.boundingBox.right=t+2*this.options.size,this.boundingBox.bottom=e+2*this.options.size):(this.boundingBox.top=e-this.options.size,this.boundingBox.left=t-this.options.size,this.boundingBox.right=t+this.options.size,this.boundingBox.bottom=e+this.options.size),this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelOffset)}},{key:"distanceToBorder",value:function(t){return t&&this.resize(t),.5*this.width}}]),i}(f1);function m1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var b1=function(t){r1(i,t);var e=m1(i);function i(t,n,o){return uU(this,i),e.call(this,t,n,o)}return yW(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover,n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{size:this.options.size};if(this.needsRefresh(e,i)){var o,r;this.labelModule.getTextSize(t,e,i);var s=2*n.size;this.width=null!==(o=this.customSizeWidth)&&void 0!==o?o:s,this.height=null!==(r=this.customSizeHeight)&&void 0!==r?r:s,this.radius=.5*this.width}}},{key:"_drawShape",value:function(t,e,i,n,o,r,s,a){var l,h=this;return this.resize(t,r,s,a),this.left=n-this.width/2,this.top=o-this.height/2,this.initContextForDraw(t,a),(l=e,Object.prototype.hasOwnProperty.call(YF,l)?YF[l]:function(t){for(var e=arguments.length,i=new Array(e>1?e-1:0),n=1;n0&&(this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelModule.size.height))}}]),i}(h1);function w1(t,e){var i=RG(t);if(D$){var n=D$(t);e&&(n=sq(n).call(n,(function(e){return U$(t,e).enumerable}))),i.push.apply(i,n)}return i}function A1(t){for(var e=1;e1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(this.needsRefresh(e,i)){var n=this.getDimensionsFromLabel(t,e,i);this.height=2*n.height,this.width=n.width+n.height,this.radius=.5*this.width}}},{key:"draw",value:function(t,e,i,n,o,r){this.resize(t,n,o),this.left=e-.5*this.width,this.top=i-.5*this.height,this.initContextForDraw(t,r),GF(t,this.left,this.top,this.width,this.height),this.performFill(t,r),this.updateBoundingBox(e,i,t,n,o),this.labelModule.draw(t,e,i,n,o)}},{key:"distanceToBorder",value:function(t,e){t&&this.resize(t);var i=.5*this.width,n=.5*this.height,o=Math.sin(e)*i,r=Math.cos(e)*n;return i*n/Math.sqrt(o*o+r*r)}}]),i}(h1);function B1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var z1=function(t){r1(i,t);var e=B1(i);function i(t,n,o){var r;return uU(this,i),(r=e.call(this,t,n,o))._setMargins(o),r}return yW(i,[{key:"resize",value:function(t,e,i){this.needsRefresh(e,i)&&(this.iconSize={width:Number(this.options.icon.size),height:Number(this.options.icon.size)},this.width=this.iconSize.width+this.margin.right+this.margin.left,this.height=this.iconSize.height+this.margin.top+this.margin.bottom,this.radius=.5*this.width)}},{key:"draw",value:function(t,e,i,n,o,r){var s=this;return this.resize(t,n,o),this.options.icon.size=this.options.icon.size||50,this.left=e-this.width/2,this.top=i-this.height/2,this._icon(t,e,i,n,o,r),{drawExternalLabel:function(){if(void 0!==s.options.label){s.labelModule.draw(t,s.left+s.iconSize.width/2+s.margin.left,i+s.height/2+5,n)}s.updateBoundingBox(e,i)}}}},{key:"updateBoundingBox",value:function(t,e){if(this.boundingBox.top=e-.5*this.options.icon.size,this.boundingBox.left=t-.5*this.options.icon.size,this.boundingBox.right=t+.5*this.options.icon.size,this.boundingBox.bottom=e+.5*this.options.icon.size,void 0!==this.options.label&&this.labelModule.size.width>0){this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelModule.size.height+5)}}},{key:"_icon",value:function(t,e,i,n,o,r){var s=Number(this.options.icon.size);void 0!==this.options.icon.code?(t.font=[null!=this.options.icon.weight?this.options.icon.weight:n?"bold":"",(null!=this.options.icon.weight&&n?5:0)+s+"px",this.options.icon.face].join(" "),t.fillStyle=this.options.icon.color||"black",t.textAlign="center",t.textBaseline="middle",this.enableShadow(t,r),t.fillText(this.options.icon.code,e,i),this.disableShadow(t,r)):console.error("When using the icon shape, you need to define the code in the icon options object. This can be done per node or globally.")}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(h1);function P1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var F1=function(t){r1(i,t);var e=P1(i);function i(t,n,o,r,s){var a;return uU(this,i),(a=e.call(this,t,n,o)).setImages(r,s),a}return yW(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(void 0===this.imageObj.src||void 0===this.imageObj.width||void 0===this.imageObj.height){var n=2*this.options.size;return this.width=n,void(this.height=n)}this.needsRefresh(e,i)&&this._resizeImage()}},{key:"draw",value:function(t,e,i,n,o,r){t.save(),this.switchImages(n),this.resize();var s=e,a=i;if("top-left"===this.options.shapeProperties.coordinateOrigin?(this.left=e,this.top=i,s+=this.width/2,a+=this.height/2):(this.left=e-this.width/2,this.top=i-this.height/2),!0===this.options.shapeProperties.useBorderWithImage){var l=this.options.borderWidth,h=this.options.borderWidthSelected||2*this.options.borderWidth,c=(n?h:l)/this.body.view.scale;t.lineWidth=Math.min(this.width,c),t.beginPath();var d=n?this.options.color.highlight.border:o?this.options.color.hover.border:this.options.color.border,u=n?this.options.color.highlight.background:o?this.options.color.hover.background:this.options.color.background;void 0!==r.opacity&&(d=UJ(d,r.opacity),u=UJ(u,r.opacity)),t.strokeStyle=d,t.fillStyle=u,t.rect(this.left-.5*t.lineWidth,this.top-.5*t.lineWidth,this.width+t.lineWidth,this.height+t.lineWidth),EY(t).call(t),this.performStroke(t,r),t.closePath()}this._drawImageAtPosition(t,r),this._drawImageLabel(t,s,a,n,o),this.updateBoundingBox(e,i),t.restore()}},{key:"updateBoundingBox",value:function(t,e){this.resize(),"top-left"===this.options.shapeProperties.coordinateOrigin?(this.left=t,this.top=e):(this.left=t-this.width/2,this.top=e-this.height/2),this.boundingBox.left=this.left,this.boundingBox.top=this.top,this.boundingBox.bottom=this.top+this.height,this.boundingBox.right=this.left+this.width,void 0!==this.options.label&&this.labelModule.size.width>0&&(this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelOffset))}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(f1);function T1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var N1=function(t){r1(i,t);var e=T1(i);function i(t,n,o){return uU(this,i),e.call(this,t,n,o)}return yW(i,[{key:"draw",value:function(t,e,i,n,o,r){return this._drawShape(t,"square",2,e,i,n,o,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(b1);function j1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var L1=function(t){r1(i,t);var e=j1(i);function i(t,n,o){return uU(this,i),e.call(this,t,n,o)}return yW(i,[{key:"draw",value:function(t,e,i,n,o,r){return this._drawShape(t,"hexagon",4,e,i,n,o,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(b1);function U1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var Q1=function(t){r1(i,t);var e=U1(i);function i(t,n,o){return uU(this,i),e.call(this,t,n,o)}return yW(i,[{key:"draw",value:function(t,e,i,n,o,r){return this._drawShape(t,"star",4,e,i,n,o,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(b1);function H1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var V1=function(t){r1(i,t);var e=H1(i);function i(t,n,o){var r;return uU(this,i),(r=e.call(this,t,n,o))._setMargins(o),r}return yW(i,[{key:"resize",value:function(t,e,i){this.needsRefresh(e,i)&&(this.textSize=this.labelModule.getTextSize(t,e,i),this.width=this.textSize.width+this.margin.right+this.margin.left,this.height=this.textSize.height+this.margin.top+this.margin.bottom,this.radius=.5*this.width)}},{key:"draw",value:function(t,e,i,n,o,r){this.resize(t,n,o),this.left=e-this.width/2,this.top=i-this.height/2,this.enableShadow(t,r),this.labelModule.draw(t,this.left+this.textSize.width/2+this.margin.left,this.top+this.textSize.height/2+this.margin.top,n,o),this.disableShadow(t,r),this.updateBoundingBox(e,i,t,n,o)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(h1);function W1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var G1=function(t){r1(i,t);var e=W1(i);function i(t,n,o){return uU(this,i),e.call(this,t,n,o)}return yW(i,[{key:"draw",value:function(t,e,i,n,o,r){return this._drawShape(t,"triangle",3,e,i,n,o,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(b1);function K1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var q1=function(t){r1(i,t);var e=K1(i);function i(t,n,o){return uU(this,i),e.call(this,t,n,o)}return yW(i,[{key:"draw",value:function(t,e,i,n,o,r){return this._drawShape(t,"triangleDown",3,e,i,n,o,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(b1);function Y1(t,e){var i=RG(t);if(D$){var n=D$(t);e&&(n=sq(n).call(n,(function(e){return U$(t,e).enumerable}))),i.push.apply(i,n)}return i}function Z1(t){for(var e=1;et.left&&this.shape.topt.top}},{key:"isBoundingBoxOverlappingWith",value:function(t){return this.shape.boundingBox.leftt.left&&this.shape.boundingBox.topt.top}}],[{key:"checkOpacity",value:function(t){return 0<=t&&t<=1}},{key:"checkCoordinateOrigin",value:function(t){return void 0===t||"center"===t||"top-left"===t}},{key:"updateGroupOptions",value:function(e,i,n){var o;if(void 0!==n){var r=e.group;if(void 0!==i&&void 0!==i.group&&r!==i.group)throw new Error("updateGroupOptions: group values in options don't match.");if("number"==typeof r||"string"==typeof r&&""!=r){var s=n.get(r);void 0!==s.opacity&&void 0===i.opacity&&(t.checkOpacity(s.opacity)||(console.error("Invalid option for node opacity. Value must be between 0 and 1, found: "+s.opacity),s.opacity=void 0));var a=sq(o=y0(i)).call(o,(function(t){return null!=i[t]}));a.push("font"),PJ(a,e,s),e.color=HJ(e.color)}}}},{key:"parseOptions",value:function(e,i){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},r=arguments.length>4?arguments[4]:void 0;if(PJ(["color","fixed","shadow"],e,i,n),t.checkMass(i),void 0!==e.opacity&&(t.checkOpacity(e.opacity)||(console.error("Invalid option for node opacity. Value must be between 0 and 1, found: "+e.opacity),e.opacity=void 0)),void 0!==i.opacity&&(t.checkOpacity(i.opacity)||(console.error("Invalid option for node opacity. Value must be between 0 and 1, found: "+i.opacity),i.opacity=void 0)),i.shapeProperties&&!t.checkCoordinateOrigin(i.shapeProperties.coordinateOrigin)&&console.error("Invalid option for node coordinateOrigin, found: "+i.shapeProperties.coordinateOrigin),ZJ(e,i,"shadow",o),void 0!==i.color&&null!==i.color){var s=HJ(i.color);BJ(e.color,s)}else!0===n&&null===i.color&&(e.color=YJ(o.color));void 0!==i.fixed&&null!==i.fixed&&("boolean"==typeof i.fixed?(e.fixed.x=i.fixed,e.fixed.y=i.fixed):(void 0!==i.fixed.x&&"boolean"==typeof i.fixed.x&&(e.fixed.x=i.fixed.x),void 0!==i.fixed.y&&"boolean"==typeof i.fixed.y&&(e.fixed.y=i.fixed.y))),!0===n&&null===i.font&&(e.font=YJ(o.font)),t.updateGroupOptions(e,i,r),void 0!==i.scaling&&ZJ(e.scaling,i.scaling,"label",o.scaling)}},{key:"checkMass",value:function(t,e){if(void 0!==t.mass&&t.mass<=0){var i="";void 0!==e&&(i=" in node id: "+e),console.error("%cNegative or zero mass disallowed"+i+", setting mass to 1.",dX),t.mass=1}}}]),t}();function X1(t,e){var i=void 0!==aG&&dU(t)||t["@@iterator"];if(!i){if(AG(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return _1(t,e);var n=pG(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return WL(t);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _1(t,e)}(t))||e){i&&(t=i);var n=0,o=function(){};return{s:o,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function _1(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i1?console.error("Invalid option for node opacity. Value must be between 0 and 1, found: "+t.opacity):this.options.opacity=t.opacity),void 0!==t.shape)for(var e in this.body.nodes)Object.prototype.hasOwnProperty.call(this.body.nodes,e)&&this.body.nodes[e].updateShape();if(void 0!==t.font||void 0!==t.widthConstraint||void 0!==t.heightConstraint)for(var i=0,n=RG(this.body.nodes);i1&&void 0!==arguments[1]&&arguments[1],i=this.body.data.nodes;if(eR("id",t))this.body.data.nodes=t;else if(AG(t))this.body.data.nodes=new tR,this.body.data.nodes.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.body.data.nodes=new tR}if(i&&jJ(this.nodesListeners,(function(t,e){i.off(e,t)})),this.body.nodes={},this.body.data.nodes){var n=this;jJ(this.nodesListeners,(function(t,e){n.body.data.nodes.on(e,t)}));var o=this.body.data.nodes.getIds();this.add(o,!0)}!1===e&&this.body.emitter.emit("_dataChanged")}},{key:"add",value:function(t){for(var e,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=[],o=0;o1&&void 0!==arguments[1]?arguments[1]:J1)(t,this.body,this.images,this.groups,this.options,this.defaultOptions)}},{key:"refresh",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];jJ(this.body.nodes,(function(i,n){var o=t.body.data.nodes.get(n);void 0!==o&&(!0===e&&i.setOptions({x:null,y:null}),i.setOptions({fixed:!1}),i.setOptions(o))}))}},{key:"getPositions",value:function(t){var e={};if(void 0!==t){if(!0===AG(t)){for(var i=0;i0?(n=i/a)*n:i;return a===1/0?1/0:a*f2(o)}});var p2=nR(iB.Math.hypot);function v2(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var g2=function(){function t(){uU(this,t)}return yW(t,null,[{key:"transform",value:function(t,e){AG(t)||(t=[t]);for(var i=e.point.x,n=e.point.y,o=e.angle,r=e.length,s=0;s4&&void 0!==arguments[4]?arguments[4]:this.getViaNode();t.strokeStyle=this.getColor(t,e),t.lineWidth=e.width,!1!==e.dashes?this._drawDashedLine(t,e,o):this._drawLine(t,e,o)}},{key:"_drawLine",value:function(t,e,i,n,o){if(this.from!=this.to)this._line(t,e,i,n,o);else{var r=rG(this._getCircleData(t),3),s=r[0],a=r[1],l=r[2];this._circle(t,e,s,a,l)}}},{key:"_drawDashedLine",value:function(t,e,i,n,o){t.lineCap="round";var r=AG(e.dashes)?e.dashes:[5,5];if(void 0!==t.setLineDash){if(t.save(),t.setLineDash(r),t.lineDashOffset=0,this.from!=this.to)this._line(t,e,i);else{var s=rG(this._getCircleData(t),3),a=s[0],l=s[1],h=s[2];this._circle(t,e,a,l,h)}t.setLineDash([0]),t.lineDashOffset=0,t.restore()}else{if(this.from!=this.to)qF(t,this.from.x,this.from.y,this.to.x,this.to.y,r);else{var c=rG(this._getCircleData(t),3),d=c[0],u=c[1],f=c[2];this._circle(t,e,d,u,f)}this.enableShadow(t,e),t.stroke(),this.disableShadow(t,e)}}},{key:"findBorderPosition",value:function(t,e,i){return this.from!=this.to?this._findBorderPosition(t,e,i):this._findBorderPositionCircle(t,e,i)}},{key:"findBorderPositions",value:function(t){if(this.from!=this.to)return{from:this._findBorderPosition(this.from,t),to:this._findBorderPosition(this.to,t)};var e,i=rG(pG(e=this._getCircleData(t)).call(e,0,2),2),n=i[0],o=i[1];return{from:this._findBorderPositionCircle(this.from,t,{x:n,y:o,low:.25,high:.6,direction:-1}),to:this._findBorderPositionCircle(this.from,t,{x:n,y:o,low:.6,high:.8,direction:1})}}},{key:"_getCircleData",value:function(t){var e=this.options.selfReference.size;void 0!==t&&void 0===this.from.shape.width&&this.from.shape.resize(t);var i=A0(t,this.options.selfReference.angle,e,this.from);return[i.x,i.y,e]}},{key:"_pointOnCircle",value:function(t,e,i,n){var o=2*n*Math.PI;return{x:t+i*Math.cos(o),y:e-i*Math.sin(o)}}},{key:"_findBorderPositionCircle",value:function(t,e,i){var n,o=i.x,r=i.y,s=i.low,a=i.high,l=i.direction,h=this.options.selfReference.size,c=.5*(s+a),d=0;!0===this.options.arrowStrikethrough&&(-1===l?d=this.options.endPointOffset.from:1===l&&(d=this.options.endPointOffset.to));var u=0;do{c=.5*(s+a),n=this._pointOnCircle(o,r,h,c);var f=Math.atan2(t.y-n.y,t.x-n.x),p=t.distanceToBorder(e,f)+d-Math.sqrt(Math.pow(n.x-t.x,2)+Math.pow(n.y-t.y,2));if(Math.abs(p)<.05)break;p>0?l>0?s=c:a=c:l>0?a=c:s=c,++u}while(s<=a&&u<10);return R2(R2({},n),{},{t:c})}},{key:"getLineWidth",value:function(t,e){return!0===t?Math.max(this.selectionWidth,.3/this._body.view.scale):!0===e?Math.max(this.hoverWidth,.3/this._body.view.scale):Math.max(this.options.width,.3/this._body.view.scale)}},{key:"getColor",value:function(t,e){if(!1!==e.inheritsColor){if("both"===e.inheritsColor&&this.from.id!==this.to.id){var i=t.createLinearGradient(this.from.x,this.from.y,this.to.x,this.to.y),n=this.from.options.color.highlight.border,o=this.to.options.color.highlight.border;return!1===this.from.selected&&!1===this.to.selected?(n=UJ(this.from.options.color.border,e.opacity),o=UJ(this.to.options.color.border,e.opacity)):!0===this.from.selected&&!1===this.to.selected?o=this.to.options.color.border:!1===this.from.selected&&!0===this.to.selected&&(n=this.from.options.color.border),i.addColorStop(0,n),i.addColorStop(1,o),i}return"to"===e.inheritsColor?UJ(this.to.options.color.border,e.opacity):UJ(this.from.options.color.border,e.opacity)}return UJ(e.color,e.opacity)}},{key:"_circle",value:function(t,e,i,n,o){this.enableShadow(t,e);var r=0,s=2*Math.PI;if(!this.options.selfReference.renderBehindTheNode){var a=this.options.selfReference.angle,l=this.options.selfReference.angle+Math.PI,h=this._findBorderPositionCircle(this.from,t,{x:i,y:n,low:a,high:l,direction:-1}),c=this._findBorderPositionCircle(this.from,t,{x:i,y:n,low:a,high:l,direction:1});r=Math.atan2(h.y-n,h.x-i),s=Math.atan2(c.y-n,c.x-i)}t.beginPath(),t.arc(i,n,o,r,s,!1),t.stroke(),this.disableShadow(t,e)}},{key:"getDistanceToEdge",value:function(t,e,i,n,o,r){if(this.from!=this.to)return this._getDistanceToEdge(t,e,i,n,o,r);var s=rG(this._getCircleData(void 0),3),a=s[0],l=s[1],h=s[2],c=a-o,d=l-r;return Math.abs(Math.sqrt(c*c+d*d)-h)}},{key:"_getDistanceToLine",value:function(t,e,i,n,o,r){var s=i-t,a=n-e,l=((o-t)*s+(r-e)*a)/(s*s+a*a);l>1?l=1:l<0&&(l=0);var h=t+l*s-o,c=e+l*a-r;return Math.sqrt(h*h+c*c)}},{key:"getArrowData",value:function(t,e,i,n,o,r){var s,a,l,h,c,d,u,f=r.width;"from"===e?(l=this.from,h=this.to,c=r.fromArrowScale<0,d=Math.abs(r.fromArrowScale),u=r.fromArrowType):"to"===e?(l=this.to,h=this.from,c=r.toArrowScale<0,d=Math.abs(r.toArrowScale),u=r.toArrowType):(l=this.to,h=this.from,c=r.middleArrowScale<0,d=Math.abs(r.middleArrowScale),u=r.middleArrowType);var p=15*d+3*f;if(l!=h){var v=p/p2(l.x-h.x,l.y-h.y);if("middle"!==e)if(!0===this.options.smooth.enabled){var g=this._findBorderPosition(l,t,{via:i}),y=this.getPoint(g.t+v*("from"===e?1:-1),i);s=Math.atan2(g.y-y.y,g.x-y.x),a=g}else s=Math.atan2(l.y-h.y,l.x-h.x),a=this._findBorderPosition(l,t);else{var m=(c?-v:v)/2,b=this.getPoint(.5+m,i),w=this.getPoint(.5-m,i);s=Math.atan2(b.y-w.y,b.x-w.x),a=this.getPoint(.5,i)}}else{var A=rG(this._getCircleData(t),3),k=A[0],E=A[1],C=A[2];if("from"===e){var x=this.options.selfReference.angle,I=this.options.selfReference.angle+Math.PI,S=this._findBorderPositionCircle(this.from,t,{x:k,y:E,low:x,high:I,direction:-1});s=-2*S.t*Math.PI+1.5*Math.PI+.1*Math.PI,a=S}else if("to"===e){var M=this.options.selfReference.angle,O=this.options.selfReference.angle+Math.PI,D=this._findBorderPositionCircle(this.from,t,{x:k,y:E,low:M,high:O,direction:1});s=-2*D.t*Math.PI+1.5*Math.PI-1.1*Math.PI,a=D}else{var R=this.options.selfReference.angle/(2*Math.PI);a=this._pointOnCircle(k,E,C,R),s=-2*R*Math.PI+1.5*Math.PI+.1*Math.PI}}return{point:a,core:{x:a.x-.9*p*Math.cos(s),y:a.y-.9*p*Math.sin(s)},angle:s,length:p,type:u}}},{key:"drawArrowHead",value:function(t,e,i,n,o){t.strokeStyle=this.getColor(t,e),t.fillStyle=t.strokeStyle,t.lineWidth=e.width,O2.draw(t,o)&&(this.enableShadow(t,e),EY(t).call(t),this.disableShadow(t,e))}},{key:"enableShadow",value:function(t,e){!0===e.shadow&&(t.shadowColor=e.shadowColor,t.shadowBlur=e.shadowSize,t.shadowOffsetX=e.shadowX,t.shadowOffsetY=e.shadowY)}},{key:"disableShadow",value:function(t,e){!0===e.shadow&&(t.shadowColor="rgba(0,0,0,0)",t.shadowBlur=0,t.shadowOffsetX=0,t.shadowOffsetY=0)}},{key:"drawBackground",value:function(t,e){if(!1!==e.background){var i={strokeStyle:t.strokeStyle,lineWidth:t.lineWidth,dashes:t.dashes};t.strokeStyle=e.backgroundColor,t.lineWidth=e.backgroundSize,this.setStrokeDashed(t,e.backgroundDashes),t.stroke(),t.strokeStyle=i.strokeStyle,t.lineWidth=i.lineWidth,t.dashes=i.dashes,this.setStrokeDashed(t,e.dashes)}}},{key:"setStrokeDashed",value:function(t,e){if(!1!==e)if(void 0!==t.setLineDash){var i=AG(e)?e:[5,5];t.setLineDash(i)}else console.warn("setLineDash is not supported in this browser. The dashed stroke cannot be used.");else void 0!==t.setLineDash?t.setLineDash([]):console.warn("setLineDash is not supported in this browser. The dashed stroke cannot be used.")}}]),t}();function z2(t,e){var i=RG(t);if(D$){var n=D$(t);e&&(n=sq(n).call(n,(function(e){return U$(t,e).enumerable}))),i.push.apply(i,n)}return i}function P2(t){for(var e=1;e2&&void 0!==arguments[2]?arguments[2]:this._getViaCoordinates(),r=!1,s=1,a=0,l=this.to,h=this.options.endPointOffset?this.options.endPointOffset.to:0;t.id===this.from.id&&(l=this.from,r=!0,h=this.options.endPointOffset?this.options.endPointOffset.from:0),!1===this.options.arrowStrikethrough&&(h=0);var c=0;do{n=.5*(a+s),i=this.getPoint(n,o);var d=Math.atan2(l.y-i.y,l.x-i.x),u=l.distanceToBorder(e,d)+h-Math.sqrt(Math.pow(i.x-l.x,2)+Math.pow(i.y-l.y,2));if(Math.abs(u)<.2)break;u<0?!1===r?a=n:s=n:!1===r?s=n:a=n,++c}while(a<=s&&c<10);return P2(P2({},i),{},{t:n})}},{key:"_getDistanceToBezierEdge",value:function(t,e,i,n,o,r,s){var a,l,h,c,d,u=1e9,f=t,p=e;for(l=1;l<10;l++)h=.1*l,c=Math.pow(1-h,2)*t+2*h*(1-h)*s.x+Math.pow(h,2)*i,d=Math.pow(1-h,2)*e+2*h*(1-h)*s.y+Math.pow(h,2)*n,l>0&&(u=(a=this._getDistanceToLine(f,p,c,d,o,r))1&&void 0!==arguments[1]?arguments[1]:this.via;if(this.from===this.to){var i=rG(this._getCircleData(),3),n=i[0],o=i[1],r=i[2],s=2*Math.PI*(1-t);return{x:n+r*Math.sin(s),y:o+r-r*(1-Math.cos(s))}}return{x:Math.pow(1-t,2)*this.fromPoint.x+2*t*(1-t)*e.x+Math.pow(t,2)*this.toPoint.x,y:Math.pow(1-t,2)*this.fromPoint.y+2*t*(1-t)*e.y+Math.pow(t,2)*this.toPoint.y}}},{key:"_findBorderPosition",value:function(t,e){return this._findBorderPositionBezier(t,e,this.via)}},{key:"_getDistanceToEdge",value:function(t,e,i,n,o,r){return this._getDistanceToBezierEdge(t,e,i,n,o,r,this.via)}}]),i}(T2);function L2(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var U2=function(t){r1(i,t);var e=L2(i);function i(t,n,o){return uU(this,i),e.call(this,t,n,o)}return yW(i,[{key:"_line",value:function(t,e,i){this._bezierCurve(t,e,i)}},{key:"getViaNode",value:function(){return this._getViaCoordinates()}},{key:"_getViaCoordinates",value:function(){var t,e,i=this.options.smooth.roundness,n=this.options.smooth.type,o=Math.abs(this.from.x-this.to.x),r=Math.abs(this.from.y-this.to.y);if("discrete"===n||"diagonalCross"===n){var s,a;s=a=o<=r?i*r:i*o,this.from.x>this.to.x&&(s=-s),this.from.y>=this.to.y&&(a=-a);var l=this.from.x+s,h=this.from.y+a;return"discrete"===n&&(o<=r?l=othis.to.x&&(t=-t),this.from.y>=this.to.y&&(e=-e);var w=this.from.x+t,A=this.from.y+e;return o<=r?w=this.from.x<=this.to.x?this.to.xw?this.to.x:w:A=this.from.y>=this.to.y?this.to.y>A?this.to.y:A:this.to.y2&&void 0!==arguments[2]?arguments[2]:{};return this._findBorderPositionBezier(t,e,i.via)}},{key:"_getDistanceToEdge",value:function(t,e,i,n,o,r){var s=arguments.length>6&&void 0!==arguments[6]?arguments[6]:this._getViaCoordinates();return this._getDistanceToBezierEdge(t,e,i,n,o,r,s)}},{key:"getPoint",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this._getViaCoordinates(),i=t;return{x:Math.pow(1-i,2)*this.fromPoint.x+2*i*(1-i)*e.x+Math.pow(i,2)*this.toPoint.x,y:Math.pow(1-i,2)*this.fromPoint.y+2*i*(1-i)*e.y+Math.pow(i,2)*this.toPoint.y}}}]),i}(T2);function Q2(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var H2=function(t){r1(i,t);var e=Q2(i);function i(t,n,o){return uU(this,i),e.call(this,t,n,o)}return yW(i,[{key:"_getDistanceToBezierEdge2",value:function(t,e,i,n,o,r,s,a){for(var l=1e9,h=t,c=e,d=[0,0,0,0],u=1;u<10;u++){var f=.1*u;d[0]=Math.pow(1-f,3),d[1]=3*f*Math.pow(1-f,2),d[2]=3*Math.pow(f,2)*(1-f),d[3]=Math.pow(f,3);var p=d[0]*t+d[1]*s.x+d[2]*a.x+d[3]*i,v=d[0]*e+d[1]*s.y+d[2]*a.y+d[3]*n;if(u>0){var g=this._getDistanceToLine(h,c,p,v,o,r);l=gMath.abs(r)||!0===this.options.smooth.forceDirection||"horizontal"===this.options.smooth.forceDirection)&&"vertical"!==this.options.smooth.forceDirection?(e=this.from.y,n=this.to.y,t=this.from.x-s*o,i=this.to.x+s*o):(e=this.from.y-s*r,n=this.to.y+s*r,t=this.from.x,i=this.to.x),[{x:t,y:e},{x:i,y:n}]}},{key:"getViaNode",value:function(){return this._getViaCoordinates()}},{key:"_findBorderPosition",value:function(t,e){return this._findBorderPositionBezier(t,e)}},{key:"_getDistanceToEdge",value:function(t,e,i,n,o,r){var s=rG(arguments.length>6&&void 0!==arguments[6]?arguments[6]:this._getViaCoordinates(),2),a=s[0],l=s[1];return this._getDistanceToBezierEdge2(t,e,i,n,o,r,a,l)}},{key:"getPoint",value:function(t){var e=rG(arguments.length>1&&void 0!==arguments[1]?arguments[1]:this._getViaCoordinates(),2),i=e[0],n=e[1],o=t,r=[Math.pow(1-o,3),3*o*Math.pow(1-o,2),3*Math.pow(o,2)*(1-o),Math.pow(o,3)];return{x:r[0]*this.fromPoint.x+r[1]*i.x+r[2]*n.x+r[3]*this.toPoint.x,y:r[0]*this.fromPoint.y+r[1]*i.y+r[2]*n.y+r[3]*this.toPoint.y}}}]),i}(H2);function G2(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var K2=function(t){r1(i,t);var e=G2(i);function i(t,n,o){return uU(this,i),e.call(this,t,n,o)}return yW(i,[{key:"_line",value:function(t,e){t.beginPath(),t.moveTo(this.fromPoint.x,this.fromPoint.y),t.lineTo(this.toPoint.x,this.toPoint.y),this.enableShadow(t,e),t.stroke(),this.disableShadow(t,e)}},{key:"getViaNode",value:function(){}},{key:"getPoint",value:function(t){return{x:(1-t)*this.fromPoint.x+t*this.toPoint.x,y:(1-t)*this.fromPoint.y+t*this.toPoint.y}}},{key:"_findBorderPosition",value:function(t,e){var i=this.to,n=this.from;t.id===this.from.id&&(i=this.from,n=this.to);var o=Math.atan2(i.y-n.y,i.x-n.x),r=i.x-n.x,s=i.y-n.y,a=Math.sqrt(r*r+s*s),l=(a-t.distanceToBorder(e,o))/a;return{x:(1-l)*n.x+l*i.x,y:(1-l)*n.y+l*i.y,t:0}}},{key:"_getDistanceToEdge",value:function(t,e,i,n,o,r){return this._getDistanceToLine(t,e,i,n,o,r)}}]),i}(B2),q2=function(){function t(e,i,n,o,r){if(uU(this,t),void 0===i)throw new Error("No body provided");this.options=YJ(o),this.globalOptions=o,this.defaultOptions=r,this.body=i,this.imagelist=n,this.id=void 0,this.fromId=void 0,this.toId=void 0,this.selected=!1,this.hover=!1,this.labelDirty=!0,this.baseWidth=this.options.width,this.baseFontSize=this.options.font.size,this.from=void 0,this.to=void 0,this.edgeType=void 0,this.connected=!1,this.labelModule=new T0(this.body,this.options,!0),this.setOptions(e)}return yW(t,[{key:"setOptions",value:function(e){if(e){var i=void 0!==e.physics&&this.options.physics!==e.physics||void 0!==e.hidden&&(this.options.hidden||!1)!==(e.hidden||!1)||void 0!==e.from&&this.options.from!==e.from||void 0!==e.to&&this.options.to!==e.to;t.parseOptions(this.options,e,!0,this.globalOptions),void 0!==e.id&&(this.id=e.id),void 0!==e.from&&(this.fromId=e.from),void 0!==e.to&&(this.toId=e.to),void 0!==e.title&&(this.title=e.title),void 0!==e.value&&(e.value=d0(e.value));var n=[e,this.options,this.defaultOptions];return this.chooser=m0("edge",n),this.updateLabelModule(e),i=this.updateEdgeType()||i,this._setInteractionWidths(),this.connect(),i}}},{key:"getFormattingValues",value:function(){var t=!0===this.options.arrows.to||!0===this.options.arrows.to.enabled,e=!0===this.options.arrows.from||!0===this.options.arrows.from.enabled,i=!0===this.options.arrows.middle||!0===this.options.arrows.middle.enabled,n=this.options.color.inherit,o={toArrow:t,toArrowScale:this.options.arrows.to.scaleFactor,toArrowType:this.options.arrows.to.type,toArrowSrc:this.options.arrows.to.src,toArrowImageWidth:this.options.arrows.to.imageWidth,toArrowImageHeight:this.options.arrows.to.imageHeight,middleArrow:i,middleArrowScale:this.options.arrows.middle.scaleFactor,middleArrowType:this.options.arrows.middle.type,middleArrowSrc:this.options.arrows.middle.src,middleArrowImageWidth:this.options.arrows.middle.imageWidth,middleArrowImageHeight:this.options.arrows.middle.imageHeight,fromArrow:e,fromArrowScale:this.options.arrows.from.scaleFactor,fromArrowType:this.options.arrows.from.type,fromArrowSrc:this.options.arrows.from.src,fromArrowImageWidth:this.options.arrows.from.imageWidth,fromArrowImageHeight:this.options.arrows.from.imageHeight,arrowStrikethrough:this.options.arrowStrikethrough,color:n?void 0:this.options.color.color,inheritsColor:n,opacity:this.options.color.opacity,hidden:this.options.hidden,length:this.options.length,shadow:this.options.shadow.enabled,shadowColor:this.options.shadow.color,shadowSize:this.options.shadow.size,shadowX:this.options.shadow.x,shadowY:this.options.shadow.y,dashes:this.options.dashes,width:this.options.width,background:this.options.background.enabled,backgroundColor:this.options.background.color,backgroundSize:this.options.background.size,backgroundDashes:this.options.background.dashes};if(this.selected||this.hover)if(!0===this.chooser){if(this.selected){var r=this.options.selectionWidth;"function"==typeof r?o.width=r(o.width):"number"==typeof r&&(o.width+=r),o.width=Math.max(o.width,.3/this.body.view.scale),o.color=this.options.color.highlight,o.shadow=this.options.shadow.enabled}else if(this.hover){var s=this.options.hoverWidth;"function"==typeof s?o.width=s(o.width):"number"==typeof s&&(o.width+=s),o.width=Math.max(o.width,.3/this.body.view.scale),o.color=this.options.color.hover,o.shadow=this.options.shadow.enabled}}else"function"==typeof this.chooser&&(this.chooser(o,this.options.id,this.selected,this.hover),void 0!==o.color&&(o.inheritsColor=!1),!1===o.shadow&&(o.shadowColor===this.options.shadow.color&&o.shadowSize===this.options.shadow.size&&o.shadowX===this.options.shadow.x&&o.shadowY===this.options.shadow.y||(o.shadow=!0)));else o.shadow=this.options.shadow.enabled,o.width=Math.max(o.width,.3/this.body.view.scale);return o}},{key:"updateLabelModule",value:function(t){var e=[t,this.options,this.globalOptions,this.defaultOptions];this.labelModule.update(this.options,e),void 0!==this.labelModule.baseSize&&(this.baseFontSize=this.labelModule.baseSize)}},{key:"updateEdgeType",value:function(){var t=this.options.smooth,e=!1,i=!0;return void 0!==this.edgeType&&((this.edgeType instanceof j2&&!0===t.enabled&&"dynamic"===t.type||this.edgeType instanceof W2&&!0===t.enabled&&"cubicBezier"===t.type||this.edgeType instanceof U2&&!0===t.enabled&&"dynamic"!==t.type&&"cubicBezier"!==t.type||this.edgeType instanceof K2&&!1===t.type.enabled)&&(i=!1),!0===i&&(e=this.cleanup())),!0===i?!0===t.enabled?"dynamic"===t.type?(e=!0,this.edgeType=new j2(this.options,this.body,this.labelModule)):"cubicBezier"===t.type?this.edgeType=new W2(this.options,this.body,this.labelModule):this.edgeType=new U2(this.options,this.body,this.labelModule):this.edgeType=new K2(this.options,this.body,this.labelModule):this.edgeType.setOptions(this.options),e}},{key:"connect",value:function(){this.disconnect(),this.from=this.body.nodes[this.fromId]||void 0,this.to=this.body.nodes[this.toId]||void 0,this.connected=void 0!==this.from&&void 0!==this.to,!0===this.connected?(this.from.attachEdge(this),this.to.attachEdge(this)):(this.from&&this.from.detachEdge(this),this.to&&this.to.detachEdge(this)),this.edgeType.connect()}},{key:"disconnect",value:function(){this.from&&(this.from.detachEdge(this),this.from=void 0),this.to&&(this.to.detachEdge(this),this.to=void 0),this.connected=!1}},{key:"getTitle",value:function(){return this.title}},{key:"isSelected",value:function(){return this.selected}},{key:"getValue",value:function(){return this.options.value}},{key:"setValueRange",value:function(t,e,i){if(void 0!==this.options.value){var n=this.options.scaling.customScalingFunction(t,e,i,this.options.value),o=this.options.scaling.max-this.options.scaling.min;if(!0===this.options.scaling.label.enabled){var r=this.options.scaling.label.max-this.options.scaling.label.min;this.options.font.size=this.options.scaling.label.min+n*r}this.options.width=this.options.scaling.min+n*o}else this.options.width=this.baseWidth,this.options.font.size=this.baseFontSize;this._setInteractionWidths(),this.updateLabelModule()}},{key:"_setInteractionWidths",value:function(){"function"==typeof this.options.hoverWidth?this.edgeType.hoverWidth=this.options.hoverWidth(this.options.width):this.edgeType.hoverWidth=this.options.hoverWidth+this.options.width,"function"==typeof this.options.selectionWidth?this.edgeType.selectionWidth=this.options.selectionWidth(this.options.width):this.edgeType.selectionWidth=this.options.selectionWidth+this.options.width}},{key:"draw",value:function(t){var e=this.getFormattingValues();if(!e.hidden){var i=this.edgeType.getViaNode();this.edgeType.drawLine(t,e,this.selected,this.hover,i),this.drawLabel(t,i)}}},{key:"drawArrows",value:function(t){var e=this.getFormattingValues();if(!e.hidden){var i=this.edgeType.getViaNode(),n={};this.edgeType.fromPoint=this.edgeType.from,this.edgeType.toPoint=this.edgeType.to,e.fromArrow&&(n.from=this.edgeType.getArrowData(t,"from",i,this.selected,this.hover,e),!1===e.arrowStrikethrough&&(this.edgeType.fromPoint=n.from.core),e.fromArrowSrc&&(n.from.image=this.imagelist.load(e.fromArrowSrc)),e.fromArrowImageWidth&&(n.from.imageWidth=e.fromArrowImageWidth),e.fromArrowImageHeight&&(n.from.imageHeight=e.fromArrowImageHeight)),e.toArrow&&(n.to=this.edgeType.getArrowData(t,"to",i,this.selected,this.hover,e),!1===e.arrowStrikethrough&&(this.edgeType.toPoint=n.to.core),e.toArrowSrc&&(n.to.image=this.imagelist.load(e.toArrowSrc)),e.toArrowImageWidth&&(n.to.imageWidth=e.toArrowImageWidth),e.toArrowImageHeight&&(n.to.imageHeight=e.toArrowImageHeight)),e.middleArrow&&(n.middle=this.edgeType.getArrowData(t,"middle",i,this.selected,this.hover,e),e.middleArrowSrc&&(n.middle.image=this.imagelist.load(e.middleArrowSrc)),e.middleArrowImageWidth&&(n.middle.imageWidth=e.middleArrowImageWidth),e.middleArrowImageHeight&&(n.middle.imageHeight=e.middleArrowImageHeight)),e.fromArrow&&this.edgeType.drawArrowHead(t,e,this.selected,this.hover,n.from),e.middleArrow&&this.edgeType.drawArrowHead(t,e,this.selected,this.hover,n.middle),e.toArrow&&this.edgeType.drawArrowHead(t,e,this.selected,this.hover,n.to)}}},{key:"drawLabel",value:function(t,e){if(void 0!==this.options.label){var i,n=this.from,o=this.to;if(this.labelModule.differentState(this.selected,this.hover)&&this.labelModule.getTextSize(t,this.selected,this.hover),n.id!=o.id){this.labelModule.pointToSelf=!1,i=this.edgeType.getPoint(.5,e),t.save();var r=this._getRotation(t);0!=r.angle&&(t.translate(r.x,r.y),t.rotate(r.angle)),this.labelModule.draw(t,i.x,i.y,this.selected,this.hover),t.restore()}else{this.labelModule.pointToSelf=!0;var s=A0(t,this.options.selfReference.angle,this.options.selfReference.size,n);i=this._pointOnCircle(s.x,s.y,this.options.selfReference.size,this.options.selfReference.angle),this.labelModule.draw(t,i.x,i.y,this.selected,this.hover)}}}},{key:"getItemsOnPoint",value:function(t){var e=[];if(this.labelModule.visible()){var i=this._getRotation();b0(this.labelModule.getSize(),t,i)&&e.push({edgeId:this.id,labelId:0})}var n={left:t.x,top:t.y};return this.isOverlappingWith(n)&&e.push({edgeId:this.id}),e}},{key:"isOverlappingWith",value:function(t){if(this.connected){var e=this.from.x,i=this.from.y,n=this.to.x,o=this.to.y,r=t.left,s=t.top;return this.edgeType.getDistanceToEdge(e,i,n,o,r,s)<10}return!1}},{key:"_getRotation",value:function(t){var e=this.edgeType.getViaNode(),i=this.edgeType.getPoint(.5,e);void 0!==t&&this.labelModule.calculateLabelSize(t,this.selected,this.hover,i.x,i.y);var n={x:i.x,y:this.labelModule.size.yLine,angle:0};if(!this.labelModule.visible())return n;if("horizontal"===this.options.font.align)return n;var o=this.from.y-this.to.y,r=this.from.x-this.to.x,s=Math.atan2(o,r);return(s<-1&&r<0||s>0&&r<0)&&(s+=Math.PI),n.angle=s,n}},{key:"_pointOnCircle",value:function(t,e,i,n){return{x:t+i*Math.cos(n),y:e-i*Math.sin(n)}}},{key:"select",value:function(){this.selected=!0}},{key:"unselect",value:function(){this.selected=!1}},{key:"cleanup",value:function(){return this.edgeType.cleanup()}},{key:"remove",value:function(){this.cleanup(),this.disconnect(),delete this.body.edges[this.id]}},{key:"endPointsValid",value:function(){return void 0!==this.body.nodes[this.fromId]&&void 0!==this.body.nodes[this.toId]}}],[{key:"parseOptions",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},o=arguments.length>4&&void 0!==arguments[4]&&arguments[4];if(zJ(["endPointOffset","arrowStrikethrough","id","from","hidden","hoverWidth","labelHighlightBold","length","line","opacity","physics","scaling","selectionWidth","selfReferenceSize","selfReference","to","title","value","width","font","chosen","widthConstraint"],t,e,i),void 0!==e.endPointOffset&&void 0!==e.endPointOffset.from&&(k$(e.endPointOffset.from)?t.endPointOffset.from=e.endPointOffset.from:(t.endPointOffset.from=void 0!==n.endPointOffset.from?n.endPointOffset.from:0,console.error("endPointOffset.from is not a valid number"))),void 0!==e.endPointOffset&&void 0!==e.endPointOffset.to&&(k$(e.endPointOffset.to)?t.endPointOffset.to=e.endPointOffset.to:(t.endPointOffset.to=void 0!==n.endPointOffset.to?n.endPointOffset.to:0,console.error("endPointOffset.to is not a valid number"))),w0(e.label)?t.label=e.label:w0(t.label)||(t.label=void 0),ZJ(t,e,"smooth",n),ZJ(t,e,"shadow",n),ZJ(t,e,"background",n),void 0!==e.dashes&&null!==e.dashes?t.dashes=e.dashes:!0===i&&null===e.dashes&&(t.dashes=Vq(n.dashes)),void 0!==e.scaling&&null!==e.scaling?(void 0!==e.scaling.min&&(t.scaling.min=e.scaling.min),void 0!==e.scaling.max&&(t.scaling.max=e.scaling.max),ZJ(t.scaling,e.scaling,"label",n.scaling)):!0===i&&null===e.scaling&&(t.scaling=Vq(n.scaling)),void 0!==e.arrows&&null!==e.arrows)if("string"==typeof e.arrows){var r=e.arrows.toLowerCase();t.arrows.to.enabled=-1!=Lq(r).call(r,"to"),t.arrows.middle.enabled=-1!=Lq(r).call(r,"middle"),t.arrows.from.enabled=-1!=Lq(r).call(r,"from")}else{if("object"!==fW(e.arrows))throw new Error("The arrow newOptions can only be an object or a string. Refer to the documentation. You used:"+qq(e.arrows));ZJ(t.arrows,e.arrows,"to",n.arrows),ZJ(t.arrows,e.arrows,"middle",n.arrows),ZJ(t.arrows,e.arrows,"from",n.arrows)}else!0===i&&null===e.arrows&&(t.arrows=Vq(n.arrows));if(void 0!==e.color&&null!==e.color){var s=OJ(e.color)?{color:e.color,highlight:e.color,hover:e.color,inherit:!1,opacity:1}:e.color,a=t.color;if(o)FJ(a,n.color,!1,i);else for(var l in a)Object.prototype.hasOwnProperty.call(a,l)&&delete a[l];if(OJ(a))a.color=a,a.highlight=a,a.hover=a,a.inherit=!1,void 0===s.opacity&&(a.opacity=1);else{var h=!1;void 0!==s.color&&(a.color=s.color,h=!0),void 0!==s.highlight&&(a.highlight=s.highlight,h=!0),void 0!==s.hover&&(a.hover=s.hover,h=!0),void 0!==s.inherit&&(a.inherit=s.inherit),void 0!==s.opacity&&(a.opacity=Math.min(1,Math.max(0,s.opacity))),!0===h?a.inherit=!1:void 0===a.inherit&&(a.inherit="from")}}else!0===i&&null===e.color&&(t.color=YJ(n.color));!0===i&&null===e.font&&(t.font=YJ(n.font)),Object.prototype.hasOwnProperty.call(e,"selfReferenceSize")&&(console.warn("The selfReferenceSize property has been deprecated. Please use selfReference property instead. The selfReference can be set like thise selfReference:{size:30, angle:Math.PI / 4}"),t.selfReference.size=e.selfReferenceSize)}}]),t}(),Y2=function(){function t(e,i,n){var o,r=this;uU(this,t),this.body=e,this.images=i,this.groups=n,this.body.functions.createEdge=HF(o=this.create).call(o,this),this.edgesListeners={add:function(t,e){r.add(e.items)},update:function(t,e){r.update(e.items)},remove:function(t,e){r.remove(e.items)}},this.options={},this.defaultOptions={arrows:{to:{enabled:!1,scaleFactor:1,type:"arrow"},middle:{enabled:!1,scaleFactor:1,type:"arrow"},from:{enabled:!1,scaleFactor:1,type:"arrow"}},endPointOffset:{from:0,to:0},arrowStrikethrough:!0,color:{color:"#848484",highlight:"#848484",hover:"#848484",inherit:"from",opacity:1},dashes:!1,font:{color:"#343434",size:14,face:"arial",background:"none",strokeWidth:2,strokeColor:"#ffffff",align:"horizontal",multi:!1,vadjust:0,bold:{mod:"bold"},boldital:{mod:"bold italic"},ital:{mod:"italic"},mono:{mod:"",size:15,face:"courier new",vadjust:2}},hidden:!1,hoverWidth:1.5,label:void 0,labelHighlightBold:!0,length:void 0,physics:!0,scaling:{min:1,max:15,label:{enabled:!0,min:14,max:30,maxVisible:30,drawThreshold:5},customScalingFunction:function(t,e,i,n){if(e===t)return.5;var o=1/(e-t);return Math.max(0,(n-t)*o)}},selectionWidth:1.5,selfReference:{size:20,angle:Math.PI/4,renderBehindTheNode:!0},shadow:{enabled:!1,color:"rgba(0,0,0,0.5)",size:10,x:5,y:5},background:{enabled:!1,color:"rgba(111,111,111,1)",size:10,dashes:!1},smooth:{enabled:!0,type:"dynamic",forceDirection:"none",roundness:.5},title:void 0,width:1,value:void 0},FJ(this.options,this.defaultOptions),this.bindEventListeners()}return yW(t,[{key:"bindEventListeners",value:function(){var t,e,i=this;this.body.emitter.on("_forceDisableDynamicCurves",(function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];"dynamic"===t&&(t="continuous");var n=!1;for(var o in i.body.edges)if(Object.prototype.hasOwnProperty.call(i.body.edges,o)){var r=i.body.edges[o],s=i.body.data.edges.get(o);if(null!=s){var a=s.smooth;void 0!==a&&!0===a.enabled&&"dynamic"===a.type&&(void 0===t?r.setOptions({smooth:!1}):r.setOptions({smooth:{type:t}}),n=!0)}}!0===e&&!0===n&&i.body.emitter.emit("_dataChanged")})),this.body.emitter.on("_dataUpdated",(function(){i.reconnectEdges()})),this.body.emitter.on("refreshEdges",HF(t=this.refresh).call(t,this)),this.body.emitter.on("refresh",HF(e=this.refresh).call(e,this)),this.body.emitter.on("destroy",(function(){jJ(i.edgesListeners,(function(t,e){i.body.data.edges&&i.body.data.edges.off(e,t)})),delete i.body.functions.createEdge,delete i.edgesListeners.add,delete i.edgesListeners.update,delete i.edgesListeners.remove,delete i.edgesListeners}))}},{key:"setOptions",value:function(t){if(void 0!==t){q2.parseOptions(this.options,t,!0,this.defaultOptions,!0);var e=!1;if(void 0!==t.smooth)for(var i in this.body.edges)Object.prototype.hasOwnProperty.call(this.body.edges,i)&&(e=this.body.edges[i].updateEdgeType()||e);if(void 0!==t.font)for(var n in this.body.edges)Object.prototype.hasOwnProperty.call(this.body.edges,n)&&this.body.edges[n].updateLabelModule();void 0===t.hidden&&void 0===t.physics&&!0!==e||this.body.emitter.emit("_dataChanged")}}},{key:"setData",value:function(t){var e=this,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=this.body.data.edges;if(eR("id",t))this.body.data.edges=t;else if(AG(t))this.body.data.edges=new tR,this.body.data.edges.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.body.data.edges=new tR}if(n&&jJ(this.edgesListeners,(function(t,e){n.off(e,t)})),this.body.edges={},this.body.data.edges){jJ(this.edgesListeners,(function(t,i){e.body.data.edges.on(i,t)}));var o=this.body.data.edges.getIds();this.add(o,!0)}this.body.emitter.emit("_adjustEdgesForHierarchicalLayout"),!1===i&&this.body.emitter.emit("_dataChanged")}},{key:"add",value:function(t){for(var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=this.body.edges,n=this.body.data.edges,o=0;o1&&void 0!==arguments[1])||arguments[1];if(0!==t.length){var i=this.body.edges;jJ(t,(function(t){var e=i[t];void 0!==e&&e.remove()})),e&&this.body.emitter.emit("_dataChanged")}}},{key:"refresh",value:function(){var t=this;jJ(this.body.edges,(function(e,i){var n=t.body.data.edges.get(i);void 0!==n&&e.setOptions(n)}))}},{key:"create",value:function(t){return new q2(t,this.body,this.images,this.options,this.defaultOptions)}},{key:"reconnectEdges",value:function(){var t,e=this.body.nodes,i=this.body.edges;for(t in e)Object.prototype.hasOwnProperty.call(e,t)&&(e[t].edges=[]);for(t in i)if(Object.prototype.hasOwnProperty.call(i,t)){var n=i[t];n.from=null,n.to=null,n.connect()}}},{key:"getConnectedNodes",value:function(t){var e=[];if(void 0!==this.body.edges[t]){var i=this.body.edges[t];void 0!==i.fromId&&e.push(i.fromId),void 0!==i.toId&&e.push(i.toId)}return e}},{key:"_updateState",value:function(){this._addMissingEdges(),this._removeInvalidEdges()}},{key:"_removeInvalidEdges",value:function(){var t=this,e=[];jJ(this.body.edges,(function(i,n){var o=t.body.nodes[i.toId],r=t.body.nodes[i.fromId];void 0!==o&&!0===o.isCluster||void 0!==r&&!0===r.isCluster||void 0!==o&&void 0!==r||e.push(n)})),this.remove(e,!1)}},{key:"_addMissingEdges",value:function(){var t=this.body.data.edges;if(null!=t){var e=this.body.edges,i=[];YG(t).call(t,(function(t,n){void 0===e[n]&&i.push(n)})),this.add(i,!0)}}}]),t}(),Z2=function(){function t(e,i,n){uU(this,t),this.body=e,this.physicsBody=i,this.barnesHutTree,this.setOptions(n),this._rng=AJ("BARNES HUT SOLVER")}return yW(t,[{key:"setOptions",value:function(t){this.options=t,this.thetaInversed=1/this.options.theta,this.overlapAvoidanceFactor=1-Math.max(0,Math.min(1,this.options.avoidOverlap))}},{key:"solve",value:function(){if(0!==this.options.gravitationalConstant&&this.physicsBody.physicsNodeIndices.length>0){var t,e=this.body.nodes,i=this.physicsBody.physicsNodeIndices,n=i.length,o=this._formBarnesHutTree(e,i);this.barnesHutTree=o;for(var r=0;r0&&this._getForceContributions(o.root,t)}}},{key:"_getForceContributions",value:function(t,e){this._getForceContribution(t.children.NW,e),this._getForceContribution(t.children.NE,e),this._getForceContribution(t.children.SW,e),this._getForceContribution(t.children.SE,e)}},{key:"_getForceContribution",value:function(t,e){if(t.childrenCount>0){var i=t.centerOfMass.x-e.x,n=t.centerOfMass.y-e.y,o=Math.sqrt(i*i+n*n);o*t.calcSize>this.thetaInversed?this._calculateForces(o,i,n,e,t):4===t.childrenCount?this._getForceContributions(t,e):t.children.data.id!=e.id&&this._calculateForces(o,i,n,e,t)}}},{key:"_calculateForces",value:function(t,e,i,n,o){0===t&&(e=t=.1),this.overlapAvoidanceFactor<1&&n.shape.radius&&(t=Math.max(.1+this.overlapAvoidanceFactor*n.shape.radius,t-n.shape.radius));var r=this.options.gravitationalConstant*o.mass*n.options.mass/Math.pow(t,3),s=e*r,a=i*r;this.physicsBody.forces[n.id].x+=s,this.physicsBody.forces[n.id].y+=a}},{key:"_formBarnesHutTree",value:function(t,e){for(var i,n=e.length,o=t[e[0]].x,r=t[e[0]].y,s=t[e[0]].x,a=t[e[0]].y,l=1;l0&&(cs&&(s=c),da&&(a=d))}var u=Math.abs(s-o)-Math.abs(a-r);u>0?(r-=.5*u,a+=.5*u):(o+=.5*u,s-=.5*u);var f=Math.max(1e-5,Math.abs(s-o)),p=.5*f,v=.5*(o+s),g=.5*(r+a),y={root:{centerOfMass:{x:0,y:0},mass:0,range:{minX:v-p,maxX:v+p,minY:g-p,maxY:g+p},size:f,calcSize:1/f,children:{data:null},maxWidth:0,level:0,childrenCount:4}};this._splitBranch(y.root);for(var m=0;m0&&this._placeInTree(y.root,i);return y}},{key:"_updateBranchMass",value:function(t,e){var i=t.centerOfMass,n=t.mass+e.options.mass,o=1/n;i.x=i.x*t.mass+e.x*e.options.mass,i.x*=o,i.y=i.y*t.mass+e.y*e.options.mass,i.y*=o,t.mass=n;var r=Math.max(Math.max(e.height,e.radius),e.width);t.maxWidth=t.maxWidthe.x?o.maxY>e.y?"NW":"SW":o.maxY>e.y?"NE":"SE",this._placeInRegion(t,e,n)}},{key:"_placeInRegion",value:function(t,e,i){var n=t.children[i];switch(n.childrenCount){case 0:n.children.data=e,n.childrenCount=1,this._updateBranchMass(n,e);break;case 1:n.children.data.x===e.x&&n.children.data.y===e.y?(e.x+=this._rng(),e.y+=this._rng()):(this._splitBranch(n),this._placeInTree(n,e));break;case 4:this._placeInTree(n,e)}}},{key:"_splitBranch",value:function(t){var e=null;1===t.childrenCount&&(e=t.children.data,t.mass=0,t.centerOfMass.x=0,t.centerOfMass.y=0),t.childrenCount=4,t.children.data=null,this._insertRegion(t,"NW"),this._insertRegion(t,"NE"),this._insertRegion(t,"SW"),this._insertRegion(t,"SE"),null!=e&&this._placeInTree(t,e)}},{key:"_insertRegion",value:function(t,e){var i,n,o,r,s=.5*t.size;switch(e){case"NW":i=t.range.minX,n=t.range.minX+s,o=t.range.minY,r=t.range.minY+s;break;case"NE":i=t.range.minX+s,n=t.range.maxX,o=t.range.minY,r=t.range.minY+s;break;case"SW":i=t.range.minX,n=t.range.minX+s,o=t.range.minY+s,r=t.range.maxY;break;case"SE":i=t.range.minX+s,n=t.range.maxX,o=t.range.minY+s,r=t.range.maxY}t.children[e]={centerOfMass:{x:0,y:0},mass:0,range:{minX:i,maxX:n,minY:o,maxY:r},size:.5*t.size,calcSize:2*t.calcSize,children:{data:null},maxWidth:0,level:t.level+1,childrenCount:0}}},{key:"_debug",value:function(t,e){void 0!==this.barnesHutTree&&(t.lineWidth=1,this._drawBranch(this.barnesHutTree.root,t,e))}},{key:"_drawBranch",value:function(t,e,i){void 0===i&&(i="#FF0000"),4===t.childrenCount&&(this._drawBranch(t.children.NW,e),this._drawBranch(t.children.NE,e),this._drawBranch(t.children.SE,e),this._drawBranch(t.children.SW,e)),e.strokeStyle=i,e.beginPath(),e.moveTo(t.range.minX,t.range.minY),e.lineTo(t.range.maxX,t.range.minY),e.stroke(),e.beginPath(),e.moveTo(t.range.maxX,t.range.minY),e.lineTo(t.range.maxX,t.range.maxY),e.stroke(),e.beginPath(),e.moveTo(t.range.maxX,t.range.maxY),e.lineTo(t.range.minX,t.range.maxY),e.stroke(),e.beginPath(),e.moveTo(t.range.minX,t.range.maxY),e.lineTo(t.range.minX,t.range.minY),e.stroke()}}]),t}(),J2=function(){function t(e,i,n){uU(this,t),this._rng=AJ("REPULSION SOLVER"),this.body=e,this.physicsBody=i,this.setOptions(n)}return yW(t,[{key:"setOptions",value:function(t){this.options=t}},{key:"solve",value:function(){for(var t,e,i,n,o,r,s,a,l=this.body.nodes,h=this.physicsBody.physicsNodeIndices,c=this.physicsBody.forces,d=this.options.nodeDistance,u=-2/3/d,f=4/3,p=0;p0){var r=o.edges.length+1,s=this.options.centralGravity*r*o.options.mass;n[o.id].x=e*s,n[o.id].y=i*s}}}]),i}(t3),r3=function(){function t(e){uU(this,t),this.body=e,this.physicsBody={physicsNodeIndices:[],physicsEdgeIndices:[],forces:{},velocities:{}},this.physicsEnabled=!0,this.simulationInterval=1e3/60,this.requiresTimeout=!0,this.previousStates={},this.referenceState={},this.freezeCache={},this.renderTimer=void 0,this.adaptiveTimestep=!1,this.adaptiveTimestepEnabled=!1,this.adaptiveCounter=0,this.adaptiveInterval=3,this.stabilized=!1,this.startedStabilization=!1,this.stabilizationIterations=0,this.ready=!1,this.options={},this.defaultOptions={enabled:!0,barnesHut:{theta:.5,gravitationalConstant:-2e3,centralGravity:.3,springLength:95,springConstant:.04,damping:.09,avoidOverlap:0},forceAtlas2Based:{theta:.5,gravitationalConstant:-50,centralGravity:.01,springConstant:.08,springLength:100,damping:.4,avoidOverlap:0},repulsion:{centralGravity:.2,springLength:200,springConstant:.05,nodeDistance:100,damping:.09,avoidOverlap:0},hierarchicalRepulsion:{centralGravity:0,springLength:100,springConstant:.01,nodeDistance:120,damping:.09},maxVelocity:50,minVelocity:.75,solver:"barnesHut",stabilization:{enabled:!0,iterations:1e3,updateInterval:50,onlyDynamicEdges:!1,fit:!0},timestep:.5,adaptiveTimestep:!0,wind:{x:0,y:0}},wF(this.options,this.defaultOptions),this.timestep=.5,this.layoutFailed=!1,this.bindEventListeners()}return yW(t,[{key:"bindEventListeners",value:function(){var t=this;this.body.emitter.on("initPhysics",(function(){t.initPhysics()})),this.body.emitter.on("_layoutFailed",(function(){t.layoutFailed=!0})),this.body.emitter.on("resetPhysics",(function(){t.stopSimulation(),t.ready=!1})),this.body.emitter.on("disablePhysics",(function(){t.physicsEnabled=!1,t.stopSimulation()})),this.body.emitter.on("restorePhysics",(function(){t.setOptions(t.options),!0===t.ready&&t.startSimulation()})),this.body.emitter.on("startSimulation",(function(){!0===t.ready&&t.startSimulation()})),this.body.emitter.on("stopSimulation",(function(){t.stopSimulation()})),this.body.emitter.on("destroy",(function(){t.stopSimulation(!1),t.body.emitter.off()})),this.body.emitter.on("_dataChanged",(function(){t.updatePhysicsData()}))}},{key:"setOptions",value:function(t){if(void 0!==t)if(!1===t)this.options.enabled=!1,this.physicsEnabled=!1,this.stopSimulation();else if(!0===t)this.options.enabled=!0,this.physicsEnabled=!0,this.startSimulation();else{this.physicsEnabled=!0,PJ(["stabilization"],this.options,t),ZJ(this.options,t,"stabilization"),void 0===t.enabled&&(this.options.enabled=!0),!1===this.options.enabled&&(this.physicsEnabled=!1,this.stopSimulation());var e=this.options.wind;e&&(("number"!=typeof e.x||b$(e.x))&&(e.x=0),("number"!=typeof e.y||b$(e.y))&&(e.y=0)),this.timestep=this.options.timestep}this.init()}},{key:"init",value:function(){var t;"forceAtlas2Based"===this.options.solver?(t=this.options.forceAtlas2Based,this.nodesSolver=new i3(this.body,this.physicsBody,t),this.edgesSolver=new _2(this.body,this.physicsBody,t),this.gravitySolver=new o3(this.body,this.physicsBody,t)):"repulsion"===this.options.solver?(t=this.options.repulsion,this.nodesSolver=new J2(this.body,this.physicsBody,t),this.edgesSolver=new _2(this.body,this.physicsBody,t),this.gravitySolver=new t3(this.body,this.physicsBody,t)):"hierarchicalRepulsion"===this.options.solver?(t=this.options.hierarchicalRepulsion,this.nodesSolver=new X2(this.body,this.physicsBody,t),this.edgesSolver=new $2(this.body,this.physicsBody,t),this.gravitySolver=new t3(this.body,this.physicsBody,t)):(t=this.options.barnesHut,this.nodesSolver=new Z2(this.body,this.physicsBody,t),this.edgesSolver=new _2(this.body,this.physicsBody,t),this.gravitySolver=new t3(this.body,this.physicsBody,t)),this.modelOptions=t}},{key:"initPhysics",value:function(){!0===this.physicsEnabled&&!0===this.options.enabled?!0===this.options.stabilization.enabled?this.stabilize():(this.stabilized=!1,this.ready=!0,this.body.emitter.emit("fit",{},this.layoutFailed),this.startSimulation()):(this.ready=!0,this.body.emitter.emit("fit"))}},{key:"startSimulation",value:function(){var t;!0===this.physicsEnabled&&!0===this.options.enabled?(this.stabilized=!1,this.adaptiveTimestep=!1,this.body.emitter.emit("_resizeNodes"),void 0===this.viewFunction&&(this.viewFunction=HF(t=this.simulationStep).call(t,this),this.body.emitter.on("initRedraw",this.viewFunction),this.body.emitter.emit("_startRendering"))):this.body.emitter.emit("_redraw")}},{key:"stopSimulation",value:function(){var t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];this.stabilized=!0,!0===t&&this._emitStabilized(),void 0!==this.viewFunction&&(this.body.emitter.off("initRedraw",this.viewFunction),this.viewFunction=void 0,!0===t&&this.body.emitter.emit("_stopRendering"))}},{key:"simulationStep",value:function(){var t=FG();this.physicsTick(),(FG()-t<.4*this.simulationInterval||!0===this.runDoubleSpeed)&&!1===this.stabilized&&(this.physicsTick(),this.runDoubleSpeed=!0),!0===this.stabilized&&this.stopSimulation()}},{key:"_emitStabilized",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.stabilizationIterations;(this.stabilizationIterations>1||!0===this.startedStabilization)&&uY((function(){t.body.emitter.emit("stabilized",{iterations:e}),t.startedStabilization=!1,t.stabilizationIterations=0}),0)}},{key:"physicsStep",value:function(){this.gravitySolver.solve(),this.nodesSolver.solve(),this.edgesSolver.solve(),this.moveNodes()}},{key:"adjustTimeStep",value:function(){!0===this._evaluateStepQuality()?this.timestep=1.2*this.timestep:this.timestep/1.2.3))return!1;return!0}},{key:"moveNodes",value:function(){for(var t=this.physicsBody.physicsNodeIndices,e=0,i=0,n=0;nn&&(t=t>0?n:-n),t}},{key:"_performStep",value:function(t){var e=this.body.nodes[t],i=this.physicsBody.forces[t];this.options.wind&&(i.x+=this.options.wind.x,i.y+=this.options.wind.y);var n=this.physicsBody.velocities[t];return this.previousStates[t]={x:e.x,y:e.y,vx:n.x,vy:n.y},!1===e.options.fixed.x?(n.x=this.calculateComponentVelocity(n.x,i.x,e.options.mass),e.x+=n.x*this.timestep):(i.x=0,n.x=0),!1===e.options.fixed.y?(n.y=this.calculateComponentVelocity(n.y,i.y,e.options.mass),e.y+=n.y*this.timestep):(i.y=0,n.y=0),Math.sqrt(Math.pow(n.x,2)+Math.pow(n.y,2))}},{key:"_freezeNodes",value:function(){var t=this.body.nodes;for(var e in t)if(Object.prototype.hasOwnProperty.call(t,e)&&t[e].x&&t[e].y){var i=t[e].options.fixed;this.freezeCache[e]={x:i.x,y:i.y},i.x=!0,i.y=!0}}},{key:"_restoreFrozenNodes",value:function(){var t=this.body.nodes;for(var e in t)Object.prototype.hasOwnProperty.call(t,e)&&void 0!==this.freezeCache[e]&&(t[e].options.fixed.x=this.freezeCache[e].x,t[e].options.fixed.y=this.freezeCache[e].y);this.freezeCache={}}},{key:"stabilize",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.options.stabilization.iterations;"number"!=typeof e&&(e=this.options.stabilization.iterations,console.error("The stabilize method needs a numeric amount of iterations. Switching to default: ",e)),0!==this.physicsBody.physicsNodeIndices.length?(this.adaptiveTimestep=this.options.adaptiveTimestep,this.body.emitter.emit("_resizeNodes"),this.stopSimulation(),this.stabilized=!1,this.body.emitter.emit("_blockRedraw"),this.targetIterations=e,!0===this.options.stabilization.onlyDynamicEdges&&this._freezeNodes(),this.stabilizationIterations=0,uY((function(){return t._stabilizationBatch()}),0)):this.ready=!0}},{key:"_startStabilizing",value:function(){return!0!==this.startedStabilization&&(this.body.emitter.emit("startStabilizing"),this.startedStabilization=!0,!0)}},{key:"_stabilizationBatch",value:function(){var t=this,e=function(){return!1===t.stabilized&&t.stabilizationIterations1&&void 0!==arguments[1]?arguments[1]:[],n=1e9,o=-1e9,r=1e9,s=-1e9;if(i.length>0)for(var a=0;a(e=t[i[a]]).shape.boundingBox.left&&(r=e.shape.boundingBox.left),se.shape.boundingBox.top&&(n=e.shape.boundingBox.top),o1&&void 0!==arguments[1]?arguments[1]:[],n=1e9,o=-1e9,r=1e9,s=-1e9;if(i.length>0)for(var a=0;a(e=t[i[a]]).x&&(r=e.x),se.y&&(n=e.y),o=t&&i.push(o.id)}for(var r=0;r0&&void 0!==arguments[0]?arguments[0]:{},i=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(void 0===e.joinCondition)throw new Error("Cannot call clusterByNodeData without a joinCondition function in the options.");e=this._checkOptions(e);var n={},o={};jJ(this.body.nodes,(function(i,r){i.options&&!0===e.joinCondition(i.options)&&(n[r]=i,jJ(i.edges,(function(e){void 0===t.clusteredEdges[e.id]&&(o[e.id]=e)})))})),this._cluster(n,o,e,i)}},{key:"clusterByEdgeCount",value:function(t,e){var i=this,n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];e=this._checkOptions(e);for(var o,r,s,a=[],l={},h=function(){var n={},h={},d=i.body.nodeIndices[c],u=i.body.nodes[d];if(void 0===l[d]){s=0,r=[];for(var f=0;f0&&RG(h).length>0&&!0===v){var m=function(){for(var t=0;t1&&void 0!==arguments[1])||arguments[1];this.clusterByEdgeCount(1,t,e)}},{key:"clusterBridges",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];this.clusterByEdgeCount(2,t,e)}},{key:"clusterByConnection",value:function(t,e){var i,n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];if(void 0===t)throw new Error("No nodeId supplied to clusterByConnection!");if(void 0===this.body.nodes[t])throw new Error("The nodeId given to clusterByConnection does not exist!");var o=this.body.nodes[t];void 0===(e=this._checkOptions(e,o)).clusterNodeProperties.x&&(e.clusterNodeProperties.x=o.x),void 0===e.clusterNodeProperties.y&&(e.clusterNodeProperties.y=o.y),void 0===e.clusterNodeProperties.fixed&&(e.clusterNodeProperties.fixed={},e.clusterNodeProperties.fixed.x=o.options.fixed.x,e.clusterNodeProperties.fixed.y=o.options.fixed.y);var r={},s={},a=o.id,l=u3.cloneOptions(o);r[a]=o;for(var h=0;h-1&&(s[y.id]=y)}this._cluster(r,s,e,n)}},{key:"_createClusterEdges",value:function(t,e,i,n){for(var o,r,s,a,l,h,c=RG(t),d=[],u=0;u0&&void 0!==arguments[0]?arguments[0]:{};return void 0===t.clusterEdgeProperties&&(t.clusterEdgeProperties={}),void 0===t.clusterNodeProperties&&(t.clusterNodeProperties={}),t}},{key:"_cluster",value:function(t,e,i){var n=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],o=[];for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&void 0!==this.clusteredNodes[r]&&o.push(r);for(var s=0;so?e.x:o,r=e.ys?e.y:s;return{x:.5*(n+o),y:.5*(r+s)}}},{key:"openCluster",value:function(t,e){var i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];if(void 0===t)throw new Error("No clusterNodeId supplied to openCluster.");var n=this.body.nodes[t];if(void 0===n)throw new Error("The clusterNodeId supplied to openCluster does not exist.");if(!0!==n.isCluster||void 0===n.containedNodes||void 0===n.containedEdges)throw new Error("The node:"+t+" is not a valid cluster.");var o=this.findNode(t),r=Lq(o).call(o,t)-1;if(r>=0){var s=o[r];return this.body.nodes[s]._openChildCluster(t),delete this.body.nodes[t],void(!0===i&&this.body.emitter.emit("_dataChanged"))}var a=n.containedNodes,l=n.containedEdges;if(void 0!==e&&void 0!==e.releaseFunction&&"function"==typeof e.releaseFunction){var h={},c={x:n.x,y:n.y};for(var d in a)if(Object.prototype.hasOwnProperty.call(a,d)){var u=this.body.nodes[d];h[d]={x:u.x,y:u.y}}var f=e.releaseFunction(c,h);for(var p in a)if(Object.prototype.hasOwnProperty.call(a,p)){var v=this.body.nodes[p];void 0!==f[p]&&(v.x=void 0===f[p].x?n.x:f[p].x,v.y=void 0===f[p].y?n.y:f[p].y)}}else jJ(a,(function(t){!1===t.options.fixed.x&&(t.x=n.x),!1===t.options.fixed.y&&(t.y=n.y)}));for(var g in a)if(Object.prototype.hasOwnProperty.call(a,g)){var y=this.body.nodes[g];y.vx=n.vx,y.vy=n.vy,y.setOptions({physics:!0}),delete this.clusteredNodes[g]}for(var m=[],b=0;b0&&o<100;){var r=e.pop();if(void 0!==r){var s=this.body.edges[r];if(void 0!==s){o++;var a=s.clusteringEdgeReplacingIds;if(void 0===a)n.push(r);else for(var l=0;ln&&(n=r.edges.length),t+=r.edges.length,e+=Math.pow(r.edges.length,2),i+=1}t/=i;var s=(e/=i)-Math.pow(t,2),a=Math.sqrt(s),l=Math.floor(t+2*a);return l>n&&(l=n),l}},{key:"_createClusteredEdge",value:function(t,e,i,n,o){var r=u3.cloneOptions(i,"edge");FJ(r,n),r.from=t,r.to=e,r.id="clusterEdge:"+d3(),void 0!==o&&FJ(r,o);var s=this.body.functions.createEdge(r);return s.clusteringEdgeReplacingIds=[i.id],s.connect(),this.body.edges[s.id]=s,s}},{key:"_clusterEdges",value:function(t,e,i,n){if(e instanceof q2){var o=e,r={};r[o.id]=o,e=r}if(t instanceof J1){var s=t,a={};a[s.id]=s,t=a}if(null==i)throw new Error("_clusterEdges: parameter clusterNode required");for(var l in void 0===n&&(n=i.clusterEdgeProperties),this._createClusterEdges(t,e,i,n),e)if(Object.prototype.hasOwnProperty.call(e,l)&&void 0!==this.body.edges[l]){var h=this.body.edges[l];this._backupEdgeOptions(h),h.setOptions({physics:!1})}for(var c in t)Object.prototype.hasOwnProperty.call(t,c)&&(this.clusteredNodes[c]={clusterId:i.id,node:this.body.nodes[c]},this.body.nodes[c].setOptions({physics:!1}))}},{key:"_getClusterNodeForNode",value:function(t){if(void 0!==t){var e=this.clusteredNodes[t];if(void 0!==e){var i=e.clusterId;if(void 0!==i)return this.body.nodes[i]}}}},{key:"_filter",value:function(t,e){var i=[];return jJ(t,(function(t){e(t)&&i.push(t)})),i}},{key:"_updateState",value:function(){var t,e=this,i=[],n={},o=function(t){jJ(e.body.nodes,(function(e){!0===e.isCluster&&t(e)}))};for(t in this.clusteredNodes){if(Object.prototype.hasOwnProperty.call(this.clusteredNodes,t))void 0===this.body.nodes[t]&&i.push(t)}o((function(t){for(var e=0;e0}t.endPointsValid()&&o||(n[i]=i)})),o((function(t){jJ(n,(function(i){delete t.containedEdges[i],jJ(t.edges,(function(o,r){o.id!==i?o.clusteringEdgeReplacingIds=e._filter(o.clusteringEdgeReplacingIds,(function(t){return!n[t]})):t.edges[r]=null})),t.edges=e._filter(t.edges,(function(t){return null!==t}))}))})),jJ(n,(function(t){delete e.clusteredEdges[t]})),jJ(n,(function(t){delete e.body.edges[t]})),jJ(RG(this.body.edges),(function(t){var i=e.body.edges[t],n=e._isClusteredNode(i.fromId)||e._isClusteredNode(i.toId);if(n!==e._isClusteredEdge(i.id))if(n){var o=e._getClusterNodeForNode(i.fromId);void 0!==o&&e._clusterEdges(e.body.nodes[i.fromId],i,o);var r=e._getClusterNodeForNode(i.toId);void 0!==r&&e._clusterEdges(e.body.nodes[i.toId],i,r)}else delete e._clusterEdges[t],e._restoreEdge(i)}));for(var s=!1,a=!0,l=function(){var t=[];o((function(e){var i=RG(e.containedNodes).length,n=!0===e.options.allowSingleNodeCluster;(n&&i<1||!n&&i<2)&&t.push(e.id)}));for(var i=0;i0,s=s||a};a;)l();s&&this._updateState()}},{key:"_isClusteredNode",value:function(t){return void 0!==this.clusteredNodes[t]}},{key:"_isClusteredEdge",value:function(t){return void 0!==this.clusteredEdges[t]}}]),t}();var g3=function(){function t(e,i){var n;uU(this,t),void 0!==window&&(n=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame),window.requestAnimationFrame=void 0===n?function(t){t()}:n,this.body=e,this.canvas=i,this.redrawRequested=!1,this.renderTimer=void 0,this.requiresTimeout=!0,this.renderingActive=!1,this.renderRequests=0,this.allowRedraw=!0,this.dragging=!1,this.zooming=!1,this.options={},this.defaultOptions={hideEdgesOnDrag:!1,hideEdgesOnZoom:!1,hideNodesOnDrag:!1},wF(this.options,this.defaultOptions),this._determineBrowserMethod(),this.bindEventListeners()}return yW(t,[{key:"bindEventListeners",value:function(){var t,e=this;this.body.emitter.on("dragStart",(function(){e.dragging=!0})),this.body.emitter.on("dragEnd",(function(){e.dragging=!1})),this.body.emitter.on("zoom",(function(){e.zooming=!0,window.clearTimeout(e.zoomTimeoutId),e.zoomTimeoutId=uY((function(){var t;e.zooming=!1,HF(t=e._requestRedraw).call(t,e)()}),250)})),this.body.emitter.on("_resizeNodes",(function(){e._resizeNodes()})),this.body.emitter.on("_redraw",(function(){!1===e.renderingActive&&e._redraw()})),this.body.emitter.on("_blockRedraw",(function(){e.allowRedraw=!1})),this.body.emitter.on("_allowRedraw",(function(){e.allowRedraw=!0,e.redrawRequested=!1})),this.body.emitter.on("_requestRedraw",HF(t=this._requestRedraw).call(t,this)),this.body.emitter.on("_startRendering",(function(){e.renderRequests+=1,e.renderingActive=!0,e._startRendering()})),this.body.emitter.on("_stopRendering",(function(){e.renderRequests-=1,e.renderingActive=e.renderRequests>0,e.renderTimer=void 0})),this.body.emitter.on("destroy",(function(){e.renderRequests=0,e.allowRedraw=!1,e.renderingActive=!1,!0===e.requiresTimeout?clearTimeout(e.renderTimer):window.cancelAnimationFrame(e.renderTimer),e.body.emitter.off()}))}},{key:"setOptions",value:function(t){if(void 0!==t){zJ(["hideEdgesOnDrag","hideEdgesOnZoom","hideNodesOnDrag"],this.options,t)}}},{key:"_requestNextFrame",value:function(t,e){if("undefined"!=typeof window){var i,n=window;return!0===this.requiresTimeout?i=uY(t,e):n.requestAnimationFrame&&(i=n.requestAnimationFrame(t)),i}}},{key:"_startRendering",value:function(){var t;!0===this.renderingActive&&(void 0===this.renderTimer&&(this.renderTimer=this._requestNextFrame(HF(t=this._renderStep).call(t,this),this.simulationInterval)))}},{key:"_renderStep",value:function(){!0===this.renderingActive&&(this.renderTimer=void 0,!0===this.requiresTimeout&&this._startRendering(),this._redraw(),!1===this.requiresTimeout&&this._startRendering())}},{key:"redraw",value:function(){this.body.emitter.emit("setSize"),this._redraw()}},{key:"_requestRedraw",value:function(){var t=this;!0!==this.redrawRequested&&!1===this.renderingActive&&!0===this.allowRedraw&&(this.redrawRequested=!0,this._requestNextFrame((function(){t._redraw(!1)}),0))}},{key:"_redraw",value:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(!0===this.allowRedraw){this.body.emitter.emit("initRedraw"),this.redrawRequested=!1;var e={drawExternalLabels:null};0!==this.canvas.frame.canvas.width&&0!==this.canvas.frame.canvas.height||this.canvas.setSize(),this.canvas.setTransform();var i=this.canvas.getContext(),n=this.canvas.frame.canvas.clientWidth,o=this.canvas.frame.canvas.clientHeight;if(i.clearRect(0,0,n,o),0===this.canvas.frame.clientWidth)return;if(i.save(),i.translate(this.body.view.translation.x,this.body.view.translation.y),i.scale(this.body.view.scale,this.body.view.scale),i.beginPath(),this.body.emitter.emit("beforeDrawing",i),i.closePath(),!1===t&&(!1===this.dragging||!0===this.dragging&&!1===this.options.hideEdgesOnDrag)&&(!1===this.zooming||!0===this.zooming&&!1===this.options.hideEdgesOnZoom)&&this._drawEdges(i),!1===this.dragging||!0===this.dragging&&!1===this.options.hideNodesOnDrag){var r=this._drawNodes(i,t).drawExternalLabels;e.drawExternalLabels=r}!1===t&&(!1===this.dragging||!0===this.dragging&&!1===this.options.hideEdgesOnDrag)&&(!1===this.zooming||!0===this.zooming&&!1===this.options.hideEdgesOnZoom)&&this._drawArrows(i),null!=e.drawExternalLabels&&e.drawExternalLabels(),!1===t&&this._drawSelectionBox(i),i.beginPath(),this.body.emitter.emit("afterDrawing",i),i.closePath(),i.restore(),!0===t&&i.clearRect(0,0,n,o)}}},{key:"_resizeNodes",value:function(){this.canvas.setTransform();var t=this.canvas.getContext();t.save(),t.translate(this.body.view.translation.x,this.body.view.translation.y),t.scale(this.body.view.scale,this.body.view.scale);var e,i=this.body.nodes;for(var n in i)Object.prototype.hasOwnProperty.call(i,n)&&((e=i[n]).resize(t),e.updateBoundingBox(t,e.selected));t.restore()}},{key:"_drawNodes",value:function(t){for(var e,i,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],o=this.body.nodes,r=this.body.nodeIndices,s=[],a=[],l=this.canvas.DOMtoCanvas({x:-20,y:-20}),h=this.canvas.DOMtoCanvas({x:this.canvas.frame.canvas.clientWidth+20,y:this.canvas.frame.canvas.clientHeight+20}),c={top:l.y,left:l.x,bottom:h.y,right:h.x},d=[],u=0;u0&&void 0!==arguments[0]?arguments[0]:this.pixelRatio;!0===this.initialized&&(this.cameraState.previousWidth=this.frame.canvas.width/t,this.cameraState.previousHeight=this.frame.canvas.height/t,this.cameraState.scale=this.body.view.scale,this.cameraState.position=this.DOMtoCanvas({x:.5*this.frame.canvas.width/t,y:.5*this.frame.canvas.height/t}))}},{key:"_setCameraState",value:function(){if(void 0!==this.cameraState.scale&&0!==this.frame.canvas.clientWidth&&0!==this.frame.canvas.clientHeight&&0!==this.pixelRatio&&this.cameraState.previousWidth>0&&this.cameraState.previousHeight>0){var t=this.frame.canvas.width/this.pixelRatio/this.cameraState.previousWidth,e=this.frame.canvas.height/this.pixelRatio/this.cameraState.previousHeight,i=this.cameraState.scale;1!=t&&1!=e?i=.5*this.cameraState.scale*(t+e):1!=t?i=this.cameraState.scale*t:1!=e&&(i=this.cameraState.scale*e),this.body.view.scale=i;var n=this.DOMtoCanvas({x:.5*this.frame.canvas.clientWidth,y:.5*this.frame.canvas.clientHeight}),o={x:n.x-this.cameraState.position.x,y:n.y-this.cameraState.position.y};this.body.view.translation.x+=o.x*this.body.view.scale,this.body.view.translation.y+=o.y*this.body.view.scale}}},{key:"_prepareValue",value:function(t){if("number"==typeof t)return t+"px";if("string"==typeof t){if(-1!==Lq(t).call(t,"%")||-1!==Lq(t).call(t,"px"))return t;if(-1===Lq(t).call(t,"%"))return t+"px"}throw new Error("Could not use the value supplied for width or height:"+t)}},{key:"_create",value:function(){for(;this.body.container.hasChildNodes();)this.body.container.removeChild(this.body.container.firstChild);if(this.frame=document.createElement("div"),this.frame.className="vis-network",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.tabIndex=0,this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),this.frame.canvas.getContext)this._setPixelRatio(),this.setTransform();else{var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerText="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t)}this.body.container.appendChild(this.frame),this.body.view.scale=1,this.body.view.translation={x:.5*this.frame.canvas.clientWidth,y:.5*this.frame.canvas.clientHeight},this._bindHammer()}},{key:"_bindHammer",value:function(){var t=this;void 0!==this.hammer&&this.hammer.destroy(),this.drag={},this.pinch={},this.hammer=new hX(this.frame.canvas),this.hammer.get("pinch").set({enable:!0}),this.hammer.get("pan").set({threshold:5,direction:hX.DIRECTION_ALL}),m3(this.hammer,(function(e){t.body.eventListeners.onTouch(e)})),this.hammer.on("tap",(function(e){t.body.eventListeners.onTap(e)})),this.hammer.on("doubletap",(function(e){t.body.eventListeners.onDoubleTap(e)})),this.hammer.on("press",(function(e){t.body.eventListeners.onHold(e)})),this.hammer.on("panstart",(function(e){t.body.eventListeners.onDragStart(e)})),this.hammer.on("panmove",(function(e){t.body.eventListeners.onDrag(e)})),this.hammer.on("panend",(function(e){t.body.eventListeners.onDragEnd(e)})),this.hammer.on("pinch",(function(e){t.body.eventListeners.onPinch(e)})),this.frame.canvas.addEventListener("wheel",(function(e){t.body.eventListeners.onMouseWheel(e)})),this.frame.canvas.addEventListener("mousemove",(function(e){t.body.eventListeners.onMouseMove(e)})),this.frame.canvas.addEventListener("contextmenu",(function(e){t.body.eventListeners.onContext(e)})),this.hammerFrame=new hX(this.frame),b3(this.hammerFrame,(function(e){t.body.eventListeners.onRelease(e)}))}},{key:"setSize",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.options.width,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.options.height;t=this._prepareValue(t),e=this._prepareValue(e);var i=!1,n=this.frame.canvas.width,o=this.frame.canvas.height,r=this.pixelRatio;if(this._setPixelRatio(),t!=this.options.width||e!=this.options.height||this.frame.style.width!=t||this.frame.style.height!=e)this._getCameraState(r),this.frame.style.width=t,this.frame.style.height=e,this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=Math.round(this.frame.canvas.clientWidth*this.pixelRatio),this.frame.canvas.height=Math.round(this.frame.canvas.clientHeight*this.pixelRatio),this.options.width=t,this.options.height=e,this.canvasViewCenter={x:.5*this.frame.clientWidth,y:.5*this.frame.clientHeight},i=!0;else{var s=Math.round(this.frame.canvas.clientWidth*this.pixelRatio),a=Math.round(this.frame.canvas.clientHeight*this.pixelRatio);this.frame.canvas.width===s&&this.frame.canvas.height===a||this._getCameraState(r),this.frame.canvas.width!==s&&(this.frame.canvas.width=s,i=!0),this.frame.canvas.height!==a&&(this.frame.canvas.height=a,i=!0)}return!0===i&&(this.body.emitter.emit("resize",{width:Math.round(this.frame.canvas.width/this.pixelRatio),height:Math.round(this.frame.canvas.height/this.pixelRatio),oldWidth:Math.round(n/this.pixelRatio),oldHeight:Math.round(o/this.pixelRatio)}),this._setCameraState()),this.initialized=!0,i}},{key:"getContext",value:function(){return this.frame.canvas.getContext("2d")}},{key:"_determinePixelRatio",value:function(){var t=this.getContext();if(void 0===t)throw new Error("Could not get canvax context");var e=1;return"undefined"!=typeof window&&(e=window.devicePixelRatio||1),e/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1)}},{key:"_setPixelRatio",value:function(){this.pixelRatio=this._determinePixelRatio()}},{key:"setTransform",value:function(){var t=this.getContext();if(void 0===t)throw new Error("Could not get canvax context");t.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0)}},{key:"_XconvertDOMtoCanvas",value:function(t){return(t-this.body.view.translation.x)/this.body.view.scale}},{key:"_XconvertCanvasToDOM",value:function(t){return t*this.body.view.scale+this.body.view.translation.x}},{key:"_YconvertDOMtoCanvas",value:function(t){return(t-this.body.view.translation.y)/this.body.view.scale}},{key:"_YconvertCanvasToDOM",value:function(t){return t*this.body.view.scale+this.body.view.translation.y}},{key:"canvasToDOM",value:function(t){return{x:this._XconvertCanvasToDOM(t.x),y:this._YconvertCanvasToDOM(t.y)}}},{key:"DOMtoCanvas",value:function(t){return{x:this._XconvertDOMtoCanvas(t.x),y:this._YconvertDOMtoCanvas(t.y)}}}]),t}();var A3=function(){function t(e,i){var n,o,r=this;uU(this,t),this.body=e,this.canvas=i,this.animationSpeed=1/this.renderRefreshRate,this.animationEasingFunction="easeInOutQuint",this.easingTime=0,this.sourceScale=0,this.targetScale=0,this.sourceTranslation=0,this.targetTranslation=0,this.lockedOnNodeId=void 0,this.lockedOnNodeOffset=void 0,this.touchTime=0,this.viewFunction=void 0,this.body.emitter.on("fit",HF(n=this.fit).call(n,this)),this.body.emitter.on("animationFinished",(function(){r.body.emitter.emit("_stopRendering")})),this.body.emitter.on("unlockNode",HF(o=this.releaseNode).call(o,this))}return yW(t,[{key:"setOptions",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.options=t}},{key:"fit",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];t=function(t,e){var i=wF({nodes:e,minZoomLevel:Number.MIN_VALUE,maxZoomLevel:1},null!=t?t:{});if(!AG(i.nodes))throw new TypeError("Nodes has to be an array of ids.");if(0===i.nodes.length&&(i.nodes=e),!("number"==typeof i.minZoomLevel&&i.minZoomLevel>0))throw new TypeError("Min zoom level has to be a number higher than zero.");if(!("number"==typeof i.maxZoomLevel&&i.minZoomLevel<=i.maxZoomLevel))throw new TypeError("Max zoom level has to be a number higher than min zoom level.");return i}(t,this.body.nodeIndices);var i,n,o=this.canvas.frame.canvas.clientWidth,r=this.canvas.frame.canvas.clientHeight;if(0===o||0===r)n=1,i=u3.getRange(this.body.nodes,t.nodes);else if(!0===e){var s=0;for(var a in this.body.nodes){if(Object.prototype.hasOwnProperty.call(this.body.nodes,a))!0===this.body.nodes[a].predefinedPosition&&(s+=1)}if(s>.5*this.body.nodeIndices.length)return void this.fit(t,!1);i=u3.getRange(this.body.nodes,t.nodes),n=12.662/(this.body.nodeIndices.length+7.4147)+.0964822,n*=Math.min(o/600,r/600)}else{this.body.emitter.emit("_resizeNodes"),i=u3.getRange(this.body.nodes,t.nodes);var l=o/(1.1*Math.abs(i.maxX-i.minX)),h=r/(1.1*Math.abs(i.maxY-i.minY));n=l<=h?l:h}n>t.maxZoomLevel?n=t.maxZoomLevel:n1&&void 0!==arguments[1]?arguments[1]:{};if(void 0!==this.body.nodes[t]){var i={x:this.body.nodes[t].x,y:this.body.nodes[t].y};e.position=i,e.lockedOnNode=t,this.moveTo(e)}else console.error("Node: "+t+" cannot be found.")}},{key:"moveTo",value:function(t){if(void 0!==t){if(null!=t.offset){if(null!=t.offset.x){if(t.offset.x=+t.offset.x,!k$(t.offset.x))throw new TypeError('The option "offset.x" has to be a finite number.')}else t.offset.x=0;if(null!=t.offset.y){if(t.offset.y=+t.offset.y,!k$(t.offset.y))throw new TypeError('The option "offset.y" has to be a finite number.')}else t.offset.x=0}else t.offset={x:0,y:0};if(null!=t.position){if(null!=t.position.x){if(t.position.x=+t.position.x,!k$(t.position.x))throw new TypeError('The option "position.x" has to be a finite number.')}else t.position.x=0;if(null!=t.position.y){if(t.position.y=+t.position.y,!k$(t.position.y))throw new TypeError('The option "position.y" has to be a finite number.')}else t.position.x=0}else t.position=this.getViewPosition();if(null!=t.scale){if(t.scale=+t.scale,!(t.scale>0))throw new TypeError('The option "scale" has to be a number greater than zero.')}else t.scale=this.body.view.scale;void 0===t.animation&&(t.animation={duration:0}),!1===t.animation&&(t.animation={duration:0}),!0===t.animation&&(t.animation={}),void 0===t.animation.duration&&(t.animation.duration=1e3),void 0===t.animation.easingFunction&&(t.animation.easingFunction="easeInOutQuad"),this.animateView(t)}else t={}}},{key:"animateView",value:function(t){if(void 0!==t){this.animationEasingFunction=t.animation.easingFunction,this.releaseNode(),!0===t.locked&&(this.lockedOnNodeId=t.lockedOnNode,this.lockedOnNodeOffset=t.offset),0!=this.easingTime&&this._transitionRedraw(!0),this.sourceScale=this.body.view.scale,this.sourceTranslation=this.body.view.translation,this.targetScale=t.scale,this.body.view.scale=this.targetScale;var e,i,n=this.canvas.DOMtoCanvas({x:.5*this.canvas.frame.canvas.clientWidth,y:.5*this.canvas.frame.canvas.clientHeight}),o=n.x-t.position.x,r=n.y-t.position.y;if(this.targetTranslation={x:this.sourceTranslation.x+o*this.targetScale+t.offset.x,y:this.sourceTranslation.y+r*this.targetScale+t.offset.y},0===t.animation.duration)if(null!=this.lockedOnNodeId)this.viewFunction=HF(e=this._lockedRedraw).call(e,this),this.body.emitter.on("initRedraw",this.viewFunction);else this.body.view.scale=this.targetScale,this.body.view.translation=this.targetTranslation,this.body.emitter.emit("_requestRedraw");else this.animationSpeed=1/(60*t.animation.duration*.001)||1/60,this.animationEasingFunction=t.animation.easingFunction,this.viewFunction=HF(i=this._transitionRedraw).call(i,this),this.body.emitter.on("initRedraw",this.viewFunction),this.body.emitter.emit("_startRendering")}}},{key:"_lockedRedraw",value:function(){var t=this.body.nodes[this.lockedOnNodeId].x,e=this.body.nodes[this.lockedOnNodeId].y,i=this.canvas.DOMtoCanvas({x:.5*this.canvas.frame.canvas.clientWidth,y:.5*this.canvas.frame.canvas.clientHeight}),n=i.x-t,o=i.y-e,r=this.body.view.translation,s={x:r.x+n*this.body.view.scale+this.lockedOnNodeOffset.x,y:r.y+o*this.body.view.scale+this.lockedOnNodeOffset.y};this.body.view.translation=s}},{key:"releaseNode",value:function(){void 0!==this.lockedOnNodeId&&void 0!==this.viewFunction&&(this.body.emitter.off("initRedraw",this.viewFunction),this.lockedOnNodeId=void 0,this.lockedOnNodeOffset=void 0)}},{key:"_transitionRedraw",value:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];this.easingTime+=this.animationSpeed,this.easingTime=!0===t?1:this.easingTime;var e=JJ[this.animationEasingFunction](this.easingTime);if(this.body.view.scale=this.sourceScale+(this.targetScale-this.sourceScale)*e,this.body.view.translation={x:this.sourceTranslation.x+(this.targetTranslation.x-this.sourceTranslation.x)*e,y:this.sourceTranslation.y+(this.targetTranslation.y-this.sourceTranslation.y)*e},this.easingTime>=1){var i;if(this.body.emitter.off("initRedraw",this.viewFunction),this.easingTime=0,null!=this.lockedOnNodeId)this.viewFunction=HF(i=this._lockedRedraw).call(i,this),this.body.emitter.on("initRedraw",this.viewFunction);this.body.emitter.emit("animationFinished")}}},{key:"getScale",value:function(){return this.body.view.scale}},{key:"getViewPosition",value:function(){return this.canvas.DOMtoCanvas({x:.5*this.canvas.frame.canvas.clientWidth,y:.5*this.canvas.frame.canvas.clientHeight})}}]),t}();function k3(t){var e,i=t&&t.preventDefault||!1,n=t&&t.container||window,o={},r={keydown:{},keyup:{}},s={};for(e=97;e<=122;e++)s[String.fromCharCode(e)]={code:e-97+65,shift:!1};for(e=65;e<=90;e++)s[String.fromCharCode(e)]={code:e,shift:!0};for(e=0;e<=9;e++)s[""+e]={code:48+e,shift:!1};for(e=1;e<=12;e++)s["F"+e]={code:111+e,shift:!1};for(e=0;e<=9;e++)s["num"+e]={code:96+e,shift:!1};s["num*"]={code:106,shift:!1},s["num+"]={code:107,shift:!1},s["num-"]={code:109,shift:!1},s["num/"]={code:111,shift:!1},s["num."]={code:110,shift:!1},s.left={code:37,shift:!1},s.up={code:38,shift:!1},s.right={code:39,shift:!1},s.down={code:40,shift:!1},s.space={code:32,shift:!1},s.enter={code:13,shift:!1},s.shift={code:16,shift:void 0},s.esc={code:27,shift:!1},s.backspace={code:8,shift:!1},s.tab={code:9,shift:!1},s.ctrl={code:17,shift:!1},s.alt={code:18,shift:!1},s.delete={code:46,shift:!1},s.pageup={code:33,shift:!1},s.pagedown={code:34,shift:!1},s["="]={code:187,shift:!1},s["-"]={code:189,shift:!1},s["]"]={code:221,shift:!1},s["["]={code:219,shift:!1};var a=function(t){h(t,"keydown")},l=function(t){h(t,"keyup")},h=function(t,e){if(void 0!==r[e][t.keyCode]){for(var n=r[e][t.keyCode],o=0;o700&&(this.body.emitter.emit("fit",{duration:700}),this.touchTime=(new Date).valueOf())}},{key:"_stopMovement",value:function(){for(var t in this.boundFunctions)Object.prototype.hasOwnProperty.call(this.boundFunctions,t)&&(this.body.emitter.off("initRedraw",this.boundFunctions[t]),this.body.emitter.emit("_stopRendering"));this.boundFunctions={}}},{key:"_moveUp",value:function(){this.body.view.translation.y+=this.options.keyboard.speed.y}},{key:"_moveDown",value:function(){this.body.view.translation.y-=this.options.keyboard.speed.y}},{key:"_moveLeft",value:function(){this.body.view.translation.x+=this.options.keyboard.speed.x}},{key:"_moveRight",value:function(){this.body.view.translation.x-=this.options.keyboard.speed.x}},{key:"_zoomIn",value:function(){var t=this.body.view.scale,e=this.body.view.scale*(1+this.options.keyboard.speed.zoom),i=this.body.view.translation,n=e/t,o=(1-n)*this.canvas.canvasViewCenter.x+i.x*n,r=(1-n)*this.canvas.canvasViewCenter.y+i.y*n;this.body.view.scale=e,this.body.view.translation={x:o,y:r},this.body.emitter.emit("zoom",{direction:"+",scale:this.body.view.scale,pointer:null})}},{key:"_zoomOut",value:function(){var t=this.body.view.scale,e=this.body.view.scale/(1+this.options.keyboard.speed.zoom),i=this.body.view.translation,n=e/t,o=(1-n)*this.canvas.canvasViewCenter.x+i.x*n,r=(1-n)*this.canvas.canvasViewCenter.y+i.y*n;this.body.view.scale=e,this.body.view.translation={x:o,y:r},this.body.emitter.emit("zoom",{direction:"-",scale:this.body.view.scale,pointer:null})}},{key:"configureKeyboardBindings",value:function(){var t,e,i,n,o,r,s,a,l,h,c,d,u,f,p,v,g,y,m,b,w,A,k,E,C=this;(void 0!==this.keycharm&&this.keycharm.destroy(),!0===this.options.keyboard.enabled)&&(!0===this.options.keyboard.bindToWindow?this.keycharm=k3({container:window,preventDefault:!0}):this.keycharm=k3({container:this.canvas.frame,preventDefault:!0}),this.keycharm.reset(),!0===this.activated&&(HF(t=this.keycharm).call(t,"up",(function(){C.bindToRedraw("_moveUp")}),"keydown"),HF(e=this.keycharm).call(e,"down",(function(){C.bindToRedraw("_moveDown")}),"keydown"),HF(i=this.keycharm).call(i,"left",(function(){C.bindToRedraw("_moveLeft")}),"keydown"),HF(n=this.keycharm).call(n,"right",(function(){C.bindToRedraw("_moveRight")}),"keydown"),HF(o=this.keycharm).call(o,"=",(function(){C.bindToRedraw("_zoomIn")}),"keydown"),HF(r=this.keycharm).call(r,"num+",(function(){C.bindToRedraw("_zoomIn")}),"keydown"),HF(s=this.keycharm).call(s,"num-",(function(){C.bindToRedraw("_zoomOut")}),"keydown"),HF(a=this.keycharm).call(a,"-",(function(){C.bindToRedraw("_zoomOut")}),"keydown"),HF(l=this.keycharm).call(l,"[",(function(){C.bindToRedraw("_zoomOut")}),"keydown"),HF(h=this.keycharm).call(h,"]",(function(){C.bindToRedraw("_zoomIn")}),"keydown"),HF(c=this.keycharm).call(c,"pageup",(function(){C.bindToRedraw("_zoomIn")}),"keydown"),HF(d=this.keycharm).call(d,"pagedown",(function(){C.bindToRedraw("_zoomOut")}),"keydown"),HF(u=this.keycharm).call(u,"up",(function(){C.unbindFromRedraw("_moveUp")}),"keyup"),HF(f=this.keycharm).call(f,"down",(function(){C.unbindFromRedraw("_moveDown")}),"keyup"),HF(p=this.keycharm).call(p,"left",(function(){C.unbindFromRedraw("_moveLeft")}),"keyup"),HF(v=this.keycharm).call(v,"right",(function(){C.unbindFromRedraw("_moveRight")}),"keyup"),HF(g=this.keycharm).call(g,"=",(function(){C.unbindFromRedraw("_zoomIn")}),"keyup"),HF(y=this.keycharm).call(y,"num+",(function(){C.unbindFromRedraw("_zoomIn")}),"keyup"),HF(m=this.keycharm).call(m,"num-",(function(){C.unbindFromRedraw("_zoomOut")}),"keyup"),HF(b=this.keycharm).call(b,"-",(function(){C.unbindFromRedraw("_zoomOut")}),"keyup"),HF(w=this.keycharm).call(w,"[",(function(){C.unbindFromRedraw("_zoomOut")}),"keyup"),HF(A=this.keycharm).call(A,"]",(function(){C.unbindFromRedraw("_zoomIn")}),"keyup"),HF(k=this.keycharm).call(k,"pageup",(function(){C.unbindFromRedraw("_zoomIn")}),"keyup"),HF(E=this.keycharm).call(E,"pagedown",(function(){C.unbindFromRedraw("_zoomOut")}),"keyup")))}}]),t}();function C3(t,e){var i=void 0!==aG&&dU(t)||t["@@iterator"];if(!i){if(AG(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return x3(t,e);var n=pG(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return WL(t);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return x3(t,e)}(t))||e){i&&(t=i);var n=0,o=function(){};return{s:o,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function x3(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i50&&(this.drag.pointer=this.getPointer(t.center),this.drag.pinched=!1,this.pinch.scale=this.body.view.scale,this.touchTime=(new Date).valueOf())}},{key:"onTap",value:function(t){var e=this.getPointer(t.center),i=this.selectionHandler.options.multiselect&&(t.changedPointers[0].ctrlKey||t.changedPointers[0].metaKey);this.checkSelectionChanges(e,i),this.selectionHandler.commitAndEmit(e,t),this.selectionHandler.generateClickEvent("click",t,e)}},{key:"onDoubleTap",value:function(t){var e=this.getPointer(t.center);this.selectionHandler.generateClickEvent("doubleClick",t,e)}},{key:"onHold",value:function(t){var e=this.getPointer(t.center),i=this.selectionHandler.options.multiselect;this.checkSelectionChanges(e,i),this.selectionHandler.commitAndEmit(e,t),this.selectionHandler.generateClickEvent("click",t,e),this.selectionHandler.generateClickEvent("hold",t,e)}},{key:"onRelease",value:function(t){if((new Date).valueOf()-this.touchTime>10){var e=this.getPointer(t.center);this.selectionHandler.generateClickEvent("release",t,e),this.touchTime=(new Date).valueOf()}}},{key:"onContext",value:function(t){var e=this.getPointer({x:t.clientX,y:t.clientY});this.selectionHandler.generateClickEvent("oncontext",t,e)}},{key:"checkSelectionChanges",value:function(t){!0===(arguments.length>1&&void 0!==arguments[1]&&arguments[1])?this.selectionHandler.selectAdditionalOnPoint(t):this.selectionHandler.selectOnPoint(t)}},{key:"_determineDifference",value:function(t,e){var i=function(t,e){for(var i=[],n=0;n=o.minX&&i.x<=o.maxX&&i.y>=o.minY&&i.y<=o.maxY}));YG(r).call(r,(function(t){return e.selectionHandler.selectObject(e.body.nodes[t])}));var s=this.getPointer(t.center);this.selectionHandler.commitAndEmit(s,t),this.selectionHandler.generateClickEvent("dragEnd",t,this.getPointer(t.center),void 0,!0),this.body.emitter.emit("_requestRedraw")}else{var a=this.drag.selection;a&&a.length?(YG(a).call(a,(function(t){t.node.options.fixed.x=t.xFixed,t.node.options.fixed.y=t.yFixed})),this.selectionHandler.generateClickEvent("dragEnd",t,this.getPointer(t.center)),this.body.emitter.emit("startSimulation")):(this.selectionHandler.generateClickEvent("dragEnd",t,this.getPointer(t.center),void 0,!0),this.body.emitter.emit("_requestRedraw"))}}},{key:"onPinch",value:function(t){var e=this.getPointer(t.center);this.drag.pinched=!0,void 0===this.pinch.scale&&(this.pinch.scale=1);var i=this.pinch.scale*t.scale;this.zoom(i,e)}},{key:"zoom",value:function(t,e){if(!0===this.options.zoomView){var i=this.body.view.scale;t<1e-5&&(t=1e-5),t>10&&(t=10);var n=void 0;void 0!==this.drag&&!0===this.drag.dragging&&(n=this.canvas.DOMtoCanvas(this.drag.pointer));var o=this.body.view.translation,r=t/i,s=(1-r)*e.x+o.x*r,a=(1-r)*e.y+o.y*r;if(this.body.view.scale=t,this.body.view.translation={x:s,y:a},null!=n){var l=this.canvas.canvasToDOM(n);this.drag.pointer.x=l.x,this.drag.pointer.y=l.y}this.body.emitter.emit("_requestRedraw"),i0&&(this.popupObj=h[c[c.length-1]],r=!0)}if(void 0===this.popupObj&&!1===r){for(var u,f=this.body.edgeIndices,p=this.body.edges,v=[],g=0;g0&&(this.popupObj=p[v[v.length-1]],s="edge")}void 0!==this.popupObj?this.popupObj.id!==o&&(void 0===this.popup&&(this.popup=new cX(this.canvas.frame)),this.popup.popupTargetType=s,this.popup.popupTargetId=this.popupObj.id,this.popup.setPosition(t.x+3,t.y-5),this.popup.setText(this.popupObj.getTitle()),this.popup.show(),this.body.emitter.emit("showPopup",this.popupObj.id)):void 0!==this.popup&&(this.popup.hide(),this.body.emitter.emit("hidePopup"))}},{key:"_checkHidePopup",value:function(t){var e=this.selectionHandler._pointerToPositionObject(t),i=!1;if("node"===this.popup.popupTargetType){if(void 0!==this.body.nodes[this.popup.popupTargetId]&&!0===(i=this.body.nodes[this.popup.popupTargetId].isOverlappingWith(e))){var n=this.selectionHandler.getNodeAt(t);i=void 0!==n&&n.id===this.popup.popupTargetId}}else void 0===this.selectionHandler.getNodeAt(t)&&void 0!==this.body.edges[this.popup.popupTargetId]&&(i=this.body.edges[this.popup.popupTargetId].isOverlappingWith(e));!1===i&&(this.popupObj=void 0,this.popup.hide(),this.body.emitter.emit("hidePopup"))}}]),t}();Z_("Set",(function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}}),g$);var S3=nR(iB.Set),M3=yR,O3=X_,D3=v_.getWeakData,R3=B_,B3=nP,z3=KR,P3=eB,F3=O_,T3=$B,N3=UT.set,j3=UT.getterFor,L3=BQ.find,U3=BQ.findIndex,Q3=M3([].splice),H3=0,V3=function(t){return t.frozen||(t.frozen=new W3)},W3=function(){this.entries=[]},G3=function(t,e){return L3(t.entries,(function(t){return t[0]===e}))};W3.prototype={get:function(t){var e=G3(this,t);if(e)return e[1]},has:function(t){return!!G3(this,t)},set:function(t,e){var i=G3(this,t);i?i[1]=e:this.entries.push([t,e])},delete:function(t){var e=U3(this.entries,(function(e){return e[0]===t}));return~e&&Q3(this.entries,e,1),!!~e}};var K3,q3={getConstructor:function(t,e,i,n){var o=t((function(t,o){R3(t,r),N3(t,{type:e,id:H3++,frozen:void 0}),z3(o)||F3(o,t[n],{that:t,AS_ENTRIES:i})})),r=o.prototype,s=j3(e),a=function(t,e,i){var n=s(t),o=D3(B3(e),!0);return!0===o?V3(n).set(e,i):o[n.id]=i,t};return O3(r,{delete:function(t){var e=s(this);if(!P3(t))return!1;var i=D3(t);return!0===i?V3(e).delete(t):i&&T3(i,e.id)&&delete i[e.id]},has:function(t){var e=s(this);if(!P3(t))return!1;var i=D3(t);return!0===i?V3(e).has(t):i&&T3(i,e.id)}}),O3(r,i?{get:function(t){var e=s(this);if(P3(t)){var i=D3(t);return!0===i?V3(e).get(t):i?i[e.id]:void 0}},set:function(t,e){return a(this,t,e)}}:{add:function(t){return a(this,t,!0)}}),o}},Y3=$X,Z3=rR,J3=yR,X3=X_,_3=v_,$3=Z_,t5=q3,e5=eB,i5=UT.enforce,n5=sR,o5=ET,r5=Object,s5=Array.isArray,a5=r5.isExtensible,l5=r5.isFrozen,h5=r5.isSealed,c5=r5.freeze,d5=r5.seal,u5={},f5={},p5=!Z3.ActiveXObject&&"ActiveXObject"in Z3,v5=function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}},g5=$3("WeakMap",v5,t5),y5=g5.prototype,m5=J3(y5.set);if(o5)if(p5){K3=t5.getConstructor(v5,"WeakMap",!0),_3.enable();var b5=J3(y5.delete),w5=J3(y5.has),A5=J3(y5.get);X3(y5,{delete:function(t){if(e5(t)&&!a5(t)){var e=i5(this);return e.frozen||(e.frozen=new K3),b5(this,t)||e.frozen.delete(t)}return b5(this,t)},has:function(t){if(e5(t)&&!a5(t)){var e=i5(this);return e.frozen||(e.frozen=new K3),w5(this,t)||e.frozen.has(t)}return w5(this,t)},get:function(t){if(e5(t)&&!a5(t)){var e=i5(this);return e.frozen||(e.frozen=new K3),w5(this,t)?A5(this,t):e.frozen.get(t)}return A5(this,t)},set:function(t,e){if(e5(t)&&!a5(t)){var i=i5(this);i.frozen||(i.frozen=new K3),w5(this,t)?m5(this,t,e):i.frozen.set(t,e)}else m5(this,t,e);return this}})}else Y3&&n5((function(){var t=c5([]);return m5(new g5,t,1),!l5(t)}))&&X3(y5,{set:function(t,e){var i;return s5(t)&&(l5(t)?i=u5:h5(t)&&(i=f5)),m5(this,t,e),i===u5&&c5(t),i===f5&&d5(t),this}});var k5,E5,C5,x5,I5,S5=nR(iB.WeakMap);function M5(t,e,i,n){if("a"===i&&!n)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!n:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===i?n:"a"===i?n.call(t):n?n.value:e.get(t)}function O5(t,e,i,n,o){if("function"==typeof e?t!==e||!o:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return e.set(t,i),i}function D5(t,e){var i=void 0!==aG&&dU(t)||t["@@iterator"];if(!i){if(AG(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return R5(t,e);var n=pG(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return WL(t);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return R5(t,e)}(t))||e){i&&(t=i);var n=0,o=function(){};return{s:o,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function R5(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i0&&void 0!==arguments[0]?arguments[0]:function(){};uU(this,t),C5.set(this,new z5),x5.set(this,new z5),I5.set(this,void 0),O5(this,I5,e)}return yW(t,[{key:"sizeNodes",get:function(){return M5(this,C5,"f").size}},{key:"sizeEdges",get:function(){return M5(this,x5,"f").size}},{key:"getNodes",value:function(){return M5(this,C5,"f").getSelection()}},{key:"getEdges",value:function(){return M5(this,x5,"f").getSelection()}},{key:"addNodes",value:function(){var t;(t=M5(this,C5,"f")).add.apply(t,arguments)}},{key:"addEdges",value:function(){var t;(t=M5(this,x5,"f")).add.apply(t,arguments)}},{key:"deleteNodes",value:function(t){M5(this,C5,"f").delete(t)}},{key:"deleteEdges",value:function(t){M5(this,x5,"f").delete(t)}},{key:"clear",value:function(){M5(this,C5,"f").clear(),M5(this,x5,"f").clear()}},{key:"commit",value:function(){for(var t,e,i={nodes:M5(this,C5,"f").commit(),edges:M5(this,x5,"f").commit()},n=arguments.length,o=new Array(n),r=0;r=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function T5(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i4&&void 0!==arguments[4]&&arguments[4],r=this._initBaseEvent(e,i);if(!0===o)r.nodes=[],r.edges=[];else{var s=this.getSelection();r.nodes=s.nodes,r.edges=s.edges}void 0!==n&&(r.previousSelection=n),"click"==t&&(r.items=this.getClickedItems(i)),void 0!==e.controlEdge&&(r.controlEdge=e.controlEdge),this.body.emitter.emit(t,r)}},{key:"selectObject",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.options.selectConnectedEdges;if(void 0!==t){if(t instanceof J1){var i;if(!0===e)(i=this._selectionAccumulator).addEdges.apply(i,sG(t.edges));this._selectionAccumulator.addNodes(t)}else this._selectionAccumulator.addEdges(t);return!0}return!1}},{key:"deselectObject",value:function(t){!0===t.isSelected()&&(t.selected=!1,this._removeFromSelection(t))}},{key:"_getAllNodesOverlappingWith",value:function(t){for(var e=[],i=this.body.nodes,n=0;n1&&void 0!==arguments[1])||arguments[1],i=this._pointerToPositionObject(t),n=this._getAllNodesOverlappingWith(i);return n.length>0?!0===e?this.body.nodes[n[n.length-1]]:n[n.length-1]:void 0}},{key:"_getEdgesOverlappingWith",value:function(t,e){for(var i=this.body.edges,n=0;n1&&void 0!==arguments[1])||arguments[1],i=this.canvas.DOMtoCanvas(t),n=10,o=null,r=this.body.edges,s=0;s0&&(this.generateClickEvent("deselectEdge",e,t,o),i=!0),n.nodes.deleted.length>0&&(this.generateClickEvent("deselectNode",e,t,o),i=!0),n.nodes.added.length>0&&(this.generateClickEvent("selectNode",e,t),i=!0),n.edges.added.length>0&&(this.generateClickEvent("selectEdge",e,t),i=!0),!0===i&&this.generateClickEvent("select",e,t)}},{key:"getSelection",value:function(){return{nodes:this.getSelectedNodeIds(),edges:this.getSelectedEdgeIds()}}},{key:"getSelectedNodes",value:function(){return this._selectionAccumulator.getNodes()}},{key:"getSelectedEdges",value:function(){return this._selectionAccumulator.getEdges()}},{key:"getSelectedNodeIds",value:function(){var t;return MG(t=this._selectionAccumulator.getNodes()).call(t,(function(t){return t.id}))}},{key:"getSelectedEdgeIds",value:function(){var t;return MG(t=this._selectionAccumulator.getEdges()).call(t,(function(t){return t.id}))}},{key:"setSelection",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!t||!t.nodes&&!t.edges)throw new TypeError("Selection must be an object with nodes and/or edges properties");if((e.unselectAll||void 0===e.unselectAll)&&this.unselectAll(),t.nodes){var i,n=F5(t.nodes);try{for(n.s();!(i=n.n()).done;){var o=i.value,r=this.body.nodes[o];if(!r)throw new RangeError('Node with id "'+o+'" not found');this.selectObject(r,e.highlightEdges)}}catch(t){n.e(t)}finally{n.f()}}if(t.edges){var s,a=F5(t.edges);try{for(a.s();!(s=a.n()).done;){var l=s.value,h=this.body.edges[l];if(!h)throw new RangeError('Edge with id "'+l+'" not found');this.selectObject(h)}}catch(t){a.e(t)}finally{a.f()}}this.body.emitter.emit("_requestRedraw"),this._selectionAccumulator.commit()}},{key:"selectNodes",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(!t||void 0===t.length)throw"Selection must be an array with ids";this.setSelection({nodes:t},{highlightEdges:e})}},{key:"selectEdges",value:function(t){if(!t||void 0===t.length)throw"Selection must be an array with ids";this.setSelection({edges:t})}},{key:"updateSelection",value:function(){for(var t in this._selectionAccumulator.getNodes())Object.prototype.hasOwnProperty.call(this.body.nodes,t.id)||this._selectionAccumulator.deleteNodes(t);for(var e in this._selectionAccumulator.getEdges())Object.prototype.hasOwnProperty.call(this.body.edges,e.id)||this._selectionAccumulator.deleteEdges(e)}},{key:"getClickedItems",value:function(t){for(var e=this.canvas.DOMtoCanvas(t),i=[],n=this.body.nodeIndices,o=this.body.nodes,r=n.length-1;r>=0;r--){var s=o[n[r]].getItemsOnPoint(e);i.push.apply(i,s)}for(var a=this.body.edgeIndices,l=this.body.edges,h=a.length-1;h>=0;h--){var c=l[a[h]].getItemsOnPoint(e);i.push.apply(i,c)}return i}}]),t}(),j5=rQ,L5=Math.floor,U5=function(t,e){var i=t.length,n=L5(i/2);return i<8?Q5(t,e):H5(t,U5(j5(t,0,n),e),U5(j5(t,n),e),e)},Q5=function(t,e){for(var i,n,o=t.length,r=1;r0;)t[n]=t[--n];n!==r++&&(t[n]=i)}return t},H5=function(t,e,i,n){for(var o=e.length,r=i.length,s=0,a=0;s3)){if(s7)return!0;if(l7)return l7<603;var t,e,i,n,o="";for(t=65;t<76;t++){switch(e=String.fromCharCode(t),t){case 66:case 69:case 70:case 72:i=3;break;case 68:case 71:i=4;break;default:i=2}for(n=0;n<47;n++)h7.push({k:e+n,v:i})}for(h7.sort((function(t,e){return e.v-t.v})),n=0;ne7(i)?1:-1}}(t)),i=$5(o),n=0;n=0:a>l;l+=h)l in s&&(o=i(o,s[l],l,r));return o}},M7={left:S7(!1),right:S7(!0)},O7="process"===AR(rR.process),D7=M7.left;OP({target:"Array",proto:!0,forced:!O7&&gB>79&&gB<83||!NG("reduce")},{reduce:function(t){var e=arguments.length;return D7(this,t,e,e>1?arguments[1]:void 0)}});var R7=FF("Array").reduce,B7=lB,z7=R7,P7=Array.prototype,F7=function(t){var e=t.reduce;return t===P7||B7(P7,t)&&e===P7.reduce?z7:e},T7=nR(F7);function N7(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var j7=function(){function t(){uU(this,t)}return yW(t,[{key:"abstract",value:function(){throw new Error("Can't instantiate abstract class!")}},{key:"fake_use",value:function(){}},{key:"curveType",value:function(){return this.abstract()}},{key:"getPosition",value:function(t){return this.fake_use(t),this.abstract()}},{key:"setPosition",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0;this.fake_use(t,e,i),this.abstract()}},{key:"getTreeSize",value:function(t){return this.fake_use(t),this.abstract()}},{key:"sort",value:function(t){this.fake_use(t),this.abstract()}},{key:"fix",value:function(t,e){this.fake_use(t,e),this.abstract()}},{key:"shift",value:function(t,e){this.fake_use(t,e),this.abstract()}}]),t}(),L7=function(t){r1(i,t);var e=N7(i);function i(t){var n;return uU(this,i),(n=e.call(this)).layout=t,n}return yW(i,[{key:"curveType",value:function(){return"horizontal"}},{key:"getPosition",value:function(t){return t.x}},{key:"setPosition",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0;void 0!==i&&this.layout.hierarchical.addToOrdering(t,i),t.x=e}},{key:"getTreeSize",value:function(t){var e=this.layout.hierarchical.getTreeSize(this.layout.body.nodes,t);return{min:e.min_x,max:e.max_x}}},{key:"sort",value:function(t){A7(t).call(t,(function(t,e){return t.x-e.x}))}},{key:"fix",value:function(t,e){t.y=this.layout.options.hierarchical.levelSeparation*e,t.options.fixed.y=!0}},{key:"shift",value:function(t,e){this.layout.body.nodes[t].x+=e}}]),i}(j7),U7=function(t){r1(i,t);var e=N7(i);function i(t){var n;return uU(this,i),(n=e.call(this)).layout=t,n}return yW(i,[{key:"curveType",value:function(){return"vertical"}},{key:"getPosition",value:function(t){return t.y}},{key:"setPosition",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0;void 0!==i&&this.layout.hierarchical.addToOrdering(t,i),t.y=e}},{key:"getTreeSize",value:function(t){var e=this.layout.hierarchical.getTreeSize(this.layout.body.nodes,t);return{min:e.min_y,max:e.max_y}}},{key:"sort",value:function(t){A7(t).call(t,(function(t,e){return t.y-e.y}))}},{key:"fix",value:function(t,e){t.x=this.layout.options.hierarchical.levelSeparation*e,t.options.fixed.x=!0}},{key:"shift",value:function(t,e){this.layout.body.nodes[t].y+=e}}]),i}(j7),Q7=BQ.every;OP({target:"Array",proto:!0,forced:!NG("every")},{every:function(t){return Q7(this,t,arguments.length>1?arguments[1]:void 0)}});var H7=FF("Array").every,V7=lB,W7=H7,G7=Array.prototype,K7=function(t){var e=t.every;return t===G7||V7(G7,t)&&e===G7.every?W7:e},q7=nR(K7);function Y7(t,e){var i=void 0!==aG&&dU(t)||t["@@iterator"];if(!i){if(AG(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return Z7(t,e);var n=pG(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return WL(t);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return Z7(t,e)}(t))||e){i&&(t=i);var n=0,o=function(){};return{s:o,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function Z7(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i=e[n])&&(e[n]=e[i]+1)})),e}function X7(t,e,i,n){var o,r,s=Vq(null),a=T7(o=sG(D0(n).call(n))).call(o,(function(t,e){return t+1+e.edges.length}),0),l=i+"Id",h="to"===i?1:-1,c=Y7(n);try{var d,u=function(){var o=rG(r.value,2),c=o[0],d=o[1];if(!n.has(c)||!t(d))return 0;s[c]=0;for(var u,f,p=[d],v=0,g=function(){var t,o;if(!n.has(c))return 0;var r=s[u.id]+h;if(YG(t=sq(o=u.edges).call(o,(function(t){return t.connected&&t.to!==t.from&&t[i]!==u&&n.has(t.toId)&&n.has(t.fromId)}))).call(t,(function(t){var n=t[l],o=s[n];(null==o||e(r,o))&&(s[n]=r,p.push(t[i]))})),v>a)return{v:{v:J7(n,s)}};++v};u=p.pop();)if(0!==(f=g())&&f)return f.v};for(c.s();!(r=c.n()).done;)if(0!==(d=u())&&d)return d.v}catch(t){c.e(t)}finally{c.f()}return s}var _7=function(){function t(){uU(this,t),this.childrenReference={},this.parentReference={},this.trees={},this.distributionOrdering={},this.levels={},this.distributionIndex={},this.isTree=!1,this.treeIndex=-1}return yW(t,[{key:"addRelation",value:function(t,e){void 0===this.childrenReference[t]&&(this.childrenReference[t]=[]),this.childrenReference[t].push(e),void 0===this.parentReference[e]&&(this.parentReference[e]=[]),this.parentReference[e].push(t)}},{key:"checkIfTree",value:function(){for(var t in this.parentReference)if(this.parentReference[t].length>1)return void(this.isTree=!1);this.isTree=!0}},{key:"numTrees",value:function(){return this.treeIndex+1}},{key:"setTreeIndex",value:function(t,e){void 0!==e&&void 0===this.trees[t.id]&&(this.trees[t.id]=e,this.treeIndex=Math.max(e,this.treeIndex))}},{key:"ensureLevel",value:function(t){void 0===this.levels[t]&&(this.levels[t]=0)}},{key:"getMaxLevel",value:function(t){var e=this,i={};return function t(n){if(void 0!==i[n])return i[n];var o=e.levels[n];if(e.childrenReference[n]){var r=e.childrenReference[n];if(r.length>0)for(var s=0;s0&&(i.levelSeparation*=-1):i.levelSeparation<0&&(i.levelSeparation*=-1),this.setDirectionStrategy(),this.body.emitter.emit("_resetHierarchicalLayout"),this.adaptAllOptionsForHierarchicalLayout(e);if(!0===n)return this.body.emitter.emit("refresh"),FJ(e,this.optionsBackup)}return e}},{key:"_resetRNG",value:function(t){this.initialRandomSeed=t,this._rng=AJ(this.initialRandomSeed)}},{key:"adaptAllOptionsForHierarchicalLayout",value:function(t){if(!0===this.options.hierarchical.enabled){var e=this.optionsBackup.physics;void 0===t.physics||!0===t.physics?(t.physics={enabled:void 0===e.enabled||e.enabled,solver:"hierarchicalRepulsion"},e.enabled=void 0===e.enabled||e.enabled,e.solver=e.solver||"barnesHut"):"object"===fW(t.physics)?(e.enabled=void 0===t.physics.enabled||t.physics.enabled,e.solver=t.physics.solver||"barnesHut",t.physics.solver="hierarchicalRepulsion"):!1!==t.physics&&(e.solver="barnesHut",t.physics={solver:"hierarchicalRepulsion"});var i=this.direction.curveType();if(void 0===t.edges)this.optionsBackup.edges={smooth:{enabled:!0,type:"dynamic"}},t.edges={smooth:!1};else if(void 0===t.edges.smooth)this.optionsBackup.edges={smooth:{enabled:!0,type:"dynamic"}},t.edges.smooth=!1;else if("boolean"==typeof t.edges.smooth)this.optionsBackup.edges={smooth:t.edges.smooth},t.edges.smooth={enabled:t.edges.smooth,type:i};else{var n=t.edges.smooth;void 0!==n.type&&"dynamic"!==n.type&&(i=n.type),this.optionsBackup.edges={smooth:{enabled:void 0===n.enabled||n.enabled,type:void 0===n.type?"dynamic":n.type,roundness:void 0===n.roundness?.5:n.roundness,forceDirection:void 0!==n.forceDirection&&n.forceDirection}},t.edges.smooth={enabled:void 0===n.enabled||n.enabled,type:i,roundness:void 0===n.roundness?.5:n.roundness,forceDirection:void 0!==n.forceDirection&&n.forceDirection}}this.body.emitter.emit("_forceDisableDynamicCurves",i)}return t}},{key:"positionInitially",value:function(t){if(!0!==this.options.hierarchical.enabled){this._resetRNG(this.initialRandomSeed);for(var e=t.length+50,i=0;io){for(var s=t.length;t.length>o&&n<=10;){n+=1;var a=t.length;if(n%3==0?this.body.modules.clustering.clusterBridges(r):this.body.modules.clustering.clusterOutliers(r),a==t.length&&n%3!=0)return this._declusterAll(),this.body.emitter.emit("_layoutFailed"),void console.info("This network could not be positioned by this version of the improved layout algorithm. Please disable improvedLayout for better performance.")}this.body.modules.kamadaKawai.setOptions({springLength:Math.max(150,2*s)})}n>10&&console.info("The clustering didn't succeed within the amount of interations allowed, progressing with partial result."),this.body.modules.kamadaKawai.solve(t,this.body.edgeIndices,!0),this._shiftToCenter();for(var l=0;l0){var t,e,i=!1,n=!1;for(e in this.lastNodeOnLevel={},this.hierarchical=new _7,this.body.nodes)Object.prototype.hasOwnProperty.call(this.body.nodes,e)&&(void 0!==(t=this.body.nodes[e]).options.level?(i=!0,this.hierarchical.levels[e]=t.options.level):n=!0);if(!0===n&&!0===i)throw new Error("To use the hierarchical layout, nodes require either no predefined levels or levels have to be defined for all nodes.");if(!0===n){var o=this.options.hierarchical.sortMethod;"hubsize"===o?this._determineLevelsByHubsize():"directed"===o?this._determineLevelsDirected():"custom"===o&&this._determineLevelsCustomCallback()}for(var r in this.body.nodes)Object.prototype.hasOwnProperty.call(this.body.nodes,r)&&this.hierarchical.ensureLevel(r);var s=this._getDistribution();this._generateMap(),this._placeNodesByHierarchy(s),this._condenseHierarchy(),this._shiftToCenter()}}},{key:"_condenseHierarchy",value:function(){var t=this,e=!1,i={},n=function(e,i){var n=t.hierarchical.trees;for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&n[o]===e&&t.direction.shift(o,i)},o=function(){for(var e=[],i=0;i0)for(var r=0;r1&&void 0!==arguments[1]?arguments[1]:1e9,n=1e9,o=1e9,r=1e9,s=-1e9;for(var a in e)if(Object.prototype.hasOwnProperty.call(e,a)){var l=t.body.nodes[a],h=t.hierarchical.levels[l.id],c=t.direction.getPosition(l),d=rG(t._getSpaceAroundNode(l,e),2),u=d[0],f=d[1];n=Math.min(u,n),o=Math.min(f,o),h<=i&&(r=Math.min(c,r),s=Math.max(c,s))}return[r,s,n,o]},a=function(e,i,n){for(var o=t.hierarchical,r=0;r1)for(var l=0;l2&&void 0!==arguments[2]&&arguments[2],a=t.direction.getPosition(i),l=t.direction.getPosition(n),h=Math.abs(l-a),c=t.options.hierarchical.nodeSpacing;if(h>c){var d={},u={};r(i,d),r(n,u);var f=function(e,i){var n=t.hierarchical.getMaxLevel(e.id),o=t.hierarchical.getMaxLevel(i.id);return Math.min(n,o)}(i,n),p=s(d,f),v=s(u,f),g=p[1],y=v[0],m=v[2];if(Math.abs(g-y)>c){var b=g-y+c;b<-m+c&&(b=-m+c),b<0&&(t._shiftBlock(n.id,b),e=!0,!0===o&&t._centerParent(n))}}},h=function(n,o){for(var a=o.id,l=o.edges,h=t.hierarchical.levels[o.id],c=t.options.hierarchical.levelSeparation*t.options.hierarchical.levelSeparation,d={},u=[],f=0;f0?f=Math.min(u,d-t.options.hierarchical.nodeSpacing):u<0&&(f=-Math.min(-u,c-t.options.hierarchical.nodeSpacing)),0!=f&&(t._shiftBlock(o.id,f),e=!0)}(b),function(i){var n=t.direction.getPosition(o),r=rG(t._getSpaceAroundNode(o),2),s=r[0],a=r[1],l=i-n,h=n;l>0?h=Math.min(n+(a-t.options.hierarchical.nodeSpacing),i):l<0&&(h=Math.max(n-(s-t.options.hierarchical.nodeSpacing),i)),h!==n&&(t.direction.setPosition(o,h),e=!0)}(b=m(n,l))};!0===this.options.hierarchical.blockShifting&&(function(i){var n=t.hierarchical.getLevels();n=oK(n).call(n);for(var o=0;o0&&Math.abs(d)0&&(l=this.direction.getPosition(n[r-1])+a),this.direction.setPosition(s,l,e),this._validatePositionAndContinue(s,e,l),o++}}}}},{key:"_placeBranchNodes",value:function(t,e){var i,n=this.hierarchical.childrenReference[t];if(void 0!==n){for(var o=[],r=0;re&&void 0===this.positionedNodes[a.id]))return;var h=this.options.hierarchical.nodeSpacing,c=void 0;c=0===s?this.direction.getPosition(this.body.nodes[t]):this.direction.getPosition(o[s-1])+h,this.direction.setPosition(a,c,l),this._validatePositionAndContinue(a,l,c)}var d=this._getCenterPosition(o);this.direction.setPosition(this.body.nodes[t],d,e)}}},{key:"_validatePositionAndContinue",value:function(t,e,i){if(this.hierarchical.isTree){if(void 0!==this.lastNodeOnLevel[e]){var n=this.direction.getPosition(this.body.nodes[this.lastNodeOnLevel[e]]);if(i-nt}),"from",t)}(i),this.hierarchical.setMinLevelToZero(this.body.nodes)}},{key:"_generateMap",value:function(){var t=this;this._crawlNetwork((function(e,i){t.hierarchical.levels[i.id]>t.hierarchical.levels[e.id]&&t.hierarchical.addRelation(e.id,i.id)})),this.hierarchical.checkIfTree()}},{key:"_crawlNetwork",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:function(){},i=arguments.length>1?arguments[1]:void 0,n={},o=function i(o,r){if(void 0===n[o.id]){var s;t.hierarchical.setTreeIndex(o,r),n[o.id]=!0;for(var a=t._getActiveEdges(o),l=0;l=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function e4(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i0&&!1!==this.options.deleteNode||0===i&&!1!==this.options.deleteEdge)&&(!0===s&&this._createSeperator(4),this._createDeleteButton(r)),this._bindElementEvents(this.closeDiv,HF(t=this.toggleEditMode).call(t,this)),this._temporaryBindEvent("select",HF(e=this.showManipulatorToolbar).call(e,this))}this.body.emitter.emit("_redraw")}},{key:"addNodeMode",value:function(){var t;if(!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="addNode",!0===this.guiEnabled){var e,i=this.options.locales[this.options.locale];this.manipulationDOM={},this._createBackButton(i),this._createSeperator(),this._createDescription(i.addDescription||this.options.locales.en.addDescription),this._bindElementEvents(this.closeDiv,HF(e=this.toggleEditMode).call(e,this))}this._temporaryBindEvent("click",HF(t=this._performAddNode).call(t,this))}},{key:"editNode",value:function(){var t=this;!0!==this.editMode&&this.enableEditMode(),this._clean();var e=this.selectionHandler.getSelectedNodes()[0];if(void 0!==e){if(this.inMode="editNode","function"!=typeof this.options.editNode)throw new Error("No function has been configured to handle the editing of nodes.");if(!0!==e.isCluster){var i=FJ({},e.options,!1);if(i.x=e.x,i.y=e.y,2!==this.options.editNode.length)throw new Error("The function for edit does not support two arguments (data, callback)");this.options.editNode(i,(function(e){null!=e&&"editNode"===t.inMode&&t.body.data.nodes.getDataSet().update(e),t.showManipulatorToolbar()}))}else alert(this.options.locales[this.options.locale].editClusterError||this.options.locales.en.editClusterError)}else this.showManipulatorToolbar()}},{key:"addEdgeMode",value:function(){var t,e,i,n,o;if(!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="addEdge",!0===this.guiEnabled){var r,s=this.options.locales[this.options.locale];this.manipulationDOM={},this._createBackButton(s),this._createSeperator(),this._createDescription(s.edgeDescription||this.options.locales.en.edgeDescription),this._bindElementEvents(this.closeDiv,HF(r=this.toggleEditMode).call(r,this))}this._temporaryBindUI("onTouch",HF(t=this._handleConnect).call(t,this)),this._temporaryBindUI("onDragEnd",HF(e=this._finishConnect).call(e,this)),this._temporaryBindUI("onDrag",HF(i=this._dragControlNode).call(i,this)),this._temporaryBindUI("onRelease",HF(n=this._finishConnect).call(n,this)),this._temporaryBindUI("onDragStart",HF(o=this._dragStartEdge).call(o,this)),this._temporaryBindUI("onHold",(function(){}))}},{key:"editEdgeMode",value:function(){if(!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="editEdge","object"!==fW(this.options.editEdge)||"function"!=typeof this.options.editEdge.editWithoutDrag||(this.edgeBeingEditedId=this.selectionHandler.getSelectedEdgeIds()[0],void 0===this.edgeBeingEditedId)){if(!0===this.guiEnabled){var t,e=this.options.locales[this.options.locale];this.manipulationDOM={},this._createBackButton(e),this._createSeperator(),this._createDescription(e.editEdgeDescription||this.options.locales.en.editEdgeDescription),this._bindElementEvents(this.closeDiv,HF(t=this.toggleEditMode).call(t,this))}if(this.edgeBeingEditedId=this.selectionHandler.getSelectedEdgeIds()[0],void 0!==this.edgeBeingEditedId){var i,n,o,r,s=this.body.edges[this.edgeBeingEditedId],a=this._getNewTargetNode(s.from.x,s.from.y),l=this._getNewTargetNode(s.to.x,s.to.y);this.temporaryIds.nodes.push(a.id),this.temporaryIds.nodes.push(l.id),this.body.nodes[a.id]=a,this.body.nodeIndices.push(a.id),this.body.nodes[l.id]=l,this.body.nodeIndices.push(l.id),this._temporaryBindUI("onTouch",HF(i=this._controlNodeTouch).call(i,this)),this._temporaryBindUI("onTap",(function(){})),this._temporaryBindUI("onHold",(function(){})),this._temporaryBindUI("onDragStart",HF(n=this._controlNodeDragStart).call(n,this)),this._temporaryBindUI("onDrag",HF(o=this._controlNodeDrag).call(o,this)),this._temporaryBindUI("onDragEnd",HF(r=this._controlNodeDragEnd).call(r,this)),this._temporaryBindUI("onMouseMove",(function(){})),this._temporaryBindEvent("beforeDrawing",(function(t){var e=s.edgeType.findBorderPositions(t);!1===a.selected&&(a.x=e.from.x,a.y=e.from.y),!1===l.selected&&(l.x=e.to.x,l.y=e.to.y)})),this.body.emitter.emit("_redraw")}else this.showManipulatorToolbar()}else{var h=this.body.edges[this.edgeBeingEditedId];this._performEditEdge(h.from.id,h.to.id)}}},{key:"deleteSelected",value:function(){var t=this;!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="delete";var e=this.selectionHandler.getSelectedNodeIds(),i=this.selectionHandler.getSelectedEdgeIds(),n=void 0;if(e.length>0){for(var o=0;o0&&"function"==typeof this.options.deleteEdge&&(n=this.options.deleteEdge);if("function"==typeof n){var r={nodes:e,edges:i};if(2!==n.length)throw new Error("The function for delete does not support two arguments (data, callback)");n(r,(function(e){null!=e&&"delete"===t.inMode?(t.body.data.edges.getDataSet().remove(e.edges),t.body.data.nodes.getDataSet().remove(e.nodes),t.body.emitter.emit("startSimulation"),t.showManipulatorToolbar()):(t.body.emitter.emit("startSimulation"),t.showManipulatorToolbar())}))}else this.body.data.edges.getDataSet().remove(i),this.body.data.nodes.getDataSet().remove(e),this.body.emitter.emit("startSimulation"),this.showManipulatorToolbar()}},{key:"_setup",value:function(){!0===this.options.enabled?(this.guiEnabled=!0,this._createWrappers(),!1===this.editMode?this._createEditButton():this.showManipulatorToolbar()):(this._removeManipulationDOM(),this.guiEnabled=!1)}},{key:"_createWrappers",value:function(){var t,e;(void 0===this.manipulationDiv&&(this.manipulationDiv=document.createElement("div"),this.manipulationDiv.className="vis-manipulation",!0===this.editMode?this.manipulationDiv.style.display="block":this.manipulationDiv.style.display="none",this.canvas.frame.appendChild(this.manipulationDiv)),void 0===this.editModeDiv&&(this.editModeDiv=document.createElement("div"),this.editModeDiv.className="vis-edit-mode",!0===this.editMode?this.editModeDiv.style.display="none":this.editModeDiv.style.display="block",this.canvas.frame.appendChild(this.editModeDiv)),void 0===this.closeDiv)&&(this.closeDiv=document.createElement("button"),this.closeDiv.className="vis-close",this.closeDiv.setAttribute("aria-label",null!==(t=null===(e=this.options.locales[this.options.locale])||void 0===e?void 0:e.close)&&void 0!==t?t:this.options.locales.en.close),this.closeDiv.style.display=this.manipulationDiv.style.display,this.canvas.frame.appendChild(this.closeDiv))}},{key:"_getNewTargetNode",value:function(t,e){var i=FJ({},this.options.controlNodeStyle);i.id="targetNode"+d3(),i.hidden=!1,i.physics=!1,i.x=t,i.y=e;var n=this.body.functions.createNode(i);return n.shape.boundingBox={left:t,right:t,top:e,bottom:e},n}},{key:"_createEditButton",value:function(){var t;this._clean(),this.manipulationDOM={},MJ(this.editModeDiv);var e=this.options.locales[this.options.locale],i=this._createButton("editMode","vis-edit vis-edit-mode",e.edit||this.options.locales.en.edit);this.editModeDiv.appendChild(i),this._bindElementEvents(i,HF(t=this.toggleEditMode).call(t,this))}},{key:"_clean",value:function(){this.inMode=!1,!0===this.guiEnabled&&(MJ(this.editModeDiv),MJ(this.manipulationDiv),this._cleanupDOMEventListeners()),this._cleanupTemporaryNodesAndEdges(),this._unbindTemporaryUIs(),this._unbindTemporaryEvents(),this.body.emitter.emit("restorePhysics")}},{key:"_cleanupDOMEventListeners",value:function(){var t,e,i=t4(IK(t=this._domEventListenerCleanupQueue).call(t,0));try{for(i.s();!(e=i.n()).done;){(0,e.value)()}}catch(t){i.e(t)}finally{i.f()}}},{key:"_removeManipulationDOM",value:function(){this._clean(),MJ(this.manipulationDiv),MJ(this.editModeDiv),MJ(this.closeDiv),this.manipulationDiv&&this.canvas.frame.removeChild(this.manipulationDiv),this.editModeDiv&&this.canvas.frame.removeChild(this.editModeDiv),this.closeDiv&&this.canvas.frame.removeChild(this.closeDiv),this.manipulationDiv=void 0,this.editModeDiv=void 0,this.closeDiv=void 0}},{key:"_createSeperator",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1;this.manipulationDOM["seperatorLineDiv"+t]=document.createElement("div"),this.manipulationDOM["seperatorLineDiv"+t].className="vis-separator-line",this.manipulationDiv.appendChild(this.manipulationDOM["seperatorLineDiv"+t])}},{key:"_createAddNodeButton",value:function(t){var e,i=this._createButton("addNode","vis-add",t.addNode||this.options.locales.en.addNode);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,HF(e=this.addNodeMode).call(e,this))}},{key:"_createAddEdgeButton",value:function(t){var e,i=this._createButton("addEdge","vis-connect",t.addEdge||this.options.locales.en.addEdge);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,HF(e=this.addEdgeMode).call(e,this))}},{key:"_createEditNodeButton",value:function(t){var e,i=this._createButton("editNode","vis-edit",t.editNode||this.options.locales.en.editNode);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,HF(e=this.editNode).call(e,this))}},{key:"_createEditEdgeButton",value:function(t){var e,i=this._createButton("editEdge","vis-edit",t.editEdge||this.options.locales.en.editEdge);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,HF(e=this.editEdgeMode).call(e,this))}},{key:"_createDeleteButton",value:function(t){var e,i;i=this.options.rtl?"vis-delete-rtl":"vis-delete";var n=this._createButton("delete",i,t.del||this.options.locales.en.del);this.manipulationDiv.appendChild(n),this._bindElementEvents(n,HF(e=this.deleteSelected).call(e,this))}},{key:"_createBackButton",value:function(t){var e,i=this._createButton("back","vis-back",t.back||this.options.locales.en.back);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,HF(e=this.showManipulatorToolbar).call(e,this))}},{key:"_createButton",value:function(t,e,i){var n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"vis-label";return this.manipulationDOM[t+"Div"]=document.createElement("button"),this.manipulationDOM[t+"Div"].className="vis-button "+e,this.manipulationDOM[t+"Label"]=document.createElement("div"),this.manipulationDOM[t+"Label"].className=n,this.manipulationDOM[t+"Label"].innerText=i,this.manipulationDOM[t+"Div"].appendChild(this.manipulationDOM[t+"Label"]),this.manipulationDOM[t+"Div"]}},{key:"_createDescription",value:function(t){this.manipulationDOM.descriptionLabel=document.createElement("div"),this.manipulationDOM.descriptionLabel.className="vis-none",this.manipulationDOM.descriptionLabel.innerText=t,this.manipulationDiv.appendChild(this.manipulationDOM.descriptionLabel)}},{key:"_temporaryBindEvent",value:function(t,e){this.temporaryEventFunctions.push({event:t,boundFunction:e}),this.body.emitter.on(t,e)}},{key:"_temporaryBindUI",value:function(t,e){if(void 0===this.body.eventListeners[t])throw new Error("This UI function does not exist. Typo? You tried: "+t+" possible are: "+qq(RG(this.body.eventListeners)));this.temporaryUIFunctions[t]=this.body.eventListeners[t],this.body.eventListeners[t]=e}},{key:"_unbindTemporaryUIs",value:function(){for(var t in this.temporaryUIFunctions)Object.prototype.hasOwnProperty.call(this.temporaryUIFunctions,t)&&(this.body.eventListeners[t]=this.temporaryUIFunctions[t],delete this.temporaryUIFunctions[t]);this.temporaryUIFunctions={}}},{key:"_unbindTemporaryEvents",value:function(){for(var t=0;t=0;s--)if(o[s]!==this.selectedControlNode.id){r=this.body.nodes[o[s]];break}if(void 0!==r&&void 0!==this.selectedControlNode)if(!0===r.isCluster)alert(this.options.locales[this.options.locale].createEdgeError||this.options.locales.en.createEdgeError);else{var a=this.body.nodes[this.temporaryIds.nodes[0]];this.selectedControlNode.id===a.id?this._performEditEdge(r.id,n.to.id):this._performEditEdge(n.from.id,r.id)}else n.updateEdgeType(),this.body.emitter.emit("restorePhysics");this.body.emitter.emit("_redraw")}}},{key:"_handleConnect",value:function(t){if((new Date).valueOf()-this.touchTime>100){this.lastTouch=this.body.functions.getPointer(t.center),this.lastTouch.translation=wF({},this.body.view.translation),this.interactionHandler.drag.pointer=this.lastTouch,this.interactionHandler.drag.translation=this.lastTouch.translation;var e=this.lastTouch,i=this.selectionHandler.getNodeAt(e);if(void 0!==i)if(!0===i.isCluster)alert(this.options.locales[this.options.locale].createEdgeError||this.options.locales.en.createEdgeError);else{var n=this._getNewTargetNode(i.x,i.y);this.body.nodes[n.id]=n,this.body.nodeIndices.push(n.id);var o=this.body.functions.createEdge({id:"connectionEdge"+d3(),from:i.id,to:n.id,physics:!1,smooth:{enabled:!0,type:"continuous",roundness:.5}});this.body.edges[o.id]=o,this.body.edgeIndices.push(o.id),this.temporaryIds.nodes.push(n.id),this.temporaryIds.edges.push(o.id)}this.touchTime=(new Date).valueOf()}}},{key:"_dragControlNode",value:function(t){var e=this.body.functions.getPointer(t.center),i=this.selectionHandler._pointerToPositionObject(e),n=void 0;void 0!==this.temporaryIds.edges[0]&&(n=this.body.edges[this.temporaryIds.edges[0]].fromId);for(var o=this.selectionHandler._getAllNodesOverlappingWith(i),r=void 0,s=o.length-1;s>=0;s--){var a;if(-1===Lq(a=this.temporaryIds.nodes).call(a,o[s])){r=this.body.nodes[o[s]];break}}if(t.controlEdge={from:n,to:r?r.id:void 0},this.selectionHandler.generateClickEvent("controlNodeDragging",t,e),void 0!==this.temporaryIds.nodes[0]){var l=this.body.nodes[this.temporaryIds.nodes[0]];l.x=this.canvas._XconvertDOMtoCanvas(e.x),l.y=this.canvas._YconvertDOMtoCanvas(e.y),this.body.emitter.emit("_redraw")}else this.interactionHandler.onDrag(t)}},{key:"_finishConnect",value:function(t){var e=this.body.functions.getPointer(t.center),i=this.selectionHandler._pointerToPositionObject(e),n=void 0;void 0!==this.temporaryIds.edges[0]&&(n=this.body.edges[this.temporaryIds.edges[0]].fromId);for(var o=this.selectionHandler._getAllNodesOverlappingWith(i),r=void 0,s=o.length-1;s>=0;s--){var a;if(-1===Lq(a=this.temporaryIds.nodes).call(a,o[s])){r=this.body.nodes[o[s]];break}}this._cleanupTemporaryNodesAndEdges(),void 0!==r&&(!0===r.isCluster?alert(this.options.locales[this.options.locale].createEdgeError||this.options.locales.en.createEdgeError):void 0!==this.body.nodes[n]&&void 0!==this.body.nodes[r.id]&&this._performAddEdge(n,r.id)),t.controlEdge={from:n,to:r?r.id:void 0},this.selectionHandler.generateClickEvent("controlNodeDragEnd",t,e),this.body.emitter.emit("_redraw")}},{key:"_dragStartEdge",value:function(t){var e=this.lastTouch;this.selectionHandler.generateClickEvent("dragStart",t,e,void 0,!0)}},{key:"_performAddNode",value:function(t){var e=this,i={id:d3(),x:t.pointer.canvas.x,y:t.pointer.canvas.y,label:"new"};if("function"==typeof this.options.addNode){if(2!==this.options.addNode.length)throw this.showManipulatorToolbar(),new Error("The function for add does not support two arguments (data,callback)");this.options.addNode(i,(function(t){null!=t&&"addNode"===e.inMode&&e.body.data.nodes.getDataSet().add(t),e.showManipulatorToolbar()}))}else this.body.data.nodes.getDataSet().add(i),this.showManipulatorToolbar()}},{key:"_performAddEdge",value:function(t,e){var i=this,n={from:t,to:e};if("function"==typeof this.options.addEdge){if(2!==this.options.addEdge.length)throw new Error("The function for connect does not support two arguments (data,callback)");this.options.addEdge(n,(function(t){null!=t&&"addEdge"===i.inMode&&(i.body.data.edges.getDataSet().add(t),i.selectionHandler.unselectAll(),i.showManipulatorToolbar())}))}else this.body.data.edges.getDataSet().add(n),this.selectionHandler.unselectAll(),this.showManipulatorToolbar()}},{key:"_performEditEdge",value:function(t,e){var i=this,n={id:this.edgeBeingEditedId,from:t,to:e,label:this.body.data.edges.get(this.edgeBeingEditedId).label},o=this.options.editEdge;if("object"===fW(o)&&(o=o.editWithoutDrag),"function"==typeof o){if(2!==o.length)throw new Error("The function for edit does not support two arguments (data, callback)");o(n,(function(t){null==t||"editEdge"!==i.inMode?(i.body.edges[n.id].updateEdgeType(),i.body.emitter.emit("_redraw"),i.showManipulatorToolbar()):(i.body.data.edges.getDataSet().update(t),i.selectionHandler.unselectAll(),i.showManipulatorToolbar())}))}else this.body.data.edges.getDataSet().update(n),this.selectionHandler.unselectAll(),this.showManipulatorToolbar()}}]),t}(),n4="string",o4="boolean",r4="number",s4="array",a4="object",l4=["arrow","bar","box","circle","crow","curve","diamond","image","inv_curve","inv_triangle","triangle","vee"],h4={borderWidth:{number:r4},borderWidthSelected:{number:r4,undefined:"undefined"},brokenImage:{string:n4,undefined:"undefined"},chosen:{label:{boolean:o4,function:"function"},node:{boolean:o4,function:"function"},__type__:{object:a4,boolean:o4}},color:{border:{string:n4},background:{string:n4},highlight:{border:{string:n4},background:{string:n4},__type__:{object:a4,string:n4}},hover:{border:{string:n4},background:{string:n4},__type__:{object:a4,string:n4}},__type__:{object:a4,string:n4}},opacity:{number:r4,undefined:"undefined"},fixed:{x:{boolean:o4},y:{boolean:o4},__type__:{object:a4,boolean:o4}},font:{align:{string:n4},color:{string:n4},size:{number:r4},face:{string:n4},background:{string:n4},strokeWidth:{number:r4},strokeColor:{string:n4},vadjust:{number:r4},multi:{boolean:o4,string:n4},bold:{color:{string:n4},size:{number:r4},face:{string:n4},mod:{string:n4},vadjust:{number:r4},__type__:{object:a4,string:n4}},boldital:{color:{string:n4},size:{number:r4},face:{string:n4},mod:{string:n4},vadjust:{number:r4},__type__:{object:a4,string:n4}},ital:{color:{string:n4},size:{number:r4},face:{string:n4},mod:{string:n4},vadjust:{number:r4},__type__:{object:a4,string:n4}},mono:{color:{string:n4},size:{number:r4},face:{string:n4},mod:{string:n4},vadjust:{number:r4},__type__:{object:a4,string:n4}},__type__:{object:a4,string:n4}},group:{string:n4,number:r4,undefined:"undefined"},heightConstraint:{minimum:{number:r4},valign:{string:n4},__type__:{object:a4,boolean:o4,number:r4}},hidden:{boolean:o4},icon:{face:{string:n4},code:{string:n4},size:{number:r4},color:{string:n4},weight:{string:n4,number:r4},__type__:{object:a4}},id:{string:n4,number:r4},image:{selected:{string:n4,undefined:"undefined"},unselected:{string:n4,undefined:"undefined"},__type__:{object:a4,string:n4}},imagePadding:{top:{number:r4},right:{number:r4},bottom:{number:r4},left:{number:r4},__type__:{object:a4,number:r4}},label:{string:n4,undefined:"undefined"},labelHighlightBold:{boolean:o4},level:{number:r4,undefined:"undefined"},margin:{top:{number:r4},right:{number:r4},bottom:{number:r4},left:{number:r4},__type__:{object:a4,number:r4}},mass:{number:r4},physics:{boolean:o4},scaling:{min:{number:r4},max:{number:r4},label:{enabled:{boolean:o4},min:{number:r4},max:{number:r4},maxVisible:{number:r4},drawThreshold:{number:r4},__type__:{object:a4,boolean:o4}},customScalingFunction:{function:"function"},__type__:{object:a4}},shadow:{enabled:{boolean:o4},color:{string:n4},size:{number:r4},x:{number:r4},y:{number:r4},__type__:{object:a4,boolean:o4}},shape:{string:["custom","ellipse","circle","database","box","text","image","circularImage","diamond","dot","star","triangle","triangleDown","square","icon","hexagon"]},ctxRenderer:{function:"function"},shapeProperties:{borderDashes:{boolean:o4,array:s4},borderRadius:{number:r4},interpolation:{boolean:o4},useImageSize:{boolean:o4},useBorderWithImage:{boolean:o4},coordinateOrigin:{string:["center","top-left"]},__type__:{object:a4}},size:{number:r4},title:{string:n4,dom:"dom",undefined:"undefined"},value:{number:r4,undefined:"undefined"},widthConstraint:{minimum:{number:r4},maximum:{number:r4},__type__:{object:a4,boolean:o4,number:r4}},x:{number:r4},y:{number:r4},__type__:{object:a4}},c4={configure:{enabled:{boolean:o4},filter:{boolean:o4,string:n4,array:s4,function:"function"},container:{dom:"dom"},showButton:{boolean:o4},__type__:{object:a4,boolean:o4,string:n4,array:s4,function:"function"}},edges:{arrows:{to:{enabled:{boolean:o4},scaleFactor:{number:r4},type:{string:l4},imageHeight:{number:r4},imageWidth:{number:r4},src:{string:n4},__type__:{object:a4,boolean:o4}},middle:{enabled:{boolean:o4},scaleFactor:{number:r4},type:{string:l4},imageWidth:{number:r4},imageHeight:{number:r4},src:{string:n4},__type__:{object:a4,boolean:o4}},from:{enabled:{boolean:o4},scaleFactor:{number:r4},type:{string:l4},imageWidth:{number:r4},imageHeight:{number:r4},src:{string:n4},__type__:{object:a4,boolean:o4}},__type__:{string:["from","to","middle"],object:a4}},endPointOffset:{from:{number:r4},to:{number:r4},__type__:{object:a4,number:r4}},arrowStrikethrough:{boolean:o4},background:{enabled:{boolean:o4},color:{string:n4},size:{number:r4},dashes:{boolean:o4,array:s4},__type__:{object:a4,boolean:o4}},chosen:{label:{boolean:o4,function:"function"},edge:{boolean:o4,function:"function"},__type__:{object:a4,boolean:o4}},color:{color:{string:n4},highlight:{string:n4},hover:{string:n4},inherit:{string:["from","to","both"],boolean:o4},opacity:{number:r4},__type__:{object:a4,string:n4}},dashes:{boolean:o4,array:s4},font:{color:{string:n4},size:{number:r4},face:{string:n4},background:{string:n4},strokeWidth:{number:r4},strokeColor:{string:n4},align:{string:["horizontal","top","middle","bottom"]},vadjust:{number:r4},multi:{boolean:o4,string:n4},bold:{color:{string:n4},size:{number:r4},face:{string:n4},mod:{string:n4},vadjust:{number:r4},__type__:{object:a4,string:n4}},boldital:{color:{string:n4},size:{number:r4},face:{string:n4},mod:{string:n4},vadjust:{number:r4},__type__:{object:a4,string:n4}},ital:{color:{string:n4},size:{number:r4},face:{string:n4},mod:{string:n4},vadjust:{number:r4},__type__:{object:a4,string:n4}},mono:{color:{string:n4},size:{number:r4},face:{string:n4},mod:{string:n4},vadjust:{number:r4},__type__:{object:a4,string:n4}},__type__:{object:a4,string:n4}},hidden:{boolean:o4},hoverWidth:{function:"function",number:r4},label:{string:n4,undefined:"undefined"},labelHighlightBold:{boolean:o4},length:{number:r4,undefined:"undefined"},physics:{boolean:o4},scaling:{min:{number:r4},max:{number:r4},label:{enabled:{boolean:o4},min:{number:r4},max:{number:r4},maxVisible:{number:r4},drawThreshold:{number:r4},__type__:{object:a4,boolean:o4}},customScalingFunction:{function:"function"},__type__:{object:a4}},selectionWidth:{function:"function",number:r4},selfReferenceSize:{number:r4},selfReference:{size:{number:r4},angle:{number:r4},renderBehindTheNode:{boolean:o4},__type__:{object:a4}},shadow:{enabled:{boolean:o4},color:{string:n4},size:{number:r4},x:{number:r4},y:{number:r4},__type__:{object:a4,boolean:o4}},smooth:{enabled:{boolean:o4},type:{string:["dynamic","continuous","discrete","diagonalCross","straightCross","horizontal","vertical","curvedCW","curvedCCW","cubicBezier"]},roundness:{number:r4},forceDirection:{string:["horizontal","vertical","none"],boolean:o4},__type__:{object:a4,boolean:o4}},title:{string:n4,undefined:"undefined"},width:{number:r4},widthConstraint:{maximum:{number:r4},__type__:{object:a4,boolean:o4,number:r4}},value:{number:r4,undefined:"undefined"},__type__:{object:a4}},groups:{useDefaultGroups:{boolean:o4},__any__:h4,__type__:{object:a4}},interaction:{dragNodes:{boolean:o4},dragView:{boolean:o4},hideEdgesOnDrag:{boolean:o4},hideEdgesOnZoom:{boolean:o4},hideNodesOnDrag:{boolean:o4},hover:{boolean:o4},keyboard:{enabled:{boolean:o4},speed:{x:{number:r4},y:{number:r4},zoom:{number:r4},__type__:{object:a4}},bindToWindow:{boolean:o4},autoFocus:{boolean:o4},__type__:{object:a4,boolean:o4}},multiselect:{boolean:o4},navigationButtons:{boolean:o4},selectable:{boolean:o4},selectConnectedEdges:{boolean:o4},hoverConnectedEdges:{boolean:o4},tooltipDelay:{number:r4},zoomView:{boolean:o4},zoomSpeed:{number:r4},__type__:{object:a4}},layout:{randomSeed:{undefined:"undefined",number:r4,string:n4},improvedLayout:{boolean:o4},clusterThreshold:{number:r4},hierarchical:{enabled:{boolean:o4},levelSeparation:{number:r4},nodeSpacing:{number:r4},treeSpacing:{number:r4},blockShifting:{boolean:o4},edgeMinimization:{boolean:o4},parentCentralization:{boolean:o4},direction:{string:["UD","DU","LR","RL"]},sortMethod:{string:["hubsize","directed"]},shakeTowards:{string:["leaves","roots"]},__type__:{object:a4,boolean:o4}},__type__:{object:a4}},manipulation:{enabled:{boolean:o4},initiallyActive:{boolean:o4},addNode:{boolean:o4,function:"function"},addEdge:{boolean:o4,function:"function"},editNode:{function:"function"},editEdge:{editWithoutDrag:{function:"function"},__type__:{object:a4,boolean:o4,function:"function"}},deleteNode:{boolean:o4,function:"function"},deleteEdge:{boolean:o4,function:"function"},controlNodeStyle:h4,__type__:{object:a4,boolean:o4}},nodes:h4,physics:{enabled:{boolean:o4},barnesHut:{theta:{number:r4},gravitationalConstant:{number:r4},centralGravity:{number:r4},springLength:{number:r4},springConstant:{number:r4},damping:{number:r4},avoidOverlap:{number:r4},__type__:{object:a4}},forceAtlas2Based:{theta:{number:r4},gravitationalConstant:{number:r4},centralGravity:{number:r4},springLength:{number:r4},springConstant:{number:r4},damping:{number:r4},avoidOverlap:{number:r4},__type__:{object:a4}},repulsion:{centralGravity:{number:r4},springLength:{number:r4},springConstant:{number:r4},nodeDistance:{number:r4},damping:{number:r4},__type__:{object:a4}},hierarchicalRepulsion:{centralGravity:{number:r4},springLength:{number:r4},springConstant:{number:r4},nodeDistance:{number:r4},damping:{number:r4},avoidOverlap:{number:r4},__type__:{object:a4}},maxVelocity:{number:r4},minVelocity:{number:r4},solver:{string:["barnesHut","repulsion","hierarchicalRepulsion","forceAtlas2Based"]},stabilization:{enabled:{boolean:o4},iterations:{number:r4},updateInterval:{number:r4},onlyDynamicEdges:{boolean:o4},fit:{boolean:o4},__type__:{object:a4,boolean:o4}},timestep:{number:r4},adaptiveTimestep:{boolean:o4},wind:{x:{number:r4},y:{number:r4},__type__:{object:a4}},__type__:{object:a4,boolean:o4}},autoResize:{boolean:o4},clickToUse:{boolean:o4},locale:{string:n4},locales:{__any__:{any:"any"},__type__:{object:a4}},height:{string:n4},width:{string:n4},__type__:{object:a4}},d4={nodes:{borderWidth:[1,0,10,1],borderWidthSelected:[2,0,10,1],color:{border:["color","#2B7CE9"],background:["color","#97C2FC"],highlight:{border:["color","#2B7CE9"],background:["color","#D2E5FF"]},hover:{border:["color","#2B7CE9"],background:["color","#D2E5FF"]}},opacity:[0,0,1,.1],fixed:{x:!1,y:!1},font:{color:["color","#343434"],size:[14,0,100,1],face:["arial","verdana","tahoma"],background:["color","none"],strokeWidth:[0,0,50,1],strokeColor:["color","#ffffff"]},hidden:!1,labelHighlightBold:!0,physics:!0,scaling:{min:[10,0,200,1],max:[30,0,200,1],label:{enabled:!1,min:[14,0,200,1],max:[30,0,200,1],maxVisible:[30,0,200,1],drawThreshold:[5,0,20,1]}},shadow:{enabled:!1,color:"rgba(0,0,0,0.5)",size:[10,0,20,1],x:[5,-30,30,1],y:[5,-30,30,1]},shape:["ellipse","box","circle","database","diamond","dot","square","star","text","triangle","triangleDown","hexagon"],shapeProperties:{borderDashes:!1,borderRadius:[6,0,20,1],interpolation:!0,useImageSize:!1},size:[25,0,200,1]},edges:{arrows:{to:{enabled:!1,scaleFactor:[1,0,3,.05],type:"arrow"},middle:{enabled:!1,scaleFactor:[1,0,3,.05],type:"arrow"},from:{enabled:!1,scaleFactor:[1,0,3,.05],type:"arrow"}},endPointOffset:{from:[0,-10,10,1],to:[0,-10,10,1]},arrowStrikethrough:!0,color:{color:["color","#848484"],highlight:["color","#848484"],hover:["color","#848484"],inherit:["from","to","both",!0,!1],opacity:[1,0,1,.05]},dashes:!1,font:{color:["color","#343434"],size:[14,0,100,1],face:["arial","verdana","tahoma"],background:["color","none"],strokeWidth:[2,0,50,1],strokeColor:["color","#ffffff"],align:["horizontal","top","middle","bottom"]},hidden:!1,hoverWidth:[1.5,0,5,.1],labelHighlightBold:!0,physics:!0,scaling:{min:[1,0,100,1],max:[15,0,100,1],label:{enabled:!0,min:[14,0,200,1],max:[30,0,200,1],maxVisible:[30,0,200,1],drawThreshold:[5,0,20,1]}},selectionWidth:[1.5,0,5,.1],selfReferenceSize:[20,0,200,1],selfReference:{size:[20,0,200,1],angle:[Math.PI/2,-6*Math.PI,6*Math.PI,Math.PI/8],renderBehindTheNode:!0},shadow:{enabled:!1,color:"rgba(0,0,0,0.5)",size:[10,0,20,1],x:[5,-30,30,1],y:[5,-30,30,1]},smooth:{enabled:!0,type:["dynamic","continuous","discrete","diagonalCross","straightCross","horizontal","vertical","curvedCW","curvedCCW","cubicBezier"],forceDirection:["horizontal","vertical","none"],roundness:[.5,0,1,.05]},width:[1,0,30,1]},layout:{hierarchical:{enabled:!1,levelSeparation:[150,20,500,5],nodeSpacing:[100,20,500,5],treeSpacing:[200,20,500,5],blockShifting:!0,edgeMinimization:!0,parentCentralization:!0,direction:["UD","DU","LR","RL"],sortMethod:["hubsize","directed"],shakeTowards:["leaves","roots"]}},interaction:{dragNodes:!0,dragView:!0,hideEdgesOnDrag:!1,hideEdgesOnZoom:!1,hideNodesOnDrag:!1,hover:!1,keyboard:{enabled:!1,speed:{x:[10,0,40,1],y:[10,0,40,1],zoom:[.02,0,.1,.005]},bindToWindow:!0,autoFocus:!0},multiselect:!1,navigationButtons:!1,selectable:!0,selectConnectedEdges:!0,hoverConnectedEdges:!0,tooltipDelay:[300,0,1e3,25],zoomView:!0,zoomSpeed:[1,.1,2,.1]},manipulation:{enabled:!1,initiallyActive:!1},physics:{enabled:!0,barnesHut:{theta:[.5,.1,1,.05],gravitationalConstant:[-2e3,-3e4,0,50],centralGravity:[.3,0,10,.05],springLength:[95,0,500,5],springConstant:[.04,0,1.2,.005],damping:[.09,0,1,.01],avoidOverlap:[0,0,1,.01]},forceAtlas2Based:{theta:[.5,.1,1,.05],gravitationalConstant:[-50,-500,0,1],centralGravity:[.01,0,1,.005],springLength:[95,0,500,5],springConstant:[.08,0,1.2,.005],damping:[.4,0,1,.01],avoidOverlap:[0,0,1,.01]},repulsion:{centralGravity:[.2,0,10,.05],springLength:[200,0,500,5],springConstant:[.05,0,1.2,.005],nodeDistance:[100,0,500,5],damping:[.09,0,1,.01]},hierarchicalRepulsion:{centralGravity:[.2,0,10,.05],springLength:[100,0,500,5],springConstant:[.01,0,1.2,.005],nodeDistance:[120,0,500,5],damping:[.09,0,1,.01],avoidOverlap:[0,0,1,.01]},maxVelocity:[50,0,150,1],minVelocity:[.1,.01,.5,.01],solver:["barnesHut","forceAtlas2Based","repulsion","hierarchicalRepulsion"],timestep:[.5,.01,1,.01],wind:{x:[0,-10,10,.1],y:[0,-10,10,.1]}}},u4=function(t,e,i){var n;return!(!YK(t).call(t,"physics")||!YK(n=d4.physics.solver).call(n,e)||i.physics.solver===e||"wind"===e)},f4=function(){function t(){uU(this,t)}return yW(t,[{key:"getDistances",value:function(t,e,i){for(var n={},o=t.edges,r=0;r2&&void 0!==arguments[2]&&arguments[2],n=this.distanceSolver.getDistances(this.body,t,e);this._createL_matrix(n),this._createK_matrix(n),this._createE_matrix();for(var o=0,r=Math.max(1e3,Math.min(10*this.body.nodeIndices.length,6e3)),s=1e9,a=0,l=0,h=0,c=0,d=0;s>.01&&o1&&d<5;){d+=1,this._moveNode(a,l,h);var f=rG(this._getEnergy(a),3);c=f[0],l=f[1],h=f[2]}}}},{key:"_getHighestEnergyNode",value:function(t){for(var e=this.body.nodeIndices,i=this.body.nodes,n=0,o=e[0],r=0,s=0,a=0;a{var e;let i=t;for(;i;){if(["hui-card-preview","hui-dialog-edit-card"].includes(i.localName))return!0;const t=i.getRootNode();i=null!==(e=i.parentElement)&&void 0!==e?e:t instanceof ShadowRoot?t.host:null}return!1};var y4={Controller:"data:image/png;base64,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",RoomStat:"data:image/png;base64,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",SmartPlug:"data:image/png;base64,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",TemperatureHumiditySensor:"data:image/png;base64,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",iTRV:"data:image/png;base64,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",UnderFloorHeating:"data:image/png;base64,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",HeatingActuator:"data:image/png;base64,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",DimmableLight:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAACgCAYAAACLz2ctAABZkUlEQVR42u29d7xlVXk+/qyy2znn9jq9whQYhqEXFaSKCihFQI2gYkzy1WCIfpOoRI2axK8mQWNiIxEVOygKUlRwEJA+zDC9z9yZub2eutta6/fH2nufcs8dQBng8rtrPudzz71z9tnt2W993vcFZtbMmlkza2bNrJk1s2bWzJpZM2tmzayZNbNm1syaWTNrZs2smTWzZtbMmlkza2bNrJk1s2bWzJpZM2tmzayZNbNm1syaWTNrZs2smfVHLDKdD/6Sey+l/3++eb+86BdyBoCvEOBeCxd/5ppMAwBecu+ltPVn3fTWb30jrPz7T8fvsL//5A+OoibpFF44BwAsac16LYPNo14fADCLH5K+GnzXKe/ceWXz5W49QE4XMJJXM/Banu5Q37npFhUD7ofrf3jm3I45p0gh34gxek5OThCPeFT5+lp7wocIRdX3MM4gQgHG2fPu02LmywMk4U/5f7XHX3ke8TESk8JSlmygTQot8kHK6O8ODh168prjr3k0BuS1n72ejJ00RF7tQCSvduC97deXryIE7x3aN/QeykkbZURKoShl5EVdWMaZEqEgjDP1xxwXC/jzXithhAoATGolatGXnoz/Fr9/IUuEgtQee/x7fP5SqGQ/NrVl0S+NdSzs+K5S+PadF9yxsfKavlqB+KoBYO0Te9naK84lBH85sn/47d5YQP3Qh5kyAR/wSp4KvABBzofHfSJ9BRlKUD61T0JY7e/61JUo41EJgJokkjRWWWIxH9Su890MgKj+XboSlm9WSDvvRV2H2uOJj10JwKGW8rhPLGYBnlKiJBVzKDEaTBiWoT9rENI8q1E0z2m5Uyl87Wdn3/5AvQd7BoA1Ui8G3tt+ffkqZpFPNfLGywDAMs2qC3aov5cOHxxBfjCvcvkcESUBkiMQgQAEIJUEhL6RxCRVoFQVwk/R8nvKaALIuhfJIKDmFOCmBJBK/wQgfQHllX+vu6TSx1fzEEhRFlI0oPqhIlQD25CgjIJmGJhFoQL90DV3NKvOo9plx+xO1pxukgDg+T6Jrx23jAd6R/u+UAnEV5M0JK8W8P10/A77B0/94J8tw/wbx3BUJfgM26b5bFYNDg6R0Z5R9B3sgxyUEK6A8AQgASUlEFZLjkmSj9ecPKUgRgQcU98TTjhCFYIKmgC5DJwXcEIRTolJEvAAQKj0wU363im+M7Zr6x07oRSgAEsx8E6O2Ytmo3V+KxpaMohBWMq7cIMSjW1Owul/zFk193Nf7f7y6KsJhK8oAF933dn0kVvXysvWXnHu/qd7vpJuc1Y2tTchZTlVBvto/ygGdw1h4uAE1ISCciWUXwEMRgBxGM0yhXQjDCCmvpmEES1pmASXHDKUUIGC8mUZ0JX7CGuAUbGP+HuJQSBNWRfUKiw/MIdXyWUVPOkYov0SC2AtHNYcC60drUi3pmBYXJjUotRiJDeexeCuIaRbMlsWnDT/r3929u0PvO66s+mSJUtfcZVMXil7DwC+c9Mt6tL73/aePY/vvdXMmGTpqsVIpdMKAIZHh0nvjj4M7h5EOBBCZEX54jNSJdlIrXo8THiaMFKl/hLQEQ5plIUCkfr/iSCQoayRTgoyKxJJF4O4fDxl1R+rzkr1SiQBiXyKUIXghFeZB7GJUPk5COiHQigt8eMHI74mIQCrDMa2pW1q/nHzSWdnhyoWCmTXxj2Y2DKhnPkOVpyy/B9+ctGPvxDfi1cShOSVAF98wqu/vOaL43vHP+pwW805YbZsb29nxKQY6h0Uu5/dy7w9ngaepwCub2wMOGJoiVWp5ipVXRy2IIJAMZX8rDr5ir9xyhEgmGQPxiq6UhpJVyIcDIAQ4E0GmF0+gPg7DvcAJLZjrZlAK2zKCrWvRNlujIEsfQnq0yppmmgFRkDTFPZRNhaumi8ZZ2q8L8sKfXk1sTdLmhY1qhUXrrz55+ffceMrDUL2cu/w+HNOIBt+tw5v/83l/85APkIEJUExQN+OATo2NIb+PQPofbKPens8qKwECEBsAmJpSUMtCmYxEEpAOAFo5FxQfQMppaCUlh0NUr65ye/RSzEFgxhQXAFG5IxQAkTfTQwCKAC8/DdQovcdUoAT8BSHNCUkJBRVoAYFlAYaoTUvTgESfTeFfpn6OymnIJzqQ4s+SwiBUkqrdEoAQkCpluCU6POUXIJyBhD9QBKij1m5EsFgiPG+CTI+PkFzA3l4Ix5pnN+gWua1EtMxTz/2+lVN27639f4Nv1uHaz97Pdnwu3UvOwD5y+1wfOeiW+Tbf3P5v1uG+TdzZ82TtpMiPV6PkgM5TOycgHIVZD5SbylSJe204KAIabXaqpRSVZqY0SonIpZMlX+TTIJgssSjJk2kVG0IR3EAXQQ0pImqrJJo9aRbcsXL/0cpSfZXlrrlc/XCAKZhlGODnpZ0DExLPihwwQGinSjCmH6YQgnlabs46PcRjgagaQYjY6BlSStZsGI+mtNN0vP9j7z9N5cjloSvxOIvt7f7jnuv+jui8DeWsuSEO0EpJzAsQ2cAsgr5XAEAkGlII48C4AONdmMCPEooGGOQVEL6EtzhIAbVN5pWeJWROiNSTfY0KwAi3FBLvvg7uJYyEyoLBzZsx9YORkXMjwgFKiIQBApSKhBa49XS6v1QWla9MSgJI4BZtkWThyyS4Ja0EvsPADgjkL6CpALwABXofYY0BPXLap/w6EKEBMpX2maFQJgi8CY8pXxJPEOHarqaO2746803DH3lmC//yyvhHbOXE3yXrb3i3DAMv8spQyhD4gc+tKMxRGR/iHyugAvPPB+f+cCn8e63vhtXnfkONGQasPHQRkgiwTgD5xyCCHQ2d6gvXfNFkuZprBt5FnbaAjUoqEnBHAZq0uR3wnUcjxACEv0NFHDh4q8v/BAuPfkSrN2+Vn+G6c//80Wfx4qO5Xh2dD1oSv+NmEQ7MVxLKhKHXAjR20Xfn6jcSKVTQ29HWPQ+lnyxZDe0tJeOgrIAaSpIU79XlpbclFEoDhBRBjmhkR0sInUtlTYZYjVOK6RqqKA8hUKpQAISwmw0iUUsFfohssXseUdft/yRO8//+Z5L7r2Ubv/+dvWakYDXfvZ68p2LbpEf6r+h9Ynbn7hN5HW6KtOVJoEbon9zP8LeAPlcAccvOA5f+/DX0D/Rj3uevhfL5y3De994He5e/ytV9ItEhAIiEgc8zXHWyrOweXQLsBXwaQArpSWGF1RnHyxH/90PPBRzRQBAAxqQttNYNnsZ1vU8ixJcGJQjcEOERojT5p+KzaktyO3Mo5E1IOvnAABNrBGUUZTcEkAAyzThlVwQg8IiZhQAp4d/zGOJygBqUCimIAxZNiVMAipI4nAISDBQUEEhHQkiCCgohJAglWaEAghIlYlBTApIrZKVryAHBPqf6Yef91WmOUPz43kV5HzVsLDptg/133DMV7u/PPpyOiVHHIC7d+8iANQzdz79NXek1DVrYbfKjefp4K4h5PpyCHuDJMbVNbcLzelmPLjuQXz11/+F8dFxtHW1QZqSKKpwwoo1WD1nNQ4WD2L3+B6MFkYBABeecgG6m7rx8913osFuwBtaXo+ns0/jjO4zMOgP4tEDf0DWz2FBZh4uOOYCAMDdO+5WB0YPkl+s+wVG3TEAwMKWherspWeT8dI4giBArqhB15XuxDtXXgMAuGvP3TiU7cWZ805Hxspga/9WdebKM8mjBx5VY7kxUgW+GHiiBoQsUrMMYCaDbwXarIhsWsZYpPLj3ykEhAYhqJaOcXxQRiEboQPfksnq9GAcuLbKIAxHAwxvHiajfBS0lZKOuR3KHSl1bX9s638BuCa+Z9NeBV9y76X0Nx+7X1629opzB/uHvrDi+GVk9vxZysqYZLRvTOV2ZolyFYhBYDXZGMO4WnP08eSC1RfgqjPfgeXLl2N7/w4xnh2nn7zyE/jUW/8RmUwGJ8xfg31D+8jJ807Gso6jsaJ9Oa5ccQUa040IRICvXvgVrGo+Fi1NLfjLY/4CQ8VhDPvD+P5F3wM3ODJGBu896VrywM4H8YXLvoAT2o/HUz1PqR+85/tkWdvRaMw0YkXHCuwa2YV9E/vwP+d/C1RSMIvi+qPfh/sP/Bp/s+YGXLPyapzcfhL5wOnX4+DwIfLM0DqYjqnVNY/UrqlfsJC8J5yAmxzUpvCNALZpQxoKzGCRGUBAQLRtCgKJSNJBgUqqU30KUEqrY6KgvWUQEBVJURV5+6psJugNIs9eKbBWjqVnLJarTzkOXQu6yPjw2Mo1Hz7x0fs/cs/LpoqPKAC3f3+7uuTeS+mBDYfuau1sam3v6CBCCNKz7wA59MwhIkeFDtqmGWiGIpvLkt9ufEB5rkda21px4fILcdyiVXQkGMH/Pe9j+OaT38KH77wBd+25G67p4l2r3onHDjyOP//9X2Jl0woc03EMns1twOnNp+Hfdt6Mr2/+Js6bcy5CI8Ty5mXqtO5TyY93/hQbhzbiPcf9GUaLY5htzkKulENbczt5w9I34JLb3qZ+tulO8vbll2JLaYs6KnUUOWP+Gfjxzp9i+/h2XH30VSiIAnziqTNmn07u2nk3/uH3H8e+wj54pgcwaHAZkQ1qa5uT8uoXsbR9aBgGQlNENiGScFLsyJD4nwJUqLTnHULbdEJpaSe1R6y9cej3MdAqQcgiECoAvrYz2xa3kdnz5xHTsoiSknqed8Ln/+ufv/25Vf8UvBwSkB5ppi6h5N2ZRQ0r29vbWZzh2L/xAMRQqDMaUWxPhALz585Tba1t8v/d9UVc8vW34/vP/ACLmhbh9EWnIwgD7B/pqVYthGBPsBfpdLr6pCIvkmcMBJ6PIAjgmA6RUsKxHHQ3deNTD34GGw5uSILI3OQYL40jX8oTACjIAuyiTYwGQ8XbdZqd+H9PfwkbD2yEYzpkKD+EHx74MXrRjz5jAEbGhJExQRwK2sD0y2bgaWPSi1kMIiURmgIwI7UcORtVooFp4Eimpgw3TeZH0GQ7wkgVqIkZefuMAGMK+zcewGBfHwCgpaVFplPpY2974nvveLlKHuiRrFd43XVnUynkx2a1dcI2HFkKSqR3Rx/8/Z62YSxApbXqAYDZbbPJL//6TvbNG7+Bz7z5Uzhz4RkYc8dw2+7vY/fYbnzs7L/Fn53ybvzV6r/A8rblMLmJFrtZAcCtg9/B13d+E7u83fj4hpvQH/QBDGi2mtGV7sKvhu4BpRQtdrP6Q/8fAABGo4FMugGhLfD7HQ9jTvMc3HTuJ3H5cZdhecdyOJaD3+98mFimVbVdxsqgg3SAU44Uc2BbNlJOCkbKgJEywBoYaKb+Cw5JXqZpgjq0GngV8crYflRCgQqShF2mzBtHNqRUclKGqNbyJ0xnTrxdLnZt3IPAdSUAdLR1QQr5ses+8EH+coRk2JGSftu/v12ddPNJ50hXfHR0YEQO9g3RoZ4hDGwbQDgQgjCANxiApY+CpTiGikPodfuwqH0RFrTOx3N9G/Ffz34N6yeew9OHnkYbb8MZ809Dyknh4bGHJWGUPN3/DPEdD3+25F24Zs5VuHLO5Uibadwx9gtIJaGkwrZgu3j04GN0b2EvTsycQE7vOh2tZise7nsYZmhiaHwIv9x6F/aN7sfps09Fykxh2+B27BzehXt23YutY9twauep5PSu09FEmvDA4AMghGJUjuLRwmMIjBDM5pCOArM5qMlAOQWzGajJdGjGoFA2wIzo/00GwSVMagJEgVIKpSpoWaIMPiEEVKhghaaO64VqkgrmikMqCaLKdqCCStS4tvsi1lASryRQnkTBLcALfeL5HrLFCdLe0t4xtnR49/bbtm040rYgOZIsl9O/fuaPxw6MvSPsD5Uf+iRAADWhIAsSNE1BmgiYycoZCE6QIzmk7BSslIWckUej2QARkQQKhQIaTR0SiX+evPgE9fVTv0YKfgH/3f8NMeT1s48u+Bh+PfIbfLvnuzgr83rMSnXj2YlnsXlkGxaac2TP4CGa9XMwi0acwIXFTYzlx+EwGwBQEm5yHHFYx2lwoJhCg92ACZrVksthsB1bA8xSYJy/sMdbxMxnzZJRoYIKZAQ+BV8EOtDtS/CAAQEgfAHpSm2/lZTmHgYAdfVtrOJERqo4JlIkJAZZFmrK0542MQnQQmBkDGSa0io9K0MWnrTgjjvOuv2K+F5OGxV87WevJ4/cula+df2ls4tbC1eOPjmK3KEs8cd80IBCuRKEaS4bM5nODFg6UMwsipZMM6yUBWpTpNNpyJS2fYhBkGnOQBgSrY0t4DZHW2sbTmw8iQQiwN/t+Hvcd/DX7LjM8egp9qAv6BeUUZzWcQo2FNZjpDSC7lQHXtf+BgoAjWYDZrV0w1ImLEvHCVe0L1dNThNs08YZc0/Hgsx8BQE4KQezWrrBTIaudCe6GjokZRQpJ4U56dmgDgO3OZjFwU2eqGLDqv/iTH8ODDCIMSUzmnssAV8oQshAg0/5ShMWJKACjY1QhtXhl4g9Uwm+KipZWE4TKgFQnyLo8zGxN0sOPXwIvb/vu+z/5D+04JFb18qYvTQtADh20hABgMFnB84ZGh0m9mwbVpcNs8WM6EQATTPALudKQzNEYIXwrUAHYaPgLDFIYh/FdhExCHwawKcB5jZ2izWzjseYGMfWwk4c27ocF7Sdj22l7Xho7BHGmL7Cp7Wdjo6G9qrjfPuSt+H/HPdXeNOSN8HNl3D1sVfjLcvfTFrsFgUAHzjh/Th+zvHE8zy896hrceXSK9BGW9GQysh5bQsoMSneO/c96oJZ56Ej1Q7qMA0ui4MxBm4ZVS+a4hW/cx2KYRzSVJMKpqigMATXLJcIfMpVgB+p5YgNHcdPAwQJbUuGcjKRtt6d5tVcSukJ8EYDRsZAw5wGOdw/rA4+evCsyns6LQA4+uMJAMD4zvE3N3Y1qGMuWqkWnr0AbC6DcjWzQyfOSUJ1JwYFDMAydDpNmTozQBlNgrOSqUlgvHrJNUwWJb6+85sI8yGOtVYBAJ7Lr4cXuODUQBAE+HXfb7F3rOxBN9gNOK3zVDxw6EFkaRZNThPmNszBzb/7CvqyfQQANo9uwX277wMMoMVpwU933Y6dhd3osrtpc9CEo53FyrU98u3B72EYoyCcgDEGZRFwxwQzeNXLoEbyXln6swkImdJMm4hwKoXUdl4FbQwR968ekzrmLlaq/Zj3WFVjEqtfjslk2BDg3QYWn7tQLn/TMtowr4EM7h16CwC0/qybThsAxiK7obVxdao9jcbWBtLU3gRZ0vYMOMAdrhP1nCCwQg0+aiXpKVFBDI0zBPFPyRTMqHxyqbEE43wcAPB/l9+I/7PkL5Ev5LB5YgekkBCuvsqXtLxFrbFWI+vlUfJKOJTtxbqeZ3FG++kgOWCiNIFtE9vxmTd/Cis7V2KsNI5CWMTVx14NADiYO4RYbQ+rITVuTGAn9hIA+LtZN6IdrRBMQFkEBjU0lWqKF4DkM7GEPtwKRYVqFWVmtBJa/TLBEoDG9TBVJQQVLxKFpxBGIIy8YTACFanshpZG2t7arqwmi/j54Nifjt9h3/qtb4RHSg2TI0E2fduvL1/Vs27/hq6Fnejs6lSDA4Nk4wObSHDAB00zsHYOYmjVS1J0kuSLVW85blWT34x+X958FD698lNo5S3wQg8/H/kFvr/3h/BFAJMZ+qcwQBlF6IeQrkDohprl7Eq0WM1qrDhO4GtJ0Wa0qlE5llyTjJNReRRIfGzc5jquZ3LAIaAOQ0eqHRNWDtzSEi4GGaOTwSWkRocKJQIZgAqC0AsQeAFUUUKWBKQvIEtaAqqS1I5HEAGrpCBdCSk1sUAFumygFoCHqzepdEKqamiEApvHcfxFq9WCJfPV2NgYHegfkM3dbcffecEdG48UU4YfAftPUZN0NhzVRDpbOyU1KSmUCkT4AuAAtWgZfAaFRavBx2wt6UgMwChxX1u1RhjB9twuXPv0+9BIMsiHRZSEC2IS2LBQ8l1wjyEsBfCoH9GbzKrc7FhurOpLh91RQlh5n3lRILWerDYLJJhhgHGGYYzCZjYkU+AV4KOUJRKn6qYDEBwwQgNChGCMIUAAxhkkxJT1K9XAUi/gM1NIHEonqWLCAAUClIBCqUAAqJaWFklMSn0EndOOjHBw78FZTmMablCihFBMFHKQvtTSwS6DDwYAE1Cm0t5uRIfiJkG9G19v+SLAsK/JBA6zEZZC+DkPMhvCL+lQBonqNERaVAO5ppiJsCkipQzgrCzdKkHCGU/U6lSSLwYiBSClqCDDKpCwsvyTAn5ZSlaFbGqr86QCEwxhJMbi0EuiLejhQZg8GBX2oPIVgmyYlHUCAC+xkwA8MC0AGDsgXtZbzVyGollCCg5KQUm3yHAEaIpCGZoDZ9kWiE0gUwowibYNUU5LMcYQ0OgCQyU3OZA6TWlIHoFA3/SwFCIY9BEOa3VLzXLZZZgToAUJ2siqi8zreYz1GCw1DwPhOj3GOCkDM0kFlqXfpBsvBRhliRQM4WtHJDbemDY/JARCEVaxtQ8XU6SEQtYiLgZhLVFX1khDXrbF8uN5NTiovd7+Pf2Yf9z8rgpH5NWtgluvagJujd53t6K9tV2VghKJwyeGbZRVr61Vr0hFBdcmS4AnDQUJBUYJDBhJqi4xXWQILjg4OITQasv3fagRocEXSvBGrrMIJQFQAp5ikL5COB6CN0QpsZouBORwPoExtSSWTGlBGaneRHhG70WF1KOUVUlBwilQSV+sKDziLDq/imOU/vNjoLLyT9VjVdUBIYkeyvGRCRI8vRuGaaiJPROkNWxvnnYqOGWl5ktPKOlL5bouEb6I0lEASU3uVKBDLGXwxYCN1Usoq2MGFrUghEBItQ0FAbAihT/ma/A1MIxvG0dxS7F8oq0c7Se3g3KKMCe06mSTQRhzmQgjgK/0Z4wYLCRJlVGwMoVekCSeIKVIQFgJvFpbMHZEgtADjTYOZYAA2oFSXDsZEBHBNgQMGAAnUKXy93DKIZiIcFXOfNTazJPiHbSszgmnOhsigHAiwMShCVBL06nzTdn0tAFgrIL9os8PDhzCwL5BAkCVxkqEMYrQDGFTBzA1Ezg0hI6Hsbj9hEKKp9BEGtGPAcx35mG+NVv1eL2kg7agnXSKrWI76ykdgEOdRBVDKAR5H9KV4M0c7v4SsusmwO1ylsHtLWHwkUF0n9cNGWo6UlyPEZc91rbTaGluURMyS5jJ0MZaMSCG0Mwb0Wa1IUsKyCIPX/pgIQOMMuBoHTuQ6ScMvu9CSIFO1oG5tAtB6MqdYh/1hY+jMwuRJ0XsLu0t24AMOL5pNQBgy+AWwFXo6uhUAyNDJECg62IIh/RkYq/qTElUCeiWpVv8PrETZVliUk61Hg6A0AvAPCqEJZlf9DkA7Aq2y2nDhskN57yRXSMkuzOLgR0DhOUijzZFE/DFmQ7t8ZbDLovZPKzOrBIAcKK9BkvJUQQA5psLMawG2Yn2GmRYBiVS0tgTAr4IQPyoMk0ojG8en/yk2Qb8EQ/BWAjKKaSvqgO7NY6I67u4cMGF5Ni2Y7AitRw3Hvc3kELiyu4rVLcxK7G9lvCFIJwikAE6VBs6VBukFFBSglGm7b0wwOtLp2C1WpGA9PXmGeggXWgMWigAnN5yKs5KnY01TWvwgcXvUw4cjJbGcFrXqbji+MuxoG0BPnbWR9HZ3KE67U7icFumeVotnLtQMINhUddCpBvSCgKY1T4LszpngVkMSxYvgQp14H/J4iWJZGQWQ6YjoyoRIJXUEjRSOI6wMW0p+WIoRKm1RJjBElYGUFMDATIpaZ+zSsjJCRJTj3apncov+aTIiuKZwnNsvrkQrWYLctmcZoEIDgiFkgwSitFhKUuBjNohaLZmIv3ipkEoV60dGO7B/Nb5GA1GkSvmsKL1aDXmjhMAmG104NLmt2AwGAYCYK41B4vMJQCAvd5uLLKWoNFowIaJ9XiWbqk+hlAmaj1rjEm4+uo8M/4sHuj/Hd49+xpy3pxz8Z3s9wAAzw6ux0+fvh25FVlcsOpCcmC4B4PuIHnfRe8jBwYOsHlnzcOBgQNoYk1kIDeAroauqv1tnbMVrY2tAIBTVpyCngP7ceWZV+KJnifJjx/+iabxGxGNS0QVeZ6lSzwxTfmAytc1qUE+qKqFlcHUkpwGBH7Jx9HWMnpiahWKQVF0kC7SRpuQMlLs7S2XYMDrk735PhgyMtAjCUYNGjkS1Wo0dIMqKUgzTD/lNTW/UuryyhiMxKDYPb5HzcnMRqvRigcOPYjzOs/D/tx+zKLdUfGTjyY0AgDW+Mch7+eR9/PJ/n6VvT8BX9bOwSsV4fteYjrks1l4vk9GozBSvPpkP5yK/jgAEBohRt0xpHkKc1Nz0Wl3kgMDB/Dt394KUQzxjXu+iYHcABZ3LcJPHvkpntryJLYe2oqv3PWfePtpb8PirkXoObBfB9ibGnDvpvvwrV/doj1oQUEDCi45KKGJLeyHvpi2ANQgRKiEQsgDKE+BjU/eXexExJ7fQHEAPxq8HVuKu/DAxFr22NgT2CMO4K7he/DY2BN4cmwdRag5clxw+CKAFFIzayLwNB7VWAW+0A0QugFalrWANzAoT1UxQSqBJ6Uu+LGIiX1j+8iyzNEwUyb2TOzB6e2nkf3FfYAN2IYjn5p4EgBwJj8N27ydAIDe0n55kAxUxyp9D41uAxZZSzDHmA2DGmjOpZE1xmQpKBERCjShEbNS3TimbTlObF6D3w88pG+QQ7G8aRnOmHs63rLizfjDvscSR66JNSWhq5SVSvbnmGXV2d3SDTfvolDUDtmTW5+sG8aRnoTwBJRZvjYmN9m0IqTOP34h6Vm/T7W9vv1yd5+7CgqSpiglLQTIao+LNXIQU/dkYSZLSAmg5Y4CQoYQMgQFQc7PaaKmBIqiCCYYEAJUUZ0+Cpn+f0YgfYlwLITVZUFZgBjTbSsoZ2hf0wHnKAfhRAhiErAG/T0qUFGtTtSTRUUFPAQQSmCIDmPbyDYMukMYCAew090Nj7oYLI6Qo5qOEpJJ+vvio9iqdmBuOAvz2DxywO1BDz+EQTGEINRZmAIrok20YBa6kCuMY4fYhePpatJG2lHy8zhQ6EG32Y1ZmIVf9fwK+7MH4RAbfslDq9GGTCaDJ/Y+iY0HNkG6Ar0jvWo0GCUD44PIhTkMDA8iq7JitG+EbhvbAc/3kStm0ZvrxfZD27Hj0A6sXHIMhBtie99O5IpZFHJ5EK57DapQm0TEJlBFCVOZCiaos8DZ2nd/70/iezvtyjIJI+ChgdALIEIBU1hJmEUyBc7KWQ8pZFWcTQjtJcc/AcCHDw6ekDa5YAlzhNoU1GYIiwLNRzWj+ahmSLdcbxtmtXXNG9ikFh216S0lANux8dSBp3Wu2qZ49MAfYGRMbBvfCcs0cV/frxlsgga7AZIp3C8egBIKJjUh8gIWt0EjO7fXO4R92KufesngSx978vtR9AuwAxsqkNg6thOyJGAoQ/erlsBgYQjf2fzdMnE2ZWLT4GZAgowcGAVhBOu2PgvLtLDv4D62w98Bm9noz/cn57Ln4F4oKbFhz3NaBfN0EoNUgYKSUpNTmTzSSvHlBSBxCOddHCEPElvDkx4MwwQCXe+atLxg5SBvrI4N0yir6To9/0wYmj0TCqhQQgYyarFLNXM4BnIhCo/YkZoWOgVIWFRnIcthi1o7FhTw4MFiFgzTgOu5YITBgw/LNOG7AVzq6mB5CDDonjVCChSDgqbcAxBMwISpvXbpw5AGQhYiwzJwvRICEcCGhZCFcH0XSigwocsyLdvSx6wU3JILk+vvlFRCBYCRMSCEgGVaYJzpiAAve7a6ro6h0Wqc/ODFQWmhtQgxCFgHhzfmwYQ5vQFoWoYQrZKRgEJVZHFYQHX6LU55VZxnZR+9RPJVODEWtRGyQNuA4PCZDxpCt3GLYnusnYIzDsfQacDk+3wBWZBQJd1dACZJugwkGQZZtgnT1FEXLbuINDvN2JLdgo25Tbhi4WVwLAf7c/thpi0sbl2EklvCJm8jjm5ajiY04kH3Iczns9Ux5jHk3txv0Og04Ci5FPeJ32IJX4gzzdOw2d+s1olNRIQCy5wleH3z69WDE78jI6URXLn4fWr90AbyRO+TuHjFW+EXfTx64FF15tIzSYZm8OuN96vB/DABJSCG0tKrNjAtDtN/Wk7tBRBGQG0KI8fZtC7LrJfGUkLBUiaEIasrvF6Ar8UMBmZoEici8idlFKYwELqhVrUtFOZsCyqrkF+XQ98venHo9oMYv2sUuceykFmBxs5GsHYeZTkA4tCEm1h5Y0phCW9ceQ7JFbL4+aaf48DYAXXVnHdg0B/EXXvuxoDbLx8behy2a6lnJ57FWDGLU52T8dTEk2jwHCwlR5GnC0/jRHsNsqUclltHJQ7Lo+HjOMY8hrSjFSVSwslNp2BtYS1Z07QGV3ZfoX47+Ft0mp143+Lr0D+hVemK7hVk7a61CgC6WroJAB08jtvJMZJkRBRTkzox1G0zHHeGDes3bnrNtWery0+r7FZahwQQ0BCEEbDoj5JJbRdCP+XCE1Cu0sArSRy8swfu9pIOuaR1zXHBKyLcGCJ8KkDbojakz2qA0WUiGPCBDAF1CFAgkFwXfMdrTsNs3Lb7d+jPDwB5kKYVjfjJtscwIbIYFxOUGARj7jgZKY0gq/L4Xv/3cKy1Co7toC/oF1uD3WyVeRyGxSj6vAEYUj+Je0r7cZS9FCfaa3COfRZaZDO2FnZidfp4OKZDtuZ3op104JjWldh0YDOOzRyjwzPGAGlKRR4+D2AxC1RqWzoqRdfXRf4RKChWayLP8mF55msMgADckotUIY0wLXT4pEIISyEn+eUGNWAoYzLTA4DMC4QTAaxuG8GIj4O3HkDoBuh+4yyYcy3QNC2HGQIJf7+H4ceGMXLrCOZftQC0helWuybRAVhXQlZckW392/D2Y9+ODQc3AAD2j/TgbUdfil2Du5CxMnhk4g/JZxtJBoEbAhZQcktoRhN7vXm6mECWtbNWLHeWodl9CF7g4/SGE2Qn2um9ud9g1B/DFY1vw5tmXSAgwHr9Ppzb/UbMot3YnN+C8+acCwAY9AdxVMsSTBSzWNC2AOuHN+iOWIECOAGJ+iFAKHDKEUIzaaigCVWrHiFBSVW/VzXTIHxtqOBI0smShNqlUFxfAPbXqGAfSS1slUoO63v+zKMICwF4kwEVKhy89QBommLhBxbDWmkDQqE4UMDE/glMHJyAO1GCudjC7HfNgT3bQc+P90floRHinahGJWqR61AbD23/PTYc3IBWuwVj7pj6xfZfJuDbU9oDAPj9wEPIennkwyK6jVnoK/bjJyN3YJOn58T8JvsgAOCJ0lNodBrwc3U3GoMW+mj4OIYxCskUHnR1zO+h0iP4RfZXOvvhPYs7x+/CuDGBQX8Qzw1txNLWpejxenBf7/2wIkeE2jRSxWUbTjABTnl1p4TKO07LnfhlSUIVVTUZgxM4jqNejuZ9R1QChlwwCl1WOGXKTggwsLIarlHBnBoIZDDJE467qBptJvb+zy6EboAF71+k+X0FBY/4CNwQdmBB+AIoAP64B3OWie63zMLB7x3A4AMDmHPFXO09G1HXqUDpXHEUlnly71MIjRApO0UsbuKpA09rZ8i2YKVN9BcGQbhulbt26PeakW3a2F7aje3BHmabNobFKO53H0jIq/fR38KQRsTIAYb9Uaz1Hmag2q57KHwENCRwMg4eGn0YSigYNsfDI4+CFqNYHeKHVgeOKY/4gLJcvqBYpJijaxqnPquJCFHH17AOHU1M9zBM1egCnWNl7QxGmwHWziEgQQWBgEhuTu0qoaQvVgCETOsKO7AhPAHeYqC4Pw/5dIjZ75wLbnN4wgcNCMh+gJUoggj91NSd6v0+H+YCC53nd6H3roPwez3QLqbDNiYB8avzw2k7iplJfUMs00raq4UiBAeHggThDA6zE1PBMM2qckvNqCYRc9up4vkZ3IABLclDP0TayujrEgo4RkoXVwmFFEtBUB1yAgME1YXqxIykVyS9CdOg47SaT1gbgil396+uwovScGRa24C0maFpeRNkm0J+JJ+cME1RkCZNSDClgZCJSU9cO2lBm9WG/eFBtIlWSLv64owFY1ChBDVNFJ7JQ3YAztGOrjQzGIKdHqSQMDJG0lle+jIBYTgSwpxjwmyzUNpaRNPsFgQi0FKQqaTYGzIaAUZJmaQgNIlBMp24DxGCG7xsw8YUr1B39pdMgZs8KduM2dO8zlgxxWQCUhUqSKHAfN3OTYUKgoUwmKELrCC0BIziqEn8U2oCrjT1SAclVdkWjBpZJpT9mLzKq5Ggz1dNby+4YV6DXLRqIRmT4yQ/ktcXKoDuixJxAeOd27AQRuhb1rAUa5rWYGe4HScaq+XR1jK6w9su3aBEz2s6H48UH5FPjQ9TwjWY8j15NM1qBLUZAhYCIwoqAIJ0iAAhbGojsH0gDdBCxIuLCJ20nSI/VkDGb5z8AFFyWGeSVlLuAwB2RKiF0uTbCEi14JNMJWWZVewYAAELQMF1IyImkzES0tfUf/2MRq08uEI83FNCd0wgTF9fKcXUDklNU/Z6TYuIQWBwQ0kIMm0ByBxKrCaLWEUHlm3B5x4EFQgMbc9ZzIRPA4ARBCwsV6LJIsbZhLCJQxpokyq5JUx4E3STtx0dVrdYN7Ex0WvUJ5CeBGnRfEILJkpuEcQoh3xcVh6ny2wO4YZJUx8zbcIddhPJK2PGcqTKKCXaFqRl24lEXeyllJrJzMpxTskkKCuHiwijiZenpTOvqpwrR+yj/jiSVtG1SBAiRACDGwi8QKcgIxAyMISh1OGpiMyhJyqVvWJIrYqJIIe16wilGvA06qntUBCbqJdjjswRA6DRYKKlsUXZjk36mnvh254mDRi68FzSoLoWxIxqQQyFIa+fLcgsRhMa0Yd+AYDZll2mxUe2pWSyKoTDTX06oRnCAAcPjUSVlqSre9AE9AXTM6RUSDekUCqU4FMfTWYTPHjwPJ2aq40h+CKAjajjAdFdsGLpV1kzbHCzboVaUi9iMggpwGpuj2Iq+YvyBaitSzkTp6JSFUdzhwUTWg2LKOeupnYumMPAOw10tnTADz0ydmhs+qrgIOdD+lI5poN5rbPljtQuxgIGy7C0HcOENoIj8DGLQ7EQWTOPpamFaifZRXr8QziOL6e2YwMlYEN+I6sEXXLjrfJ0ItmgQCIGdljhfjuhg5AHGgiGLgU1TRMu3HJlmUGT6rSCX8TJ3Sdi9ZzVmCBZPLnrCXXKklNJs9OM+/ffr86cp9NiPV4PqEPx8MijOLf7HAyqfmwNd2lHAoAvfZzVeCY6SBeG5ACGUzmcLI5HL9VNIQ+RAQxjFKvJsVinNsHkBsIwSOqHGThEoGtfwjBM2ngohySqmDOuHRJTAiWVhFJi8cUEA6iurYnVcJU0pFGvRlMhFThqeNOwUq4i05YP2Da/jaXa09h/YB+GR4eJ7aQYcxhoSpdE+jTQF9IkCfhMx0LKSQMMeEZuJLvDfQhogGfkRrJV7gazOLJmHozzBGwxe9c0TcDRXeXTjemk21Xcl48YFMKJht8YAG/i4PbkZ0/KcmuLtJnCltGtuOWZ/8WCtvnwrQCPHHhEpXkKp3aeSkIvxNrBtVjVciwWNCyAbdpYmVqu9roHcGJqFdpZK5pFIxzDQQfRDOVN5i6cLI7HU2w9Gt0GzJazcLI4HqvVCiw3j0YX7cBF4hxcTC5M1HSsupVFwKPuW4zrnoMwy4VSyoymNDEkYZlE6zKBUIaJKqaEVjWwJEyXliqqMLpllOQO5Wg6k0Ln67po66IWH4gqHl/tAIwPcvaKWWz+6nkk3dBAU5YDw9YcQGIRhLbOPDDGqsAHBihDQRmazhTnfk2qhzErQyUtzSqnHMVAZDaHFBKNVgaNnY2wiFlFwzc8DhMWeKsBmo5u7OHy7ZSg4BfxphUXYFPPJvQN9JN8KU8O5XrR7DSjN+iFV/LUkBzG/tx+XDH7MmwpbiNttBXHZY7HifYaXNRwPmarLtwvHsCQGkiANSCHkLVzaLQbqnY5DN31/ym2HowboFFNCeG0oucMKTczimtpjJrpmSziNvLyJCZO+eQccU0zIyIJREkg05ZRqeVpsuCsRWT5shXmtFTBtmPDYhItLS1ybGyMghEIR2hD3OSAqavgTIMl4ItJBwJCzz+Lc5sATJjw4Vcb1DW1HtShyHp5IA00zm1CPpsv91VhOmugmAKzme67EorqKUVxwJYB+UIBb1pxAc5Zfg5uX38HTu4+EW0tbWh2mtHj9WB+Zj5WNq4kPRM92FPag/cddR3+YdsnkDdK+PHoHSAWxeLMAvQYvTiDnpwcZy/tw1vl+YACsm4OG+ytGBBDmO3Owmq6QoMy0NJPaOO2XD8cVIOGMgowBcI1+0dUGneURNk2HRcU0Oyh2COubHhUOQVKSQmXe8RKG7KLt03vQLRtONKwo5pAU3umNOIAUqY7JDDOoYxyn2ha2yuPM8hQJHw63/AhmKhyRnTEWulYn6MHugTpEIatH17LNTUty9A3MpwIqmtTRDUtTAnAoTa29m1VI2MjhDgUg+6gakMb2XBwA9YPb8CC2fPRaXdiY24TuM3xmU2fkVmWp7RCxByQvTBg4CAZwBJ7Ee4lDyZ65xAZQMH0Iuq7hQ1sa2TQ7oBpWgkI49YZQoqkS5hiCpKLcjeFSmlmRlOcRJQbPoyzFduDcUwzsZe5LRlnyrBtdqTHhRwxAHpWCEc6pDJuZlErcTykoWBTu0ol0ClUYgzCei0yKr1gmROQrgBPG0kfQSkkPNvXHqMr4A94UHmZjH6dUgNzisHsENk/fiC2Ccndu+5J2vb2jw9gp7EbrU4LAGCff4imHAeCiaqidckUhsgIRoNxmKYNRjk2YadOLSqAEV6lfgfYkC60pxxChmCUQVEJIQUMqlt5kMoiryh4rYwoNVdvqHWFLZhIwQpNwiVHPefutUXHYmUJQxkFo7qlbaX0Kxcq8YpccVgGpyh7dWFNmFgKqXup+AShG1al9pIOoyXd3lYFanLngAqvMJ5ABEqQ5qkkDtjMmnS9SKS2mlijTscZult+vYKrGAqMG2ARQYAxlgCvbLrxKvUap9DiOmJG9TkTTgEhJjUzSniAlXn3uMyAao+4cqBhpRSMf1ZmP0JLH0mj2TR9AWiZZnUwMyqbZIwhZKGuDzGqpR+bIicsQ01aMKkJF2FV7tIVLiovE/EJgiCo7iwloIvRo/gePSxzpzoWSGuJmhF9HSLOdNConoWBU+2lUvbHU0li8Gkp+OIiIZTSyao5AqJgQodknmf5hv+ysaRePjpWhQcmhCh3RH2hB1qhngWbfFMqAZmEU6LuB5Xgm7K3Xr1MQR0qmIrBVxO0rjIHKlruxh294mq/ei076rV0q/18JRBV+DznEHvCFWNjK0kIiUcsqrsiVA7CydDUawuARJBkQF8yUuCFaO5IIsY2oApV8hTLSvUTyopeys/f2LGqMIfV0tajIvVodnBdhg+rLjeobNsGNhkktU0qK4H1fFIu7qYVyKC6b2Cda6y9fvXC6PU1Ia24TMLhtqKcwHJSrx0AQlQHel8o30yIMAGfL33dM7mim/yU+4gkn27UXQaV9GUVEKlFy8fB6ql+mRQpJao5HhAjNBFhEigEqhyFqVTspL+rcMr/m/TZUJRZOzVaxoKV2LK0hnVTT3uEKgSXLzs5/hVwQmTZYWDRkBYW1MSv6tl+Ue1vPEEorpyrrKCbql1tJfjKPWCeR/XGMbSwTMuqIiRE9p9kmvIU07EOV+4vpYCQtGzbqfDwAJMhRNTkKJbwVBCEIpz0EErocQ5EaFU7UZrQ5QEAjILOHFX22a5tdxeDT1H1GgZgJDFCP/JQQwWPeUgJDgIyJQhj8IUiBPU1SRNCV/LTlDFlKm3KoqiaPp/Sk3VBI+VkNUZqe1XX2vpx30ARqWCm1aYRGoDJNJgoq2sLTmX7yXoqWtS3f6UrkUFanbnodLK8ezkAIJ/N43fb1op9B/cxalIYMJK+i5UPTKhCMMlemwD0hJ+Ag0Z2WtzbpegXkDLTmihpKIhAJNVjAQ1Ape5wHzOEVagS1Rv6oVahMSdPvMDKvMoSCYs+TxVfGYhaBcf1Z+X+grWOCDd5NIyGgtMyC6Ze296480O1Y8ITEFLKJgOQ1a+jfuvSt+CaVVeRzlRnUsIgpcT1Z72f3b/t1/iPn9+sin6RcMoTKSiVppVRQctosAhhL09Z8JEDoOXx5NsDNywHSeMCJSHBQqXb7Iah7iqg6R/6CRW6hkEKAaFCqIp5alUY8aQmI9Q09E7U7wu1ekUdZ+T5DPkarp1gAswyooHVEf/PNJKe0bG3y2j1ZTe5Vdf+i9NxBjcRwNddF0IJxRSC6IJSRhGGAdrsVnSZnbhr868wXhqHVShfk+1j2/GG+W/AF9/5BXLDd/8Gnu8lefC4YIkSHQcklAKeUmPFLMmPjUovbU0/AGZHs0FrugVIA/lsVh08dIh40oOlTK2mfIBE4wkMGBqAnFRThSL7RgAgoaaIV4EvQFL3e1h7rtb+m8oGNMtmAmFR53hao5KlitrpTg5ka26jnhNHUxzcNGFwMwFeJehi6RQHnxllYGAQRCTOyKRnI2psTjgFESQZ61ASLo5uX6xuWvlJAujxtIZhQAqJjkwHbnv4Nvz46Z/g9394GP/yvs/jC5f9C/7qux9CiqRqQoVRCw+DYHzHBCkOlZBbMUEWnb5QTVsVHA87yQ5mCYJoWnygICEhfS39AmguHwNDAB+cGgip9soUFEIZgAmWqJo4vZak3zx52EbdVZJsqhhgVC5QFYiO+8Ug+hl7tbIchE4qz7iuqGMpCpricOwUGDdgcmtKwE0O3XEwFjknUQ9NIUQZuFFO2I/ywQELdCYEwGWLLiPLO5Zjwp1IvOyOTAd++MyP8IX7vgjKKGbNmaXmtc0jJx91Mlbcvxx7h/dVeciSaXY1tSiCMR+l0VIomkM2bcMwnvCRHc2p3FCBep4Hw+PwuA/uMpieoese4iCxkBBCQAgBL3B1za8MklFU0o8aUcYFRkJT1imjOPuSsybTqlh1nK8qlnc4D5jVqF5a/yqpms8TTvQkJaZnwpmmDZNbYIzB5BZMpl+MMv2T8ORlUgsmtcAIAyNMv48+lwCY8qQDfxLYZrqpeYfVilPSJ2O8NA4pJfzQR2u6FT985kf4l7u+ACkkHOKor7//v8kZR58BQHdJdYWbNIkPI4krQgFp6Dx5o9NAeJpP3zigCAXGxybI6ISmdfvUh6XMJDcbg075egqkFFKPXhAc0hcgPimDrTpYVvVr+7IO3VFfhPUDxpXg46T+GVfafqxOfWwd6ZkMi66oXyacgJs65xvnexllVYCLgRa/6icyKlRzRUqP0PLMOc44ODVgWQ4yTiYJrzTbzfjhMz/Cv97zBUAqZDIZ+fX3/zdZNW8VRoojSBmpSS1841AMlxHZl5eZ5tMWgDJU8CY8JfMaQKY04YV+YrirIBpD7+tYGnzAF345z3qYNFPV2KxSeaZGrQOR3F9KyuomakREGKmWnGJyVVzc+IdG29OkERCSWOCkbq+VKjUB3+EBd1gQJmAsgzKeIBrS8hgLpRSa7WbcvuEOfO7Bz0edUh35tXf9Fz1m0TEYd8cT1T8hJqrBRyLnL/o+Qik8y4NhGdMYgJ5QxeFC0pvPj+a1xeEYS5p1A8k+CxCyMClCf94TcGj9BHsEEmrqF2EAs3QbC8pp3WCxThWS8ijZCtAlrxqyQlUKrs6IhhcDurp2YYUUrB2EY1ADQ+4QenO9yJgZ/GrbPfj8w/+CuBD//132r3TVvFUYy44lD0AxKKK3v7eculNTB/Mtx5q+VXHCEyocE0T6AmjWXVJZnLBnWg2b0oBvhhoLdUIgicNRM1CmlpI/OUY2mSxARMV4UAHAJNWRf1bhDYOAiPiz5PDdvGJnqOZYYuknlPiTQBgDMQ7Uy5qYoC8CrBt/Vs1umE0++dA/AgBm27PUl674Ijlj4RkYL4yju7EbxaAIgxjYMrQFD2x+ECmeSiR4WCcrIyzJjEY+feOArnRpqVRCVKEaScEAFizdiwUUnvC19GL1x2AJpilYh0251eY3IyDTmqCvrCEDUKM8+JpFdbnMjMIhVEzOrES09So6u6lVP2V0cl76j5SAQtUPxaCmY5iI3HaTGfjmjv8hJzSvwbXHvAdfe/zr6JrbTbb0bsWju/8AVmCJym1iTbjrybt0twdOESpdJccl1wFpQkFtCtaij9mmtpy+ZZluCOnJScnwOOCrmILFzKQjwlRpuDp3qJp6VapudhnPIWF2jSqsEa+aw1dIwjjMZAlln8WOZsDqDpCeqi6lstuBkCIxcF48COvTsMoqPqgiO3jSw8ef+CT++dTP4c9OeBd6R3rRUziAVtGCUrOLk9MnAQC++7vvYevANqSsVEJAkJCJ7QcBGGkDDV0NKsj5EEaopm8qzgeYR4XicWdJ3QtmqkF/9ZqU+/D1IJqp7D9BsfbXa3UfQAMgdlRt16CHSktTlQdfG7QqkE0dBnuxBzvvgjcbSWG7NFUd4mn5b6awEPqaEBuzYKYaJfsnmzF1aFpSCoigmpBrmzYGxgdx/X0fxHuPuhbnLHsj3jLvzTC4gdHCKDbu34jv3f89PLbvCT3OQSDpsgAB0ApXwDZttC1qUbmhAjUPm6d8lQPQD30EYcBoyECgW8n6VHf1jA1gT/ggoJNsqkpvMr44EprnprMjET+uGCB9cibJjMQTzWmGgWY4WIpO6cmpUKHtvC40vr41afMRA3OqFQqdIkRIQTwClRWJ/WfUxCKnIpk+n+r9YyhaKtQxyMAN8KVH/h3fevQWNKsmBQCFfBEj4yMEqJ4lUjljOE7FhTSEx3w0tDRSxpmgFmPTFoAqUEqJMh0/5IEGYgV3rZKBWzkjuDK2FiJ4QTTymBjKTQ6a4TBbLNAUn9QIqHZkFo8AygyOsOSDO2bdz1dy/kQQIvQC+NyDzAd1yaMv3tFgVSCMpV8l+CZN36yQgqEIAQa0OM0I8yGGiyNECgkaUDgpp0zWrQGeEgqMM4Q0TOpD0g1ppCyHFb3SNG7N4QVQJRWqtOIEAPc5hCF1zYKUyaw4xspOSAy+gIZRBVgIjgiEYJBCTLK34gA0BwdxdErM4AzcMmDZDhifPMk8ZpsIKeD7bgIuo8GOKtfYlCpRSQlp6vrmwAvAQo5QBklsrnJUazIvOAJWpS14OIlX3xYMq0AY+mFFvlwkXMA4A0SY7v7PwDT7PLK9Y44jJeXRrnEssLINciqdVp7wp28YJvCDqoMPzbBKAk59RFG3+lBT4kMaJukzKiiCYpC0WIsdgjilRLjuFEAdBu6YSRlkpWovV6NZ8EMPJtc/lZSwTKf+TJIaJrMferpM0jLgc5k0QVKhTCRgktOl5WDyVKB7PscjflhEqCn58QOjAp0pUqGsYAFVO3FVpQ8RiTZhP0ddU6UqT8iMpaRlmsp2bBIgmKZOiKdUnHs1pQElVZn6Y9Sp3Kpo12vEhxWpmHI+WINMuiIpwQRDVQlm3JuvSuLVpMVqVznnyqpAMEkSsjI4lJQILR+Ch7qTQyUtS4YJkCu94RfrCVdNS5e6NjiQAaQQUWfZiA8YPP80glr2cyXY4vsiQwlLHPmuqC9PILqkk6fKlxj3J8ADDtMy4UNPTUojDRUoCFMknm69gC4EEIgASugBhfC1mmFRb764w4Fu5BhABgpEUtgRk5jFbWqZri+pHL83ifZUk0+udyOF0nPspBQIECBQAYQfIpAE1GMoucUKVS+mnvT0AupFKtVuEPp6yrrnQXpST930fYQIQQWgXAUv9MF8PX5L+AKBH4AKCle49TMdgaVbcUQdwkzPgCe86QvAeGI6AHh5jwKQS1uXINuaV6ZnwHQs+JZPTG4CJmDYHL4VwLKcwzoXnlcCuL5AAQl1tsLUoR6f+6j8PpViaOdtgOKwaQomsw5DZ3+eafRqqgiTB1cU0RpkkLVyCIvaBjSFiUa3ATA4UALsuKrsTwznul5RHysDoFqQRU5PiLIJlB8iMEJ4KU9ZhgWfeeCBIV2/RAEgHaRJyXdf8L7stK0sZSkAcAxHBeE0VMH5gQINSgEanQby3x//bzSkGogbuC86NPHHrDh9l8TmwiOwEwIgpV9SSGDeFClEiT85TiiFBE1VzNCzpjQRSIX9yP6YkJCQAha3yM9H7ySb/c1qWqtg5VYEb7kJQggIJXowyst0VkqpiGNnoiRKIER7hiY14crDSwWb2vClX3dAzlT7SpBA9LDAFE8hUAH80Nd/q3ed6hzjlHeI67iozW0Y3EAxKMIXgW4q/hJcVwUFh5a1kfSfp4XEq5oNU5JVdadSRh6bUi/bixGGQX8I67AejOi5wr7ysQ7r9WdQZzto2v06rMegPwQKOvU+ou0NZiBtpJE20jC5iVCFUFB4ZPhR9Iz3wORm3W1DFSJtpDHoD2HbyDY4zDns+cQB+Tv2/wz//uzN+ruZoW3kF3hNpJz6HtR66dQ88oPjjggA/aLP4amqGJMeAj35Rf6IV73t4/dV3i01MWgP4TOj/4pNdAvSRhrjwQTuy95fFZMjFdsKJWBSE8/k1mODs0nP/oWofxxKz/zYObwTNz7wUfztnR/FtoPbML95Pu7dfB8+fMcN8EIPTLG69qVJTOwe240PP/PX+IP7OCzTSvY1mbQtYFMbX13/3+jN9mF103H4wmNfxEh2BA53Xrj1EH935XWcSoj4Ur2mZsWRI/g9pOICa/dbXzt3tIRjikvU7cWfYmnnYqKJEq5EZuqHj1KKfDYL6nWBdtLJdbjRdxNCUAyL+J9H/xdvO+FSAMCtz3wHuVIOv9p6Dz531j9hcctilGRp0rERQhCIAPccvA/HNB4L27WqGzlVAkMpMOgh10s6FuOC7vMxr3UeHtz+OzzTtw5vaXozPOVpxjReYEe/2GQ4DACpSckRsaGPtATMDee8gijiFVtKJUCakOOY480lZ/AzyH/2/rdII4VgQD7veZuuARFnDRRNQKci8CilkOIpPLfvOTSkG3Hu4nNwyYqLMTc1F5/+5WfUJy/8ON527KWarSzL29Tmf29c8xGcgOMR5AIy5cMWSVyhBC6ZfzFa0634/jM/wP6R/Th7yVkohsVIIkeq+oW8CMGrYVG8xleD24jSRAmXz78ME/3j7Jfb7kJqwtHOxRSiwuAGShMlBIGe0RGr3Bh8ldJv5fyV+ItT/hwA8PC2h/GD3/8Qf37+n5MT556IcXcc/3nPVzFQGIARcbxILAmVSgYK5kQuSa1N9UCpirnJd276BX762E/xLxd9PrEvSY1ZgjrmSpXpghdeYjtNKfnyFQVeLG1yxRyKY1oa/+WKD+LWJ7+D3b27E0BMtYpjRahxldhflZKv8r3JTXQ3deOBPQ/i33777/joW27EExuewFB+CGt3PYTR7CjmN8+HH/pJaDHeXhL5vKaGigErJdJGGj975ue4ff0duPma/0BbYxu8wCtL11hKV25baZ7UCXFOBcRSUCIA0NjaaEx7GzBU4csKvkp110Kb0aQaUQyKWN6xHH+1+i9w77b7YBADPqaeh9vsNOO2Z7+vHtv7GBl1x/CBE96PM44+A3k/X/X9hBKMFEdw19q78Lfn3YjXL389gG/gA7f+OTpYB/7i4g9OcgBU9JMq/fw3sAbkzFzdODiJAEspRSEo4O51d4M4FJ+973OgWYr3vPHPsHzucg3wSA3HtmYlCGuBebhYuxf4eG1OTH+ZQVgMizhu4XFYtWAV/NCHF3i49ORLceGaC1EMi1PUqDNMuBN4/8nvxdWr3pEICNuyy7ZWBciVVGCU4RPv+DjSVhr7RvbhqtOvwnmrz0PKToETnsQBY8lHKqTghDuBC5dfAKEExkvjZeZ2HTtNKYWbr/kPuF45hmlbNgIRVG2j6oCwLuAiwCb7qfhP5cvq8Q/TblpmBZmWE35YaXOk1K+CqrrxcYzOYIYmPjBWFWOLgRXXj7Q1tsEgBgIVwAs8PR+O0rpqWCmFgleAZVpwQxeNTiNc30WIMNkPSLUHHed9ucFhEw0kIQQopWWAV4CdUgqDGDDTJlI8BcklPN9DGIRV2xxOnVe9rziHSrCX3BKKXgnEpORIT4ujr0UVnEgoqSn5TU1NEEJgJDuColuE4zhIp9MQQlTFAGNQWIaFpqYmZEtZ9E/0I1vKorGxEalUKtmm0iMWQsBxHLQ2t6LoFjFeGEfBK6CpqQm2aZe3iURSvE06nUZTUxOKbhEj2REIIdDU1KRTeVJOigcKIdDQ0ADbttE/0Y/BkUEoqdDU1JQ8OJXbHC4kE3vXteCLi7myfgFuyZ2+EjDNUvAsD6+E8xHfDMuw4PouPvelf8LvfvMQUp0OWCtHa6kF77zuXTjvjPMwMTGhR6lWgGJwZBBf/dJX8MQjT6FheQPEaIgOpwM3fOwjOGbRMSgUCmW6VbTN5r2b8eUv3oyh0hBYK0duWw4rTliOj3/kE+hs65y0TVNTEx557hH871f/B6POGMRoiOJgCW88/yz81fUfQtpKwwu8Konb1NSEX97zS9x5588x6ozh4M6DaBJNuPTtF+P97/kALGZVbRN7u+pw4apaNQygNFGCP+gi6E6h4BaCaSsBTW6yeqrxSEu+GHwj2RFc9o7L8OUv/SeGVo2AternbcvJO/Duj/wZbvvRbYl0lFImQDr/4gvwv3d9B9lz8xCjIYIThHq2/TlcfMnFWPvk2kR6xuBb++RaXHzJxXiw9BBKyzwlRkMY77Lwy/W/wvkXX4DNezcjnU5rJngEvtt+dBveedU78XTjs9r2bOXIvbWIb/7PLbjyqisxkh2BZVhJ6iyVSuErX78Zf/WvH8L6WRshRkM0n9GiDiw6hM9++vO4+oNXwfVdMM7Kar7GCcHhvGClQBWFwQ2IgyF6d/ahf08/8gN6yHIl02l6AJAf3js9UtIv/n5mMHzypk/guQ3PYf67F+KEt52Auak5WNm+HF9515dxykdOxcc/83Fs2LkB6bSmZXm+hxs/dCNyuSxO+cipOPes89DhdODa499DPn3TP6H5rFbc8JGPYHBkENzg4AbH4MggbvjIR0CXcZx/w3lYtXQV6XA68E9X/BOu/dqfyRGM4MYP3QjXdUEIQTqdxoadG/Dxz3wcbZd34g3veh265nbhpHkn4BPXfxIrPnqMem7Dc/jkTZ8AMxhCGSKVSmHtk2vxpS//O469/licfdbZ6HA6cPWaq8n7v/BBdF3Ujcd/8wS+8JV/QTqVTlSxUioBYWVIptYzrkrRARjNjiIcDzCwY1CnVQEsNZbRaQNAp8s5RBsZGhY0qHrq8UiBMMlQpFJ4fMvjuOuXd4PN52ha3KRWjR6LxlQDUk4Kc3OzsXLJMfAbAnzrf78JzjlSqRQeWPsAntvwHJpe14KG5ow8du8KpNpSSJfSaBlpxMI3LMRgzwBu//lPkE6lkU6lcfvPf4LBngEsvmCxSg9ksGh8PlJtKfi7XLTnOmn36bPw3Ibn8ODvH4TjOOCc48c/+iH8hgCLT1uIWdtnYx6ZAwBYeHAu2me1KetoB3f98m48vuVxNGb0NPcf3Pp90JM45mbmYuGOuUi1pWDnLMzqaVfOihScFge3/eAH2Nm3E7ZpVwXN8TxecJIijFZrYytohsHhtmwN2iemjQqOnxKjYA3RBopUexqGYYDI6tDFkQShUgqcc+zbsk+bAW0WJvZMkNKOvA4wl4r43+/dgod+vlaZbRa2rtuGbDYLzjme27I+KejJP5Gno+PDaEw14Lkt6/GT//oRDmw5CKfFwfp1G7RzFYZYv24DnBYHY73jpLSlAABoTDVg3R+exq9+8CuIvPZ0H3/mD+Ccwyt5eOKRp2C2Weh7ul82jJdLJe/6xS+w+Z4ttDvTCQDYt2UfOOcYy45h//4eZHgaQxsGAQDdbV0YHR/Gkz94nHj7PTQ0NKI0VsL+vfthOZHqrlCztYHpWDqi5n0QBhCtEuYcE8yhZNDuH5l2NiCdhV5OOYb7h9W4Nw7GWGLLvBwgrMrIFCQEEzigDiV/O6AOIZ1JwR/x6naNF0MhvGZPbc5tTUCbnZ+HykmUxkoV5ZkVNRs5iVLGRf9QPwBgc24raCdRcrx+IZI/4oE5lDytnk32cUAdAtJAabja+4ynPmX7c1XH1T/Uj23pHUoWBXK57GGJ3ZUxwdrrX/k+UAFGg1GkXEcBgNVobQCA0cv65asegPFBzp4zZ0PT4iY159RZ6BP9YIrVTWMdCRASQhCGIRauXAgAaHIbEfYGeHLsaX0Tizk8MfwURnaPSNETYsGC+Wht1sXpC+cu1iZEycbQoWGy29ujUk4KTxfXY+OBTeA79eXqntcVd4/C4qMXoTRWgj1kiU39mzFi636Iz41sUr27+gj0rEOsPOpYhGEIZjCsOGE5zJwBf5dPNvVvxgF1CNliDo/3PYlgl5+AqXt+N8IwRGdbJ1KdDhpGMujfN0CeG9mkAGDL8DYM7B0k47snUBorgc3nWLBoAbyS9oRJHdsPhwEfpxzZUhYti1rFwhMWEGuhQ2bPmbNh2kjAX170CwkAd15wx0YzbW2VQtG94V4tiYg84iCMv69YLOK0lafhzKvOxGDPANR2BWufKWL1GOzy4W/2GQC887p3IQxDZLNZvPlNb8aCExZg/7r9IFsUMkNp0phpRKpoY+TZEQzu1ervqquvgVfy4JU8XHzppXBaHPQ+e4h521z05weQclJwB0pydOMoBnsG0Dm/C+e88Ry4rpZsb7v47SiNlZDfkIfRyzGPzEFjqgETeyaAA0BprITTzj8Vr1/zehQKBXDOcdVbrsZgzwD4Tgo5IkhsG47tHAMd0ud/6ZWXYFHHIrhRDUitE4Ka61577RljGPfGUeA5yjgDd/mWd53yzp0A0PJ0h5oWKvi6D3yQA0BoBPccOHQIG/MbZSEo6CaIBEcUhFXE0kDgi3//RSw5Z6kY7BnA7gd3sZSTQspJYfDRAQz2DOCGj34Y551xHopFnZZrtptx87/eDOtoB/vX7cfOx3YhNU/HAUvPFlAaK+E/bv4PrD5qNVzfheu7WH3Uanz1374KABh8aABtfS3oXjEH/mafeTu0VPryzTejs60TQggUi0WcfcrZuOnTn8BgzwD23LUbAJByUig8nsNgzwCcNWl87h8/D4NoJk4ul8PVV1yNq977Duxftx/5DfnkuLwdJZTGSlh88RL8w/s/DhGIJJicBNjrgK8yYkCIntPCFMO2YBtKQYkM7BhEaAT3XNl8uXvdBz7Iv3PTLepIzS96Sdf8z8/F9u9vV6ffeGb/oacO/uUEcmR51zIsSi1CIILk4tSqgFq18KdIQUopQhGiM9WJCy64kHpdHsYnxtHc2IxtIztALYq//9w/4EPv/jAKhYKuFaEUbuBi8ZzFeNMFF8INSxhho0LwkO7p3SeWLT2KfvFLX8Jbz38r8vm8LoCnFKVSCatXrcbJbzgZB/2DKBkuJrwJDA0O4dg3HIsv/eu/4Q3HvqEqEB2GIc449UysPHYlBosDUF3AzoO7MBgM49LrLsE3bvo6lnctR97PJ9dLCIG3XnAxUo02xoqjaGaNWN/7nCgaJfquG96FL97wRcxyupNAdBX54TAPe/x73LzytqHvy0MHDqrhnhGy7Ixl/7j11i1743v6aiYpV61rP3s9+c5Nt6ijP778BxN7J6458YQT8V9X/KeeR6vKFyaOV72UIKzcXkoJTjlSmRTGc+PY379fe+tzliKdSiObzU7avxACaSMNnuLYN7of+4b3od1pw/JZevJQoVDQHVFRvU2D1QBq02SbOQ2zsahjEWhIkfNyST443peUEk1NTQjDEHuH9uJQrhcL2xdibuMciEBUZTQqr0tDQwMKxQL2juzFcGlkym3qPdz1wBenStucNtz28G34j61fAR9ksnFJ453P3PjU5XgZJri95KthQSPtWb9PnfXZs8f7nup7z/at2zGvay7WLFgDL4wuEnSnhHoXq5b8+WLVcNXsXCXhui5MaqKzuRPtje0IRQjXdesm8Cml8IUP13XRaDRgfvN8tKXa4HoufN9PJp3XUvi90Eu2WdKyBA12g95G+GUyQo2p4LouwjBEW7oNi5sXwSIWXM+FkKIKSJXnFduRnZnOqm2kki8KfKhg5RjEwODEIP7xzk+p8W3jRKYUOeaClR/eeuuWvZfceyk9UtLviAGwZ/0+9brrzqb3f+SePbMunb3MSBurhucMiZM7TqHtVhtc6SZVavUuWu0F/FNAmAAaqmo0KqGkru0YA6p2m1hNVx7fVNsEMpi0TWUxk6ooGYjrcX3hJ+ydqbapsnFrtpnqAZ5K8pGKzFHKSOHbO7+DpweeJqqg0H1c188evOa3//q6686mv/nY/XJa5oJbr9IzzC/46ws/NNuZLfbs3M8+8fgn5Jg7Boc7CFVYRTOqdExeiqxJLctl0gtkEoieb5t6wKv3O2oKpGofonrfFwO48u/1Hqp6+6r9qZ7H4Yg/IyDQkmrB7RvuwAP7H4AFC90Lu9Ssc2Z/uPIeThsAXvvZ60llSOa6D3yQf7X7y6Nz3jLnwtZMC3bu203/9scfxUh2BBmWSWjqldLgpQQhXgEK2CSAHaH91D4Y9dKdtdK28roqpdDmtOGHz/wIX3zoS/AmPGXNsrHggoXn3338L3qv+8AHeRxWmw6VklUA3L17F4lTc0SBf/uWb7infPu0d9uwvneorw/LjKPxyQs/juUdyzFSGgFVtEp1xFKx3gWdWc8fBz2ctysgYDADDnXwrcdvwS1P/g/auttgzDLQ1dZ57S8uvPO7773+g7aKCjJ3BdslACxZslQBwEsdjmEvBeiOP+cE0rCgkbblOxiZoLSNthtttJ2BwgEBP/7kExv/4tM3rv/tyfflitn8+Qf3HMQ9G++VDrHJiQtOhMlM+MLXbc5ADxssnVkvriamsrCdEYYWpwWD44P40sP/jh8+/kMoX8ETHuxS6u9uvP6m/7U+aLZEHooJArONtKONtjNkKcgEpZnjGvDGy8/Dht+tw7WfvZ5s+N26Vw6AcbilYUEjjaVdDDowlQIhDiFoISDO1tWb5px48OT1h+YfPKQ8eW52/wS995n7sG3/VrS2tGJO6xzdmgIKiuhwTXwRBQTUi/xHXyMVpy/23ONWInH2KR5Q4zAHOS+HuzbdjU898hm1fucGolwFhzuypaPt7y/aePHPnjjl0bmEghGCjDaSYYIqHgOSKKhW1q52D+/EGy8/D9+56Rb1p4KQvBQSkPQwRpRmACoKCxQZEvc+C0mGCppWBCkw1QxBxkU6OG7Tgg3XhXa4shSU4BgOTlp4Et48502Yn5qPTrMDJjXrTzJ6Aat2Jsh0Xy/0vOudezEsYqAwgPXZDbjr4F2qd7ifAAD3GKDIlmP3r76VFYzn4ntDFIqSSU3r4SqvgAKgfEjiAwCR8BRBuCvYLh+5da18VVHyNfiUmeC6FnwAlCHnU5+NH7fzhJsPLt5/eqm1cEmYDts2Zzdhc3YTOhra0Um6MSvVjdnmrOS7S37pBethx3SIYbz0JV0s6ksdd0xgnE56X/uZP3UFQfCizz1+3+v3oa/Yj/6gDyOlEZieQZrSDZChGnEK6V/O3bPgsfieEEmyYKpZiWRucwEhyRCuoEAAqhCDEK/qmhBJfFBMFl+CjIOpZiJJVlHVCABz9yx4TB4UW3vnHlwxykZOVaFcsd3aSbZjZ1IS6Al/Smld1WW/og+fyczn7SFY2bOvdj5J7crw1POedj4s1v1cPiw+b/+/eu8rO+F70iP1jleK8pAeFtRMmTIkLGkmfbRTrqOCtLW1VbQ9Mfvg3K3UZ+PJdZSkPpeLq3zlfSUSSZHPkiVL1SNY++rwgl933dmJDVghBU0CpBGSTNRgXEtCAIk0jIAYg1Kaorl37sEV+aZs2s8HxwIAtWnrVPu1LPNlqFx9+Zbn+YFlmUbtz+fbpi6wXTkaVb9vaw3aJ2YfnLuVubynvqFJxgGgvvoFIJE/Eur3JZOAS5YsVbt2b5dLjWUhkQAk8RSFpajywfVJSC4SmxAKQ3o4DE3rTgFIEUHGWUB75m9b9Hj8txiolWCte7FN0Ux9Ni5N0XxYySdpEwBIKifi96/0io9FUnlY6nulxKorSWqlWAWokmtIkKr8PQEbVTHgYgLrJLsv2j7cFWyXL5X0e0lV8CO3rpVLPrtU7dq9Sy41llEohCQkXmwbKiAPqkxwNRZdMlNwUSuO04c1dkKSAVf5WKomN6fEQAVNQ2iwU0HThw9TsFR8cxKp/IKMQG2oP+/fnk/tRPslCkUaBSLoFAGJGCRU0HQCmDpqUilkqlQmm1wDkki0iv4HVaZTNaAT0O0My7HAR25a+5KB74iyYWoD0jU3gNdzYIiEpyisF+4eqj9ipgAx9YUn5ssv7+rtN/6b8l+Unf1Cz7bCbqt7RHU6ANYGn49EAPqIAvD50nTx2r17F4lPMgYr/ogiqCMW0K14UCpvVL2/1z5U6gi1dozB8ceaSof7/yMFspk1s2bWzJpZM2tmzayZNbNm1syaWTNrZs2smTWzZtbMmlkza2bNrJk1s2bWzJpZM2tmzayZNbNm1syaWTNrZs2smTWzZtbMmlkza2a95Ov/A54mNf0Y/U9UAAAAAElFTkSuQmCC",OnOffLight:"data:image/png;base64,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",LoadControl:"data:image/png;base64,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",Shutter:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAACgCAYAAACLz2ctAABMg0lEQVR42u29d5Bk93Xf+/n9buo8OW7OOWCBXSQCIAiCFAiSIsUkKtCUSFoqqZRs+VW5nl316tnPqWzr2fX0Sk9yULKtQEWSIsUEEjktFlhgc5qdnZ0cO9/0+70/7u2e7p6ZXYCSsBC2T9XU7oTbffvec0/8nu+BtrSlLW1pS1va0pa2tKUtbWlLW9rSlra0pS1taUtb2tKWtrSlLW1pS1va0pa2tKUtbWlLW9rSlra0pS1taUtb2tKWtrSlLW1pS1va0pa2vAkR79QTO3DoiKhUXdG+RX9zSSYc/fprr+j2lWhLW/6+WMBjd9+7cXpuvgdACIHWyw9w6/erfjARfbSb/d3tIP093XMvvvDcaFsBbyLbd+2TF8+dUvfed/9HqyF/2rYPf0PR0f21bEeIoProC88/+53aNX6nnKL5TrxuhmFcm5ucCHsHhm1DQNg2Yj/YdYyv3dzsdDjU1z3/TjzHd5QCVgsLAsD3g+752anQ93wGh9cpYdhSa61Fza++m4zUm4wRap99rb8XQojG30kCESgdTk1cNyqlkrF5/fAu4MQ77fPLd8qJrB8eNsbGx8O777nvkdGxsT8KgzC5OD+D6/u1cxRaa1b7egs3+4Z/X/td69/c7Jg3+7qrfS/WEFNqYUpd//5mf9/8Oy2kNPB931hamKeju5fZhfzvP/L+D/zoxXOn1PZd+2Q7BlxD+aZnZv+0VC7mADq6ekmnMzrUUryZhGOtQEhrgQ4DhGkAELgeQRhgJ5KoUBH4PolkAinivxUgEFTdKoY0sW1zWXE0IEQcYOn4CkqU1igVEgYKpRSOYyOERAiF1qKeONXOVakoQBNCoxvsgEChtMJ1AwBs28YwZP3Y6BQ0AnGT4E8j0NrzXGFIRwtDCaEJe7tyP/Gdb3/zD94psaDxTlK+fKn056VyOatUSFdPP9lsljAMEVIKRHQTV/u6oRUUkb5kM0k83wOtWb9ugHVDvQRBQFdHis0bBygWi4RBgJASjQKt2Lx+gGTColio4PoeUkoQiiAMEAiUAt8P8QMf2zRI2BaD/Z0MDfZQKBRwvQClFaDwfR8hDXzPRWmFlBJBGNuASF2E0KACHNtky6Yh+no7qVaqFMsVhBT4vgdCYhqSMFQ3/OyRUgshTFtHl0CHGIZRLlc/vn/f3vPHX3r+9e279sn5uRl92yrg9l375MjIZVVTvkrVywSeSy6yfCoIQqQUQmtJZJM0usl46zWVElH7C41tCh647wgXr4zSmXZ4+KH7mJ2dIwxD7rxjL57rsmvnFi6NjGEakmrV5cC+HezeuZkgCKi6HuuHukklHe46vJdCoYQUmnQqyfBgL/29nRSLJe65ax8bNgwT+B47tm6gWMjT29ONQcj6oV7K5Srrh/uxTJOjd+zFD0IWF5cwpBlb3Uh1wjDk0IHdDA70UlhapK+3B0MK1g10kUo63HP0ABcvXcUwjOi6rHYN0GghEErFJl1IQ6K0NI2q6/3Ivj173hFKaNxKyzcyclnde9/9H10sVP48VCpVKZfDXGeXzGazBKEWSCNSvijCWdPprHTBuqaeCDSGFKwf7ufUqXPYTppd29dz7dp1ShWPTDrB1775HHce3sP4xAyeF7lVCaSSDkEQsmP7RoaHB+jv7aJULtPf141bKXPXnfuxLQNDCrZvWc/E1ByD/d2kM2lK5Qq7d26lsyPD8PAAvb29dHVm2bl9I50dObLZJNeuTVAo+UhDImLvLqVBpeIRhj62ZdLf101/fzd9vd0MDfUjhcBxLC5cvoZpmsQxQfxv/JlrVlGI2M1H10ghhCF1qJBGuVx5R1hCeSvd7r333f/RhXz5j0KtnDAMda6zy0ilUvh+oBEyjsdEHEPFT/Rq1u4m8WEYhmSzKe4+epiuzgye5+MkktiWSTab5WOPP0ixUKBYqiIMiVKajlwG1/Xp7+/BMEw8z2dqeo4gCEkkbPbu3YlWIZZpYJomqXSacsVlZnaBEyfPk8lkCEJFuVxhemYeKTRdnVlc12NpaYn8Up5UKoXWQeR6qcWWIKQgmUwg49DX90OmZ2bQKiSVShGGmkQigVLLngAd/SMgumYiUkQtBCr60hqhQyUNiVLSkMY7ITERb6e7rZVaGpVPo50gCELHcQzHSagwDAUCgTAjxYuvas2avZlT1jULqAWIAJSiI5ejsyPL1PQcSUeSzmSZX1jCsmyymSTjk3MoFcVmSkukhA3DfSwuFcgXCvT3djO/VCKVsJFSYFsmhmmyc9tGTp25SL5QJFACx5IUyz4d2WRU5zINKhWXjlya2bkFcrksSml838OybBaWSnGS0ZwlO5ZAKYVpWiSTDqVSmY5chvmlErlMkmLZxfeD6AFsuCyNFrCmhI03WwmhJUpIgVJISeg3JSa1v327EpRbkgU/8v4P/Oj1qdnfCVVoqzAMnUTScGyLMFQaaQodaVycIYof4CQjixDdgBBDguv55BcXUCog8D3CMMS2k1iOTSLVQSLhRMlAPdvUuJ6LZVpEJQ0vcnlKEaLQcaYbWSgfwzAQwkAphWEIwlCjdZTVChlZYdO0UWGARiIEaA2mGVl44oy4Jkqp2EEpwjDEMCzC0McwLLQKEbIeNCK00ayAqzyo9c/V5KvRUiAalfBdawE/9/mf+vwnP/kJ59/923/nTczM/5Y0DKOmfLZlaaUUdcvHsvt4s1Zv5cWOLKAUitD3KJaKSCmw7ASWYaAAt1qhUi4ihKSzuw/DtGNLpNd07UKAJMQPAoIgKpXIWmlFa6QQ9X/fjDQes2ac1Pqa0sAwDaSQUZatzWVlvGGRRsdeAS21FiqubUuhhFupeL2dmZ/94pe+OPHd7z4x+Lu//d9/+++9Ah44dES8/tor+r577+uamJ4duf/+Y7nZ2TmeeuoZ+gaHdSadFaZl6bgkBkLGxks0WL+3poCNFkwIgVYBpWLkap1ECnSI67oorXEcBykEi4sLhEFAT18/Qhj12FPoBvevwzie9CkWCnhuJVZIucZ5KLSKPtKbPvfY6Qm5/LpaqxXvoUKFkJDt6CaVTBDWnGUcN0eWVKypgELU7SBCaor5pXBxfsbYvnM3G9cP8saps8WuTHrjs889u1C7h38vW3GTU5MAnDxzzu7q7Ew8+fSLemBwSAyu2xgChpNw8P0gunDCWL4oTa73rT0jrbUxz3MxTAvHcQiCyA1H9T4oLkGuq5vOrm7mZ2cpFvJ0dHQSag0Nbi0KByJlLhbz2jBMkc11RnW5tcoLpoVlO5FRF7UOS/P/GxWs7n611kEYCt/z0Fqt8RklYRiSn5+Brp4oMVEqjgWNG9obUctZ4gdMopFSGslUFtf19amzl4XW0jp9/oL9rukFm4ZESIll22JmZkqnUmnDth0dKR+iZvnqN4cfzPWuqoha4Vg2SmuKhSWElPQNDCClpFQuU1iax+rtJ53JUC6XoxspzPrD0OgZXc/HsRPCMi3mZiZBGBimuaqiqKBApqOLZDq3ogUXnVsY/1DGxXIjtm6eWJqfj5XYbLKodeXzXVLZDlLZDoqFPMlkMnbTb93/aY3OZLI6mUzKMADTtPCCAMexeNeBEWoX0fd9TDMhtLSiO6xFU+zyg1i+NeMnaSOFiQbCIKCjswswUYEmmchQrVRwXRfHcTBcFxWG2jANoRvev9Yuk8JE2hZutUi1WmXDlh2Aaor3NNHDNj87RbVaJZPJECqFxqpX6yLPbtQCvKbQIVQG1UqJdZu2YJlmkzWvvXZ+cY5ysUjfwAC+7xH4AaZl1q31zS6djjMgDSghhVZCCGGgRYDQAt5G0Id5Swo/tRZaQ2Cv9d9RQCqNFoCqEb13rXwRF3+jf6OLr5dTyvpJa63BiB4Q2QB21VrV63cACoEhli1npFhG9L1YTg60bjax9T6xUCgVopQmVCrOhkFKGblrBKrB1JnmW7+FUWwr6r1tIUCr5lrk7QHHakkY1np8dXzBROONavn/au5XCIEh4wxSGmSyOZYWp+ns6kEKSbFUxDAMHNsiCAKEkFG/d81QwkJrTTKZJJXJMjV+FUMaa8Zdua5ulJIgdJwA3BhAobXGsW1yXb3MTl1f87XD0KOjuw8VKgzDRJoW6q30FETDs8VtigfUWtdRJzdSpkaF0i1JRivCZFlZGw2ggdYaFQSksx0kk0nm5ubQSmE7Nql0BuJuiWnZy7FUvaxR/w8CgWEIDCEYXreBSrXSVMNrTDKklFEio+JuBGp1C9iokFqjwoDBwSFcz0Wp5det2dfGso/ruthOEuoW9mZlmIZkhBYlXPGD28ICxl2LmyBa1rJ6qymtqPvzZeU0TZNQCCrVKgknSd/AEEEQJwHKr/+/VlhudL81+EP9IdACaRgoFWJaDqufdgzBinMMKQQIefMQQ0RZatX3kNLANGSrw4jOQYWEYYDjOAhpouK6Z2MJ680ENE0Pc5z28TbP0Nw6BZTxDYnBnKtZs7WUsNYyW/MY0dzR0DrEsSRS2nieVy9yR68lQWksJw0iwvXREA0IatY3igyV0rh+WMfm3ajFruN4963l8xKBjJVtDeslTUxhQFMBO7Z9ovEJWs2srRXqSIQ24xjQf/crYC0QZg1rdjOXfCOkcqPyRTFTlCwYhonjmIRhgFIaHYZIKZCmvfz3YmUbsNGqiiZktWjqkCyfjv4B+gC6pexzI5+4fN0az6l+LWn+mWiwoI2fS2u9SlIkbp8YUDUoWZMbFo3xXUOjvdH90hDrtbTtRIsFFCLKHJXym95PNNXZatYj7n40dBRaFVrUrZquOS503CqLcMgN3YbWh0jrBjepm/VPtCplq7WqZa0K9PIDoxsfjMaj6g/VyuIf75DxmlvngrWIkMcNFm3ZsrXGhqLpRq+wHY2oD7EyvmmNG1ezMDX0TL041OiGWx+SmmXRECofIQxMQxCqECGMCCgQI2IbyzFxmSd25aBCPypmGzI+hhWoGCmXY0+BQgqNHygMjKiGGH82IZexf7pBt6XUBGGAVhrTdBoetNt9Kk5opJDLwXPdujTUBeuWkIZW1nKmW/9d/YlePbPUzf6xjrOL8A9Qr73W4i7RCIZYA/yqo8/Q2dFBpVKhVC6TTCRwPY9AgSEjV29bFjoaNcV1vXr86tgm2VyGMAyoVH0qVR/DMKMaYpyVW5aJ6/pYllWPRwPfZ2iwj6rrMze3hJ2IQLN+4KNDHaFxLAPLtDAMA9/z6OzI0d3VwaWRCWzbjOZRRKvhvTVp8K2LAWM31mghai5ICo0KFOVKFAybtoFpWtRgw0IIlFYEcZ/XkMZyPFN3fSyXJuKST82weV6A1grHslAijEsa0TyIbZkNLa1lF9w4EiCEIAgC+nqyHD2yj5GrY7heyLqhHiqVKqVyFT8ISCaTqDB6/b7eHubm5wAolX08z2X/3u1cG5sknUpScT3y+SI9XTlsO2qDFYplXM/j6tg0SocRSkEKyhWXwwd2cfzVU8zOFVg33Mv64T6ymRTJZILpmXlGRifJF0qkUykOH9jFyVMXYmu67D2aqw8aZCi00LfnXPByQ17geSE9HTa7d+1FKcXFSyPML7mI2FVpDUnbZMuO9YyNz1Ioe8sXVzT7Z61jdEn8ve+7bN4wiGGYXLl6HdMykWh27trMwmKBqbmluAW2XCZafu3lCq4Rv2ChUGDPri2MXpvAdX26Ojvo6uygUq2yfdsmRkevk0qncasu27ZsJJ1O8MKLrxEEIYYUuNUK+/Zsx/M8ypUqxWKZTCaF57p0dg4yOTVLwjYpVavxQJLB4uIir75+jjsO7ubi5Wv88OPvBWBmbp6B/h5SyQT3HjvEzNw84+MzvPr6OeYX8zhOIq4trlaLVCgi/OJtk4TQAqkXQuNVPTZuHOSXfvZTeH4Q/+ZB/t3//fvMLuQBqFZcdu/YwC/97Cf5j7/+R4ydOEdHLo1G4PmR1dShxnYcTBM8Lxq9NA2JYcKPfvIDnDk3wrkLI/hhhCL5yc9+iBdfPs0f//kThKbC96JRTcMwqFSqWJaN57o4toVhSTAkxbLL+OQ8Z89dIpnOUipV6i7W9yPLValUMQ2JaRoEQYhpGszNLxFqwflL16h6Id998iUSjkXV9UkmE/ieR9X1kVKSTiepelGXRmmF0ALLSbC4lOfEybM8/OBRLl4a5aUTZ/D9AN/38APFow8fY/eunXz9m89RLHux8umGBGpl+Uei3vYpjbdFAYNQ3bQQGgXckqrrsW/3FtYN9fLrv/UnPPHUS2wY7qdc9ejIpDhyaCeu67OUL7JUqNLb08n7H7qTi1euEwQhQwPrUErT39fFq6+fZ36hxKYN/ezfu43Ll69y9tIEzz7/GlevjmEaJnce3hmjoSOQhFKKuw/tprMjwwvHz1B1Pe48tINr12fYumkrY+MzTM/OY5gW1WqFkdFxpJRMzxexrSgU8AOFbRksXZvAjDsx9Z5xnFgIw+DchSuYponna6QEy5RMTc8ipIFhWAitmZ3PY1l2HABEA25aaRzbolAo8uQzJ3j/w0dZyhcZ6Ouiq7OfpXyJjRsGGB0dZalQJpVKoMKa8mlEY3JVz5wFWhlaCCneNVNx6UxWlIsFUulMxkkkfkUahqHRGIYpbMuph7yNCYg0BKViiV07N/OB9x3jjoO7uHhlnEKhwD/7336aHds2kM1l0Bq2bh6mp6eTQwd2cHDfdiqVKr/4M59ASIP33HOIwYEeFhfz/PLP/yQTk9M8/NBR3GqVR957lFQqw5ZNg3zqY++j6nrs2bGeEycvcOfh3Tz84BEW8yUe+8B9XB25xi/8zGfYs2sz77nnEBOTs1weuY4wBF0dHRw+sAPbtrhj/3ZSKYe+3k62bBxmoK+L/r4utm4aJpNOsHXTOtYN9ZHLptFacOfB3aRTSbZsXMeu7esZGuhloK+L4cE+Du7fwdJSgXLVj+PBuG0pohC3BueyLIvFpSW2bFrP+qEeMpkU9x47xN49Wzh1+hJPP/9q3EsWDZWcGBPIyrJSnFGLUPlhtVL8tVKhUBoYHBLTUxPvoqk4TZ0ZoFYeqXU10GCZNuOT0/wf/+o3+fXf+hMAfuFnP80nP/YI2XSSf/0ffpv/89/8F149eY5UKsGff+V7/Lff+TPWDfcxONhLuRrw2//jq3zzuy8y0NfNo+87BtqrW+G9e7ZSqYZYluThB+/kz77yPX7t1/+AiakF+vt7OHbXXhbzLgAduTTr1w/jej7XJ+b4x//7f+LEyQs4iRSeq+jpzpEvFCnk83h+QFdnJ5Wqx+BgL7Zt49g21apLT3cHQRAwOzdPX283AN1dObo6c0gpmFtYoqe7g0wmS1dXJ5l0knQqQRgnMK319khxTBQGlmWzuJjn4pXrADz34mv89u9/Fc8L8IPW4r5oKsG8E6h2bmEWXMPGNbhgQ1Iulbj36D527dzMd554nsHBXj78gbvxvICEY7Bn5xYsy2ZwoKdeUilUA555/iSvvX6Bzo4MpuWQSSdxbJN8vkIqlWDk6hinz14hmbD4zI88wviEYmGxwMaN69i2ZT1dnTmqVY9SKYLaP/vCSc5duApAKpXgjVPnWcpXyOUkIHGcBCPXJtm9YxPZXI6Z2cVo5sQ0eePUeZLJJJVKBcuKpugq1QhzePXaBPlihTPnrmCaERInX6hw/tI1pBCUyhU6chkKxQqGEYMMasjRuIAtdEO3g6isspQvcuzOfRRLFU6euoBtmwRBEM+56HqNsLUDI27QtHt3xoANrgCh67Ff9DQqDNNianaJD75/iF/95S+C9vjyXz7N1/76aZSCj33kIZbyJV45cZar16ZwXZdsJkVnZ44f+ejDvPTyGxTyJWbnlhi9Ps1ffO0JcrkkDz1wFwAnXj3LxNQi8wt5Xj5xmp/+yY/y45/5IRYW80xOzfLGmYt85kce5RMfe4RSqcozz7/K1WtTBKEi4dhEIPaojhYGIadOX8ELAgyjxh8T03vEOD50SBiCYRoYUhKq6DOevXi9DseXhiIMYjShMLk2Po8hiNHWetllohu0JbJuge/j+T6PPHSMr3/rWbo6c7z3/iMUS9X49ZfLUY3x3zIPQ4vyvc1lmL9TG9w3OCxmJsd1prNnoLu7e9S0LFtppS3LEQkn09R2bOw2+H6AVi4duYgbplAs49gWrueTy2aREipVnyDweezR9/AjH76PZ148y/jENB943zH+3//yZ3jVIocO7uWNM5eZnVti/XAfY+MzzC8UyObSSClZWpgjlcmSStgsFcpYtonrBphC0dnZSRgGeJ6PFgbVahXDsKKuhdD4vk9vdye7d2xkYbHAuYtXMWIsYVdHGieRpFCsMNDXieuFeJ7L9Mw869cNMTM7h2GYuK6LlAbJpEOl4uKHCseK5j2EMKh6XgRmrcduy/1iKTWeH5ByLD7y2EO88PLrXLw8ThAEHD2yi/17t/N7f/BVUulcHUWzXJhfCYOLUDYaJARuxVuYm9w4NT4+9fd6KOnNjI+L1v6wUpimgRBpSiUPLQTJOEtNJJMUK1WkMBBa09mR496je3jmxbP8P7/xe3zuxz7J2QtXyReKHNq/k1Bp5heW2L51HZZpsLhU4PCBbYyOTVMoldm3dweuFzI6NsM9d+5j9Np18sUK64YHGJ+Ypbu7gzAImJia49D+HVwbm6JQqCBMgQoDctkMvT1dJBMJpIRNG9dHQ+u2ydjYFKXiCHcfPcj161Nksylc1yOZSlAqufUa4qZNm5kYHyOXy1J1PRYX8/T2dlMulfj+s69Flk7WkoTI9UoJvueSy6Q4tH8HZ85dJJNO0t2VxrEkdx3Zz87t6/nIY+/lK19/imQq3dQXfpNorXd/J0S2lGFa+fmEEQ0rhWr56TVNCyk0YRBw5+E9mJbFy6+8QX9/P4cPbObb3zvOxOQsdxzYSSrp4DgOYRgShiEP3HuIOw7t4fiJ04yNT7N/z3aef/FVMimbw4d2c+rsFTZtGOLQgZ3MzD5Pd2eGUrnC/XcfAGAkDFBCIxEIw6JcLnPi5Dksy6C3u5OlpXxU9zNNpmeXKFd9zp67zFK+SFdnLoLXzy8xt5AnDHxyuSyTk5PMzC1QLFWRUlCquCxdHiUIFYYkhluJetQihYoSno4cdx7ew7MvvEoymeSTH3uE9GtnkTGL1vmLY8zOznPv0X0cf+080rQaJuJWxZ0DvhbaELcRGEE3lQLWgllpGqgrtCbQIJA88t47+fZ3X2Bmepp/8GMfJZVKcv7iVWrhV9R71YShwjQjzpd8ocD84hJWPMQjDYtKtcDs7DzJpIOUkrPnR7h0ZYyd2zZQrrgopRtmLxRam1imzczcAtVqRLuWcKbwwzCK1MKo92sYBs+9eAppCJASCXhuBWFYmIZA6UkMKeLzs/B8H8e2o4F3GaOqha6j/QBCFZBJJjh8YBcvHD+ty9VQBKrKf/u9P6dSCQDFC8dPYztJFhcWOXxgO4f2b+fEGxexTDvWPL1KElKrByredXVAO5HKJJPJpjqgaVr1ALhV8VagnFsUVEqB70Xo5g++/wHe9+CdhCrkd37/L7k6PovjJFhcmEMh8T2f6ZlFiqUqI9fG8Tyf+YUC18Zn4s6EydzcEvlCEcsymJyap1SuYkiDYrlCoVBkZGySbCZFqeziVqsIadaTp0P7t5PNpFlYzCOA7s4OEgmbIFCEKsC2omm6INQoDft2b6G3u4NSqYJp2WgVYjtJgiAgnUrihwrDlMuDSJHTbbgQYBoG18cnKbueqJFnCiEiwiXHiZIgHZJKp5iZXaJYKhFqFYNdddOogW6qA6qoDhiqt60OaN4qVrjGKjyrrGBYjflK6+XhHssy+dpff5/XT51HSIOro2MobZBIJNBaM79YZWL6fARkMCwqboCQNq+fHcEyLZKJRL12ZjsO1ycXYoJ0SbnqY5gmS8VKPFhucOLkBSzLwjCcCDZfddmzcyNhGFIul3nv/YfxgxDfD+jt7WZ+fhGApXyRcxevsm6wm+nZeXbt2MyFS6Mc2r8DKWWd/dQ0JDNzS/R0d1Kturz02hmENhtmUmrXxaTqhegwJAwjgqJlg+a1QAk9EBCWQizTivGCoinTFU146tsmBgzfVCE0igtbuVpq2bKBbUuujc2ghcZ2UjF1Rjy4Y5qkLLMO14qsgsaxHTSRW7Ysq/4+tm22YPGIptJiSSYTNE5S2qbJwmKBnds2IKRBKp0mDBUzM7NRJtyZpVCsIA2DZMKhI5dmKV9iZHSci5evsXP7BoYG+7Ftm0uXR9mwfhDLMslmkliWFc3nNhSQG6+BUoqe7iw7t+2tj23eSC5euc7cYgFDmssP/Y0KtLcLGqY1GWvtDSOiHmkNZi5jq1i76EIY2AkDrUI0IVrJKGKUEqXCFota+3kDyZAUKB3Uh8Q1AVJEhWZNgBBmnbAlUoJlbmjDMplfyPPK6xcJw4DTZ69Eiuw4vHLyQlREVgEIA6UEr58ZwbFt3jhzBa0FZ85f4+z566iYc+bcxWtYdoLXT12J0DvSbILR1zCThiGolD22bhrmH37+w5EFvIFYlsl//o0/YXJmATNh3nzmSBu3DyIaVMNwumhCK9cwG9VKFaUiC6S0olIpYNhJpJD4nhs18S0j5mkxsJ0ElXI56qFKCHyFZdlUyx6gcBJJDCOaEymXKiSSDqFSeHGJJCIugoTjUKlUo7lbGdXgwlBjyNo5RlRpnhfEiGSzjjWUhhWNG8iIbUsakDQT9UGjGteQ0hpkxNogDSPikY67HzXgbVNIovUPNLQmpWjijhWr2sB4KInbZSaEBmh903hgDUQqCIMqB/dtw3FsTp+9jGXZ3HXHXUxOTuEFmuHBXvzA5/r1SQYGNscMpfPs37ObS5dHKVdchvs7mZ4tsnXLMLlMkpHRSapVn2TCYt/uzZy/MEI6m2ZoYANnzl5m04YhLDPCCh7ev5X5hQKeH1Aul+nsyOH5QX2MM18oIQ2rqcldG2xvfaBqzAONsy6iCYUslofiV1G+xtDASTicv3SN/+s//P6aBEaNMjm9pB3bFK2DVGsh1W87QGrzRY6g+tVqlXuP7iWTTlIsVdi1YyPrhgcZuz7Jjh3bOHPuMjt3bOLipVHWrRtkz67tPPn0i9x5eA+GFDi7tlAqV7n76EH+5x/9FQ8/cAevvX6BatWnXM5z/z33A3Dszn0IEdFePHj/HYRKYxgWw4PdLC4V2L93G9Wqx8zsPHt2bWF+oYjnuVwbn2FhqYw0IFSqHh7oNab56re+da55eSDlTTiNGpxLslSoMDufv7nB0mBZtjAMc8WAUtNUXJNn4t2/qKYJldF0VeJtGUoxPDzAC8dP89fffbEOEnjqqRd4+rlXuHptmtFrk4xcHaNU9rl8ZZTt2zaRyWR4+pkX6O7uZHRsmvGJaXKZBGfPXSWZcNi9cwMH9+8mlUrw9LOvMDDQg9aK5148yfbtGxkdm2J0bJKlfIHLI9epVKqcPHWRXTs2Mzk1h2VKOjpyTExOY8b4P3mD8dEmpWwYQ60nYUIsj1k2fLUOatVGWWuvZxgGyWSCZOImX8lE054RoXUDm4OoUUvfssbIO2ZjzootFxLGx6e44+AuHnnoLrq7OgA4euwOHn7wKJ0daRKORTKdJQwDFvNFUqkkYRhw5MgdlMsVFpcKEUhAWizli5imQUcug+97eK7LXUf2MT+3iCEFRw7t4erVSdYN9TE82E06leKTH3uE6ZkF5uYXSKcTLOWLEbjC96lUvGUGQ7FyFFQp1cxspfXfQtgsVvRu62wJWtdjzIiVTjf9W7OyuomvUNfZyG7VVtFbCMm/EWedxk5YvHLyHHt2bsGxLV594wLJhMOenVs4f+EK+UKBsxdGmV+qIPHZv2c7Lx4/TeiV2bVrOydOXsGxHV4/dZ7FxSUG+rqYmV3k1LmraKWZXyyxfcswz7/8BrlMksHBfr71vRfYunkDUmrmF4pUXS+CTDk2f/2dF6hUXK5PzNYJKHXDgMWqXC/87WLvRCOTvhArMCWNylmfY5Et0351llTe/au61kbDpEQykSSsxyCigWRbI7RAi2jDkFf142JxAqVDvKofQZvMaFuQbRoEYUgYhJi2hYHE9XxMy4rKLKrGjlBbfWUhpCQIfALPx05YKAVhEJEVBb5XdwwxbzWObaNDBYZCx2UKQ9bcmlyzg9P681ZSpbUYvf424umqW8WxnTqBuhGPBkDLwH1DbEmotBBSeH753Y6GCRuoLfQazCUCoQ0yaYMg1FHxWkA24xACCSsiEipXqnRkU5SKZQKlwNAkkhaOFV30UskjnbYplXXcQov490zDxEpF7UDTEGBFCmfbEVu+0iquCUb5uqwthRGNREHNRfJWhVuzt91CmbEWFckKRobGnHkNZjAhBCpUHNq7lYsjU2zdNMDcfJ65xTxWTMLeFPPVlO92c8FrYnBjoKpEUHFdjuzZydzcIvv3buPa2CR+EDA00Esum+bU6fNkO9axbfM6Xjx+ilTKYdOGdbx4/HUeeegY5y6M4Lou+/ftZPTaBC+/eh7HcWJCJJqY6hvZp2pKp6LeaIMiNWwkegsbMtdi9tINP1uLdu5mzGCtShoBFhQH9u9hdGySXTs2c+7CCNNzi1hmVGZZDY51qxKRd14SImp4oRApAvL5Itu2RHi+9cMD9Pd2Y0hBOp2ms6uLns4Mz7/4Knt2bcUyTaSAjlyGXC5FMuGwZfNGXnzpNfp6ukgm7SY+mhutfRUtyUVtsk01sJZGu0GWf187ppaA1L4aE5IatceqWa5YnddGtzCIraV8y1ZN4bllPM/H8zzCwAd945jr9smCG1kHxIoqVDNbaDxDsWf3NkavT2PbJplMivOXxnjy6RfZvXNzNPtrRD3gcxev1pmvvvntZ+np7mRwoKu+/qq+ymoVy6VblGCtHcJSyiZquMbBqtbXWAtQoRqUshUPeTOKOr0KcKNOU1I3gRFu8uiRvWTSWbZt2UjCsephj76tuWFEC0tT6/NXp9WIyPN93+P8hVEmJmdRYYjnBximybE793H81bNIIbjrzkM8/fxrOHaE0fPcCvfcfYTJyWnOnL/CPccOc+HSKJWqh+3Yy3zIjQpzk6XVN1LOVvcoGtx6XTnXSEjWIuFcKw5sjTXrzKo6GrBXKGzHQkoYGZ3gxMkLJJNOPG8iV7pafWND8K5Z0/CWFVRIlFIkEhm+9cSLOLbF9OxSHRR6fXw6Tk4U5y9dQ2uFlBavnRoB4Ct//TRCKwIF45MzhMrAtiPlWyvYXxGhrgILa1VQDWjVvLtXr9LxWAti1mrN1uKoblVCFb9nZP3UMt2GAtuyGL02ydj4NIZhR/AyYxmIoGkkftK3dCjJhHdaCXqZmarGfZxIRhg/s+HmaKCRIF7Uf9b8kex4/41hNO5LWyY5Ws3CrGUV1xorWEbnNP//zZBqNkKsWpV1LSuotV41dguDaFi9VC7z9PMnSCYSqHglhG4iwV+Z8HC7EVSubQD1Cr6/Op1Yg8cWqzDPijX4HhupKJZJL8UN629rucSahVLxTWvNYg3DaFKmmiKr5TWBK95jte3vq8Z6az0cWiCkZv/uLaSSScqVCucujeMHfj02lHGL70a1yHdtEtI0F3zTJEQsV/wb+6S0fLX0Tlt/Jmo/06KJMku00metYp1WtYYNWMTGJn6j4jRmyE2vW6trrrLreDWFqMWNy/PSNP1cCIkUgoRjkrAlUij27txCuVzhmedfoVyusHvHBkxD4NgGCXuZQVVpddNk57a2gDfLW/4u+zytN/vNbWdvzpBbFbn1Rq+meK1ZcC1rrxOkr5oQhezYtgnTkAShYv26Qf7ia0+QSGS4cGmUDz/2MI5l1A3AmXNXUErGxfU2Q+qNkYK1Del62YeKFvJt0YIeahr2EstWZwUAvcE3C61X9eF1FtYGt7tWFqta6no3y5qV1sgWRW5SvKa1X3rNrDvQguOvnkEI8D2PfL7A4YO7OX9hhL179nLuwlXOnD2P5SQjSjfbbCo3i9ueI3otiH5d+RqIvOszEZoGIvs4aRMN2ZuoMefWZ75EIzeFaODopraqoYFOVYuGVKi5Ry1qKxG0XoGlE2t0Pm5klFtrgK0dDoFYs09ca+XZTgrQJByHkWuTDPb3smPbBhYWlrg+MUs2m0Vh1JMOrZuJ0evneauIYd5pCiiaaCMaGO9FPYqqK1WdFV7Uvo9HGBsGkOo7d1dcYF3nga5ffSGWCcGJX0+reluurhKChkXRtY6JhNr2S8SaheM1g/81QAw3S9aU0tE2eDdEiBClFL4fxsxjCs8LsGqsqKvuT2nO2sRtbwHrcKGIjsLzPHQYIgwDEd9gIS3CIAQUtpOIOFLcajTTalhYpk21UsaxHbzARQhQGNimACRB4GE5qagYLQRSRUMafhjiVstYlo3ScUkjnrkNQh0vrAaBia88hOEghcK0HDyvimlaKyb3Vs2uVwlNxZuEbTV1XZSHISW+p+jr6+RDH7gXgMWlEp0daaQ0+eo3nmJyeoGk4xA9L80zOKusrbq9OyGivsVbEHo+O7duYNeOTbxx5hLdnRkG+nt4+fhJtm/bQiLh8PxLJ6l6Afv3bGPzpvW8fuo8o2MTPPzAEY6/epb777kT1/UpVypcvTaJUrB18yaee+kMqVQy4vyWJr7v0dWV5f677+bi5TEKxTJHDu/h2edexnaSZLNp1g0NMHptDGkYbN28njdOXyKdTnLyjUscPbKLyyPXWVrKI0wnGv1cDQGzWs5/g6RmLatZQ2EHQUgul+Izn3iUU6cu8K0nnsf1wTJNPvi+u/jMJx7ld//nVymVvCh7Rqxan7yV5ZhbyIxgN4bEK7MIQnLZNLMzM9x1x0HOnr9MGIbce89RpqZnMAyJaRlMTEyQzXVQLpfZtnk9OvQ5csd+qtUqUkiCIGDL5vWUKxW6O7NkM2mchEM2nUArTRhoqq7LkYM72bxpHZcuXWHnjq2MXL3O9q0b0MDhgzvxfB+lNH29vYxdn2Lf7i309/cgpebg/l34fsD99x6hK5fhysg4tmUtL9BpqffdrFDd+ncrETMCw5BUykUe+8CDXLo0yvbtm3nPvUd46eVX+fmf+RTd3R0cf+U0hw/s4pXXzpFIJho2Ka1h7aLi/LucIZW164BaNGS10mJsfIod27fy5LMvUypX6O3p4dSZ87iux+T0Ant3b+N9D93L7Ow8w0MDXBoZ5667DlIuV1m/bpDZuXn8UHHx8igb1w2wYf0gF69cZ6i/m0MHdpHNJKm4ZRIJi6mZeb79xPPcdddBkkmHkdFxurs7kRI8z2dqeo6NG4ZAB0zNLGCYJqYh6cxlAJidmcbzfC5euR61HhuK0PoG7rQJcbMaqHU1ly2izomTTNHdleHipRGq1Sqlcol/+qs/g+f5VCoul6+MksulSKdtlArinrFu6oXfDFb2rnHB+k1M8DcmGZVyhR9+/AH6+zq5MpLg7kfuZnGxwJWrRXZu24hhGrz48hvMLyzx4R96AGlIrlyFZ58/ybE793Hx8ijbtkR/983vvkBnRxbTsrg2Ns3U1DRBKOntyXL4wA5eee0Ctm2xYXiY8Zgz5n0P3c3iYp5SKWIzXT88wPjEDKZpcO+xg4yNTQLw9HPHkdLg7rvvjIvD0YIYdC154qadjVW3PzWtJWuYYRCrzzUYhuSb33mhngx94P33oeLbq4VAxlzRUqxstzXCyd79MaC+GWNgdEESyQTPPP8qVox8/vOvPkky6VAqlZmdi9itZufz2KbJt554AcdxqLqBnptbFDOzeSqey+xcniDUOgyUeP74WdCKVDqNaUQoG8MwqVR9LAuujIxRKJSYnV9EhYLu7ixL+RJCStyKy8JigZnZPFJKOjpSzM8XcByDjo4eXj99kVNnr5BMOvURACX0mlD9my1gvGkfWUeZt1utMDe3xP69OygUKziOzamzI+zesYF8vsyBvVuj2ZZSiWw2S6Dk2nuYeZdvShINQ9drl2HqG+EQQpAvVdGqWl9ks1QoY5smoQ7Ruort2KA0+aIH+QpIQ6RTScIwxLZsFpbKAMK0rTpnDAJUGJEB5ZfyLC4uRvEaMD45jWmaCGEyM7OIZZhoQizTZmJyPvo+VMzMLGKYFuVqiCUEbqgJdUixWEELgWGaK7ZrNjLR3yj4v1FS0GQRgWQiyRNPvcxP/eQPc+rUBS6PjOHYJiPXptmyaZiDB3byu7/3pyQTyRg9I5uR4Eo1DTq1C9G1jkdcuDOkiSbAMC1UGJCwrWhRn5SAGUGrAFNKhCEbqGglCo1hyDojf9MixBre0JAYmNH7CY1lRbi5aJjbarhZqul7w7LQREocFbUFpogINXUMPBBxOyb6TGLFVNtaYIcbARAafYUCpGmRL7r8jz/8Bo9/8D6+8LmPUyyVyKTTKBXwh3/8VyyVXJxEMuLP0Wu8RzsGXAUfKQSlQonPfOL9XLh4lXMXr/LZTz3OX/7Vk8zOL0Z1N6I4S6/Am9eY5PWKLZyi7uiNlipQrb0ilzPypvWpy5VaESudEqusQq1P9em4eL0qHemqsx3cZOCoNWIOdbTlfWGhwO/+r6+xbqifTCZJsVhhfHIaKQ1sO0G07cFYVaGbFDsmhHp3u2B9Yxdcu4+h57Nvz1Y6O9K4rsvWzetQKmD7lnVMTU1h2w5hGA/YrHKH9SqQreVlzauU/VdscW3Bf636+mL1HkXtd+JNLm28ybLuteBiUYstxLIEkGRicp4gDBDSwLGdeECJ+hLHVuBDkyK2XXCDu9LRgp/NG/qR0mTnji2Ypsnk1Dy7d23i9dMXo/aTlGuOc4lVr2qTM7xBO+LmcBpxg1+Lt3hHbzbEfqMEBSHr2z1Ny8K0LdAqXpzduJiwmXFr1ez83QxIrbtgcfMyjNYCKU2+++RLbNgwTmdHhkqlwquvneLonYfoyGUYm5zDlja3k6wO41ou4msEEcWzpJGGZi2cY3NyxO21L7i5jrVyKAkdEYhfvTbB1WvRcvDO7n5OnRvBlGa0CPqds3n+Fg8xNMQcLdWU+prZm7KE6ne/CzYIUc0gprXn1UX0JJvmcrcwYpO3G55ebislXC1zbhozQDQ9zysILt8hMPx3SCG6kZpDN6yOasQDNltL0ZIYtAI2b08X/OauwVqzJtxihTRvKR2SaHYBjd5gGRG9PO6xvOtMNJDNLtcOG49pbDPXYF6rBqANgIGaF2t4izir1atntfVjxHKZpvH4FYgf3ZAlN5eNaPgMrWih2nus9sDVtoxGf9OIb6x9Bt00Cbei7MKtmwl+2xUwxIBVFqFoLZoSTyFbi8cNZD6ipY5Vh5hHd6HGh1xriSGoj3mKtTCItTHQ+H1qG5winWuu6608djl7ry9ejMGiK4iLRGOdkJa27rLlr9n3GrCWGvvBGhlc/cGpZx3LQ1C1Q1SdSk7Xr/c7gSHhHVEHjOpzy0y1nu9jW3YLl/KN6mHLMx1uJWJSdRKJFRawBvlvvPmiwQIiBFoFuF6I7dj1ORTWsICiwQLWrJPrRnvgHCdiogp9Hy10zEy1ugVsVr7aZ5ZUK1VM24g6QjfoK4smCxiZ3yDwCAMdP/CSRMKJkDC1EAexRh2T24mcqDbHEUHK0QEJW7Jz6waCIGhmd19z8GeZ7Fui+fFPP8aPf/oxAr+KjCndViq9XvUhUKFHRy7Dxz/yEFLqt7Q2Q0qN53l85Ifew7E7dlGtVHCrLvffc4AjB3dSLldiKl+9xgMYK58MCUNNsVDkofsP0dfdged7TbPAN4puJJLQ9+ntTPGZH3kfX/jcR7jj4DY8txSz/TefQuOw661gRpC3hpVNrzKbK6lUAvbs3MzPffHjWKZEh6pOALlaBtfK+i6l5PDB7Rw+uL2xALmcLTfGc6tcikBBKumwb88WbNMgVPotzexopdm6ZZgf+/QH6ezIUq3k2bhhkKHBfvwgWJt0qNbeEwKUJpOy+dTHH+Gzn3yUXCaBDvWq88w3ks9+5sNMTs3x3e+/zOM/9ADrhgcbdoqIFZa8rne3BUm5aFyRF1NHhJpMJsljH7iPdUO9PPbofZTKFXzfbS41NBRMW7NC161QKkVf1UolHu6OyjfElByiBafXKkopKlUdYemEauBSWd7atJKSIS4zmQZzc4ucvXCVT338/QSeRxCGBL5f3yV8s8vi+wFbNg0yPT3Ha6cuxnA0Ve8U3awiqHSI7Vh8/6mXefL5k5w+fY5iKdrCHgYhrXqsASVuHWOWfNs7IXrldBcIQiVIpxIEocJ1q5iGZMumQd73wFHCMCbiWY62V2SCnudxcN8OujqzdHVmufvoQe66Yy/vuecIuUyECBZvwoLUhssNEWCIRhLv5iSh2TTWZoQVuVyWb37rGWzb4sEH7yafL2GYxpuiRNRK49gWb5y5zNe//VzDkhl5050/tWRIS0Gg4MTJS4Rehc/9+McpFIqcOn8VJ+EsM6TqZQS6FrdsKvOdQVBZ29U2Nj7DidfOAfDk0y/SkcvQ3ZXBiEswDdF2UzG65v7CUNGRTZBKJXBsmxePv0EiYdHd1UHghW+pYO0HGs/XBKGqr8uqr826CfuCaVn8rz/+Oo++7z0MDnRTjXmuuVEfOo4mlNbYlkkum2jO5t+EAteyX7TGMjX/4Md/GNu2+a+/+5VoT1zjwsda4+TtB8C885IQRDRmaUhJLpfGcRKksx28ceYyhUIZYca80oQrJ8o0aK1IJBO8dOIcr54a4fVTV3jiyRe45+gBJqdmuXh5jGTCWUb/6jV3eAKQTAh6OlP0dufo6bCJRzzqVng1T6xjM2JISTqdZHx8gqefPc5j77+nvreu2QXoNYr0JgqDIBA4jhMTrasbJ1GimQ7O932++PmPY9smf/qX36avt4tUwmjYFdLotDXidkDDiJvEQEorTFMzPj7Dq29colKp4iQSLCwuNa2jEq2DOmJ5oV8i6fAXX/0eQRAyPDzEpk2buXTpEl1dnbpUKglR23656tVWSEOwlC8xMTnDRz/8CEoFBIHmy3/xhC4UK8IwRL3coUXDTjstEDI6x2vXp8gXKmQynTz34qvs3rWJYrHUQO+x4hOscO8RGENydXSSYtnFMGPlYTmOXVESEvWCH6lUor4R4Kc/93EAvvr1Jxkdn4k4EnXzOSx/nttmTYMjEk4aVauGiqApk1RhEPP8RVsvRSPBpTaX64axH9HUVlhpfD9AxuhkoSSJhIHrxaz8QsZF2GYAa/SzECk0SkkCFb1GlLgIDFGLw0ST+1p+AAQIFYFUQx8haqxWEt+vRmsSpFXDMTfQz4l6sbsptIi7PCr048K4iW5BDK3wIy2sB2FQxTTNmB+w1mGRdQhXjYdRsNwFithKbos1Dc0pv4g3Z0ZBt4FhGvXiriFNdN2FyaZYpx7HxEqoVYBtGcvORQqqrhdz4xHh5kTjDt64eBu/ptIaRIhlmU0QMR1x39ZvlG7ZNxkpkIy3XlpR/RENQuEkUqAD0GFM3auicWzBSnbShl3KCKLZEpYRL1q30Lk1jhPVlS/6OLZlRcpbj7RUfSwzOsxYw53r22gqTiwPSNf2rXm+i+95hCrQUkhhmBaOZSNNY/kG1G6eXl6yImqcLUGIH/jx+taovmjZNnbD4hrN8g7eRg2onUPge7iuSxiGSCkwTAvHTsUAWL3cX9XE45eiYQ44usm+5+H7XsTfYhg4jhMPPIk1kCzNVln5Aa7r1sMPy7IxLQdpWM20bw3zxI3Ubkpp3GqVMPBRWmlDmqJ2DhrRUkPVK4zCbYEHFDqoL572gpBSYYlycQnfdfF9X4QqGgZKJJNkO7rJZLOI2goqYdSBNNGN8CmVypSLRcqlPJ7rEqoosbEdh3Q2R7ajG9uJBnTQqokjWQqB5/uUS0UKiwtUK2VCVbv50Tl0dPWQyWSjjrbWIJY3skdPQ0C1WmVpYZZSsYjv+/WtSrVzyHV2Y1sWoTaW23EN2XXoBxQKBfILs/XP0HoO6XQnEglKRfvjGkZApQgpF0sszs9QrVRq5yAsy8I0TTK5TrIdnVi2g1KrFKZuN47o6Ma7LM3NkM8vocKQSrkc/c6QeNUqpUKBcrGI291HT39/DBaoQbcAHVIsFFian6VaKeO6VVSoouNDRaVcplQsUirk6R9aTzKVQqkGYsm4h5tfmGNxYb7peACvWqVSLlHI5+kbGKKrpzfiho7daeQOo3OYmbxOpVxqPr7hHCqlEr0DQySS6RhKH9GQCDSu5zM7dZ2lhQWCWHmlIVGhwqtWcatVysUiPf0enV198bC5angIQ5YWF5ibnqRUKKw43rQsKpUK1UqJ7r5BEokUQolmZ3RbWUAhCIKAwtIiiwvz0ebyapWhdevZsH6Y7p5ulAq5dPESly5eBmaQhqSnty++ThHbU7VcrCtfpVymo6uLrVs20dffB8Dc3DzHXzpOqVhkemKMwXUbcRynvrQmCAIK+cW68jlOgk2bNrJx04Z6WeP733uSwPeYiXlSenr7arNpgKRaKtWVD2Db9q1s3LSRZDJJ1fU58cqrLMzNUshHTP/9Q+sia6wVQkT1xoXZybry9Q8NsXPnDrq7OiiWKly+eIGRK1cBWJibRkhJZ2cvjZRH5VKemYnr9Wuwe/cu1m9YT6lYZHx8nJOvnsQECvk8AL0D63DsZNPAO7cFOZE0hGk6KAS+V2V+ZjKOuQKO3HWEn/iJHyWRTFCuVNmyZTP/6Fd+mcsjI1y5dBmlQpxECsuJs+EwpLAwx9LSIr7nMrRhI1/8wo8zNDRMqVQik83yq//oV5Cm5MQrrxKGIUJoUpkcGhOEpFSMrKfruqTTGT77Y5/myJ0HKVc8fM/nS1/6AocPH+L733uKMAwIg4BkKoNl2UihCQOfuZlJSsUiQkge//CH+NCHfoiq6+FWq3zg0ffzmU9/ku8/9QyVcokwDDGkSTKdooa3KBULzExN1q/BT33+J7Etg2KxxMGDe/mFX/gFTrx2kqmJyXhVa4CTSmLZCdAhKvSYmZygVCowtGEjv/gLP8P69YMsLhbo7enil3/pF8mXy5w5dTreJxdiWjZO0kEK3chj/e4kJ2pqxdVwacrHDzxdLpdRKiSb6+C+++7hzNnzmKbJxz7yKGfPXeCb3/prvvSlL5DOZqmUS5SLxTqeMgx8SsUCge8hpcH73vseSqUqs3PzfObTnyYMFb/1X/87jz/+OLv37CbwfarlMq4bcQdqFeKWi9TO4a5jRxkcGODc+RE+9NgH2bx5I7/xG/8fmzdt5gMffD8qVPi+T6mYR8SZe7VaoVwsEvg+27dv4667jvD6G2d46IF7OXb0Dv74y39KobDAj332U6hQocKQcikfgQNEtOWpsDRP4Ht09fTy+OPv58qVK2zatJkPPfYo33viaZ5++ml+6vOfw04kUCrEc12qlUocf0rK5TKF/BKmZfOxj34Iz/Xw/ZBPfuLjnL9wmS//yZ/w8R/+CEPr1qNUiO/7VMoFfM+L74fithzLDLxApFIp9h/YhzRMLl26zOVLVwAYHh7itddOMjszzbWxSe44cgf5pUVmZuZR8cakWpfg6LFjpFIJ5ufnuXDhEhcvXWb/vr2cPXOWhaUCpikZXr8ewzSZnJrG9zwSyQxoRblc4sCBfXR2dWJbJi++9DIvvPAyW7dsYOz6BK+88hp/2PEnABw8fJDr45O41QoqVJiWSaVUZv2G9WzZsgmA106e4tvf+k68IDvLG2+c4o++/JdkcznuOHKY6xNTFJaWCHwPJ5HC98p0d3Vy97E7AbhwcZTnnnmW9Rs38d4H7+fc+QuYlsmGjes5fOgg18bGWVyYR4UBYejVk5QPPf5DBEFAsVjg+PETTE1OMNDfzaWLl8kvLeJ5Hrt3b8exDcYnpqLrHwTYWt+ypph5awdsJEnHwEulOHrXHZiWhWFIpqamOX3qDE8//SyFfJ7cnt3s2rGNvt4eRkZGIgXUGqk1lhXt/z10aB/9ff0AvHLiVV56cZbvfPf7XBu9xsDgAHt2bWdoMM/lbIaZ2TnCMMqEzbjmt2PXTg4dPEAYBoyOXuOb3/gWzz33IlOTEQvWwX17cN0y6UyWuYUC1UoJxXLwv2HjRj7w6KOUKyU81+MbX/9rThw/QTqTplIusW/vLvr6eunIpiiWylTjRKsWY3ZlUzz2wfcSKkUQGLz4/AucP38BKSVLCwts2Lieo3feRU93D77vkc8vIQ2zPhNsG5r3PXwfiUQ66shcG2N8Yorvff85pibH2bN3N0fvPMDgYD9+oJiZncdJJAlVoKOZQ3F79YKjKS1Nd3c3vuczcm2CpaU8mUyWz/7oZ9i7bw9vnD5Pb/8Adx87QjKVIp/PMzszR6hCpDRQSpNOZzAti9HR68zPz2Kagh/52GPc9573cPXKZRKpFA88cB893R1Uqx6FpcX6psvaYpl0Nsfk5DQzM1MEQZX777+fj37sI4xfv06hVOGBB9/D5k1DGKaJW62gtcK2k8tLFVMZivk80zORsu7Zs5fPfvZT+L7H+PgU99x7D0eOHCGVTCOlge+5WI4Tt+ei7UaeH3Dt+hSlcsCGjRv47Gc/QzadZHTkCrv37Obhh95DT28PyaSD50edItu2QYeYhoHneYxcvU6xWCWb7eKTn/gQmzZt5NzZc2zcuIFH3vcQ27ZuIpPJIqXE933SSQcppLhV7vdtbcV1dXaOWo4TteJMWyQSGTQBjm1z+uSJeuZ27713c/jwPubnFymXq4RKkc2kePL7z3D+/HlMy6Z/cB2dXX2EKBzbZnz0EtMTE9iJBHfccZj77z9GuVwlXyji+wGDA30cP36Cl19+BRWG9A0Mk8nlSCQyKBFSKRa4fO4M0pDs3LmTBx+6n2QiwczcAq7rsX54gEtXRnnqyacp5JfI5jrIdfWS6+iKMtgg4NqVi5QKBYbWree9Dz/A8NAAU1MzVKoufb3deJ7H17/+baYmx5HSoLu3l66efhzHIVSwMDfF9MQ4TiLBAw/cz+HD+5icnKVcqZDLZujoyPGNb3ybM6dPo0JFrqOD3sFhEqkMhmFQLha4euk8SoUcPXaMBx+4m1LZI5/PY9sWGzcM893vPcvzzz2PV61iJxIMrtuAk0jGK700Qptveyvu7cuCE4lfMUzT0FpjmKYwTQe0wDQlQRhSKhaihXpK4fkBnZ2d/NzP/RyXL13ga1/9BjOz8xiGSVdXN8l0BtNO1HumpmWRX5zHNE28MNp0HirNP/nVf0TgeXz5j/+UkavXAE0mGxFVptMZDCOi0bVsi1KxAAgCpbBMk3Klyhe/8NNs3rSJL3/5zzh1+ixutRp1JEyLXGdX3X2bpkkYhGit6uDTcrnMhz/8OA89+AB/9fVv8NwLJ1haXMCQ0Sb3bEc3yWQy3nwU2QLbMqPuh1KUK1XuPnaYn/iJz/HkU0/zxHe/z/j18Trzf7ajg2Q6i2k5dcre3p5OQqUpFkt4vs+WLRv5whe+yMWLF/jG17/F+fMXUWGAUiGpVIpUJkeiZomRtyQLviVgBMdOCMu2owkGCcmEw9lTr7O0sEAylSLb0cG6oQEsy2ZhcZGxmBzcth3S2Q4yHV2YtfXz2iedTDI1NcHopQvYiQTpdIbh4UEymQyVSplLl66gwhBpGCSSSbp7B6IeLTJeZCgJvAoXz51GhSHpTIb+/j66OjsJVcjly1epVpZjtr6hdVFHpD5oBFLC9dErFPJ5Eo5Dd3cnPb29mKbF6OgYc3OzEau979PXP0CuqycqoQgJWiGFweLiDIXFBTzPJZfrYHh4AMdxmJqc5NrYOIaUuG6VbK6Dnv5BEokkhmmj4im3IKhiy5Dr41EosC6+BktLeS5fugwQgX0tm4HhDSSSSRKJREx6LnWNmdF3q+7C/NSmt8MCvu0uOPADbVoWqXQ6en+lI6XLJHnj9ZNMT0zUOwi1boJp2ViWRUdXN9mObizLjp7YOAGQQtPb08X4taucP39+xXk4TgRPSmUydHb3kUimEfGkWTSHoUilkxq/JE6dPkOlXIpjzDAGmEbvb0hJZ29/rHwmGqOOxDEMiWMZXL1ygfnZ2fqxKlTYiQSWZaHCkM7uPnJd3UjDwYj5BGUMrrBsyC/MMDU5VS8LNR7vViPl6+4bqPe3o5ZgRFMihSIMPJYWF5ifmcJ1q3WAh5NIxBbcondwHalUCsOyMaLdKBoVlfalIfFc721TwLfFBd91xx324lL+F5XSdhAEKgw8qWMSSGFI4fo+pmmyc+c2HMfGjyH4pmlGPdRMhp7+QTLZXNRMF2bzdk00ruuxbsMGBgcH8PwYaCmiHqyTSNLR3Utndx+W4yCk2dT710Lgeq7IZnNs2rQJw5D4foBhmFiWjeM4ZLKddPf1k0wmEaYZ0wmKOte6DhVaaDZvXEcy3UkQRpsqbcfBcRySqRQ9/YNkc7kI8WOYTdzQQmtUqOnq6aGjqydmsteR1U4ksB2Hrp5+unr7MSwb06y1AOXyCjOi98tls5i2g1bRnLJj2ziJBB1d3fT2D0Wu3zARhgla6SAIhOu6BEEQaq2lFGL68N5dv3b2/Hnv77ULbrSCO3fv+VKhWPlNIUFrEaK1kcnlcBIJrYUQSoFj22RSCTw/1NVqVajAjxB0snEOw1yr0g1ALpuOXY2LHwQRh2DjXLFc+5kLVUjCSZJOWrhuhGbxA4XQCuQyojjC060cVEcrhBRk0ymCUGvP90UYBCgVuVhdyzbXWhgYf4ZkwsGyTHw/IAh8wjCMFE1rQq2Rwlh7vECrGvpGC0IRBGFUcooHrlSo0EJG10EHOggC4bnVBhSCFpbgV8+dPf0favfu720W3Co7d+/5UrFc+U0dFdBCIbSRzuRwHCdavaJVbUoJKQ10TKqt8VtXWsV+QwohtK7j5ZuJT1aycAnBqsxIWqNjeEHj8VLIVc9Ba7H8vs2QZL2MkkCv+hka/3b1yZD6+cqGh6UR1t94rvVr8BaOr73/aspnoP/lhXNn/vm7ogyzmiXctXvvPy6Uy/9eCIlSOhRCG4ZpI0U0A6nRslVnVjBgte4sFAiBUDqCNouWDQYrdVLXcZt1RL8UQtXeu/X4VbZaNb1//f8t711rP9bGESJcbPQ5ldayPq5M3aOLtbiClvcKCiWkEGGoVn3/1uO1Uoh6pr18vFJKSENquQxMbVK+v+vY75ZYwLWUMGYHMHQYYpjWWBgG5bXhW3JYCzJai7CFXcDQYQhCnL/BKSigX0jZ3Xo8WhumaXhB4F++QYFehUGwxTBtJ6JyWPX95xNOYkWcUHWrgRTSrrqVjG3ZIM2Vxys1D0yv8f7KMMxMpVJabxgGhumsdfysYZipxt9ZppmrutUgDIJ0qEIHwHZSoWWZoWU7RqgC2ZnJ/udXX3npl99O5bsl1MCNSpgvlv99tGgyunG5TOZf9XR1/rf+3u5gtWPXr1+nvvqNbz/j+uGhuHpRq2IAar67s/PnH37g3q+MjV1fcQOnZ+fNZ597dmHHrj3/olgs/jNhGE3Hm6bhrR8e/NS1kStfu+vOI6nVjv/jP/j9/MMffPynC4Xib9aOr4V0OgzJZjP/8As/9flvBGGYWO38p6emvL/6xje/uJRf+mdmvP+kfg5hSCaT+ZcXzp355/fde1/XatdgenbevHZ9/NeKpdI/iDL5etgYZeuS3/mzP/jdL/3hn32lq/az3t5eB2B8fFwef+VE99Wro7+0sDj/aSeRTCZTUU20M5v5T7dC+W6JAjZ+wJ2793zJc72fD8Pw1Q0bNvzrZ5956tybiSM91/t5wIt/ZCOYXb9u3T95+qknT9zs+Pvuf2DX+MT4r6PJNfzYTqfT/+bUGyf/4M18hh279vwL3/M+0ngOlm1/5c3GTu954MGfGhu7/kutn2F4aPjn38w1uPue+x6Zmp76pz/oZ3jPAw/ecfXq6C8ZhrHXcZw/tJ3Ef3z9tVf02618t5IcvS7Xr1421m3aGgJs37VPJhOOnpyaZHBgcMXf1i7O9auXjYnrY3Urd9d9D/qNx6/2Pq+/9opuzOpefvZJC2Bo3XoFsG7T1rBvcFis9r6rnUPt+LdyDpWqKy6eO6VqnwGg9jlqx9fO8cChI6L1fVsVpPEchtatV7Xr2Hps4/sDNJ5D4zFvt/LdcukbHBa1f7fv2vc3Aka82eNr7/lmf/53+bl/0HP427hWtff6m75WW9rSlra0pS1taUtb2tKWtrSlLW1pS1va0pa2tKUtbWlLW9rSlra0pS1taUtb2tKWtrSlLW1pS1va0pa2tKUtbWlLW9rSlra0pS1taUtb2tKWd7/8/ztw30VG7rjyAAAAAElFTkSuQmCC",SmokeAlarmDevice:"data:image/png;base64,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",WaterLeakageSensor:"data:image/png;base64,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",MotionLightSensor:"data:image/png;base64,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",WindowDoorSensor:"data:image/png;base64,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",CFMT:"data:image/png;base64,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",PowerTagE:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAACgCAYAAACLz2ctAABL/UlEQVR42u29d3xb1302/pxz7sAGF7iHKIra05ItS4kt0vFInB2XyptmNY0r503bJO371klTtxTtthn9NW127ORt9rDokdiJt03SQx4SLVmToiiJ4iY4QGzg3nvO+f0BXBiiKXnUqW0JX3/wwTB0gcv74Due7wIKUpCCFKQgBSlIQQpSkIIUpCAFKUhBClKQghSkIAUpSEHOVyHn+wlKKSkhRLxex9u2bZty1113XRyJRKRlWWRychLBYBCMMco5F83NzVdUVVWteOqpp0RdXR1taGiAZVkghACAT1VVP+f8lrKyskde5nsrhBDrfL8+ynn/CyNEHDp0SFu1apUrFApJkhUppaSUXu5wOCrC4bDM/zEyxtjIyMiHZ2ZmHE6nE5qmQVVVouu6VBTFYxjGasuyMDU1hYqKCjQ3N8MwDACA3+9HX18fFEVBU1MTnE4nhMjgXwgBKSWSyeTDwWDwOUKIkFISQogEIHVdl5TS8Vgs9v8RQp6RUlL7HAoa8C2o+QDIqampZofDcS+AylQqdcY5ezwer9PphJTyJf8+EokgmUwilUqBc24DE5RSmKYp3W43UqkUent7UV1djVWrVgEAdu/eLTnncuvWrQAAy7LyfwzIAo56PJ6FvjM0TUMsFjM4518pLS3dmX2dARBZoBYA+FY4LxtUQ0NDB8rLy1fH43GoqgopZQ5wpmkKKaXImsczhFJKKKUghEAIAcuyYFkW0uk0MU2TptNpMMYQjUYxMTGBpUuXor+/Hz6fDxdddBFM04QQwja9yP+M7OfzBV4nUkrJGGN+vx/JZPJZ0zSvLy0tPWQDkRDCCwB8a5yXlFLSgYGB07quVxNCpKZplDGWr/HIqzDlufusJoNlWZBSghCCSCQCAKiqqsqZY/u9eaBb8D7/cfbYEgB3u92KEMIkhNy0Z8+eb7W2tqb27t2rbtq0ySwA8K0DwBOqqi4yDENomkYdDgcURcmByL7o803hucBHCAFjLHcjhEBRFFBKcwHHQlo1H2i2PyilBOccQojczX5dCMEJIbS0tJQkEonHU6nUF8vKymzfkJwP2vBCCEKIfdHT6TQ453A4HNA0DZTSs2o7G5j5gKOU5gBn39tmOvcHVZRX6qPmboyxXKAyD4yMc46pqSnL7/dfrqpq1/T09FcIITefL74hvWD4piyQLMtCIpFAMpnMBQgLaav8185mSm1Nxjk/4/l8DZf///JvnPMc4PL/Tf5nMsagqqoSjUa5ZVkOv9/fEY1Gn56amno/IYRnA3pW0IBv3mj4jHtbu9nRraZpZ2jDfPNrm0c7ELH9Rzu4yAfmfLN7NtN+Nh/Qfj4fhHnHYkIIOTc3x91u96V+v/+3sVjs7/bs2fMdQkjKjvrfatrwvPcBjx8/flLX9YZ0Oi0URaH5Ws8Gia7rcDgcYIydFYQ2AO332IDNP858kJ8l+n2JqZ8PQvv4+Vox39RLKTkAWVZWpkSj0W4A7T6f73EA6OrqUlpbW60CAN8kAOzv7z/pdDobIpGICIfDtLKy8gzNZgNBVVXoug5VVXMXPx8Q803tfK16Lo0733yfK0Cx+UYbnJTSl/iZtnDOucfjYYwxWJb1/cnJyY6mpqZJKaUCgL8VtOEFoQE1TWtIpVJiZGSExuNxLF68GG63G6ZpnkGrMMZyIJzPGc43ozYgbQ2V/zg/0j2bL2rfbIDZILOj6bNF0vNFZD+ktLSUJhKJgVQq9X8DgcDvAGDXrl1s+/btvADAN1gDejyehng8LnRdp9PT0zh16hQqKytRU1MD0zRzmsY2pZqm5YBo+3/nClJeiW+3EADna8hzmeuXC7A459zlcrFspuaHiUTib6qqquJvdt/wvI6Cd+7cCUIIpqenEQ6HYRgGAoEA1q1bh2g0isOHD4NzDkVRcoGFlBKGYSCRSCCdTkMIkdNQZ6NRbBDY72OMQVEUqKqaC3Lsm6qqOS03/7hnA+1Cfmm+WTcMA4QQFo/HRTgc5l6v9y98Pt+BWCx2DSFEEEJkV1eXUtCAbwwRfTIYDDaEw2GxbNkymu/zDQ8PY2xsDPX19QgEAjBNc346LgscHZqmvkTb5QcbrxdVtJCPaD+3c9LpdBqpVArRaBRutxvJZBJutxsAkEql4HQ6La/Xq3g8HhBCvhsKhW6uqqoKvhl9w/MegH19fScVRWlIJBLC5XLRfLpF0zREIhGcOnUKuq6jsbHRNmdglELmyGUGh8N51gDlXOZ5IY11Fl8uBzDLsnKaF0Aur+zz+UApRTqdRjgcBmMsRyXZj21/1LIska3Ioel0+rhhGP+3pKTknjebb3hBAJAQ0pBOp88AoBACiqJA0zSYponBwUGEQiE0NjbC7/fDMk0gDzSU0gXpmoX4vnNxkvO1Zr52SyQSiMfjue8lhICmaZBSIhaLwel05qJ3+zsxxmCaJvx+PxhjSKVSuWNEo1EQQnhNTQ3TdR2mad42ODj4t+vXr3/T+IbnPQCPHj16kjHWkEqlcgCklCKZTOLHP/4x3vWud2HVqlUwDAMzMzM4deoUSkpKUFtXC8HFGQEKgDPomvwU2rnANo9QXhC48wOh/ODEzt6k02mk02n4fD6Ew2EQQuByuRCPx+FwOMA5h67rsCwrl5fWNA2JREL4fD7U1NTQRCJxgnP+v4uKih5+M1TYnPepuPysxXxwVFRU4M4770RXVxc45ygqKsL69euRSqVw5PARmKaZC1BsMU0zVydoX+j5hPLZItr812yqx4647cJXh8MBXddBCMnlrmOxGBKJBHRdz5lgVVXh9XqRTCah6zqSyaTknPN0Os2FEDwej3OXy8X9fj8vKSkRAEQwGExxzpsURXkgFot9Y2xsLPBGFzSc96m4s4GBMYaTJ09ibm4Oe/fuxdatW2GaJhhjWLFiBYKTY+g7ehhV1XWorKw4I2/MOc+l8myTnK8l87XbQiS0qqqYm5tDIpGwawxhmiampqZgGAacTieWLl0KxhgMwxCEEGH7h263WzFNE0VFRVAUJfcD8Xq9pKioiOX/4Gxt7/f77deU7I+GMsb+hjH2hbm5ub/3+/3fyJpjqwBA/HFywbZomnZGEYCqqigpKcHY2BiOHz+OtWvXorS0FFVVVfD5inCs/wRCoRCWLGmCoig5rWfTH0II6LqeCwTORl7nm9nHHnsMTz75JDjnSKfTOQ2aTqdzFTU1NTW48sorcdFFF1GHw0Htfx+Lxc7Q7Da9YxhGKJlMHqCUEiATPxFChKqq1DCMpy3LOsQYs10TQwhh+nw+J6XUJISYBQ34P6QJT506lSsaLS8vR1lZGZYtW4Yf/ehHGBsbQywWw8joCP7sE5+Epjuwbt0aDA8P4eDBg1i0aBFKSkpyGZT8iNX2vxRFyfmGC5HTQgh4PB4YhoFUKoWrrroKuq7bVS857cw5F0ePHqWlpaXPBAKBhzVNc3LOw6Zp3mGfj67rtk8oJiYmhhobG1Ov4QeqSSkbotHou3w+3w8KAHydG5IOHjwo8zm7EydOQNd1VFRUwOPxYHp6GqdPn8bJkyexadMmzIVCoITi9OBJLFu+AmnDQH19PYqKijEwMJCLlO3IlVIKIUTOX8sPUGzaZn5QceWVV8LtduN3v/sdkskkXnjhBcTjcVBKkUgkYJomFi1aJMvKyuTU1NTxZcuW/RshJHquc41EItvm5uYceXWJxLIsCWCJ0+m8IpVKSSklExCSUroSAj5CSCoSiVQDoJxzFUABgK+njI6OumZmZpR82sXhcIAQglAoBMYYlixZgoMHD6KhoQFbt27F6MgI9vT24t3vuhpCcBBCYRgWfD4f1q5di8HBQRw8eBBNTU3wer1naEPTNHO8nN/vh9vtXrCowbIs1NXVYfHixeCco6ysDH6/H6qqwuFwQFVVBAIBlkgkpK7rH4/FYm2zs7OjlFKSrYSZH1A5vF5vXX42Z37qT9O03PvTqRSEkKCMwDSt15VMLwAQQFdXF2ttbbWcTucVlmXVxONxizGmcM5hGAZUVUVRURHKy8vhdDqxfPlyjI6O4siRI2CMwelwgHMJgIKQTPFoOBxGcXExmpubMTU1hePHjyMQCKC2tjZHANt543Q6naNO8gtTbQBSSpFKpRAMBlFaWgqfz4dkMpn7t7FYDOl0GoZhEI/HI5qbmx26rjfla1MbbHYFdjwe53aPyks5KSJVXYNhGlAYAwgoJGCkTOTIzjeIkjuvNaCiKKyoqIjMzc1BURRIKaGqKkzThGVZiEYzVm3//v0Ih8MoLS1FeXk5lixZAkJY9pbJLHz/e9/D5Zdvw7aWbSgrK4PP50N/fz8OHz6MpqYmOByO/Ab0M4KV+Wk2G5SMMYTDYUQiEaRSqTMon9LSUrv+kHLOZSKRkHYkbPt/QgiEQiFwzmGaJisvL4eu62eCUAJSAe7Y9wdctGgNBmZP4RfP3oVPXrod72jcaueR3zAteF7zgFkTlssqMMaQTqehKAoMw8Do6ChOnz6NUCgEl8uFSy+9FBUVFRBCwuKG3TkJIQRWr16Nnscfxy9/+cucFlu9ejVKS0tx5MgRTE1N5YKIhSpc7KAjkUic8bqiKLko2i5gyPcdbX9ubm6O9vb20qeffpr29vZSy7IoALr/+X30oQcfos88/QxOnTqVKyOzza2qKDg9N4Injj+LuJLGj576DRKKifsOPYqkTINIvKEmmJ5vzehSShoIBKiUknLOia1RCCE5f81OYTHGcPjwYfj9frzvfe9DMpmEqqooLimGy+mEEBnTqus6nn72GYTDczh9eihH43DOUVdXh9WrV2NiYgLHjx/PmeN82iUSieD555/H008/jd7e3lzAMb9XZH4doW3WOecIBAKorKyE0+lESUlJ7of03ve9DytXrjhrRTelDNFUHNCA+448CgqGL7R+GsSUsKTIWGBSIKJfVnbterHx5vDh7gX+ZN0ib4SFAQADAwOGrusACKQUud4P0zThcrkwMjICKSWam5sxMjKCn/zkJ3jPe96DsbExNDctQlV1DVLpDNdXXFSMDAHsx+TkJI4cOYJVq1ahsrISHo8HGzZswIkTGc6wrKzsDPCUlJSgqqoKw8PDOfDkZ1DyS//zK3FsTaooCoLBIGZnZwEAyUQCHq/HDrQQCoVQUlKMxsZGGIZxRomXYRlYElgEQih+u/dB3HTt56EmCNZVr4RHccI0syYYsgDAedqMdHd3s9buboGODrF9+8unjKSUdVlnmgHgU1NT1RltQ2BZAsFgEJxzuFwupFIp1NXVIZlMoqamBoZhYPXq1RBC4J3XXIPaulqYlgVd1xGPx+H1elFaWorVq9fg9ttvxzPPPIMdO3bgF7/4BT7xiU+gsrISixcvRjgcPsMXVBQFMzMzmJmZgdPpRCwWw4oVKzAzM5N7T77msmkd28zb7xFCIBAIIBaLZUFLEI3F8Pz+56HpOsoCAbhcLiSTyYx2zfM3i3Qv3rPhSkylQxCcY/2i1dhQuwZW2gSh5FUXwJ73ANy1a5edIM+lhk6ORbYd6h92USLXlZcXbR4enxOCSyqERWZnpuTk6Kjzm9//6TvikVkSC88gnU7g6quvIY2NjRBCKEIIjI6O2g47AGDp0qV49NFH0dPTg6amJqxcuRInT57ECwcOwOvzoDwQwJ69vaiqqkJ1dTXGxsbw0EMPore3F1dddRUmJiZQWVmJgYEB1NXVIZFI5GgYzMtHl5aW5jg+O0DJ13YOhwP5lTrz03eJRAJDQ0Pw+XyZczAMMEpBQHJgFUJkrKkkICTbc0wZxmJB3Pn071FbWoXbn/odatwV2BhYhZQ0QAlBIReclfZ2STs6iNi+fTuXUmr7j0+29Z2eeffkdOTi2x/ev0QQJ5KGBTmQgJAEhDJQSsBoBWSgDMORWSiOUqRSbhw7+iQuT5tnBB7FxcW55H08HscDDzyAqqoqjIyMYN26ddizZw/q6uoQmpuDy+EAt0yYponhoSHE43GsWLECg4ODWLp0KVatWgVN0/DDH/4Q69atW7DwwDbDhmFgbGzsjKLR/EDFLkpQFOUl6TnbZaioqEAsFkMsFsPixYtzhQtLly7FoQMH4ff7M8AlBJJISCEhpYCu6hgOjaHGV4l/fe/f498e+AFmk2E4nS4ko+mcprzgNaANPimlct8Thz/+nduf/ULMIGunoybiKRMpw5AESSFBILLXWQKQhGasLmFEUTWqMRf0QAUufe8KLFpSQ4x0GkxRkUzEMTMzg0AgAADwer1obGxET08PGGN47rnncvxgaWkZvB53rtaurKwMTU1N4JyjtrYWiqLgxIkT8Hg8KCkpQTKZRCKReEnZvu0D+v1+SCkxPDyM8vJyuFyuXDmVre3y2zzzzbH92Ol04uKLL85RPDxbxHD48GEYlvkigEjmGLpTg5ASkBLV/nI0ltfh+clDqCgOIMlTeHZoP5pLGzI0zYVORGd6WYk1OZdc8puHD97RPxxdNxU1kEoanLLMX1RXCM36diCZcj9YIhPJWQKwBIclGFJUIh1NQS9lcOg6rGQCLEt11NfXY3R0FIZhoKKiAoqioLm5GfX19Th06BAuv/xyDI+MoKysDKbgMDmHEJko+MSJE3A4HDh48CCmp6dRVFQETdPQ2NgITdNw4sQJLF68+Gztk3A6nYhEIpidnc35iHYknB98ELw4EcEGp6IomJ6eRn9/P1KpFHRdx+ZLLgHLZnZCM7PglpWhlCUAJnH3C/cjlI7g6pWXgygMz5zah7sPPwRKGRTCsL58JZa9IxMNyws5Cs5OMLUe6OpdsuuhA48NBtN10XjapCphDgdjCiXQFAYlVyJPAUIgMs4Sl1LAEhLxtCUTBmcmF0RwwOPUoVAOzihsIlpVVXg8Hui6junpaTz++OO4+uqr4ff7c6VYRX4/+o8dw3vefS1AKJxOB8LhMEZGR6EpCkKhECiluPzyyxGJRHJjPmzw5YPJ1mKWZSESiaC5uTn3PpuK4dmi0fyCVJfLBUIIsvMMcwUMixcvxuzsLLhpIZVKweP1QlNVlAXKoOsOCCHh0HTsGT2AR/t3o7y0DF/a9a+4pPki/OVVfwbN5cDPunfhsmWXoqV+M3jaBAh9Q6uSlTfW7LZTALL30NCSR/aeenRkTtSZ3LIcGlNVhUJVFJiSIGyYiCcTYEQC3IQwDS6lwYo9LuZ1e6FoCtwuN1JJEzHDFKaZglNxUgIJTdMhJTAxMQGPx5Or6zMMA9dddx2OHTuW00aKoiAcDqO+vh7JRAw+rxfRaBT19fVwOhw4cuQwvB4v3vPe9+YAVFpaCq/Xi4mJCTQ1NZ1RnGqDUFEU+Hw+DA4O4sSJE9i2bVsu8gUhUFUNkAIAgUDm3taC+SbYLkp1FRdDzwYtxaUlGBsfRyqdyvh/EjClBQ6OT7V8BP1DJ/CTp25HdWkljo0O4PTUCP5kXSk0zpCQJkBk1qJcYACUUpKdmYfqs0fGHhyPknrD4pbGiKIqCuIcGJmJYjw4DhEJQkmHIBPTMOIhsXRxHVvRvFgub161V/eU/W4iFBmvLvN9YHhs6qKEcNe4NBUeFZIQSQTnqK6uAiEZzszpdEJRFKTTaRw4cAB1dXWYmJjA1NQUTp8+jZKSEtTX12eKCywj14cxPDyMdNrAxo3LEAqF8LOf/Qzr16/PBTnr1q07g4TODzIopQiHw0gkEqirq4OqqrncL6UUpmVmMy8EKlMzkWnWBBNC4HA4MDQ0hOHhYcTjcfh8PlRUVCAcDuPUyVNgjGFmZgb1DQ1Ip9NYW70SDkXHt35/Gz6y5UNY07QSfRMD0Lw6NvjXoNIXQJpne14kLkwientnJ+3cvp03/6H3a6emrcWxRNpSGVEk0XAoGMOxsXFERo/BPXcCemoac8ER6XMQvu3yrcrypsCP33X1Jf+55qJLD+Y11fyXlLLk3icPvW1iiv5tsYtuE1xISghJJpO5PLDP58v1Svj9flRUVCAajeKyyy7DvffeC4/Hg+LiYvj9xWBMARcCpmmitrYWXq8X9XX1AAGWL18OTdNwySWXIDvNNFcYkO8HMsYwOzuLQCCAoqIimKaJRCIBj8eDmpoaWJYFh0MHZQxMYdBUHXq2yBQAampqcoFHtkomFy07nU7U1dVhenoaNTU1EJxDAnAQDX/d+ud49NAT+N2z92EmHcbmxRvw3Mn9GJudQGvDFgRKi2GZ6VfcUHVeAdCeXH/kRHDp3U8M/NVkOCVUSpghFbwwHMLA+Cj40PNgI3tBmImpuTlUlPrEBz7wPuXaa9/1lZaWli9/8R9uymVIOtFpX/hZAPcCuHd4ZOxHqsI+HYmELQCK7WdZlpVL+j/77LOIx+NIp9PYsmULPvzhD+M3v/kNLrvsMiiKilOnBmEaGQpn5cqVePjhh/HQQw9i2fLlWL9+PXp7e9HX14fm5uYcP4cFelI8Hg/Gx8dzALILUK+66qqslqNQFAaNqeCCw5IcBC8GInYkHgqFsHjxYoRCoVw3XyQSQTAYxPT0NKoqq+yWTCz21WLxZX+KgdnTSFtp1JfU4p3r34GfPdmJcDIKRhkACULohUdE7+zupgCsx184/fejUamYnFsSqnJkOoJjwSmQyaMw+x6Dz6tjLhJBkVfjmy7ewNatW/uVlpaWL2/cuFH94he/KLZv387zMyRSStI9OKi3Njam3Q7tJDIsv7TNYFNTE44ePYry8nJwzrFp0yZccsklGBkZwYMPPojGxkZs3HgR+vr6sGbVckQjYQhBkEwmce+996KsrAyTk5Pw+/04fPgwiouLMTU1hRUrVmDp0qUvGc1r+4M2ySyEQCKROMM0U5p5jwDH/uAJeDUXaj2VEFLkTLCu6xgbG0NRURGCwSCCwSDKysqg63qmhnF0FNFoNOMHQkJhDM+PHMKR4T4ouoaqkgr8avfdCBohiLSFa5ZeDkvwMyzvG6UJ35BihI7WVktKuWw2wT8yPhsXIIwNxwwMzESgpGeRPPwoPApHOm2CcEM0NtTRpqYlBz760Y9+ua2tje3du9daqLGaECK9MzMcgORS6lKSnEMPACMjI2hqaoLf78/1ze7evRvNzc0QQuCJJ55AcXEJampq4HQ44HK54PF6UF5ejoaGBuzbtw+Dg4PYt28fQqEQ6urqUFdXh+LiYhw7duwlxQB2ADI5OQlFUdDY2JgBSir14gQsEKiKitFYEJ/99Zfxvad/DqfbBeDF6atCCPj9foyOjmJ6ehplZWVwOBz2ygcUFRUhGo2iv78/U6YlJeZSEZQXl6O4pAQKGNYvWQOX14UPvO1arKxshmEZoJRdmAMqpZTk908PXDcepbphScuQRDkRikFKDn76IEg0CLWsBOHQLMpLvLK2to5uWL/+X9rb22lLSwt5Jc3UQgiZT+Sm02kEAgEEg0EkEgksXrwY119/Pe666y7cc889iMfjWLduHbq6uvChD30IhCmYm5uDx+OBv8gPn8+H8vJyrFmzBi+88AIuuugijI+P58jioqKil2RBpJQwTTM3BGl4ZBiNjY3w+LzgPJsvlhIKU+HXfbhy7WUYC03gqcFebK3bgFQqlaFquEAgUI7i4iLomgMSMldZ/eyzz8IwDExOTGLjpk2ZSJpzLAsshmEZsISA2+nGY88+jcGJYTwY7cKKoiY0eeqQtoyzjik+rzUgIUQOT0beNTqbACeUTCUMhEwOZsWRHDoAl0OFkU6DESlKiouZ2+3p/+AHP3h3R0cHXv3wRZnj/xKJBMrLy2FZFl544QUEAgF87nOfw6WXXopQKISxsTEkEgk888wziMYTWLJ0OYy0gdmZWdx/3/1YtWoVqqqqcuPd/H4/hoeHEYvFkEwmX+JL2UBUFAUrVqzAxRs3oaqqChACQIbz0zUNJ+eGoagq/v39/4ibP3Ajfvn0nTgS7IdTdWTJaAkhOBhTYJpGblSHqqpYtWoV3v72t+OKd1yBkpKSbGTNYHGO4dA4Qqkw9o0cgltz4rrN70aJ24/TMyNglEECF6wGbPjHH3UvjiRNySXoZNoACAENjUCEx+HwOxFLJOHWVeFw6NTlcnUSQsxt27YpPT09r2hrUP4vWwgBp9MJXdcxNTUFl8sFp9OJAwcOoL6+Hu9///uxatUqHD58GF6vF5s2XQyNUSSSKRQVFcEwDPzpn/4p9u17Pkdke71eTE5Oori4OEca51ewzJ+IkE6nc5RH5v9n2jkPBY/hJz27UOotQm1ZDWLpBBYV1aDEUwLOJFSomSyHXV1NMqwdpRSxWAx79uwBYwyNjY1Yu3YtkslMZTUYwWx8DltqNqLEXYS0NDAemYIiFVyyeD1ACSglFyYARyOoSRNndSwVl1B1EjY5nAqBGTwFKtIAdUMKC5SqKAsEsHXrlkP/8R/fIN3d3WhtbcVrnZAAZPZ4zM7OIpVKoba2FqOjo5ibm0NTUxPq6upAKUVFRTmEsDA5OQGm6ODCQu++XlRWVGJsbAxjY2OYnp4GACxbtgzJZDLX7HTOMb1511tlKgZDI/h/j/8an3nPp+ASOo4OHcPyqiXY2LQOx0b68R8P3Ib3bboa2xo3I56IgxAKQgAhZK7HmTGGSCSSG04EKUEIMDB5EqdnRxAYK8WqhmUY7w9iMjmLkiI/dp/oRTKSxLs3vAPS4FkC+wIqyb//ied9p4JxKZmKqCkAKVHEJOKhUWgKhRQcBFIqTKGMsei1117bRwiR3d3d/+2daZZloaSkBMXFxYhEIqiqqoIQAgcOHEAsFsNVV10Ff1ERkslUlizm0DQd1VXVKCsrg9vtxkUXXZQz1w6HAzU1NWfMGDyjMiZ/fqCtESGhagr8Ti8qigJ4eE8XpuZmsLx2KVyqEz957Ne4c8/9eO+Wd+LBwz147PhuODVnrmjUDkzC4XBu3mAgEMhoXZpJB66rX41rVrdiY+NaROIxjMyMYyoxg0Q6AUYoCOz503hDTfEbAsC6qrJPpIhGTFCRtDicTIFqxGHGQlAVAiksKJSAEEodDkfK7XYfAICOjg75avzMhapT7FUNNnASiQRcLhfKysrQ19eHiYkJ1NbUQtNdAGEoLi4Gtyw8+eST2LdvH4aGhlBbW4v3v//9CIVCSCaTqKqqyvlfC8/5y0TjIlexQvCbZ+/BrBHGP733b7C6bjmeOPksbt97Dx7tfwqLKutw0/s/j+WBxZkJDCLb+pnFM6UUhmFgz5490DQNdXV1OHXqVK7xijKKkdlxvDB4GP1jA6gtqcLS2iWYC8+BMYbNjRvwgYveCZgy4xJcaCb4+WPjaYMDAgSG4NAUBjMaBVIxMJohXymj4IKjsrJyDoAGIP1qRqElk0kVgMyZpnn1evaYs6qqKoRCISQSCdTX12NsbAzxeBzlZSWgBIjH45BSYOPGjVi0aBEikQj27duHxsZGrFy5EjMzMxgeHobT6VywC04C2Tzvi11qmqIgUFqOHz76S1y8ZD2uWL4Vrc1bwGVGg07FZ9C59/c4eOoIrr3oSmxt2IhEMnlGdbSqqlAYw8TEBDRNw8qVKyHztnISLrGleRMIgKMTAzhw4hD++prrce8zD+DQ5HG01m1GHEmwN7gt6A0BIKPinbORJCRTKAeBk1KYqRhgpcAcGQddSsGdTqfy3HPP3UsISW3cuFF9JTNMNm7cKLLFBg/OzMz8g2VZNNPpJhb0cyzLQnFxMZxOJ6anp1FZWYloNIaTJ06guXkJBk4MgtIMEI8fP46WlhYcP34cnZ2deG+2KAHIbNdcaANmDnW2niEElsVxRdMWLKmsxyMHn8B3HvkpFJVCUVRYFgfhEovL6/GX7/xzVOplSOWBD5CQMpPi29bSgmQymelldjqRzrZYQgJNVY0YmR5DsacI0oqBKQwz4RmkRBK/6v0txoPjuHb1FYCFN6wf5A0DoO5yVKbNMKiikgwgCZJmChAcBBSAAM3W/Om6/mothJBS0uHh4b3FxcWDnPNFw8PDRmVlpaaq6hnrGWxNZWV7P6qrqzE1NQVd1+CuqsapwSFUVlagtrYWbrcHt99+Ox566CHouo5169aht7cXmzdvRkVFBYLB4EuKShcaw0ggIQlBMp1AjV6BT7/tf2E6NYdQbA6WsKAzHaXeIvhVL8yUgWQ6CUroi9WC5MWgyh7rZj8XUgASoIziyFAfRucmUeYpQ1N1Awhj+N2Rh1HlC4AYmWYlCorMoAVyYfmAsWRaSgpIe4QYCIRpADKTHiIEIDRT6Zzpant1HCMAWV9fn1QU5Vqn0/lsc3OzNjo6asVisVzv7nzf0NaQlZWV2Xl7KVRXV2Nubg59fX1YuXIlbrzxRjQ0NORyyBMTE3j88cdx/Pjx3GyYlyN2MyY5UwJlcAuJWBI+6cRiby2WFTeiwVMFh6UiHo/DlNaL4CN2n8eZ39myrBcnM2T/k0KgvCSA1YtXYGXdEpR7SrGuYQUS0TjKtGLc9O7P439tfD+kxbPHvcAAKEGJAAWRFDqlGZ0nZaZJmmT4qcx1lK+JqbcXojc2Nh4VQrxTCPHtJUuWKOFwWAaDQXG2xS8AcuNuy8rKEI1GUVpaCk3T8Nxzz8E0TXz0ox/FzTffjObmZjQ0NGDjxo32FFLkr4I967T7vI+lBKCMgEuBNDeQNk0YwgTPnjc5Q3OeqUkXHAGXAyeFYjEcOnoIp4NDGJ4bx3MD+1FfVYfB4BCePf48CCeQ8gIlohmVkCDgNGNoucyYJRBAcgFBRY7vsjMMr2Uy1q5du1hjY+McgM8NDw+PLVmy5CsjIyNkZGSEV1ZWMlVVz2ihzDfJqqqipqYGwWAQqqqiqqoK/f39KC8vx9q1a7Fy5Urcf//98HgyueJgMHhWPzM3sA/AQklE22+zVeSLwJMvuztkocn6nHPUllajyF+EZDqJganTuLhuPSzFwrHQMRS7/RBSIHMVyIVXjABIGRcSwbQJbvdGUAWEMXBhgTEGh9NpD4F8zd8x211H9u7dq9bV1X01mUxeUlVVNVFbW8tGRkbMaDR6VpMshYQUAlVVVdA0DclkEvX19Zibm8MLL7wAy7LQ2tqKhoYGTE5OntFM/pKKmDMN8FnschZw0n5hfsQvX3btq/02xhQcnzyJ5/qfx0xkBtVFFSgvLoMFgbVL1mBpYFHGByT0wlxU4/V4SFII+DUFNR4X/BoDmAJQFYxSOF0u6FpmHvLU1FQS/82886ZNm8xdu3axpqamPalU6hJd13+5bt06dW5uTgSDQWlXpsxXWzJrkouKihAIBBAOhxEIBHJpPMMw0NDQkCsSffnVr2fZnkkWNtFnaj5y1j0iZxyPAFJI+N1+uJ1uVJVUZaayHuzB7hN7sGdwP05NjUBV1Bd5yQsNgJKLuVK3A8WaIiml4EJC0ZwA08CYYs9xoYlEAhs2bNgipVR6e3u5lK+9fyurDVlzc/NwbW3txxKJxBezLZZkZGSE23nchVZr2Sa5trYWhmHkRuj29/djbGwMUsocHTM/G3KuXXELmdZzrQB7JekyKQUIA46Pn8TozAQGxk/CrTnxtuZLcMmidQgnw6AazaXsXstqsLe8DxhK8Hsri3wfjyYMMWVwFkuYILobUlEhZQKWaSGZTJBkMgmn07kuS0Qn/rt8ASGESylpZ2cnqa+v//rQ0FB/bW3tz2ZmZrzDw8O8vLyc5TcuLbRWtbKyMjdSbdGiRTnzu2bNmtyos3NNx3+1M63P9Z6FGsoJCLgQqC2uwqqaZUibKfgVN65bdS1SLI25yRBi8TiolwLijQXfGwbAmgofYYMhxIXEqWQKOiHw6W5Ac8FKhpBMp5GIJ0EocPTo0QSA1OvlKNsDjKSUCiHkt0ePHl3r8XjuWL169cajR4+aiURCqaioIPkgzM/AmKYJn88Hp9OJyclJlJaWwjAM7N+/H3V1dS92u51lU9J/V+PMH2g0H3xCCoBLVPsz5LtHdcKyOMJmBBICn239JBSqvEhaZ33Xhb73eWuCawO6xiiHIQEDBBwEUnWDOr0wLQ6ZTcUBkJZlufv6+poBoL29nbyONYlWV1eXsmLFikGXy3WFEOKWNWvWqIQQMjQ0xOcvjplvkhljZ2zbrKmpwfj4eG5lw/wI9WyLqc8VVCy0eXP+Ypz8lQxMYVBzG+AZVEUBZQyarsOh63DqTvh0L5yKDqa8uFoinU7nXIgLQgNWl5aOe7UxaQiBEkWBIgDAAd1dDNPicOgaHA4HMYy0RSn1P/XUUxsAHGtpaaEdHR3i9foerZnWAEoIiQD4p9HR0b7Kysr/sCyr/NSpU1ZFRYXi8XjOmAM9XwvZXXWhUAg1NTXweDwLAudss5txloGW59L29vSs/JtpmtmbBSE4BJfg3ILFLXDBc7NiLC4g8nYb25H7G6UB3xAAril33u7WjM8bpqAVDg1CMKTTHJovgFhm5EGmS0z1YGJiAidPDiyTUpI/BldFCBHZ4IYRQn41PDx8yO12f3Pp0qUtJ06ckIlEAoFAgCzU8QZkcslerxe6riMYDCIej+eom/yWgPxCAvs1y7JyN3vVg53ZsJ/Pv80famkfO7MilmV7TWiu0d6uGcyY2Uy+ef662HwC/ULpC044VBJPWJaLOTUpBCeMMVB/BTjVYVkcjCpQNI1YloF0yngHIaQDf6TStWz6zsr6hQcAtI6Njf1o8eKmT01MTNDR0VFeWVnJMv0Z/CXbj2yTXFtbi2AwiKGhIXtRIOzB4Ta4bLDNN5/2c3vPiE0N2ZP98zep22NG8oE0X5vO3y98rp3E9o/hggEgIeSFv9+176hJjE0WZVyhnMUlAfFXQupumGYIqgJwLggA9PX1lUopPYSQRFYT/rGAaGW3SBJCyPXDw2P31dc3/GRmZto7PDzEy8srmNvtXvBi2RexvLw8NycQQG7es62NbIDZWisfbOdaLbaQWZ8/3vfVri3Dm6At8w2bjLA84JoKqHOYSibh1xTMpE043aVQiipgTISgCCAejVDCDSGkWHnw4L6NAB7v7Oykuenhf6TlNnlbJO/at+/o86WlvjtLS0sv6us7aiaTSaW0tPQlJjk/Sna73SguLj7rNvT52mf+ouyzAfHcJPdrp34uuGIEAKgodv3monJdGsmUnIzGIUCQUpzQypfAAoUFhkTKgpBETE/PyPvue+g6APKRRx6h/0Namksp2YYNKwZTKUerlPjntWvXqZxzMjIywuc3Ps2vrDFNE4Zh5G72Epv8vSHzV7POv70WkLwWML1Skvu8AuA162ofrNaMRI1KlHqdyiKFwpAUtHYlhO6DJQR0lxdcSBYOh3HixInrpJTFoVBItLe3K/+DIKRLl5ZFqqoq/jEWi360srJyuqamhg0NDVn2bo+Fsifzsx7nSp+93hrojZ738qYHYHt7lwJgalGZ64karyaLqeC1GoWbKeC+GuhNFyOdtqBoDhDFTSYnpsTIyEj1t771rR91dnbyjo4OCwBta2tjXV1dipSS/HfSdK8kSpZSKvX19b8SQlzlcrm6ly1bpgSDQTk9PS0XKmj472z0xOu4KfRsPuP83cZvVIM6eeMmorZazx4Z+eQveoZ/cvB0iLscKps2gFORBJKhEaQPPwYxfhQuYsBMhOFgXK5auQKXX375/7v++uv/rampqX+BeYPKqlWrZFtbm/hjBCrZKNkCgNHR0f/inP/ZxMQEMU2TV1VVMTvqtecBvpqLutAG9Ver9eZH1OfyEedzioZhyIqKCnpBANAeTrlz5052693PH+w6OtucMjl0RaMRLjAWNzAXDiE2MQBz+jSU2CTURBBIzspAkZeUlPgTq1etPNjU1PTY1q2bD23Z8vYHspOxztDu2c/grycY86Jkfvr06e26rv9oenraGwwGrerqasWe2eL1ehfMpJwNODhHscK5gJTfZGUYRo7qsYMbm/7JJ63t53n766SiKGTz5s3kggGgPaLtyd5TW545Nr27d2CGg4AyRgkIRUIAMYsglkwiEpmDNCLwyhj85oxlzg4r40MnQKSJ+roalAfKwn6f98iKFcsPrF+//o4tW7bsJoQk7M/atm2b0t3d/XoCkdgLEfft27coEAj8VtO0dUeOHLG8Xi+rqKggNgDng2e+lssHh/3cXuVgE8/24/wgZj6w8jekZz9DKooi7K3q+aQzYyxXgkYplU6nU+WcJ8rLy90XDACBzD6Q7du38/uePHJL35hx06FTQZMLySAlBQgIpSCEgoMgagkMzsaRjIdxWaNXNnohnn3yEdn7TBdRKWG6rsLv96K8rAxul+tk85LFg9V11bs+s+MzdxNCgrbWfT1TebYrEYlEypLJ5Lc45x8ZGhqClFKUl5dTez1YPrjyyegFcrwyn4zO35SkKIpgjEkbaDYRrSgKtd+XzXgQAFJVVWprY/v49mN7n5ytnZPJpIjH4zdWV1f/+wUFQHvA5PbthN/3+KFbphLqTUdPTSKWsixLiOy+t0ynl0eniEsVj5+cQWxmBB/ZugJLyn3ofuS3eLrrD9Lt0oUUQpqGQRkjVFVV1NVUIRAom6ypqv7O577wuduqqqqCAEj2Dy9fT00OAGNjY/9IKf27ubk5bzQatRhjxAZMfgaDUiptwNjLCbPgUezC1vz8sT0j2o6484sSkslkjhi3X1dVFbFYLMo5P5oNoCSlVCqKQiilZjqd/g3nPMUYkyUlJTSVSu0tLy/fd8EEIfNHtXV2gm7fTvjB/onPHz0V/NtQUtZPhxOIxlLSFIRLIYjHQammMuweSZDeU+PYUuvB5sZKGMkofvT9r2Bq+Cj8viJ4PW44NVUQyWUsHpeMUaWyohzNzU2TW7du3Xn99df/AABpb28nr5c2lFKS3t5eZdOmTebAwMDGoqKiO71eb8P8AlfbVObPEbRNqD3n2bKsOft120Tquk5SqdQTnPMxIQRhjElVVYXH46Fzc3P3m6Y5SgghiqJIALKqqorEYrFgSUnJ0Ks5hz9WhulNvaYhe9K8vb2drlla+U0p5U+eOzj4v0NRR1sokrzIkqoSS5gw0gn4vQ40xbnsC7rJrAGE4hacuhsNy9ZDxCcsKSSmQnNUoYz6vS54fR6YaUOeHhrhk5OTFeMTE9//4Q9/+L7rr7/+g4SQ9Ov1R88ew8xmT3qfeeaZtXV1df+pquqK7J5fqiiKcDgc1DTNsXQ6/QcAhDEms3tARCAQoJTSvmQyeZAxRqampmR2ho0sKysj2Yqd1xIwvRL6LX/R44W5Kamjo0N0dXUphJAwgK8C+GooFNswPhP9k7loalky5Wi1TMO5JOF0Nky6MJMwMBmzUCQodH85Lm+9QpGJEIJTsxgPzsjpuRiPpQxW5nUSr8elRGMJeejwEZ5MxN81Nzf3eynlB3fu3JmSUr5uwYlNXGfB8uevd9B2Ft5WdnZ2vuTFtrY2eQ5QiTfLdX9T7YrL1ueRnd3drKO1lRcXe/YB2Je9AN4UUoHooyefrCtOVwYTc4hYkpAUh8Pjx8aV1f8HkWlnyjCuGxsb2zA2NqH0nTiNYCjMS30O5nKqJBoTyvGBE+kHH3zwymg0+o8333zzF7N/A+v1Jq47OztpW1vbS4Dd2dlJ2traFnR9Ojs7ZVtbmzhHjlrgPJM33bZMuzTK/tV3d4N2d+8UhJAogOiPf9c7w6hSBaqKhKBEMzmIomFsfPZn3+i4cRrAv/T09Fy0f//zn2pcVH/9nv2HHMcGTvFir850TUEiaenHjh0zCSH/56677jr4oQ996Bd2NP56uxUoyFt7YXX+r9721yZmYixlqQBhSEuKmGHA63XjuvduKevt3jbX09Mjt23b9jyA5/fv3/9t351336jr+qcPH+0TPqdKSUoibQo2eOoU/e1vf/t1KeVvd+7cmZjXP14QnOfFCK9x3IYaSXKWsCQEJUhLgpRhwu9zY+vGNVZPT48lpZTt7e1027Ztyvr16/s7bum4fvOGdd+uLK+giZTJdU2DZVo0FA5bfX19VV/60pc+2dHRIbZt28YKcCgA8GwOuA2OrSXlZUtC8TSXikpTAkhbAn6v5yUBTU9Pj7Vr1y4GgP3rV//1c1e0XP4CZSoDwCklMAxOR0ZGRH9///+VUjp7enr4m4GWKgDwTSwWoKQFoQkuEZcUIS6RlgRupyoXMp/bt2/nu3btAgD6Z5/400+sWL5UJtMmVVUFnAsajcbE+NjYom9/97ufBiALWrAAwHNKLAWZMAVioJgTQEgQJDjg8/rI2fzZTHDRRtauXXugvr72l06nh0gpuaSAkCAjo6Py4AsvbJdSKuXl5QUfsADABeiJ7P3k9BxSpkRCECQJQQJUSN2J8enIAIApe/0rXlJ5s5IAwHvedc3PFjU2wDAtqWa6xGg0GiGDg4OXnj59uq6zs5P/seoKC3IeaEAA4BJICXvqPEgyM2RfBUA7OnbKs5DcHAB53/ve97jX7epVFE2hBJwQRgih5tTUlHL33Xe/V0pJdu7cWTDDBQCeKW3Z+9IyjwQl0hAcZaqKal0n0bQFb7GvAUBpdvreQhpM7tixQyGEpJc0Nz/sLyqSgnPOGIXT6aJTU1NkamqqjRAiX89qmYKcZxqwzKFoTqdKLC5Q7tRQ5dShaBqm5hISL5MluPLKKwUAvKO15Um/308sIRVVYdB1jVqWKfv7+xdJKYszQXfBDBcAuPAIx5PxeHzWoTCiUSoVSqGrGqbmkmR2NJkCgJ07z6JFMyku8u53v/MJt9N5WoJQRonMlExRMTMzU/vAAw+szuZWaQEaBQBifq8uIeQ4lXzUpSmUZhfRMEK5QVSMWKFrAAAt3fQc6TFKCIk0L11ySNU0WBYXAOByueTIyIjcvXv3NgD47ne/W9CABQAuXLO2pMbjgshMpFJAQAjjKaIhGJONAFDt9Z4VPNu2bSNSSlJeFrjPX1SEWDIpKaFgTCGpVIqMjo62SSm1lpaWgh9YAOBL0EcIIdIB8zRjCuKmkCoBFI3RYIxjYGiuXEpJfnVv9KxcXktLiyCEyKuu2nKP1+2dM9IGM01DEkKYEFwODQ2tmZycXN7R0SHOUUtXkAsRgLfe1qsAgODaPUV+N0LptCCEwKEqdCqWhmTi3QCUno5MSddZ6BgJAK2t144sX740SKhC4omkFIJD1x3W2NgYfvazn30wS8cUAFgAYJ5szNxdvLLG6VUpYoYFCwQaZYDiwLGRaMpe5XWONki5Y8cOVUpJlixuuKc8UC4TySTnnIMxxiKRCHnmmWc+kKVjCuVUBQAuQMV4WLRYJyJuGCQlJHTGiBAQoSQvllIuBc49SfXKK68UhBD5wQ9+8M6G+hoiJZR0Kg0hBGWM8YGBgZXf+MY33gZAtrW1FUjpAgAzMnbvRg4AdWWeeyscacoFV+KcS40SAhCRVlxFh4OJtVlf76znlaVj6ObNmw80NzcdcTpcxLIsYZomGGOYi4S1ffv2/VOBCywA8Ez/bSckMrnekE+1DumaijnDlASA06GR09MpORac/QAAfG9qSp6rrnDbtm2UEJJYunTpLRUVAYAQYRoGpJTMTBv85MmTV+/evXtLZ2cnz5Z0FeSCN8GEyG1ooYSQaHVJ6aFilwNzhiUEZdAUBRGLkf7RaJmUkqDz3Ifq6enh7e3t9Mtf/nJnSUnxIVXVGQjhhmFA1zUMDZ3GT3/6038CgMOHDxcqZAoAzNIo2fvVdb5UscJl1LRgCgG3StlcIoXh4OzbAJR3dm7nL0OjyO7ubkoI4cuXL/tXt9tFGFOyEwskMwxTHDhw4Kqenp6tHR0dBV+wAMCM7NzZIgGgNuC/o7nUQYx0mqQ5h04ZCCFyJEE9SWA5AHS+THVzT0+PBYDeeOONdxUXFx0hlDJVVYVhGNA0XY6MDNP//M//bAcgg8FgwR8sAPDFnPCKSndfiWpMq5SQiMklAaCoDms6rcv9J4PvAIBQb+/Lntu2bdvo0qVL05s3X3KL2+0GY4qAFBCCM86F6Ovru/pb3/rWu3p6eqxsrWFBLmQA5uWET6yo8M25CGiUW1IQwK2pJBhOk2cPDVcBwK/uvfdlfTfbF/zmN795R3VV5WEhJNMcTmFm98GFQiHZ3d19m5TS19HRgUJkXNCA2LVrF5NSkmXV/kNVPg3RtCW4BFwqozPxFEJp+T4ppbeno8PCywPGLlCwLr/88n/xer1ESkjKKAzDoIQQvm/fvtqbb775mwBEoVi1AEAEAgFCCJGN5eovKz2EG6aJhBBwMEYtqVinI6wsDmyRUpKu7m72CkaCWABYe3v7XRs2rOvnFmdOp1twzkEpZclkUtx9990f+dWvfrWqo6OjYIovdAB2d3cLAFhbW/5Uk0cSYplK1OKSUgqX7sDgTJo+eWDwYkKI7O5+Zcdsa2sDISR95ZUtf15WVmIYpiUdDicMwyCKoiAYDOp33HHHT6WU5MiRIwUzfCEDsGPnTtnWtosBmGsOePb5XSqihiWklHDrCp2IGjg1mdwupXQD3eKV+G2dnZ28vb1d+dSn/uKprVu33qPrGlMUhQOAZVkUgHXw4MGNX/rSl/6xs7OT79ixQy1A5wIFIAiRK1cGCCEkWVes317t0ZBOmzIlJdyqSqMpgb6xyFoAZdn+jleqsQQA9ld/9Vf/Z1FDw3gymYTH45HZRYUsGo3ynp6eG++///6LbrvtNrOQIblQAYgX+cDWDXXPLfarImGZJMYFVEbgdDis47NcHjw9fRkA0t39ys6xo6NDtLe3k9WrVw9dd92HvlFTW8vSacNyOp0wTYMoCiOjo2Pub37zm9+RUvq/+93vkkJUfIECkBDCAaDK69zb6OVjGhUsapgSAHwOB8bjhDx3cvbDAOT3pjrlKwf2Tt7e3q589rOf/e7FmzY+S5miaprOCaHgXFAhuDU0NLTl85///Dd6enqsG264QSlA6AIEIJBZdkMIia+q9jxQ53PIUNq00qDwaIyF45bsG4++TUoZ6Ny+/RU3mxNC5KpVqyQhJPnpT3/6r5cvWxqKRuPweLzSsiwQQpRIJGJ2dXX92be//e3P3Hbbbeb/1NamAgDx5kwMb1u7qLPZz0g8naYRw4CDEqKqmjgWNIpfGAm9K+sDvuLz3L59O29vb1cuueSSPVdddeVfNzTUsXg8YbndHpiWCcYYi0aj5De/+c3XbrnllqYCNXOBAnBnSwuHlKSx1PH0Up81rhHJplKGEISg2KXL0QjQfWD0OgCyZWc3eZXjgq1bb71V/eIXv/jLK69ovdvn96pSwlKYAsMwKGNMDg8P+/bs2fOolLIZ557HXJDzEYCEENm+s5sRQqKbFlf+YXGRQ86k0iLBBbwKZXGDyxcGZ6+UUi7v2dnCXy1AduzYYQEgX/na1z6/Yd26Y4lkgum6UwgpYJom1TTNOnToUMP111//q46ODkEyAwwLQckFY4LzouH3bqq7c2utm4hkkkwbBnRFIZqqWQMxzfWH3uHtIETedlsve7UA37VrFyWEDH/+C1+44W1bt5JINAKH7pLJZBIAFNOyrD/cd9+mD3/4wz8AwAkhtADCCwiAhBAOKYnboXSvK1f6Ai6VjsRTPCkFvG6dHZyMyu4jox+RUqo7dmx81YPIbX9w69atPZs3X/LputpaRGMxDlDMzMxACKHE43F+4MCBG/7hH/7h+zYICz7hBSTtXV0KAHQdGP7Ye/7jaan8zaNWxU275ZJb9kjyhYfNa/59t3zyyPBf5L/31crGjRtVAPi7v/u7m7Zs2SpdHn/a5fFLt8cnvb4iWVxSarS0tMhbb731+/nLGAtX5zzXgACA7m4BKUnLmtoHNpUryTpFsCS3xIlYHFR3kKNjUXTvG/uylFJFN15TSdXevXut9vZ25etf//q/v/vd77qvaXGDpjBm6roTiqJCYUwdHDxl3nvvvZ/ZuXPn90OhUFFHR4coVFLjrT0l/xVnMFpaFLS0zGxcUvxfByb4X+6bSgudUWpaFgMoPzSeXtS9f/Cmjo7W9ur37lUBmK9hQDonhFhSyg+Mjoz+luCpa2dmZjljKosn4ognkurx48etcDj8mbGxsat+/vOfv/vjH//4sW3btinZ6uuCnJcaMEvJEELkey5p+urGWj3qEwapYlLW6wxendETwSg/eGL279NpedENmzaZXa/BFBNCZHt7OyWEWN/7/vc/sHz5ivtLSkqYw6HxQFkpGKUIhUJKMBjke/fubXr44Yeff/DBB/+yp6fHamtrYwWa5jwGICFEZtd8jWxdVvSzTQ0ljBppy0clNCJJyALp6ZtmDz7X/6iUcmNra6u169Ah7TVp2/Z2QgixbrzxxvdffvnlJ4uLi5mqqFZpSSl0hwNzc2EWi8XE/v37XT/+yU++88///M+f7ezs5NlqbpIHxkK0fD79Edrb22k3Wmj3zhb/d393YO/9B0MNCdMSiqKy6bSFZCIpVpYw+ieb62ZWLnJftX5p47729i6lo6PVeq17jhOJxNu+/vWv33///fd7k8mkEELQRCKJRDIFv98r3W6nqKyoYq2trfd97GMf+2JVVdWhed9ZASAu5Kms59Wv0AbG/uOT19zz7PADzw2ETBCmCErInCkwG0vyxR6FXVqvhq59+5IbNi1v6ERbG+v67GdJS9aMv9rPmpycfNtXv/rV+59++mlvIhG3pJRKJBqH3+tFaWkJEsmkdDgcpK6uDnV1dc80Njbee+mllz64Zs2afXaPS1tbG+vs7OQFAJ4PIJSSbSeEP/zcwA+fO5G8fs/xCW5KwkAp4hwIxVKiVDHphzYvwpblJTdvXFHXfiatI5UWdOOVANLemP6HP/zhbU888cQDe/bs8czMzFqxWFQpLSmB2+ODaaYhhBCmaVJd1+Hz+eBwOERZWdkLlZWVv7/yyit/dNlllw1l3SFRAOBbXaQkt97Wq9xwwybzF/ft++mBEeMTxycilimJIglBigvEYjHhI2nZuraeraj3/6Eu4P/ZxpU1DxFC5l7tEmcbhKdPn377D37wg2/s3//CxUNDpyVAiN9fBMZIbvu5EEJwzoWUUqGUwuPxoKioKPye97zne5/85Ce/3NbWxlauXHlBDUo/Px1hKQkyI9rk7Q8f6u89lWw+MRmyUoIoGpXwKRZMS8LiQjg0lRZ7VXgcZNrr1o83Lgrs3rKy5lSd3/VjQkhi1y7Jtm8n/JWYYymldtNNN9310MOPXTs5OSldTp16vR7ougZK2fxxwZJzLizOlUUNDVi0aNE3v/rVr37hjdxeXgDg6+wPHm5rkx8fnlj51IGJR45OGBUDExFpckFKHASSS0RSBmYSaT4dT0lDCIVQinKfE4vKPFhayvb+2ZVLP1BfXz/a3tWldLSeO1i59dZb1RtuuMH8zne+s/6OO3+77/TpIcEYpZQAbo8LCmOwLAuWlTmMEAKcc3DOZTKZFA6Hg1188cVdHR0dn1i6dOlIe3s7vRA04XlbTJndE8eWbN9+6EBfX4uk2v2DM8n6cNqQ8bBBNXBYlgXDshgoBRdSMkDORVPiWDyN0JSySWcDBydDoesriovvAtopcHZAPPLIIwIAmZqacrldDjgdDphCwjJSGD59GrF4HKqqQlU1CMHBGIPucMDr8ZDa2loWDAate+65p1VRlG4p5aWEkNkLQROe19W827dv59+8r19fu3xp3/978NhPdYejnSYtk6ouapkG0lwiKSUsKqBqKtEVQtwKo25NBVco7zqeKJ6848iuZ06Gfri5seivgJ0UgDwHKGRpaSlRFCa9Ppc0TAtjoSmEIxGs33ARWluugKqrgBCIxqLwer0oC5TB7XQjlUoq3//e9/lTTz3VdMstt5QCmM6OCS4A8K0sh4cjor1d0nhkj1LkVDETEpCSIqXomDQp5swwuJkGBIciLMSZhA4JlYExIuWhI4fIZEJ8ZvaKJnbtmuod7RkSWS5g8iUhBB/+8Idjx471k9HRUeL1uKRhpElVdTW2b/8wYrEYxsfGoOkaIARmpmdx8OBBxKNRXPcnf4IPfPAD7NZbb+UPPPCABQAdHR0omOC3uGwEcEMHEd+74zmlxKnKuFfHeIJjKBLDxP5HsSKgYcmiWvBUHFYyDmkkUVFagtJiP7wunTwXPYG7f3nMaq75/J9LKb9JCDkspaQ2hzdvbg2pqKh44ec///nXZmdnvnjy5EkJSFFRUUEDgQB6enrw9DPPwOtxo3FxI9KpNEaGR0ApRe/z+8AYRXFxMXv729+u7d69G4VihPNI6itLZsJDUeLTiIwyF2b2PYWlyT58eMNVSBlRcM0E86sIh+PQlQRCQyMwXE5sv/ZycvJX3XRudooCKALOOfpNtrW1sY9//ONf2rVr17Hdu3f/1+DgIBkdGbHGx8fo4sVNiCeSxOlwEEIAr8eH8kA5JIB4PCZisThtamo69LWvfe3k3Nyceuutt1rnGLheAOBbQXbs2Gjt2CFJNBr9cSQW+xvJ3VWTIS54cJBuWrUYPr8ft//XnZienITP50NDQz1OD53GyPAoqiqrUFxcDJ/PC0VRgWzuvA3nnrKQpWV+vHfv3qOnTp366XPPPbv0Jz/5Ma644hrU1dTCtExBKKGMUoBQMEqgqirxeL2iob6h/KGHHtt82223PR4KhRgAXgDgW7xQQUpJfT7ftJSy5aFnjv96eP/cRarqssbGJ5SS4hKUFJWAgUDXdSSTaVSUV6GqsgaKquHA4WOSOppJcVHxIIAT2UJT8UoqqTdt2vSMlPKKz33uc/94cmBgM6FCbN166Yqp6Wnn+MSExS2uMIUBUiJD2ACh0Fx57/N77/vpL37x0U9+7GO/a29vV3bu3Cnmm/wCD4i3Gjcts31DknTuPvXcL7r6N91z27+YH2pZzQJ+L2angpIQwaiiglEGQiQoZWCKyjVfNdt0yYZf/8X2d/7pqyGKbYI6/7Whyckljz/62Hdi0dg1x/sHuGGmWQZ7FIQAlFKpqiqpqqpCaUnJtz7+8Y9+/nzOF19QJUFdXV1Ka3e3kDt3Nv/8qcGbH9/bt31i4AA2LymHkg5jZGxEpA2TUsbACAEBAVEUSCGF3+tBbVX5v372szu+RgiJLRSI4CxVOh0dHSSrNQkAIaXUH3jgwZ8PDp5uOz00zKPRKFEUhRICMMagKIoECHc4daWysuK3n9mx4wuEkNPt7e1KdpxcAYBvdU2Yfbx11gScAH3ovntvGBuf+NipwdM8EksQVWGUEAIQAsoYICGLfR6yYkXz89vb2q4mhMy8FkBkgSsByN///vc7ZkPhW/v6jiEcDgvGKFUUBYwxMKaCc9Pyet1Kkd8/sHbt2mtbWlqOn28ZkguyKDIfBPmvP/DAw18Kh8NfOXy0D7OzIUEopZQQAASUAEJw0+l0qOXlZfs2rF93dWtr6/RrBCG57bbblBtuuME8dOjojt7n9/7ziRODgVAoZKkKVRijWf+VgnPTAqA0NDSkli9f/rmrr776hwuZ9kIQ8hacNb1LSobOTrS1teG2226j73znVV/du3dvJB6P/ZPCWMVkcIoLQhilFIJLECLVeDzGBwfjG0yTP79nz56/vfjii+94tSDMgt9sb29XVq9ecdvTT3c9pKrqoxMTwcUTE+Om1+MiiqKAUQWKwihlzDIMQ4tEIrcFR4N95TXlT7xSF6CgAfGWqqpWOjo6rN/97v5VkejsI8NDI5XjE5OWkFIhhABCgFCAEsIJpay8okx43f7tf/3Xn73ztQLCLueSUtb9+te/7kilUp9yuz1QVQVSAoZhgBACzk2UlQWwYsWKlvr6+h4pJbOnhBU04HkiHR0d1t69e9VNmzYdHhgYuMrr8dyrKGzR+PiEACGUUhWKwiSlFJQSIxlPwuP2/vrxxx+/iRDyb6/FNLa2tlrZZqdhAH/+5JNPnkgmk426rkPX9Vh/f/9vGGPS4/ESn8+XqK+vP5A/oq6gAc9fH1FIKd2/+tWvvz8Xnvu4kTaE7nBQxhg8bjcIJRCco7i4GIZh/fKDH3z/x2xt9lp7Wnbu3CkvlDrAggZ8GR9x165djBASB/CJrq7H3LFY7EOEMEkIQlNTU/crigKnUxcej4cA+Dbw4gD119rf3NHRga6uLqW/v58AwNKlS+VU3uLFtrY2eb4S0gUpSEEKUpCCFKQgBSlIQQpSkIIUpCAFKUhBClKQghSkIOef/P+EJe1R0GiVQgAAAABJRU5ErkJggg==",ButtonPanel:"data:image/png;base64,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",BoilerInterface:"data:image/png;base64,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"};const m4="data:image/svg+xml,"+encodeURIComponent(''),b4=Object.assign({},y4);const w4={autoResize:!0,height:"100%",nodes:{shape:"box",color:{background:"#edf2f8",border:"#c9d5e4",highlight:{background:"#dce9f8",border:"#5288bd"}},font:{size:14,face:"system-ui, sans-serif",color:"#26364a"},margin:{top:14,bottom:14,left:18,right:18},widthConstraint:{minimum:100,maximum:160},borderWidth:1,shapeProperties:{borderRadius:12}},groups:{Controller:{color:{background:"#dceee6",border:"#91bba7"}},RoomStat:{color:{background:"#eee6f2",border:"#c9b3d5"}},iTRV:{color:{background:"#f7eadc",border:"#d9bc98"}},SmartPlug:{color:{background:"#dceef0",border:"#94bec4"}},HeatingActuator:{color:{background:"#e1e9fa",border:"#aabce0"}},UnderFloorHeating:{color:{background:"#e1e9fa",border:"#aabce0"}},Shutter:{color:{background:"#e7ebef",border:"#b4bec9"}},OnOffLight:{color:{background:"#f5efd9",border:"#d6c68e"}},DimmableLight:{color:{background:"#f5efd9",border:"#d6c68e"}}},edges:{arrows:{to:{enabled:!0,scaleFactor:.45}},color:{color:"#8a9bac",highlight:"#5288bd",hover:"#5288bd",inherit:!1},smooth:{enabled:!0,type:"cubicBezier",forceDirection:"horizontal",roundness:.45},width:1.5,font:{align:"horizontal",color:"#66788a",size:11,face:"system-ui, sans-serif",strokeWidth:0}},interaction:{hover:!0,dragView:!0,dragNodes:!0,selectConnectedEdges:!0,zoomView:!0,keyboard:!1},physics:{enabled:!1}};const A4="data:image/svg+xml,"+encodeURIComponent('');async function k4(t,e,i){const n=i||(await t.callWS({type:"wiser/hubs"}))[0];if(!n)return;const[o,r]=await Promise.all([t.callWS({type:"config/entity_registry/list"}),t.callWS({type:"config/device_registry/list"})]),s=new Set(r.filter((t=>t.identifiers.some((([t,e])=>"wiser"===t&&e===n)))).map((t=>t.id))),a=o.filter((i=>{if("wiser"!==i.platform||!i.entity_id.startsWith("sensor."))return!1;const o=t.states[i.entity_id],a=null==o?void 0:o.attributes;if(!a||null==a.node_id||Number(a.node_id)!==e.id||void 0===a.displayed_signal_strength)return!1;if("Controller"!==e.group&&a.product_type!==e.group)return!1;const l=r.find((t=>t.id===i.device_id));return!!l&&(s.has(l.id)||null!=l.via_device_id&&s.has(l.via_device_id)||l.identifiers.some((([t,e])=>"wiser"===t&&e.startsWith(`${n} Wiser `))))}));return 1===a.length?a[0].entity_id:void 0}function E4(t,e){const i=t=>"number"==typeof t&&Number.isFinite(t);return 0===t&&0===e?{}:{rssi:i(t)?t:void 0,lqi:i(e)?e:void 0}}function C4(t,e="horizontal",i,n="none"){var o,r;const s=new Map,a=t.nodes.filter((t=>"Controller"===t.group)),l=(a.length?a:t.nodes.slice(0,1)).map((t=>t.id));l.forEach((t=>s.set(t,0)));for(let e=0;e"Area"!==t.group)),s=new Map(r.map((t=>[t.id,t]))),a=new Map,l=new Map;for(const e of r){const n=t.edges.find((t=>t.from===e.id&&s.has(t.to)&&i.has(t.to)&&i.has(e.id)&&i.get(t.to){var i;const n=c.get(t);if(n)return n;const o=null!==(i=a.get(t))&&void 0!==i?i:[],r=Math.max(e?115:65,4*ai(s.get(t).label).length+30),l=Math.max(0,...o.map((t=>d(t).radius))),u=o.length?Math.max(r+l+h,o.length>1?(l+h/2)/Math.sin(Math.PI/o.length):0):0,f={radius:u+(o.length?l:r),orbit:u};return c.set(t,f),f},u=[],f=(t,e,i,o)=>{var r;u.push(Object.assign(Object.assign({},s.get(t)),{x:e,y:i}));const l=[...null!==(r=a.get(t))&&void 0!==r?r:[]],h=null==n?void 0:n[t],c=t=>{const e=null==n?void 0:n[t];if(e&&h)return((Math.atan2(e.y-h.y,e.x-h.x)-o)%(2*Math.PI)+2*Math.PI)%(2*Math.PI)};l.sort(((t,e)=>{const i=Number(a.has(e))-Number(a.has(t));if(i)return i;const n=c(t),o=c(e);return void 0!==n&&void 0!==o&&Math.abs(n-o)>1e-6?n-o:s.get(t).label.localeCompare(s.get(e).label)})),l.forEach(((n,r)=>{const s=o+2*r*Math.PI/l.length,a=d(t).orbit;f(n,e+Math.cos(s)*a,i+Math.sin(s)*a,s)}))},p=r.filter((t=>!l.has(t.id))).sort(((t,e)=>Number("Controller"===e.group)-Number("Controller"===t.group)||t.label.localeCompare(e.label)));let v=0;if(p.forEach(((t,e)=>{const i=d(t.id).radius,n=e?v+i+h:0;f(t.id,n,0,0),v=n+i})),e)for(const[t,e]of a){const i=u.find((e=>e.id===t)),n=(t,e=t.x,i=t.y)=>{const n=ai(t.label),o=Math.max(40,4.5*n.length+12);return{left:e-o,right:e+o,top:i-42,bottom:i+72}},o=(t,e)=>t.lefte.left&&t.tope.top;for(const t of e.filter((t=>!a.has(t)))){const r=u.find((e=>e.id===t));if(!r.area_id)continue;const l=e.filter((t=>a.has(t)&&s.get(t).area_id===r.area_id)).map((t=>u.find((e=>e.id===t)))).sort(((t,e)=>Math.hypot(t.x-r.x,t.y-r.y)-Math.hypot(e.x-r.x,e.y-r.y)));let h=!1;for(const t of l){const e=Math.atan2(t.y-i.y,t.x-i.x),s=Math.max(150,(n(t).right-n(t).left+n(r).right-n(r).left)/2+20),l=[0,1,2,3].map((t=>({inward:s+90*t,side:65})));for(let t=1;t<5;t++)for(const e of[1,0,2])l.push({inward:s+90*e,side:65+130*t});for(const s of l){if(h)break;for(const l of[1,-1]){const c=s.inward,d=l*s.side,f=t.x-Math.cos(e)*c-Math.sin(e)*d,p=t.y-Math.sin(e)*c+Math.cos(e)*d,v=n(r,f,p);if(u.some((t=>t.id!==r.id&&("Controller"===t.group||a.has(t.id)||t.area_id===r.area_id)&&o(v,n(t)))))continue;const g=n(t),y={left:Math.min(v.left,g.left)-18,right:Math.max(v.right,g.right)+18,top:Math.min(v.top,g.top)-110,bottom:Math.max(v.bottom,g.bottom)+18};if(!o(y,n(i))){r.x=f,r.y=p,h=!0;break}}}if(h)break}}}for(const e of t.nodes.filter((t=>"Area"===t.group))){const t=u.filter((t=>{var i,n;return"Controller"!==t.group&&(null!==(i=t.area_id)&&void 0!==i?i:"")===(null!==(n=e.area_id)&&void 0!==n?n:"")}));u.push(Object.assign(Object.assign({},e),{x:t.length?(Math.min(...t.map((t=>t.x)))+Math.max(...t.map((t=>t.x))))/2:0,y:t.length?Math.min(...t.map((t=>t.y)))-110:0}))}return e&&li(u,new Set(a.keys())),{nodes:u,edges:t.edges.map((t=>Object.assign({},t)))}}(t,"area"===n,s,i);const h=new Map,c=Math.max(0,...s.values())+1;for(const e of t.nodes){if("Area"===e.group)continue;const t=null!==(o=s.get(e.id))&&void 0!==o?o:c;h.set(t,[...null!==(r=h.get(t))&&void 0!==r?r:[],e])}const d=[];for(const[o,r]of[...h].sort((([t],[e])=>t-e))){const s="vertical"===e?"x":"y";r.sort(((e,n)=>{var o,r;const a=e=>{var i,n,o;const r=null===(i=t.edges.find((t=>t.from===e)))||void 0===i?void 0:i.to;return null!==(o=null===(n=d.find((t=>t.id===r)))||void 0===n?void 0:n[s])&&void 0!==o?o:0},l=a(e.id)-a(n.id);if(l)return l;const h=null===(o=null==i?void 0:i[e.id])||void 0===o?void 0:o[s],c=null===(r=null==i?void 0:i[n.id])||void 0===r?void 0:r[s];return Number.isFinite(h)&&Number.isFinite(c)&&h!==c?h-c:e.label.localeCompare(n.label)})),r.forEach(((t,i)=>{let s=i-(r.length-1)/2;d.push(Object.assign(Object.assign({},t),{x:"vertical"===e?s*("area"===n?230:170):o*("area"===n?300:270),y:"vertical"===e?o*("area"===n?300:150):s*("area"===n?260:110)}))}))}for(const e of t.nodes.filter((t=>"Area"===t.group))){const t=d.filter((t=>{var i,n;return"Controller"!==t.group&&(null!==(i=t.area_id)&&void 0!==i?i:"")===(null!==(n=e.area_id)&&void 0!==n?n:"")}));d.push(Object.assign(Object.assign({},e),{x:t.length?(Math.min(...t.map((t=>t.x)))+Math.max(...t.map((t=>t.x))))/2:0,y:t.length?Math.min(...t.map((t=>t.y)))-110:0}))}return{nodes:d,edges:t.edges.map((t=>Object.assign({},t)))}}const x4=t=>{class i extends t{connectedCallback(){super.connectedCallback(),this.__checkSubscribed()}disconnectedCallback(){if(super.disconnectedCallback(),this.__unsubs){for(;this.__unsubs.length;){const t=this.__unsubs.pop();t instanceof Promise?t.then((t=>t())):null!=t&&t()}this.__unsubs=void 0}}updated(t){super.updated(t),t.has("hass")&&this.__checkSubscribed()}hassSubscribe(){return[]}__checkSubscribed(){void 0===this.__unsubs&&this.isConnected&&void 0!==this.hass&&(this.__unsubs=this.hassSubscribe())}}return e([Ln({attribute:!1})],i.prototype,"hass",void 0),i};var I4={"common.version":"Version","card.title":"Zigbee network","card.description":"An interactive map of your Wiser Zigbee network","card.hub":"Wiser Hub","card.devices_one":"{count} device","card.devices_other":"{count} devices","card.connections_one":"{count} connection","card.connections_other":"{count} connections","card.controls":"Network controls","card.fit":"Fit view","card.tidy":"Tidy layout","card.link_labels":"Link labels","card.save_layout":"Save layout","card.load_error":"Unable to load the network. Try refreshing.","card.updating":"Updating network…","card.empty":"No devices found","card.unknown_device":"Unknown device","card.hint":"Double-click to zoom in or out. Drag to rearrange. Tap a device for Zigbee details. Long-press for More info.","map.accessible_only":"Interactive Zigbee network map. Double-click a device or empty area to zoom in, and double-click again to zoom out. Drag to rearrange. Tap a device for Zigbee details. Long-press for More info.","map.accessible_list":"Interactive Zigbee network map. Device and connection details are available in the list below. Tap a device for Zigbee details. Long-press for More info.","map.accessible_details":"Interactive Zigbee network map. Tap a device for Zigbee details. Long-press for More info.","layout.storage_error":"Browser storage unavailable. Copy the layout into your card configuration.","layout.device_list":"All devices & connections","editor.auto_update":"Auto refresh","editor.show_device_list":"Show all devices & connections","editor.orientation":"Network view","editor.loading":"Loading Home Assistant controls…","signal.connected":"Connected","signal.online":"Online","signal.offline":"Offline","signal.no_signal":"No signal","signal.very_good":"Very good","signal.good":"Good","signal.poor":"Poor","zigbee.type":"Device type","zigbee.node":"Zigbee node ID","zigbee.parent":"Parent node ID","zigbee.channel":"Zigbee channel","zigbee.signal":"Signal quality","zigbee.device_rssi":"Device RSSI","zigbee.device_lqi":"Device LQI","zigbee.hub_rssi":"Hub RSSI","zigbee.hub_lqi":"Hub LQI","editor.map_height":"Map height","card.show_detailed_view":"Show detailed view","card.zoom_in":"Zoom in","card.zoom_out":"Zoom out","editor.group_by":"Group","card.unassigned_area":"Unassigned","editor.show_labels":"Show link labels","editor.link_status":"Link status","editor.links":"Links","editor.both":"Both","signal.medium":"Medium","layout.config_save_error":"Unable to save this card’s configuration. Use the card editor to save, or copy the layout YAML for a YAML dashboard.","editor.magnifier":"Magnifying glass","editor.lens_size":"Lens size","layout.copy_error":"Unable to copy the layout. Check clipboard permissions and try again.","panel.menu":"Toggle sidebar","panel.settings":"Panel settings","panel.description":"Customize this panel. Dashboard cards keep their own settings.","panel.editor_error":"Unable to open the editor. Close this dialog and try again.","panel.save_error":"Unable to save settings to Home Assistant. Please try again.","layout.paste_error":"Unable to paste these settings. Copy settings and layout from a Wiser Zigbee card or panel first.","layout.paste_save_error":"Unable to save the pasted settings and layout. Nothing has been changed.","layout.paste_hint":"Paste the settings and layout copied from a Wiser Zigbee card or panel below."};const S4={"en-US":I4,"en-GB":{"common.version":"Version","card.title":"Zigbee network","card.description":"An interactive map of your Wiser Zigbee network","card.hub":"Wiser Hub","card.devices_one":"{count} device","card.devices_other":"{count} devices","card.connections_one":"{count} connection","card.connections_other":"{count} connections","card.controls":"Network controls","card.fit":"Fit view","card.tidy":"Tidy layout","card.link_labels":"Link labels","card.save_layout":"Save layout","card.load_error":"Unable to load the network. Try refreshing.","card.updating":"Updating network…","card.empty":"No devices found","card.unknown_device":"Unknown device","card.hint":"Double-click to zoom in or out. Drag to rearrange. Tap a device for Zigbee details. Long-press for More info.","map.accessible_only":"Interactive Zigbee network map. Double-click a device or empty area to zoom in, and double-click again to zoom out. Drag to rearrange. Tap a device for Zigbee details. Long-press for More info.","map.accessible_list":"Interactive Zigbee network map. Device and connection details are available in the list below. Tap a device for Zigbee details. Long-press for More info.","map.accessible_details":"Interactive Zigbee network map. Tap a device for Zigbee details. Long-press for More info.","layout.storage_error":"Browser storage unavailable. Copy the layout into your card configuration.","layout.device_list":"All devices & connections","editor.auto_update":"Auto refresh","editor.show_device_list":"Show all devices & connections","editor.orientation":"Network view","editor.loading":"Loading Home Assistant controls…","signal.connected":"Connected","signal.online":"Online","signal.offline":"Offline","signal.no_signal":"No signal","signal.very_good":"Very good","signal.good":"Good","signal.poor":"Poor","zigbee.type":"Device type","zigbee.node":"Zigbee node ID","zigbee.parent":"Parent node ID","zigbee.channel":"Zigbee channel","zigbee.signal":"Signal quality","zigbee.device_rssi":"Device RSSI","zigbee.device_lqi":"Device LQI","zigbee.hub_rssi":"Hub RSSI","zigbee.hub_lqi":"Hub LQI","editor.map_height":"Map height","card.show_detailed_view":"Show detailed view","card.zoom_in":"Zoom in","card.zoom_out":"Zoom out","editor.group_by":"Group","card.unassigned_area":"Unassigned","editor.show_labels":"Show link labels","editor.link_status":"Link status","editor.links":"Links","editor.both":"Both","signal.medium":"Medium","layout.config_save_error":"Unable to save this card’s configuration. Use the card editor to save, or copy the layout YAML for a YAML dashboard.","editor.magnifier":"Magnifying glass","editor.lens_size":"Lens size","layout.copy_error":"Unable to copy the layout. Check clipboard permissions and try again.","panel.menu":"Toggle sidebar","panel.settings":"Panel settings","panel.description":"Customise this panel. Dashboard cards keep their own settings.","panel.editor_error":"Unable to open the editor. Close this dialogue and try again.","panel.save_error":"Unable to save settings to Home Assistant. Please try again.","layout.paste_error":"Unable to paste these settings. Copy settings and layout from a Wiser Zigbee card or panel first.","layout.paste_save_error":"Unable to save the pasted settings and layout. Nothing has been changed.","layout.paste_hint":"Paste the settings and layout copied from a Wiser Zigbee card or panel below."},de:{"common.version":"Version","card.title":"Zigbee-Netzwerk","card.description":"Eine interaktive Karte Ihres Wiser-Zigbee-Netzwerks","card.hub":"Wiser Hub","card.devices_one":"{count} Gerät","card.devices_other":"{count} Geräte","card.connections_one":"{count} Verbindung","card.connections_other":"{count} Verbindungen","card.controls":"Netzwerksteuerung","card.fit":"Ansicht einpassen","card.tidy":"Layout anordnen","card.link_labels":"Verbindungsbeschriftungen","card.save_layout":"Layout speichern","card.load_error":"Das Netzwerk konnte nicht geladen werden. Bitte aktualisieren.","card.updating":"Netzwerk wird aktualisiert…","card.empty":"Keine Geräte gefunden","card.unknown_device":"Unbekanntes Gerät","card.hint":"Zum Vergrößern oder Verkleinern doppelklicken. Zum Anordnen ziehen. Für Zigbee-Details auf ein Gerät tippen. Für weitere Informationen gedrückt halten.","map.accessible_only":"Interaktive Zigbee-Netzwerkkarte. Zum Vergrößern auf ein Gerät oder eine freie Stelle doppelklicken, zum Verkleinern erneut doppelklicken. Zum Anordnen ziehen. Für Zigbee-Details auf ein Gerät tippen. Für weitere Informationen gedrückt halten.","map.accessible_list":"Interaktive Zigbee-Netzwerkkarte. Geräte- und Verbindungsdetails stehen in der Liste darunter. Für Zigbee-Details auf ein Gerät tippen. Für weitere Informationen gedrückt halten.","map.accessible_details":"Interaktive Zigbee-Netzwerkkarte. Für Zigbee-Details auf ein Gerät tippen. Für weitere Informationen gedrückt halten.","layout.storage_error":"Browserspeicher nicht verfügbar. Kopieren Sie das Layout in Ihre Kartenkonfiguration.","layout.device_list":"Alle Geräte und Verbindungen","editor.auto_update":"Automatisch aktualisieren","editor.show_device_list":"Alle Geräte und Verbindungen anzeigen","editor.orientation":"Netzwerkansicht","editor.loading":"Home-Assistant-Steuerelemente werden geladen…","signal.connected":"Verbunden","signal.online":"Online","signal.offline":"Offline","signal.no_signal":"Kein Signal","signal.very_good":"Sehr gut","signal.good":"Gut","signal.poor":"Schwach","zigbee.type":"Gerätetyp","zigbee.node":"Zigbee-Knoten-ID","zigbee.parent":"Übergeordnete Knoten-ID","zigbee.channel":"Zigbee-Kanal","zigbee.signal":"Signalqualität","zigbee.device_rssi":"Geräte-RSSI","zigbee.device_lqi":"Geräte-LQI","zigbee.hub_rssi":"Hub-RSSI","zigbee.hub_lqi":"Hub-LQI","editor.map_height":"Kartenhöhe","card.show_detailed_view":"Detailansicht anzeigen","card.zoom_in":"Vergrößern","card.zoom_out":"Verkleinern","editor.group_by":"Gruppieren","card.unassigned_area":"Nicht zugewiesen","editor.show_labels":"Verbindungsbeschriftungen anzeigen","editor.link_status":"Verbindungsstatus","editor.links":"Verbindungen","editor.both":"Beides","signal.medium":"Mittel","layout.config_save_error":"Die Kartenkonfiguration konnte nicht gespeichert werden. Speichere im Karteneditor oder kopiere das Layout-YAML für ein YAML-Dashboard.","editor.magnifier":"Lupe","editor.lens_size":"Lupengröße","layout.copy_error":"Das Layout konnte nicht kopiert werden. Prüfe die Berechtigungen für die Zwischenablage und versuche es erneut.","panel.menu":"Seitenleiste umschalten","panel.settings":"Panel-Einstellungen","panel.description":"Dieses Panel anpassen. Dashboard-Karten behalten ihre eigenen Einstellungen.","panel.editor_error":"Der Editor konnte nicht geöffnet werden. Schließe den Dialog und versuche es erneut.","panel.save_error":"Einstellungen konnten nicht in Home Assistant gespeichert werden. Bitte versuche es erneut.","layout.paste_error":"Diese Einstellungen können nicht eingefügt werden. Kopiere zuerst Einstellungen und Layout von einer Wiser-Zigbee-Karte oder einem Panel.","layout.paste_save_error":"Die eingefügten Einstellungen und das Layout konnten nicht gespeichert werden. Es wurde nichts geändert.","layout.paste_hint":"Füge unten die von einer Wiser-Zigbee-Karte oder einem Panel kopierten Einstellungen und das Layout ein."},fr:{"common.version":"Version","card.title":"Réseau Zigbee","card.description":"Une carte interactive de votre réseau Zigbee Wiser","card.hub":"Hub Wiser","card.devices_one":"{count} appareil","card.devices_other":"{count} appareils","card.connections_one":"{count} connexion","card.connections_other":"{count} connexions","card.controls":"Commandes du réseau","card.fit":"Ajuster la vue","card.tidy":"Réorganiser la disposition","card.link_labels":"Libellés des connexions","card.save_layout":"Enregistrer la disposition","card.load_error":"Impossible de charger le réseau. Essayez de l’actualiser.","card.updating":"Actualisation du réseau…","card.empty":"Aucun appareil trouvé","card.unknown_device":"Appareil inconnu","card.hint":"Double-cliquez pour zoomer ou dézoomer. Faites glisser pour réorganiser. Appuyez sur un appareil pour afficher ses détails Zigbee. Maintenez-le enfoncé pour afficher Plus d’informations.","map.accessible_only":"Carte interactive du réseau Zigbee. Double-cliquez sur un appareil ou une zone vide pour zoomer, puis à nouveau pour dézoomer. Faites glisser pour réorganiser. Appuyez sur un appareil pour afficher ses détails Zigbee. Maintenez-le enfoncé pour afficher Plus d’informations.","map.accessible_list":"Carte interactive du réseau Zigbee. Les détails des appareils et des connexions figurent dans la liste ci-dessous. Appuyez sur un appareil pour afficher ses détails Zigbee. Maintenez-le enfoncé pour afficher Plus d’informations.","map.accessible_details":"Carte interactive du réseau Zigbee. Appuyez sur un appareil pour afficher ses détails Zigbee. Maintenez-le enfoncé pour afficher Plus d’informations.","layout.storage_error":"Stockage du navigateur indisponible. Copiez la disposition dans la configuration de votre carte.","layout.device_list":"Tous les appareils et connexions","editor.auto_update":"Actualisation automatique","editor.show_device_list":"Afficher tous les appareils et connexions","editor.orientation":"Vue du réseau","editor.loading":"Chargement des commandes Home Assistant…","signal.connected":"Connecté","signal.online":"En ligne","signal.offline":"Hors ligne","signal.no_signal":"Aucun signal","signal.very_good":"Très bon","signal.good":"Bon","signal.poor":"Faible","zigbee.type":"Type d’appareil","zigbee.node":"ID du nœud Zigbee","zigbee.parent":"ID du nœud parent","zigbee.channel":"Canal Zigbee","zigbee.signal":"Qualité du signal","zigbee.device_rssi":"RSSI de l’appareil","zigbee.device_lqi":"LQI de l’appareil","zigbee.hub_rssi":"RSSI du hub","zigbee.hub_lqi":"LQI du hub","editor.map_height":"Hauteur de la carte","card.show_detailed_view":"Afficher la vue détaillée","card.zoom_in":"Zoom avant","card.zoom_out":"Zoom arrière","editor.group_by":"Grouper","card.unassigned_area":"Non attribué","editor.show_labels":"Afficher les libellés des liaisons","editor.link_status":"État des liaisons","editor.links":"Liaisons","editor.both":"Les deux","signal.medium":"Moyenne","layout.config_save_error":"Impossible d’enregistrer la configuration de cette carte. Utilisez l’éditeur de carte ou copiez le YAML de disposition pour un tableau de bord YAML.","editor.magnifier":"Loupe","editor.lens_size":"Taille de la loupe","layout.copy_error":"Impossible de copier la disposition. Vérifiez les autorisations du presse-papiers et réessayez.","panel.menu":"Afficher ou masquer la barre latérale","panel.settings":"Paramètres du panneau","panel.description":"Personnalisez ce panneau. Les cartes du tableau de bord conservent leurs propres paramètres.","panel.editor_error":"Impossible d’ouvrir l’éditeur. Fermez cette boîte de dialogue et réessayez.","panel.save_error":"Impossible d’enregistrer les paramètres dans Home Assistant. Veuillez réessayer.","layout.paste_error":"Impossible de coller ces paramètres. Copiez d’abord les paramètres et la disposition d’une carte ou d’un panneau Wiser Zigbee.","layout.paste_save_error":"Impossible d’enregistrer les paramètres et la disposition collés. Aucune modification n’a été effectuée.","layout.paste_hint":"Collez ci-dessous les paramètres et la disposition copiés depuis une carte ou un panneau Wiser Zigbee."}},M4={"panel.cancel":"ui.common.cancel","panel.retry":"ui.common.retry","common.copy":"ui.common.copy","common.paste":"ui.panel.lovelace.editor.card.generic.paste","editor.theme_mode":"ui.panel.lovelace.editor.card.map.theme_mode","editor.theme_auto":"ui.panel.lovelace.editor.card.map.theme_modes.auto","editor.theme_dark":"ui.panel.lovelace.editor.card.map.theme_modes.dark","editor.theme_light":"ui.panel.lovelace.editor.card.map.theme_modes.light","common.copied":"ui.common.copied","common.saved":"ui.common.successfully_saved","editor.icons":"ui.panel.lovelace.editor.features.types.climate-preset-modes.style_list.icons","editor.pie":"ui.panel.lovelace.editor.card.energy-devices-graph.mode_options.pie","common.invalid_configuration":"ui.panel.lovelace.editor.condition-editor.visibility_status.invalid.headline","editor.none":"ui.common.none","editor.area":"ui.panel.lovelace.editor.card.area.name","common.refresh":"ui.common.refresh","common.close":"ui.common.close","common.save":"ui.common.save","common.title":"ui.panel.lovelace.editor.card.generic.title","common.loading":"ui.init.loading","editor.horizontal":"ui.panel.lovelace.editor.card.tile.content_layout_options.horizontal","editor.vertical":"ui.panel.lovelace.editor.card.tile.content_layout_options.vertical","signal.unknown":"state.default.unknown"},O4={"zigbee.type":"ui.panel.config.zha.visualization.device_type","card.unassigned_area":"ui.panel.config.automation.editor.unassigned","signal.medium":"ui.panel.config.matter.visualization.strength.medium","common.version":"ui.panel.config.zwave_js.visualization.version","card.empty":"ui.panel.config.zha.groups.no_devices_found","card.unknown_device":"ui.panel.config.integrations.config_entry.unknown_via_device","signal.connected":"ui.panel.config.serial.connected","signal.online":"ui.panel.config.zha.configuration_page.status_online","signal.offline":"ui.panel.config.zha.configuration_page.status_offline"},D4=[...new Set(Object.values(Object.assign(Object.assign({},M4),O4)).map((t=>{var e;return null===(e=/^ui\.panel\.([^.]+)\./.exec(t))||void 0===e?void 0:e[1]})).filter((t=>!!t)))];function R4(t){var e;const i=((null===(e=null==t?void 0:t.locale)||void 0===e?void 0:e.language)||(null==t?void 0:t.language)||("undefined"!=typeof document?document.documentElement.lang:"")||"en-US").replace(/_/g,"-").toLowerCase();return"en-gb"===i?"en-GB":"de"===i||i.startsWith("de-")?"de":"fr"===i||i.startsWith("fr-")?"fr":"en-US"}function B4(t,e,i={}){var n;const o=R4(e);let r;const s=M4[t]||O4[t];if(s){const i=null===(n=null==e?void 0:e.localize)||void 0===n?void 0:n.call(e,s);if(i&&i!==s&&(r=i),M4[t])return null!=r?r:""}return r||(r=S4[o][t]||I4[t]||t),r.replace(/\{(\w+)\}/g,((t,e)=>{var n;return String(null!==(n=i[e])&&void 0!==n?n:t)}))}function z4(t,e,i){const n=R4(i);return B4(`card.${t}_${"one"===new Intl.PluralRules(n).select(e)?"one":"other"}`,i,{count:new Intl.NumberFormat(n).format(e)})}function P4(t,e){if(!t)return B4("signal.connected",e);const i=t.match(/^([a-z\s_-]+?)(\s*\([\d.,]+%\))?$/i);if(!i)return t;const n={connected:"connected",online:"online",offline:"offline",nosignal:"no_signal",verygood:"very_good",good:"good",poor:"poor",medium:"medium",unknown:"unknown"}[i[1].replace(/[\s_-]/g,"").toLowerCase()];return n?B4(`signal.${n}`,e)+(i[2]||""):t}function F4(t,e){const i=t.match(/\(([\d.,]+)%\)\s*$/);if(!i)return P4(t,e);const n=Number(i[1].replace(",","."));return!Number.isFinite(n)||n<0||n>100?P4(t,e):new Intl.NumberFormat(R4(e),{style:"percent",maximumFractionDigits:1}).format(n/100)}function T4(t){for(const e of["ha-icon","ha-button","ha-icon-button","ha-tooltip","ha-expansion-panel","ha-button-toggle-group","ha-alert","ha-dropdown","ha-dropdown-item","ha-slider"])customElements.get(e)||customElements.whenDefined(e).then((()=>{t.isConnected&&t.requestUpdate()}))}class N4 extends Bn{constructor(){super(...arguments),this.hideHubSelector=!1,this.hideMapHeight=!1,this._hubs=[],this._formReady=!!customElements.get("ha-form"),this.boundLayoutSaveHandler=this.save_layout.bind(this),this.computeLabel=t=>this.t("name"===t.name?"common.title":"hub"===t.name?"card.hub":"show_detailed_view"===t.name?"card.show_detailed_view":`editor.${t.name}`)}t(t){return B4(t,this.hass)}setConfig(t){var e;this._config=Object.assign(Object.assign({},t),{auto_update:null===(e=t.auto_update)||void 0===e||e}),this.loadNativeForm()}connectedCallback(){super.connectedCallback(),T4(this),window.addEventListener("wiser-zigbee-save-layout",this.boundLayoutSaveHandler)}disconnectedCallback(){window.removeEventListener("wiser-zigbee-save-layout",this.boundLayoutSaveHandler),super.disconnectedCallback()}updated(t){var e;t.has("hass")&&this.hass&&!t.get("hass")&&(e=this.hass,e.callWS({type:"wiser/hubs"})).then((t=>{this._hubs=t})).catch((()=>{this._hubs=[]}))}async loadNativeForm(){if(customElements.get("ha-form"))this._formReady=!0;else{if(this.loadingForm)return this.loadingForm;this.loadingForm=(async()=>{const t=(await window.loadCardHelpers()).createCardElement({type:"button"});await t.constructor.getConfigElement(),await customElements.whenDefined("ha-form"),this._formReady=!0})();try{await this.loadingForm}catch(t){this.loadingForm=void 0}}}render(){var t,e,i,n,o,r,s,a,l,h,c;if(!this.hass||!this._config)return qi``;if(!this._formReady)return qi`

${this.t("editor.loading")}

`;const d=[...new Set([...this._hubs,...this._config.hub?[this._config.hub]:[]])],u=Object.assign(Object.assign({},this._config),{hub:this._config.hub||this._hubs[0],name:null!==(t=this._config.name)&&void 0!==t?t:this.t("card.title"),theme_mode:null!==(e=this._config.theme_mode)&&void 0!==e?e:"auto",show_detailed_view:!(null!==(i=this._config.map_only)&&void 0!==i&&i),map_height:null!==(n=this._config.map_height)&&void 0!==n?n:null,show_device_list:null===(o=this._config.show_device_list)||void 0===o||o,show_labels:null!==(r=this._config.show_labels)&&void 0!==r&&r,magnifier:null!==(s=this._config.magnifier)&&void 0!==s&&s}),f=[{name:"hub",required:!0,disabled:0===d.length,selector:{select:{options:d,mode:"dropdown"}}},{name:"name",selector:{text:{}}},{name:"map_height",selector:{number:{min:100,max:2e3,step:1,mode:"box",unit_of_measurement:"px"}}}],p=[{name:"show_labels",selector:{boolean:{}}},{name:"magnifier",selector:{boolean:{}}},{name:"auto_update",selector:{boolean:{}}},{name:"show_detailed_view",selector:{boolean:{}}},{name:"show_device_list",selector:{boolean:{}},disabled:!u.show_detailed_view}];return qi` "hub"!==t.name)):d} + .data=${u} + .schema=${f.filter((t=>!(this.hideHubSelector&&"hub"===t.name||this.hideMapHeight&&"map_height"===t.name)))} .computeLabel=${this.computeLabel} @value-changed=${this.valueChanged} > ({value:t,label:this.t(`editor.${t}`)})))}}}]} .computeLabel=${this.computeLabel} @value-changed=${this.valueChanged} @@ -145,7 +146,7 @@ function xG(){return xG=Object.assign||function(t){for(var e=1;e({value:t,label:this.t(`editor.${t}`)})))}}}]} .computeLabel=${this.computeLabel} @value-changed=${this.valueChanged} @@ -153,21 +154,29 @@ function xG(){return xG=Object.assign||function(t){for(var e=1;e({value:t,label:this.t(`editor.${t}`)})))}}}]} .computeLabel=${this.computeLabel} @value-changed=${this.valueChanged} > + ({value:t,label:this.t(`editor.theme_${t}`)})))}}}]} + .computeLabel=${this.computeLabel} + @value-changed=${this.valueChanged} + >
- ${u.map((t=>X`qi``))}
-
${this.t("common.version")}: ${"3.0.0-dev.67"}
`}setOrientation(t){var e;this._config&&["horizontal","vertical","pie"].includes(t)&&(null!==(e=this._config.orientation)&&void 0!==e?e:"vertical")!==t&&(this._config=Object.assign(Object.assign({},this._config),{orientation:t}),Gt(this,"config-changed",{config:this._config}))}valueChanged(t){var e,i,o,n;if(t.stopPropagation(),!this._config||!t.detail.value)return;const s=Object.assign({},t.detail.value);"show_detailed_view"in s&&(s.map_only=!s.show_detailed_view,delete s.show_detailed_view),!("map_height"in s)||null!=s.map_height&&""!==s.map_height||(s.map_height=null);const a=Object.assign(Object.assign({},this._config),s);(a.hub||this._hubs[0])===(this._config.hub||this._hubs[0])&&(null!==(e=a.group_by)&&void 0!==e?e:"none")===(null!==(i=this._config.group_by)&&void 0!==i?i:"none")&&(null!==(o=a.orientation)&&void 0!==o?o:"vertical")===(null!==(n=this._config.orientation)&&void 0!==n?n:"vertical")||(delete a.layout_data,delete a.layout_orientation,delete a.layout_group_by),null==this._config.name&&a.name===this.t("card.title")&&delete a.name,this._config=r(a),Gt(this,"config-changed",{config:this._config})}save_layout(t){var e,i,o,n,s,a,l,h,c,d,u,f;this._config&&(null!==(e=t.detail.hub)&&void 0!==e?e:"")===(null!==(i=this._config.hub)&&void 0!==i?i:"")&&(null!==(o=t.detail.orientation)&&void 0!==o?o:"horizontal")===(null!==(n=this._config.orientation)&&void 0!==n?n:"vertical")&&(null!==(s=t.detail.group_by)&&void 0!==s?s:"none")===(null!==(a=this._config.group_by)&&void 0!==a?a:"none")&&(null!==(l=t.detail.layout_id)&&void 0!==l?l:"")===(null!==(h=this._config.layout_id)&&void 0!==h?h:"")&&(null!==(c=t.detail.name)&&void 0!==c?c:"Wiser Zigbee Network")===(null!==(d=this._config.name)&&void 0!==d?d:"Wiser Zigbee Network")&&(this._config=r(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},this._config),"boolean"==typeof t.detail.magnifier?{magnifier:t.detail.magnifier}:{}),"boolean"==typeof t.detail.map_only?{map_only:t.detail.map_only}:{}),"boolean"==typeof t.detail.show_labels?{show_labels:t.detail.show_labels}:{}),t.detail.preferences_only?{}:{layout_data:t.detail.layout_data,orientation:null!==(u=t.detail.orientation)&&void 0!==u?u:"vertical",group_by:null!==(f=t.detail.group_by)&&void 0!==f?f:"none",layout_orientation:void 0,layout_group_by:void 0})),Gt(this,"config-changed",{config:this._config}))}}N3.styles=wt` +
${this.t("common.version")}: ${"3.0.0-dev.84"}
`}setOrientation(t){var e;this._config&&["horizontal","vertical","pie"].includes(t)&&(null!==(e=this._config.orientation)&&void 0!==e?e:"vertical")!==t&&(this._config=Object.assign(Object.assign({},this._config),{orientation:t}),Gn(this,"config-changed",{config:this._config}))}valueChanged(t){var e,i,n,o;if(t.stopPropagation(),!this._config||!t.detail.value)return;const r=Object.assign({},t.detail.value);"show_detailed_view"in r&&(r.map_only=!r.show_detailed_view,delete r.show_detailed_view),!("map_height"in r)||null!=r.map_height&&""!==r.map_height||(r.map_height=null);const s=Object.assign(Object.assign({},this._config),r);(s.hub||this._hubs[0])===(this._config.hub||this._hubs[0])&&(null!==(e=s.group_by)&&void 0!==e?e:"none")===(null!==(i=this._config.group_by)&&void 0!==i?i:"none")&&(null!==(n=s.orientation)&&void 0!==n?n:"vertical")===(null!==(o=this._config.orientation)&&void 0!==o?o:"vertical")||(delete s.layout_data,delete s.layout_orientation,delete s.layout_group_by),null==this._config.name&&s.name===this.t("card.title")&&delete s.name,this._config=ei(s),Gn(this,"config-changed",{config:this._config})}save_layout(t){var e,i,n,o,r,s,a,l,h,c,d,u;this._config&&(null!==(e=t.detail.hub)&&void 0!==e?e:"")===(null!==(i=this._config.hub)&&void 0!==i?i:"")&&(null!==(n=t.detail.orientation)&&void 0!==n?n:"horizontal")===(null!==(o=this._config.orientation)&&void 0!==o?o:"vertical")&&(null!==(r=t.detail.group_by)&&void 0!==r?r:"none")===(null!==(s=this._config.group_by)&&void 0!==s?s:"none")&&(null!==(a=t.detail.layout_id)&&void 0!==a?a:"")===(null!==(l=this._config.layout_id)&&void 0!==l?l:"")&&(null!==(h=t.detail.name)&&void 0!==h?h:"Wiser Zigbee Network")===(null!==(c=this._config.name)&&void 0!==c?c:"Wiser Zigbee Network")&&(this._config=ei(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},this._config),"boolean"==typeof t.detail.magnifier?{magnifier:t.detail.magnifier}:{}),"boolean"==typeof t.detail.map_only?{map_only:t.detail.map_only}:{}),"boolean"==typeof t.detail.show_labels?{show_labels:t.detail.show_labels}:{}),t.detail.preferences_only?{}:{layout_data:t.detail.layout_data,orientation:null!==(d=t.detail.orientation)&&void 0!==d?d:"vertical",group_by:null!==(u=t.detail.group_by)&&void 0!==u?u:"none",layout_orientation:void 0,layout_group_by:void 0})),Gn(this,"config-changed",{config:this._config}))}}N4.styles=mn` :host { color: var(--primary-text-color); } @@ -184,11 +193,39 @@ function xG(){return xG=Object.assign||function(t){for(var e=1;e{this.dispatchEvent(new CustomEvent("hass-toggle-menu",{bubbles:!0,composed:!0}))})),this.shadowRoot.getElementById("settings").addEventListener("click",(()=>this._openEditor())),this.shadowRoot.getElementById("cancel").addEventListener("click",(()=>this._closeEditor())),this.shadowRoot.getElementById("save").addEventListener("click",(()=>this._saveEditor())),this.shadowRoot.getElementById("editor-dialog").addEventListener("closed",(()=>this._closeEditor())),this.shadowRoot.getElementById("editor-dialog").addEventListener("close-dialog",(()=>this._closeEditor())),this._editors=[],this._cards=[],this._generation=0}_t(t){return B3(t,this._hass)}set hass(t){this._hass=t,this._localizeControls();for(const e of this._cards)e.hass=t;for(const e of this._editors)e.hass=t;this.shadowRoot.getElementById("settings").hidden=!t?.user?.is_admin}_localizeControls(){const t=this.shadowRoot;for(const[e,i]of[["menu","panel.menu"],["settings","panel.settings"]])t.getElementById(e).setAttribute("aria-label",this._t(i)),t.getElementById(e).title=this._t(i);t.getElementById("cancel").textContent=this._t("panel.cancel"),t.getElementById("save").textContent=this._t("common.save"),t.getElementById("editor-description").textContent=this._t("panel.description");const e=t.getElementById("editor-dialog");e.setAttribute("header-title",this._t("panel.settings")),e.heading=this._t("panel.settings")}set panel(t){const e=t.config;JSON.stringify(e)!==JSON.stringify(this._config)&&(this._config=e,this._loadCards())}_cardConfig(t){return{layout_id:`wiser-zigbee-panel:${t}`,...this._config.card_configs?.[t],type:"custom:wiser-zigbee-card",hub:t}}async saveZigbeeCardConfig(t,e){if(!this._hass?.user?.is_admin||!this._cards.includes(t))throw new Error("Only administrators can save panel settings");const i=this._config.hubs[this._cards.indexOf(t)],o={...e,type:"custom:wiser-zigbee-card",hub:i};return await this._hass.callWS({type:"wiser/zigbee_panel/configure",configs:{[i]:o}}),this._config={...this._config,card_configs:{...this._config.card_configs,[i]:o}},o}_selectHub(t){this._activeHub=t,this._cards.forEach(((e,i)=>{const o=this._config.hubs[i]===t;e.hidden=!o,this._tabs[i].setAttribute("aria-selected",String(o)),this._tabs[i].tabIndex=o?0:-1}))}_renderHubTabs(){const t=this._config.hubs,e=this.shadowRoot.getElementById("hub-tabs");e.hidden=0===t.length,this._tabs=t.map(((e,i)=>{const o=document.createElement("ha-button");o.setAttribute("appearance","plain"),o.className="hub-tab",o.textContent=e,o.id=`hub-tab-${i}`,o.setAttribute("role","tab"),o.setAttribute("aria-controls",`hub-panel-${i}`),o.addEventListener("click",(()=>this._selectHub(e))),o.addEventListener("keydown",(e=>{let o;if("ArrowRight"===e.key)o=(i+1)%t.length;else if("ArrowLeft"===e.key)o=(i+t.length-1)%t.length;else if("Home"===e.key)o=0;else{if("End"!==e.key)return;o=t.length-1}e.preventDefault(),this._selectHub(t[o]),this._tabs[o].focus()}));const n=this._cards[i];return n.id=`hub-panel-${i}`,n.setAttribute("role","tabpanel"),n.setAttribute("aria-labelledby",o.id),o})),e.replaceChildren(...this._tabs),this._selectHub(t.includes(this._activeHub)?this._activeHub:t[0])}_closeEditor(){this.shadowRoot.getElementById("editor-dialog").open=!1,this._editors=[],this.shadowRoot.getElementById("editors").replaceChildren()}async _openEditor(){const t=this.shadowRoot.getElementById("editor-dialog");if(t.open||!this._cards.length||!this._hass?.user?.is_admin)return;const e=this.shadowRoot.getElementById("editors"),i=this.shadowRoot.getElementById("editor-error"),o=this.shadowRoot.getElementById("save");this._drafts={},this._editors=[],i.textContent="",e.replaceChildren(),o.disabled=!0,t.heading=this._t("panel.settings"),"headerTitle"in(customElements.get("ha-dialog")?.prototype||{})||this.shadowRoot.getElementById("editor-actions").removeAttribute("slot"),t.open=!0;try{if(!window.loadCardHelpers){const t=document.createElement("partial-panel-resolver"),e=t._getRoutes?.({lovelace:{component_name:"lovelace",url_path:"lovelace"}});await(e?.routes?.lovelace?.load?.())}const i=customElements.get("wiser-zigbee-card");for(const o of this._config.hubs){const n=await i.getConfigElement();if(!t.open)return;const r=this._cardConfig(o);this._drafts[o]=r,n.hass=this._hass,n.hideHubSelector=!0,n.setConfig({...r}),n.addEventListener("config-changed",(t=>{t.stopPropagation(),this._drafts[o]={...t.detail.config,type:"custom:wiser-zigbee-card",hub:o}}));const s=document.createElement("section"),a=document.createElement("h3");a.textContent=o,s.replaceChildren(...this._config.hubs.length>1?[a,n]:[n]),e.append(s),this._editors.push(n)}o.disabled=!1}catch(t){i.textContent=this._t("panel.editor_error"),console.error("Unable to open Wiser editor",t)}}async _saveEditor(){const t=this.shadowRoot.getElementById("save");t.disabled=!0;try{await this._hass.callWS({type:"wiser/zigbee_panel/configure",configs:this._drafts}),this._config={...this._config,card_configs:{...this._config.card_configs,...this._drafts}},this._closeEditor(),this._editors=[],this._loadCards()}catch(t){this.shadowRoot.getElementById("editor-error").textContent=this._t("panel.save_error"),console.error("Unable to save Wiser panel settings",t)}finally{t.disabled=!1}}async _loadCards(){const t=++this._generation,e=this._config,i=this.shadowRoot.querySelector("main");try{const o=customElements.get("wiser-zigbee-card");if(1!==o?.panelApiVersion)throw new Error("Wiser Zigbee needs its matching Zigbee card build. Update the card resource and refresh the browser.");if(t!==this._generation)return;const n=e.hubs.map((t=>{const e=document.createElement("wiser-zigbee-card");return e.setConfig(this._cardConfig(t)),e.hass=this._hass,e}));this._cards=n,i.replaceChildren(...n),this._renderHubTabs(),this.shadowRoot.getElementById("settings").disabled=!n.length}catch(e){if(t!==this._generation)return;this._cards=[],this.shadowRoot.getElementById("hub-tabs").hidden=!0,this.shadowRoot.getElementById("settings").disabled=!0;const o=document.createElement("p");o.setAttribute("role","alert"),o.textContent=e.message||"Unable to load Wiser Zigbee network. Please try again.";const n=document.createElement("ha-button");n.textContent=this._t("panel.retry"),n.addEventListener("click",(()=>this._loadCards())),i.replaceChildren(o,n),console.error("Unable to load Wiser Zigbee network",e)}}}function U3(t,e,i=4){return t.lefte.left&&t.tope.top}function L3(t,e,i,o){const n=o?{x:t.x,y:t.y+.45*(e.y-t.y)}:{x:t.x+.45*(e.x-t.x),y:t.y},r=o?{x:e.x,y:e.y+.45*(t.y-e.y)}:{x:e.x+.45*(t.x-e.x),y:e.y},s=1-i;return{x:s*s*s*t.x+3*s*s*i*n.x+3*s*i*i*r.x+i*i*i*e.x,y:s*s*s*t.y+3*s*s*i*n.y+3*s*i*i*r.y+i*i*i*e.y}}customElements.get("wiser-zigbee-panel")||customElements.define("wiser-zigbee-panel",j3),window.customCards=window.customCards||[],window.customCards.some((t=>"wiser-zigbee-card"===t.type))||window.customCards.push({type:"wiser-zigbee-card",name:"Wiser Zigbee Card",description:B3("card.description")});class Q3 extends(S3(Pt)){constructor(){super(...arguments),this.loading=!1,this.error="",this.showLabels=!1,this.savingConfig=!1,this.magnifier=new n,this.magnifierHeld=!1,this.layoutStatus="",this.textColor="",this.statusPalette="",this.displayLanguage="",this.collapsedAreas=new Set,this.areaPositions={},this.infoRequest=0,this.fitAfterHeightChange=!1,this.requestId=0,this.pendingLoad=!0}t(t){return B3(t,this.hass)}deviceName(t){return t?"Controller"===t.group&&"Wiser Hub"===t.label?this.t("card.hub"):t.label.replace(/\n/g," "):this.t("card.unknown_device")}get visibleData(){var t,e;const i=null!==(t=this.mapData)&&void 0!==t?t:this.zigbeeData;return i&&"area"===(null===(e=this.config)||void 0===e?void 0:e.group_by)?function(t,e){const i=t.nodes.filter((t=>{var i;return"Controller"===t.group||"Area"===t.group||!e.has(null!==(i=t.area_id)&&void 0!==i?i:"")})),o=new Set(i.map((t=>t.id)));return{nodes:i,edges:t.edges.filter((t=>o.has(t.from)&&o.has(t.to)))}}(i,this.collapsedAreas):i}static async getConfigElement(){return document.createElement("wiser-zigbee-card-editor")}static getStubConfig(){return{}}setConfig(t){var e,i,o;if(!t)throw new Error(this.t("common.invalid_configuration"));this.magnifier.hide(),this.suppliedConfig=t;const n=Object.assign(Object.assign({},t),{auto_update:null===(e=t.auto_update)||void 0===e||e}),r=this.config,s=this.mapHeight,a=r&&this.network&&[...new Set([...Object.keys(r),...Object.keys(n)])].filter((t=>"map_height"!==t)).every((t=>JSON.stringify(r[t])===JSON.stringify(n[t])));if(this.config=n,this.showLabels=null!==(i=t.show_labels)&&void 0!==i&&i,void 0===t.map_only)try{const t=localStorage.getItem(`${this.layoutKey}:map-only`);null!==t&&(this.config.map_only="true"===t)}catch(t){}if(void 0===t.show_labels)try{this.showLabels="true"===localStorage.getItem(`${this.layoutKey}:labels`)}catch(t){}a?this.fitAfterHeightChange||(this.fitAfterHeightChange=s!==this.mapHeight):(this.cancelDeviceInfo(),this.areaDrag=void 0,this.mapData=void 0,this.collapsedAreas.clear(),this.areaPositions={},this.fitAfterHeightChange=!1,null===(o=this.network)||void 0===o||o.destroy(),this.network=void 0,this.infoReturnView=void 0,this.zoomReturnView=void 0,this.layoutStatus="",this.pendingLoad=!0,this.requestId++)}get orientation(){var t,e;return"pie"===(null===(t=this.config)||void 0===t?void 0:t.orientation)?"pie":"horizontal"===(null===(e=this.config)||void 0===e?void 0:e.orientation)?"horizontal":"vertical"}get mapHeight(){var t;const e=null===(t=this.config)||void 0===t?void 0:t.map_height;return null==e||""===e?null:"number"==typeof e&&Number.isFinite(e)?Math.min(2e3,Math.max(100,Math.round(e))):null}getGridOptions(){var t;return null===this.mapHeight?{columns:12,rows:(null===(t=this.config)||void 0===t?void 0:t.map_only)?6:9,min_rows:3}:{columns:12}}getCardSize(){var t;return(null===(t=this.config)||void 0===t?void 0:t.map_only)?"vertical"===this.orientation?6:8:"vertical"===this.orientation?7:9}hassSubscribe(){return[this.hass.connection.subscribeMessage((t=>{var e;"wiser_updated"===t.event&&(null===(e=this.config)||void 0===e?void 0:e.auto_update)&&!y3(this)&&this.loadData()}),{type:"wiser_updated"})]}connectedCallback(){super.connectedCallback(),T3(this),this.pendingLoad=!0,this.requestUpdate()}disconnectedCallback(){var t;clearTimeout(this.magnifierHoldTimer),this.magnifier.hide(),clearTimeout(this.activeIconTimer),this.activeIcon=void 0,this.cancelDeviceInfo(),super.disconnectedCallback(),this.requestId++,null===(t=this.network)||void 0===t||t.destroy(),this.network=void 0,this.areaDrag=void 0,this.infoReturnView=void 0,this.zoomReturnView=void 0}updated(t){if(super.updated(t),this.positionAreaIcons(),t.has("hass")&&this.network){(getComputedStyle(this).getPropertyValue("--primary-text-color").trim()||"#273448")===this.textColor&&p(getComputedStyle(this))===this.statusPalette&&R3(this.hass)===this.displayLanguage||this.drawNetwork(!0)}this.fitAfterHeightChange&&this.network&&(this.fitAfterHeightChange=!1,this.network.setSize("100%","100%"),this.fitNetwork()),(t.has("selected")||t.has("selectedEntity")||t.has("config"))&&this.focusAboveInfo(),this.pendingLoad&&this.hass&&this.config&&(this.pendingLoad=!1,this.loadData())}async loadData(){var t,e,i,o,n;if(!this.hass||!this.config)return;const r=++this.requestId;this.loading=!0,this.error="";try{let l=await(s=this.hass,a=this.config.hub,s.callWS({type:"wiser/zigbee",hub:a}));"area"===this.config.group_by&&(l=await async function(t,e,i){const[o,n,r,s]=await Promise.all([t.callWS({type:"config/entity_registry/list"}),t.callWS({type:"config/device_registry/list"}),t.callWS({type:"config/area_registry/list"}),i?Promise.resolve([i]):t.callWS({type:"wiser/hubs"})]),a={"config/entity_registry/list":o,"config/device_registry/list":n,"wiser/hubs":s},l=Object.assign(Object.assign({},t),{callWS:async t=>a[t.type]});return Object.assign(Object.assign({},e),{nodes:await Promise.all(e.nodes.map((async t=>{const e=await k3(l,t,s[0]),i=o.find((t=>t.entity_id===e)),a=n.find((t=>t.id===(null==i?void 0:i.device_id))),h=r.find((t=>t.area_id===((null==a?void 0:a.area_id)||(null==i?void 0:i.area_id))));return Object.assign(Object.assign({},t),{area_id:null==h?void 0:h.area_id,area_name:null==h?void 0:h.name,area_icon:null==h?void 0:h.icon})})))})}(this.hass,l,this.config.hub));const h=x3("area"===this.config.group_by?function(t,e){const i=t.nodes.map((t=>Object.assign({},t))),o=new Set(i.map((t=>t.id))),n=[...new Set(i.filter((t=>"Controller"!==t.group)).map((t=>{var e;return null!==(e=t.area_id)&&void 0!==e?e:""})))].sort(),r=t.edges.map((t=>Object.assign({},t)));for(const r of n){const n=t.nodes.filter((t=>{var e;return"Controller"!==t.group&&(null!==(e=t.area_id)&&void 0!==e?e:"")===r}));let s=2166136261;for(const t of r||"__unassigned__")s=Math.imul(s^t.charCodeAt(0),16777619);let a=-(s>>>0)-1;for(;o.has(a);)a--;o.add(a),i.push({id:a,group:"Area",area_id:r,area_icon:n[0].area_icon||"mdi:floor-plan",label:n[0].area_name||e,x:0,y:0})}return{nodes:i,edges:r}}(l,this.t("card.unassigned_area")):l,this.orientation,void 0,this.config.group_by);if(r!==this.requestId||!this.isConnected)return;let c=(null!==(t=this.config.layout_orientation)&&void 0!==t?t:this.orientation)===this.orientation&&(null!==(i=null!==(e=this.config.layout_group_by)&&void 0!==e?e:this.config.group_by)&&void 0!==i?i:"none")===(null!==(o=this.config.group_by)&&void 0!==o?o:"none")?this.config.layout_data:void 0;if(!c||"object"!=typeof c||Array.isArray(c))try{const t=JSON.parse(localStorage.getItem(this.layoutKey)||"null");t&&"object"==typeof t&&!Array.isArray(t)&&(c=t)}catch(t){}const d=Object.assign(Object.assign({},this.areaPositions),null===(n=this.network)||void 0===n?void 0:n.getPositions());h.nodes=h.nodes.map((t=>{var e;return Object.assign(Object.assign({},t),null!==(e=null==d?void 0:d[t.id])&&void 0!==e?e:this.validPosition(c&&"object"==typeof c?c[t.id]:void 0))})),this.zigbeeData="area"===this.config.group_by?l:h,this.mapData=h,await this.updateComplete,this.drawNetwork()}catch(t){r===this.requestId&&(this.error="card.load_error")}finally{r===this.requestId&&(this.loading=!1)}var s,a}drawNetwork(t=!1){var e,i,o,n;if(!this.zigbeeData)return;const r=t?Object.assign(Object.assign({},this.areaPositions),null===(e=this.network)||void 0===e?void 0:e.getPositions()):void 0,s=this.visibleData;t&&"area"===(null===(i=this.config)||void 0===i?void 0:i.group_by)&&(this.areaPositions=null!=r?r:{});const a=getComputedStyle(this).getPropertyValue("--primary-text-color").trim()||"#273448";this.textColor=a;const l=getComputedStyle(this);this.statusPalette=p(l);const h=null!==(n=null===(o=this.config)||void 0===o?void 0:o.link_status)&&void 0!==n?n:"links",u="links"===h||"both"===h,v="icons"===h||"both"===h;this.displayLanguage=R3(this.hass);const g={nodes:s.nodes.map((t=>{var e,i,o,n;const s=function(t,e){if("Controller"===t.group||"Area"===t.group)return!1;const i=e.edges.filter((e=>e.from===t.id));return!i.length||i.every((t=>{const i=t.label.split("(")[0].replace(/[\s_-]/g,"").toLowerCase();return["nosignal","offline","disconnected","noconnection"].includes(i)||!e.nodes.some((e=>e.id===t.to))}))}(t,this.zigbeeData),h=s?"Offline":null===(e=this.zigbeeData.edges.find((e=>e.from===t.id)))||void 0===e?void 0:e.label,u=v&&"Area"!==t.group&&"Controller"!==t.group?f(h,!0,l):void 0,p="Area"===t.group?E3:null!==(i=w3[t.group])&&void 0!==i?i:b3;return Object.assign(Object.assign(Object.assign({},t),null!==(o=null==r?void 0:r[t.id])&&void 0!==o?o:{}),{shape:"image",image:c(p,u,s),brokenImage:c(b3,u,s),size:32,label:"Area"===t.group?`${t.label} ${this.collapsedAreas.has(null!==(n=t.area_id)&&void 0!==n?n:"")?"▸":"▾"}`:"Controller"===t.group?this.deviceName(t):d(t.label),font:{color:a}})})),edges:s.edges.map((t=>{const e=f(t.label,u,l);return Object.assign(Object.assign({},t),{label:"",color:{color:e,highlight:e,hover:e,inherit:!1}})}))};if(this.network){const t={position:this.network.getViewPosition(),scale:this.network.getScale()};this.hoveredEdge=void 0,this.network.setData(g),this.network.moveTo(Object.assign(Object.assign({},t),{animation:!1})),void 0!==this.selected&&g.nodes.some((t=>t.id===this.selected))?this.network.selectNodes([this.selected]):this.selected=void 0}else this.network=new g3(this.shadowRoot.getElementById("zigbee-network"),g,Object.assign(Object.assign({},A3),{edges:Object.assign(Object.assign({},A3.edges),{smooth:{enabled:!0,type:"cubicBezier",forceDirection:"pie"===this.orientation?"none":this.orientation,roundness:.45}})})),this.network.on("hoverEdge",(t=>this.hoverLink(t.edge))),this.network.on("blurEdge",(()=>this.hoverLink())),this.network.on("click",(t=>this.deviceClick(t.nodes[0]))),this.network.on("hold",(t=>this.deviceHold(t.nodes[0]))),this.network.on("doubleClick",(t=>{var e;this.cancelDeviceInfo(),this.toggleDeviceZoom(t.nodes[0],null===(e=t.pointer)||void 0===e?void 0:e.canvas)})),this.network.on("beforeDrawing",(t=>{this.moveAreaDevices(),this.drawAreaGroups(t)})),this.network.on("afterDrawing",(t=>{this.positionAreaIcons(),this.drawLinkLabels(t),this.magnifier.refresh()})),this.network.on("dragStart",(t=>this.startAreaDrag(t.nodes[0]))),this.network.on("dragEnd",(()=>{this.moveAreaDevices(),this.areaDrag=void 0})),this.network.on("resize",(()=>this.fitNetwork())),this.fitNetwork(),this.requestUpdate()}startAreaDrag(t){var e,i,o,n;if(this.closeDeviceInfo(!1),this.areaDrag=void 0,!this.network||"area"!==(null===(e=this.config)||void 0===e?void 0:e.group_by))return;const r=null===(i=this.mapData)||void 0===i?void 0:i.nodes.find((e=>e.id===t&&"Area"===e.group));if(!r)return;const s=this.currentPositions(),a={};for(const t of this.mapData.nodes)"Area"!==t.group&&"Controller"!==t.group&&(null!==(o=t.area_id)&&void 0!==o?o:"")===(null!==(n=r.area_id)&&void 0!==n?n:"")&&s[t.id]&&(a[t.id]=Object.assign({},s[t.id]));this.areaDrag={headerId:r.id,origin:Object.assign({},s[r.id]),members:a,dx:0,dy:0}}moveAreaDevices(){const t=this.areaDrag;if(!t||!this.network)return;const e=this.network.getPositions(),i=e[t.headerId];if(!i)return;const o=i.x-t.origin.x,n=i.y-t.origin.y;if(o!==t.dx||n!==t.dy){t.dx=o,t.dy=n,this.areaPositions[t.headerId]=Object.assign({},i);for(const[i,r]of Object.entries(t.members)){const t={x:r.x+o,y:r.y+n};this.areaPositions[i]=t,e[i]&&this.network.moveNode(Number(i),t.x,t.y)}}}areaBounds(t){var e,i,o;if(!this.network||"area"!==(null===(e=this.config)||void 0===e?void 0:e.group_by))return[];const n=null!==(o=null===(i=this.visibleData)||void 0===i?void 0:i.nodes)&&void 0!==o?o:[],r=null!=t?t:document.createElement("canvas").getContext("2d"),s=this.network.getPositions(),a=new Set(n.filter((t=>"Area"===t.group)).map((t=>{var e;return null!==(e=t.area_id)&&void 0!==e?e:""})));return[...a].map((t=>{const e=n.filter((e=>{var i;return"Controller"!==e.group&&(null!==(i=e.area_id)&&void 0!==i?i:"")===t})),i=e.map((t=>{var e;const i=s[t.id];if(!i)return this.network.getBoundingBox(t.id);const o={left:i.x-32,right:i.x+32,top:i.y-32,bottom:i.y+60};if(!r)return o;const n="Area"===t.group?`${t.label} ${this.collapsedAreas.has(null!==(e=t.area_id)&&void 0!==e?e:"")?"▸":"▾"}`:d(t.label);r.save(),r.font="bold 14px system-ui, sans-serif";const a=n.split("\n"),l=Math.max(...a.map((t=>r.measureText(t).width)))/2;return r.restore(),o.left=Math.min(o.left,i.x-l),o.right=Math.max(o.right,i.x+l),o.bottom=Math.max(o.bottom,i.y+32+14*(a.length+1)),o})),o=e.findIndex((t=>"Area"===t.group)),a=e[o],l=a&&s[a.id],h=i.filter(((t,e)=>e!==o));if(l&&h.length&&!this.areaDrag&&"vertical"===this.orientation){const t=(Math.min(...h.map((t=>t.left)))+Math.max(...h.map((t=>t.right))))/2,e=t-l.x;Math.abs(e)>.01&&(this.network.moveNode(a.id,t,l.y),this.areaPositions[a.id]={x:t,y:l.y},i[o].left+=e,i[o].right+=e)}return{left:Math.min(...i.map((t=>t.left)))-18,right:Math.max(...i.map((t=>t.right)))+18,top:Math.min(...i.map((t=>t.top)))-18,bottom:Math.max(...i.map((t=>t.bottom)))+18}}))}drawAreaGroups(t){const e=this.areaBounds(t);if(!e.length||!this.network)return;const i=getComputedStyle(this).getPropertyValue("--primary-text-color").trim()||this.textColor;t.save();for(const o of e)t.beginPath(),t.roundRect(o.left,o.top,o.right-o.left,o.bottom-o.top,14),t.fillStyle=i,t.globalAlpha=.04,t.fill(),t.strokeStyle=i,t.lineWidth=1/this.network.getScale(),t.globalAlpha=.22,t.stroke();t.restore()}positionAreaIcons(){var t,e;if(!this.network||"area"!==(null===(t=this.config)||void 0===t?void 0:t.group_by))return;const i=this.network.getPositions(),o=64*this.network.getScale();null===(e=this.shadowRoot)||void 0===e||e.querySelectorAll(".area-icons ha-icon").forEach((t=>{const e=i[Number(t.dataset.node)];if(!e)return;const n=this.network.canvasToDOM(e);t.style.left=`${n.x}px`,t.style.top=`${n.y}px`,t.style.width=`${o}px`,t.style.height=`${o}px`,t.style.setProperty("--mdc-icon-size",`${o}px`),t.style.setProperty("--ha-icon-size",`${o}px`)}))}cancelDeviceInfo(){clearTimeout(this.deviceTapTimer),this.deviceTapTimer=void 0,this.infoRequest++,this.selectedEntity=void 0}closeDeviceInfo(t=!0){var e;this.cancelDeviceInfo(),this.selected=void 0;const i=this.infoReturnView;this.infoReturnView=void 0,t&&(null===(e=this.network)||void 0===e||e.unselectAll(),i&&this.network&&(this.zoomReturnView=i.zoomReturnView,this.network.moveTo({position:i.position,scale:i.scale,animation:!1})))}deviceClick(t){clearTimeout(this.deviceTapTimer),void 0!==t?this.deviceTapTimer=setTimeout((()=>{var e,i;const o=null===(e=this.mapData)||void 0===e?void 0:e.nodes.find((e=>e.id===t));"Area"===(null==o?void 0:o.group)?this.toggleArea(null!==(i=o.area_id)&&void 0!==i?i:""):this.showDeviceDetails(t)}),300):this.closeDeviceInfo()}toggleArea(t){var e;this.closeDeviceInfo(!1),this.areaPositions=Object.assign(Object.assign({},this.areaPositions),null===(e=this.network)||void 0===e?void 0:e.getPositions()),this.collapsedAreas.has(t)?this.collapsedAreas.delete(t):this.collapsedAreas.add(t),this.drawNetwork(!0)}async deviceHold(t){var e,i;this.closeDeviceInfo();const o=null===(e=this.zigbeeData)||void 0===e?void 0:e.nodes.find((e=>e.id===t));if(!o||!this.hass)return;const n=this.infoRequest;try{const t=await k3(this.hass,o,null===(i=this.config)||void 0===i?void 0:i.hub);t&&n===this.infoRequest&&this.isConnected&&Gt(this,"hass-more-info",{entityId:t})}catch(t){}}showDeviceDetails(t){void 0!==t?(!this.infoReturnView&&this.network&&(this.infoReturnView={position:this.network.getViewPosition(),scale:this.network.getScale(),zoomReturnView:this.zoomReturnView}),this.cancelDeviceInfo(),this.selected=t,void 0!==t&&this.openDeviceInfo(t,this.infoRequest)):this.closeDeviceInfo()}async openDeviceInfo(t,e){var i,o;const n=null===(i=this.zigbeeData)||void 0===i?void 0:i.nodes.find((e=>e.id===t));if(n&&this.hass)try{const i=await k3(this.hass,n,null===(o=this.config)||void 0===o?void 0:o.hub);i&&e===this.infoRequest&&this.isConnected&&this.selected===t&&(this.selectedEntity=i)}catch(t){}}toggleDeviceZoom(t,e){if(!this.network)return;const i=!window.matchMedia("(prefers-reduced-motion: reduce)").matches&&{duration:250,easingFunction:"easeInOutQuad"};if(this.zoomReturnView)return this.network.moveTo(Object.assign(Object.assign({},this.zoomReturnView),{animation:i})),void(this.zoomReturnView=void 0);if(!(void 0!==t||e&&Number.isFinite(e.x)&&Number.isFinite(e.y)))return;this.zoomReturnView={position:this.network.getViewPosition(),scale:this.network.getScale()};const o=Math.max(2*this.zoomReturnView.scale,1.25);void 0!==t?this.network.focus(t,{scale:o,locked:!1,animation:i}):this.network.moveTo({position:e,scale:o,animation:i})}focusAboveInfo(){var t,e,i;if(!(null===(t=this.config)||void 0===t?void 0:t.map_only)||void 0===this.selected||!this.network)return;const o=null===(e=this.shadowRoot)||void 0===e?void 0:e.getElementById("zigbee-network"),n=null===(i=this.shadowRoot)||void 0===i?void 0:i.querySelector("footer.map-info");if(!o||!n||n.hidden)return;const r=o.getBoundingClientRect(),s=Math.min(r.bottom,n.getBoundingClientRect().top-12);s<=r.top||this.network.focus(this.selected,{scale:this.network.getScale(),offset:{x:0,y:(s-r.top-r.height)/2},locked:!1,animation:!1})}zoomStep(t){this.network&&(this.prepareGestureZoom(),this.network.moveTo({position:this.network.getViewPosition(),scale:Math.min(10,Math.max(.01,this.network.getScale()*t)),animation:!1}))}prepareGestureZoom(){var t;this.network&&(this.closeDeviceInfo(!1),null!==(t=this.zoomReturnView)&&void 0!==t||(this.zoomReturnView={position:this.network.getViewPosition(),scale:this.network.getScale()}))}touchZoomStart(t){t.touches.length>=2&&this.prepareGestureZoom()}panZoomedView(t){if(t.ctrlKey||t.metaKey)return void this.prepareGestureZoom();if(t.stopPropagation(),!this.network||!this.zoomReturnView)return;t.preventDefault();const e=t.currentTarget,i=this.network.getScale(),o=this.network.getViewPosition(),n=1===t.deltaMode?16:2===t.deltaMode?e.clientWidth:1,r=1===t.deltaMode?16:2===t.deltaMode?e.clientHeight:1,s=t.shiftKey&&0===t.deltaX?t.deltaY*n:t.deltaX*n,a=t.shiftKey&&0===t.deltaX?0:t.deltaY*r;this.network.moveTo({position:{x:o.x+s/i,y:o.y+a/i},scale:i,animation:!1})}fitNetwork(){var t,e,i;if(this.zoomReturnView=void 0,!this.network)return;const o=null===(t=this.shadowRoot)||void 0===t?void 0:t.getElementById("zigbee-network");if(!o||!o.clientWidth||!o.clientHeight)return;this.network.redraw();const n=function(t,e,i,o=8){const n=t.filter((t=>Object.values(t).every(Number.isFinite)));if(!n.length||e<=2*o||i<=2*o)return;const r=Math.min(...n.map((t=>t.left))),s=Math.max(...n.map((t=>t.right))),a=Math.min(...n.map((t=>t.top))),l=Math.max(...n.map((t=>t.bottom))),h={x:(r+s)/2,y:(a+l)/2},c=2*Math.max(Math.abs(r-h.x),Math.abs(s-h.x)),d=2*Math.max(Math.abs(a-h.y),Math.abs(l-h.y));return{position:h,scale:Math.min((e-2*o)/Math.max(c,1),(i-2*o)/Math.max(d,1))}}([...(null!==(i=null===(e=this.visibleData)||void 0===e?void 0:e.nodes)&&void 0!==i?i:[]).map((t=>this.network.getBoundingBox(t.id))),...this.areaBounds()],o.clientWidth,o.clientHeight);n&&this.network.moveTo(Object.assign(Object.assign({},n),{animation:!1}))}hoverLink(t){var e;this.hoveredEdge!==t&&(this.hoveredEdge=t,this.showLabels||null===(e=this.network)||void 0===e||e.redraw())}drawLinkLabels(t){var e,i,o;if(!this.showLabels&&void 0===this.hoveredEdge||!this.network||!this.zigbeeData)return;const n=this.network,r=null===(e=this.shadowRoot)||void 0===e?void 0:e.getElementById("zigbee-network");if(!r)return;const s=n.getScale(),a=n.getPositions(),l=this.visibleData.nodes.map((t=>{const e=n.getBoundingBox(t.id),i=n.canvasToDOM({x:e.left,y:e.top}),o=n.canvasToDOM({x:e.right,y:e.bottom});return{left:i.x,top:i.y,right:o.x,bottom:o.y}})),h=(null===(i=this.config)||void 0===i?void 0:i.map_only)?null===(o=this.shadowRoot)||void 0===o?void 0:o.querySelector("footer.map-info"):void 0;if(h&&!h.hidden){const t=r.getBoundingClientRect(),e=h.getBoundingClientRect();l.push({left:e.left-t.left,right:e.right-t.left,top:e.top-t.top,bottom:e.bottom-t.top})}t.save(),t.font=14/s+"px system-ui, sans-serif";const c=[];for(const e of this.visibleData.edges){if(!e.label||!this.showLabels&&e.id!==this.hoveredEdge)continue;if(!a[e.from]||!a[e.to])continue;const i=F3(e.label,this.hass);c.push({id:e.id,text:i,width:t.measureText(i).width*s,from:n.canvasToDOM(a[e.from]),to:n.canvasToDOM(a[e.to])})}const d=function(t,e,i,o,n){const r=[];for(const s of t){let t;for(const a of[0,14,-14,26,-26,40,-40]){for(const l of[.5,.4,.6,.3,.7,.2,.8]){const h=L3(s.from,s.to,l,n),c=L3(s.from,s.to,l-.01,n),d=L3(s.from,s.to,l+.01,n),u=d.x-c.x,f=d.y-c.y,p=Math.hypot(u,f)||1,v={x:h.x-f/p*a,y:h.y+u/p*a},g={left:v.x-s.width/2-6,right:v.x+s.width/2+6,top:v.y-13,bottom:v.y+13};if(!(g.left<4||g.top<4||g.right>i-4||g.bottom>o-4||[...e,...r].some((t=>U3(g,t))))){t=Object.assign(Object.assign({},g),{id:s.id,text:s.text,anchor:h,center:v});break}}if(t)break}t&&r.push(t)}return r}(c,l,r.clientWidth,r.clientHeight,"vertical"===this.orientation),u=getComputedStyle(this),f=t=>u.getPropertyValue(t).trim(),p=f("--ha-tooltip-background-color")||f("--ha-color-surface-default")||f("--card-background-color")||"#fff",v=f("--ha-tooltip-text-color")||f("--primary-text-color")||this.textColor,g=parseFloat(f("--ha-tooltip-border-radius")||f("--ha-border-radius-md"))||4;t.textAlign="center",t.textBaseline="middle";for(const e of d){const i=n.DOMtoCanvas(e.center),o=n.DOMtoCanvas(e.anchor),r=n.DOMtoCanvas({x:e.left,y:e.top});t.strokeStyle=this.textColor,t.lineWidth=.5/s,t.beginPath(),t.moveTo(o.x,o.y),t.lineTo(i.x,i.y),t.stroke(),t.fillStyle=p,t.beginPath(),t.roundRect(r.x,r.y,(e.right-e.left)/s,(e.bottom-e.top)/s,Math.min(g,(e.bottom-e.top)/2)/s),t.fill(),t.fillStyle=v,t.fillText(e.text,i.x,i.y)}t.restore()}toggleLabels(){this.showLabels=!this.showLabels,this.drawNetwork(!0),this.saveLayoutClick(!0)}tidyLayout(){var t,e,i,o;this.zigbeeData&&(this.mapData=x3(null!==(t=this.mapData)&&void 0!==t?t:this.zigbeeData,this.orientation,null===(e=this.network)||void 0===e?void 0:e.getPositions(),null===(i=this.config)||void 0===i?void 0:i.group_by),this.areaPositions={},"area"!==(null===(o=this.config)||void 0===o?void 0:o.group_by)&&(this.zigbeeData=this.mapData),this.closeDeviceInfo(!1),this.areaDrag=void 0,this.drawNetwork(),this.spaceRenderedAreas(),this.fitNetwork())}spaceRenderedAreas(){var t,e;if(!this.network||"area"!==(null===(t=this.config)||void 0===t?void 0:t.group_by)||"pie"!==this.orientation)return;this.network.redraw();const i=this.visibleData,o=this.network.getPositions(),n=i.nodes.map((t=>Object.assign(Object.assign({},t),o[t.id]))),r=[...new Set(i.nodes.filter((t=>"Area"===t.group)).map((t=>{var e;return null!==(e=t.area_id)&&void 0!==e?e:""})))],s=this.areaBounds(),a=new Map(r.map(((t,e)=>[t,s[e]])));u(n,new Set(i.edges.map((t=>t.to))),(t=>{var e;const i=t[0],n=o[i.id],r=i.x-n.x,s=i.y-n.y,l="Controller"===i.group?this.network.getBoundingBox(i.id):a.get(null!==(e=i.area_id)&&void 0!==e?e:"");return{left:l.left+r,right:l.right+r,top:l.top+s,bottom:l.bottom+s}}));for(const t of n){if(t.x===o[t.id].x&&t.y===o[t.id].y)continue;this.network.moveNode(t.id,t.x,t.y),this.areaPositions[t.id]={x:t.x,y:t.y};const i=null===(e=this.mapData)||void 0===e?void 0:e.nodes.find((e=>e.id===t.id));i&&(i.x=t.x,i.y=t.y)}this.network.redraw()}get layoutKey(){var t,e,i,o,n,r,s;const a=`wiser-zigbee-layout:${JSON.stringify([location.pathname,null!==(e=null===(t=this.config)||void 0===t?void 0:t.hub)&&void 0!==e?e:"",null!==(o=null===(i=this.config)||void 0===i?void 0:i.name)&&void 0!==o?o:"Wiser Zigbee Network",null!==(r=null===(n=this.config)||void 0===n?void 0:n.layout_id)&&void 0!==r?r:""])}`,l="pie"===this.orientation?`${a}:pie`:"vertical"===this.orientation?`${a}:horizontal`:a;return"area"===(null===(s=this.config)||void 0===s?void 0:s.group_by)?`${l}:area-topology`:l}validPosition(t){return t&&Number.isFinite(t.x)&&Number.isFinite(t.y)?{x:t.x,y:t.y}:void 0}currentPositions(){var t,e;if(!this.network)return;const i={};for(const o of null!==(e=null===(t=this.mapData)||void 0===t?void 0:t.nodes)&&void 0!==e?e:[])i[o.id]={x:o.x,y:o.y};return Object.assign(Object.assign(Object.assign({},i),this.areaPositions),this.network.getPositions())}prepareConfirmation(t,e){var i,o;return function(t,e){if(!t)return()=>{};const i=t.ownerDocument,o=t.getBoundingClientRect(),n=getComputedStyle(t),r=["--ha-tooltip-background-color","--ha-tooltip-text-color","--ha-color-surface-default","--primary-text-color","--ha-font-family-body","--ha-tooltip-border-radius","--ha-border-radius-md"].map((t=>[t,n.getPropertyValue(t)]));return()=>{const t=i.createElement("div"),n=i.createElement("span"),s=i.createElement("ha-tooltip"),a=`wiser-confirm-${Math.random().toString(36).slice(2)}`;t.style.cssText=`position:fixed;left:${o.left}px;top:${o.top}px;width:${o.width}px;height:${o.height}px;pointer-events:none;z-index:1000`,r.forEach((([e,i])=>{i&&t.style.setProperty(e,i)})),n.id=a,n.style.cssText="display:block;width:100%;height:100%",s.for=a,s.trigger="manual",s.setAttribute("placement","bottom"),s.textContent=e,s.setAttribute("role","status"),t.append(n,s),i.body.append(t),s.open=!0,setTimeout((()=>t.remove()),2500)}}(null!==(o=null===(i=this.shadowRoot)||void 0===i?void 0:i.querySelector(`[data-action="${t}"]`))&&void 0!==o?o:null,this.t(e))}async copyLayout(){var t,e,i,o,n,r;const s=this.prepareConfirmation("common.copy","common.copied"),a=this.currentPositions();if(!a)return;const l=`magnifier: ${null!==(e=null===(t=this.config)||void 0===t?void 0:t.magnifier)&&void 0!==e&&e}\nshow_labels: ${this.showLabels}\nmap_only: ${null!==(o=null===(i=this.config)||void 0===i?void 0:i.map_only)&&void 0!==o&&o}\norientation: ${this.orientation}\ngroup_by: ${null!==(r=null===(n=this.config)||void 0===n?void 0:n.group_by)&&void 0!==r?r:"none"}\nlayout_data:\n`+Object.entries(a).map((([t,e])=>` ${JSON.stringify(t)}:\n x: ${Math.round(e.x)}\n y: ${Math.round(e.y)}`)).join("\n");try{await async function(t){var e,i;if(null===(e=navigator.clipboard)||void 0===e?void 0:e.writeText)try{return void await navigator.clipboard.writeText(t)}catch(t){}const o=document.createElement("textarea");o.value=t,o.readOnly=!0,o.style.cssText="position:fixed;top:0;left:0;opacity:0;pointer-events:none";const n=document.activeElement;try{if(document.body.appendChild(o),o.focus({preventScroll:!0}),o.select(),!document.execCommand("copy"))throw new Error("Clipboard copy failed")}finally{o.remove(),null===(i=null==n?void 0:n.focus)||void 0===i||i.call(n,{preventScroll:!0})}}(l),this.layoutStatus="",s()}catch(t){this.layoutStatus="layout.copy_error"}}async saveLayoutClick(t=!1){var e,i,o,n,r,s,l,h;const c=this.currentPositions();if(!c||!this.config)return;const d=t?()=>{}:this.prepareConfirmation("card.save_layout","common.saved");try{t||localStorage.setItem(this.layoutKey,JSON.stringify(c)),localStorage.setItem(`${this.layoutKey}:labels`,JSON.stringify(this.showLabels)),localStorage.setItem(`${this.layoutKey}:map-only`,JSON.stringify(null!==(e=this.config.map_only)&&void 0!==e&&e)),this.layoutStatus=""}catch(t){this.layoutStatus="layout.storage_error"}if(t||y3(this))Gt(this,"wiser-zigbee-save-layout",{layout_data:c,show_labels:this.showLabels,map_only:null!==(s=this.config.map_only)&&void 0!==s&&s,magnifier:null!==(l=this.config.magnifier)&&void 0!==l&&l,preferences_only:t,hub:this.config.hub,name:this.config.name,orientation:this.orientation,layout_id:this.config.layout_id,group_by:null!==(h=this.config.group_by)&&void 0!==h?h:"none"}),t||this.layoutStatus||d();else{if(this.savingConfig||!this.suppliedConfig)return;this.savingConfig=!0;try{this.suppliedConfig=await a(this,this.suppliedConfig,{show_labels:this.showLabels,magnifier:null!==(i=this.config.magnifier)&&void 0!==i&&i,map_only:null!==(o=this.config.map_only)&&void 0!==o&&o,layout_data:c,orientation:this.orientation,group_by:null!==(n=this.config.group_by)&&void 0!==n?n:"none",layout_orientation:void 0,layout_group_by:void 0}),this.config=Object.assign(Object.assign({},this.suppliedConfig),{auto_update:null===(r=this.suppliedConfig.auto_update)||void 0===r||r}),this.layoutStatus="",d()}catch(t){this.layoutStatus="layout.config_save_error"}finally{this.savingConfig=!1}}}renderZigbeeDetails(t){var e,i,o,n;const r=this.selectedEntity?null===(i=null===(e=this.hass)||void 0===e?void 0:e.states[this.selectedEntity])||void 0===i?void 0:i.attributes:void 0,s=null===(n=null===(o=this.zigbeeData)||void 0===o?void 0:o.edges.find((e=>e.from===t.id)))||void 0===n?void 0:n.to,a=C3(null==r?void 0:r.device_reception_RSSI,null==r?void 0:r.device_reception_LQI),l=C3(null==r?void 0:r.controller_reception_RSSI,null==r?void 0:r.controller_reception_LQI),h=[["zigbee.type",t.group],["zigbee.node",t.id],["zigbee.parent",s],["zigbee.channel",null==r?void 0:r.zigbee_channel],["zigbee.signal",(null==r?void 0:r.displayed_signal_strength)?P3(r.displayed_signal_strength,this.hass):void 0],["zigbee.device_rssi",null==a.rssi?void 0:`${a.rssi} dBm`],["zigbee.device_lqi",a.lqi],["zigbee.hub_rssi",null==l.rssi?void 0:`${l.rssi} dBm`],["zigbee.hub_lqi",l.lqi]];return X`
- ${h.filter((([,t])=>null!=t)).map((([t,e])=>X`
+ `,e([Ln({attribute:!1})],N4.prototype,"hass",void 0),e([Ln({attribute:!1})],N4.prototype,"hideHubSelector",void 0),e([Ln({attribute:!1})],N4.prototype,"hideMapHeight",void 0),e([Un()],N4.prototype,"_config",void 0),e([Un()],N4.prototype,"_hubs",void 0),e([Un()],N4.prototype,"_formReady",void 0),customElements.get("wiser-zigbee-card-editor")||customElements.define("wiser-zigbee-card-editor",N4);class j4 extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this.shadowRoot.innerHTML=`\n \n
\n

Wiser Zigbee

\n \n \n \n
\n \n

Customize this panel. Dashboard cards keep their own settings.

\n
\n
\n Cancel\n Save\n
\n
\n

Loading Wiser Zigbee network…

`,this.shadowRoot.getElementById("menu").addEventListener("click",(()=>{this.dispatchEvent(new CustomEvent("hass-toggle-menu",{bubbles:!0,composed:!0}))})),this.shadowRoot.getElementById("settings").addEventListener("click",(()=>this._openEditor())),this.shadowRoot.getElementById("cancel").addEventListener("click",(()=>this._closeEditor())),this.shadowRoot.getElementById("save").addEventListener("click",(()=>this._saveEditor())),this.shadowRoot.getElementById("editor-dialog").addEventListener("closed",(()=>this._closeEditor())),this.shadowRoot.getElementById("editor-dialog").addEventListener("close-dialog",(()=>this._closeEditor())),this._editors=[],this._cards=[],this._generation=0}_t(t){return B4(t,this._hass)}set hass(t){const e=this._hass;this._hass=t,this._localizeControls();for(const e of this._cards)e.hass=t;for(const e of this._editors)e.hass=t;this.shadowRoot.getElementById("settings").hidden=!t?.user?.is_admin,!t||e&&e.language===t.language||this._loadTranslations().catch((t=>{this.shadowRoot.getElementById("editor-dialog").open&&(this.shadowRoot.getElementById("editor-error").textContent=this._t("panel.editor_error")),console.error("Unable to load Wiser editor translations",t)}))}async _loadTranslations(){const t=this._hass;if(!t?.loadFragmentTranslation)return;if(this._translationLoad?.language===t.language)return this._translationLoad.promise;const e={language:t.language};return this._translationLoad=e,e.promise=(async()=>{let i;for(const n of D4)if(i=await t.loadFragmentTranslation(n)||i,this._translationLoad!==e)return this._loadTranslations();i&&(this.hass={...this._hass,localize:i})})().catch((t=>{throw this._translationLoad===e&&(this._translationLoad=void 0),t})),e.promise}_localizeControls(){const t=this.shadowRoot;for(const[e,i]of[["menu","panel.menu"],["settings","panel.settings"]])t.getElementById(e).setAttribute("aria-label",this._t(i)),t.getElementById(e).title=this._t(i);t.getElementById("cancel").textContent=this._t("panel.cancel"),t.getElementById("save").textContent=this._t("common.save"),t.getElementById("editor-description").textContent=this._t("panel.description");const e=t.getElementById("editor-dialog");e.setAttribute("header-title",this._t("panel.settings")),e.heading=this._t("panel.settings")}set panel(t){const e=t.config;JSON.stringify(e)!==JSON.stringify(this._config)&&(this._config=e,this._loadCards())}_cardConfig(t){return{layout_id:`wiser-zigbee-panel:${t}`,...this._config.card_configs?.[t],type:"custom:wiser-zigbee-card",hub:t,map_height:null}}async saveZigbeeCardConfig(t,e){if(!this._hass?.user?.is_admin||!this._cards.includes(t))throw new Error("Only administrators can save panel settings");const i=this._config.hubs[this._cards.indexOf(t)],n={...e,type:"custom:wiser-zigbee-card",hub:i,map_height:null};return await this._hass.callWS({type:"wiser/zigbee_panel/configure",configs:{[i]:n}}),this._config={...this._config,card_configs:{...this._config.card_configs,[i]:n}},i===this._activeHub&&this.setAttribute("theme-mode",Pn(n.theme_mode)),n}_selectHub(t){this._activeHub=t,this.setAttribute("theme-mode",Pn(this._config.card_configs?.[t]?.theme_mode)),this._cards.forEach(((e,i)=>{const n=this._config.hubs[i]===t;e.hidden=!n,this._tabs[i].setAttribute("aria-selected",String(n)),this._tabs[i].tabIndex=n?0:-1}))}_renderHubTabs(){const t=this._config.hubs,e=this.shadowRoot.getElementById("hub-tabs");e.hidden=0===t.length,this._tabs=t.map(((e,i)=>{const n=document.createElement("ha-button");n.setAttribute("appearance","plain"),n.className="hub-tab",n.textContent=e,n.id=`hub-tab-${i}`,n.setAttribute("role","tab"),n.setAttribute("aria-controls",`hub-panel-${i}`),n.addEventListener("click",(()=>this._selectHub(e))),n.addEventListener("keydown",(e=>{let n;if("ArrowRight"===e.key)n=(i+1)%t.length;else if("ArrowLeft"===e.key)n=(i+t.length-1)%t.length;else if("Home"===e.key)n=0;else{if("End"!==e.key)return;n=t.length-1}e.preventDefault(),this._selectHub(t[n]),this._tabs[n].focus()}));const o=this._cards[i];return o.id=`hub-panel-${i}`,o.setAttribute("role","tabpanel"),o.setAttribute("aria-labelledby",n.id),n})),e.replaceChildren(...this._tabs),this._selectHub(t.includes(this._activeHub)?this._activeHub:t[0])}_closeEditor(){this.shadowRoot.getElementById("editor-dialog").open=!1,this._editors=[],this.shadowRoot.getElementById("editors").replaceChildren()}async _openEditor(){const t=this.shadowRoot.getElementById("editor-dialog");if(t.open||!this._cards.length||!this._hass?.user?.is_admin)return;const e=this.shadowRoot.getElementById("editors"),i=this.shadowRoot.getElementById("editor-error"),n=this.shadowRoot.getElementById("save");this._drafts={},this._editors=[],i.textContent="",e.replaceChildren(),n.disabled=!0,t.heading=this._t("panel.settings"),"headerTitle"in(customElements.get("ha-dialog")?.prototype||{})||this.shadowRoot.getElementById("editor-actions").removeAttribute("slot"),t.open=!0;try{if(await this._loadTranslations(),!t.open)return;if(!window.loadCardHelpers){const t=document.createElement("partial-panel-resolver"),e=t._getRoutes?.({lovelace:{component_name:"lovelace",url_path:"lovelace"}});await(e?.routes?.lovelace?.load?.())}const i=customElements.get("wiser-zigbee-card");for(const n of this._config.hubs){const o=await i.getConfigElement();if(!t.open)return;const r=this._cardConfig(n);this._drafts[n]=r,o.hass=this._hass,o.hideHubSelector=!0,o.hideMapHeight=!0,o.setConfig({...r}),o.addEventListener("config-changed",(t=>{t.stopPropagation(),this._drafts[n]={...t.detail.config,type:"custom:wiser-zigbee-card",hub:n}}));const s=document.createElement("section"),a=document.createElement("h3");a.textContent=n,s.replaceChildren(...this._config.hubs.length>1?[a,o]:[o]),e.append(s),this._editors.push(o)}n.disabled=!1}catch(t){i.textContent=this._t("panel.editor_error"),console.error("Unable to open Wiser editor",t)}}async _saveEditor(){const t=this.shadowRoot.getElementById("save");t.disabled=!0;try{await this._hass.callWS({type:"wiser/zigbee_panel/configure",configs:this._drafts}),this._config={...this._config,card_configs:{...this._config.card_configs,...this._drafts}},this._closeEditor(),this._editors=[],this._loadCards()}catch(t){const e="invalid_config"===t?.code&&"string"==typeof t.message?` ${t.message}`:"";this.shadowRoot.getElementById("editor-error").textContent=this._t("panel.save_error")+e,console.error("Unable to save Wiser panel settings",t)}finally{t.disabled=!1}}async _loadCards(){const t=++this._generation,e=this._config,i=this.shadowRoot.querySelector("main");try{const n=customElements.get("wiser-zigbee-card");if(1!==n?.panelApiVersion)throw new Error("Wiser Zigbee needs its matching Zigbee card build. Update the card resource and refresh the browser.");if(t!==this._generation)return;const o=e.hubs.map((t=>{const e=document.createElement("wiser-zigbee-card");return e.setConfig(this._cardConfig(t)),e.hass=this._hass,e}));this._cards=o,i.replaceChildren(...o),this._renderHubTabs(),this.shadowRoot.getElementById("settings").disabled=!o.length}catch(e){if(t!==this._generation)return;this._cards=[],this.shadowRoot.getElementById("hub-tabs").hidden=!0,this.shadowRoot.getElementById("settings").disabled=!0;const n=document.createElement("p");n.setAttribute("role","alert"),n.textContent=e.message||"Unable to load Wiser Zigbee network. Please try again.";const o=document.createElement("ha-button");o.textContent=this._t("panel.retry"),o.addEventListener("click",(()=>this._loadCards())),i.replaceChildren(n,o),console.error("Unable to load Wiser Zigbee network",e)}}}function L4(t,e,i=4){return t.lefte.left&&t.tope.top}function U4(t,e,i,n){const o=n?{x:t.x,y:t.y+.45*(e.y-t.y)}:{x:t.x+.45*(e.x-t.x),y:t.y},r=n?{x:e.x,y:e.y+.45*(t.y-e.y)}:{x:e.x+.45*(t.x-e.x),y:e.y},s=1-i;return{x:s*s*s*t.x+3*s*s*i*o.x+3*s*i*i*r.x+i*i*i*e.x,y:s*s*s*t.y+3*s*s*i*o.y+3*s*i*i*r.y+i*i*i*e.y}}customElements.get("wiser-zigbee-panel")||customElements.define("wiser-zigbee-panel",j4),window.customCards=window.customCards||[],window.customCards.some((t=>"wiser-zigbee-card"===t.type))||window.customCards.push({type:"wiser-zigbee-card",name:"Wiser Zigbee Card",description:B4("card.description")});class Q4 extends(x4(Bn)){constructor(){super(...arguments),this.autoHeight=!0,this.themeMode="auto",this.loading=!1,this.error="",this.showLabels=!1,this.savingConfig=!1,this.pastingSettings=!1,this.pasteDialogOpen=!1,this.pasteError="",this.magnifier=new ti,this.magnifierHeld=!1,this.layoutStatus="",this.textColor="",this.statusPalette="",this.displayLanguage="",this.collapsedAreas=new Set,this.areaPositions={},this.infoRequest=0,this.fitAfterHeightChange=!1,this.requestId=0,this.pendingLoad=!0}t(t){return B4(t,this.hass)}deviceName(t){return t?"Controller"===t.group&&"Wiser Hub"===t.label?this.t("card.hub"):t.label.replace(/\n/g," "):this.t("card.unknown_device")}get visibleData(){var t,e;const i=null!==(t=this.mapData)&&void 0!==t?t:this.zigbeeData;return i&&"area"===(null===(e=this.config)||void 0===e?void 0:e.group_by)?function(t,e){const i=t.nodes.filter((t=>{var i;return"Controller"===t.group||"Area"===t.group||!e.has(null!==(i=t.area_id)&&void 0!==i?i:"")})),n=new Set(i.map((t=>t.id)));return{nodes:i,edges:t.edges.filter((t=>n.has(t.from)&&n.has(t.to)))}}(i,this.collapsedAreas):i}static async getConfigElement(){return document.createElement("wiser-zigbee-card-editor")}static getStubConfig(){return{}}setConfig(t){var e,i,n;if(!t)throw new Error(this.t("common.invalid_configuration"));this.magnifier.hide(),this.suppliedConfig=t;const o=Object.assign(Object.assign({},t),{auto_update:null===(e=t.auto_update)||void 0===e||e}),r=this.config,s=this.mapHeight,a=r&&this.network&&[...new Set([...Object.keys(r),...Object.keys(o)])].filter((t=>"map_height"!==t&&"theme_mode"!==t)).every((t=>JSON.stringify(r[t])===JSON.stringify(o[t])));if(this.config=o,this.autoHeight=null===this.mapHeight,this.themeMode=Pn(t.theme_mode),this.showLabels=null!==(i=t.show_labels)&&void 0!==i&&i,void 0===t.map_only)try{const t=localStorage.getItem(`${this.layoutKey}:map-only`);null!==t&&(this.config.map_only="true"===t)}catch(t){}if(void 0===t.show_labels)try{this.showLabels="true"===localStorage.getItem(`${this.layoutKey}:labels`)}catch(t){}a?this.fitAfterHeightChange||(this.fitAfterHeightChange=s!==this.mapHeight):(this.cancelDeviceInfo(),this.areaDrag=void 0,this.mapData=void 0,this.collapsedAreas.clear(),this.areaPositions={},this.fitAfterHeightChange=!1,null===(n=this.network)||void 0===n||n.destroy(),this.network=void 0,this.infoReturnView=void 0,this.zoomReturnView=void 0,this.layoutStatus="",this.pendingLoad=!0,this.requestId++)}get orientation(){var t,e;return"pie"===(null===(t=this.config)||void 0===t?void 0:t.orientation)?"pie":"horizontal"===(null===(e=this.config)||void 0===e?void 0:e.orientation)?"horizontal":"vertical"}get mapHeight(){var t;const e=null===(t=this.config)||void 0===t?void 0:t.map_height;return null==e||""===e?null:"number"==typeof e&&Number.isFinite(e)?Math.min(2e3,Math.max(100,Math.round(e))):null}getGridOptions(){var t;return null===this.mapHeight?{columns:12,rows:(null===(t=this.config)||void 0===t?void 0:t.map_only)?6:9,min_rows:3}:{columns:12}}getCardSize(){var t;return(null===(t=this.config)||void 0===t?void 0:t.map_only)?"vertical"===this.orientation?6:8:"vertical"===this.orientation?7:9}hassSubscribe(){return[this.hass.connection.subscribeMessage((t=>{var e;"wiser_updated"===t.event&&(null===(e=this.config)||void 0===e?void 0:e.auto_update)&&!g4(this)&&this.loadData()}),{type:"wiser_updated"})]}connectedCallback(){super.connectedCallback(),T4(this),this.pendingLoad=!0,this.requestUpdate()}disconnectedCallback(){var t;clearTimeout(this.magnifierHoldTimer),this.magnifier.hide(),clearTimeout(this.activeIconTimer),this.activeIcon=void 0,this.cancelDeviceInfo(),super.disconnectedCallback(),this.requestId++,null===(t=this.network)||void 0===t||t.destroy(),this.network=void 0,this.areaDrag=void 0,this.infoReturnView=void 0,this.zoomReturnView=void 0}updated(t){if(super.updated(t),this.positionAreaIcons(),(t.has("hass")||t.has("themeMode"))&&this.network){(getComputedStyle(this).getPropertyValue("--primary-text-color").trim()||"#273448")===this.textColor&&ci(getComputedStyle(this))===this.statusPalette&&R4(this.hass)===this.displayLanguage||this.drawNetwork(!0)}this.fitAfterHeightChange&&this.network&&(this.fitAfterHeightChange=!1,this.network.setSize("100%","100%"),this.fitNetwork()),(t.has("selected")||t.has("selectedEntity")||t.has("config"))&&this.focusAboveInfo(),this.pendingLoad&&this.hass&&this.config&&(this.pendingLoad=!1,this.loadData())}async loadData(){var t,e,i,n,o;if(!this.hass||!this.config)return;const r=++this.requestId;this.loading=!0,this.error="";try{let l=await(s=this.hass,a=this.config.hub,s.callWS({type:"wiser/zigbee",hub:a}));"area"===this.config.group_by&&(l=await async function(t,e,i){const[n,o,r,s]=await Promise.all([t.callWS({type:"config/entity_registry/list"}),t.callWS({type:"config/device_registry/list"}),t.callWS({type:"config/area_registry/list"}),i?Promise.resolve([i]):t.callWS({type:"wiser/hubs"})]),a={"config/entity_registry/list":n,"config/device_registry/list":o,"wiser/hubs":s},l=Object.assign(Object.assign({},t),{callWS:async t=>a[t.type]});return Object.assign(Object.assign({},e),{nodes:await Promise.all(e.nodes.map((async t=>{const e=await k4(l,t,s[0]),i=n.find((t=>t.entity_id===e)),a=o.find((t=>t.id===(null==i?void 0:i.device_id))),h=r.find((t=>t.area_id===((null==a?void 0:a.area_id)||(null==i?void 0:i.area_id))));return Object.assign(Object.assign({},t),{area_id:null==h?void 0:h.area_id,area_name:null==h?void 0:h.name,area_icon:null==h?void 0:h.icon})})))})}(this.hass,l,this.config.hub));const h=C4("area"===this.config.group_by?function(t,e){const i=t.nodes.map((t=>Object.assign({},t))),n=new Set(i.map((t=>t.id))),o=[...new Set(i.filter((t=>"Controller"!==t.group)).map((t=>{var e;return null!==(e=t.area_id)&&void 0!==e?e:""})))].sort(),r=t.edges.map((t=>Object.assign({},t)));for(const r of o){const o=t.nodes.filter((t=>{var e;return"Controller"!==t.group&&(null!==(e=t.area_id)&&void 0!==e?e:"")===r}));let s=2166136261;for(const t of r||"__unassigned__")s=Math.imul(s^t.charCodeAt(0),16777619);let a=-(s>>>0)-1;for(;n.has(a);)a--;n.add(a),i.push({id:a,group:"Area",area_id:r,area_icon:o[0].area_icon||"mdi:floor-plan",label:o[0].area_name||e,x:0,y:0})}return{nodes:i,edges:r}}(l,this.t("card.unassigned_area")):l,this.orientation,void 0,this.config.group_by);if(r!==this.requestId||!this.isConnected)return;let c=(null!==(t=this.config.layout_orientation)&&void 0!==t?t:this.orientation)===this.orientation&&(null!==(i=null!==(e=this.config.layout_group_by)&&void 0!==e?e:this.config.group_by)&&void 0!==i?i:"none")===(null!==(n=this.config.group_by)&&void 0!==n?n:"none")?this.config.layout_data:void 0;if(!c||"object"!=typeof c||Array.isArray(c))try{const t=JSON.parse(localStorage.getItem(this.layoutKey)||"null");t&&"object"==typeof t&&!Array.isArray(t)&&(c=t)}catch(t){}const d=Object.assign(Object.assign({},this.areaPositions),null===(o=this.network)||void 0===o?void 0:o.getPositions());h.nodes=h.nodes.map((t=>{var e;return Object.assign(Object.assign({},t),null!==(e=null==d?void 0:d[t.id])&&void 0!==e?e:this.validPosition(c&&"object"==typeof c?c[t.id]:void 0))})),this.zigbeeData="area"===this.config.group_by?l:h,this.mapData=h,await this.updateComplete,this.drawNetwork()}catch(t){r===this.requestId&&(this.error="card.load_error")}finally{r===this.requestId&&(this.loading=!1)}var s,a}drawNetwork(t=!1){var e,i,n,o;if(!this.zigbeeData)return;const r=t?Object.assign(Object.assign({},this.areaPositions),null===(e=this.network)||void 0===e?void 0:e.getPositions()):void 0,s=this.visibleData;t&&"area"===(null===(i=this.config)||void 0===i?void 0:i.group_by)&&(this.areaPositions=null!=r?r:{});const a=getComputedStyle(this).getPropertyValue("--primary-text-color").trim()||"#273448";this.textColor=a;const l=getComputedStyle(this);this.statusPalette=ci(l);const h=null!==(o=null===(n=this.config)||void 0===n?void 0:n.link_status)&&void 0!==o?o:"links",c="links"===h||"both"===h,d="icons"===h||"both"===h;this.displayLanguage=R4(this.hass);const u={nodes:s.nodes.map((t=>{var e,i,n,o;const s=function(t,e){if("Controller"===t.group||"Area"===t.group)return!1;const i=e.edges.filter((e=>e.from===t.id));return!i.length||i.every((t=>{const i=t.label.split("(")[0].replace(/[\s_-]/g,"").toLowerCase();return["nosignal","offline","disconnected","noconnection"].includes(i)||!e.nodes.some((e=>e.id===t.to))}))}(t,this.zigbeeData),h=s?"Offline":null===(e=this.zigbeeData.edges.find((e=>e.from===t.id)))||void 0===e?void 0:e.label,c=d&&"Area"!==t.group&&"Controller"!==t.group?hi(h,!0,l):void 0,u="Area"===t.group?A4:null!==(i=b4[t.group])&&void 0!==i?i:m4;return Object.assign(Object.assign(Object.assign({},t),null!==(n=null==r?void 0:r[t.id])&&void 0!==n?n:{}),{shape:"image",image:si(u,c,s),brokenImage:si(m4,c,s),size:32,label:"Area"===t.group?`${t.label} ${this.collapsedAreas.has(null!==(o=t.area_id)&&void 0!==o?o:"")?"▸":"▾"}`:"Controller"===t.group?this.deviceName(t):ai(t.label),font:{color:a}})})),edges:s.edges.map((t=>{const e=hi(t.label,c,l);return Object.assign(Object.assign({},t),{label:"",color:{color:e,highlight:e,hover:e,inherit:!1}})}))};if(this.network){const t={position:this.network.getViewPosition(),scale:this.network.getScale()};this.hoveredEdge=void 0,this.network.setData(u),this.network.moveTo(Object.assign(Object.assign({},t),{animation:!1})),void 0!==this.selected&&u.nodes.some((t=>t.id===this.selected))?this.network.selectNodes([this.selected]):this.selected=void 0}else this.network=new v4(this.shadowRoot.getElementById("zigbee-network"),u,Object.assign(Object.assign({},w4),{edges:Object.assign(Object.assign({},w4.edges),{smooth:{enabled:!0,type:"cubicBezier",forceDirection:"pie"===this.orientation?"none":this.orientation,roundness:.45}})})),this.network.on("hoverEdge",(t=>this.hoverLink(t.edge))),this.network.on("blurEdge",(()=>this.hoverLink())),this.network.on("click",(t=>this.deviceClick(t.nodes[0]))),this.network.on("hold",(t=>this.deviceHold(t.nodes[0]))),this.network.on("doubleClick",(t=>{var e;this.cancelDeviceInfo(),this.toggleDeviceZoom(t.nodes[0],null===(e=t.pointer)||void 0===e?void 0:e.canvas)})),this.network.on("beforeDrawing",(t=>{this.moveAreaDevices(),this.drawAreaGroups(t)})),this.network.on("afterDrawing",(t=>{this.positionAreaIcons(),this.drawLinkLabels(t),this.magnifier.refresh()})),this.network.on("dragStart",(t=>this.startAreaDrag(t.nodes[0]))),this.network.on("dragEnd",(()=>{this.moveAreaDevices(),this.areaDrag=void 0})),this.network.on("resize",(()=>this.fitNetwork())),this.fitNetwork(),this.requestUpdate()}startAreaDrag(t){var e,i,n,o;if(this.closeDeviceInfo(!1),this.areaDrag=void 0,!this.network||"area"!==(null===(e=this.config)||void 0===e?void 0:e.group_by))return;const r=null===(i=this.mapData)||void 0===i?void 0:i.nodes.find((e=>e.id===t&&"Area"===e.group));if(!r)return;const s=this.currentPositions(),a={};for(const t of this.mapData.nodes)"Area"!==t.group&&"Controller"!==t.group&&(null!==(n=t.area_id)&&void 0!==n?n:"")===(null!==(o=r.area_id)&&void 0!==o?o:"")&&s[t.id]&&(a[t.id]=Object.assign({},s[t.id]));this.areaDrag={headerId:r.id,origin:Object.assign({},s[r.id]),members:a,dx:0,dy:0}}moveAreaDevices(){const t=this.areaDrag;if(!t||!this.network)return;const e=this.network.getPositions(),i=e[t.headerId];if(!i)return;const n=i.x-t.origin.x,o=i.y-t.origin.y;if(n!==t.dx||o!==t.dy){t.dx=n,t.dy=o,this.areaPositions[t.headerId]=Object.assign({},i);for(const[i,r]of Object.entries(t.members)){const t={x:r.x+n,y:r.y+o};this.areaPositions[i]=t,e[i]&&this.network.moveNode(Number(i),t.x,t.y)}}}areaBounds(t){var e,i,n;if(!this.network||"area"!==(null===(e=this.config)||void 0===e?void 0:e.group_by))return[];const o=null!==(n=null===(i=this.visibleData)||void 0===i?void 0:i.nodes)&&void 0!==n?n:[],r=null!=t?t:document.createElement("canvas").getContext("2d"),s=this.network.getPositions(),a=new Set(o.filter((t=>"Area"===t.group)).map((t=>{var e;return null!==(e=t.area_id)&&void 0!==e?e:""})));return[...a].map((t=>{const e=o.filter((e=>{var i;return"Controller"!==e.group&&(null!==(i=e.area_id)&&void 0!==i?i:"")===t})),i=e.map((t=>{var e;const i=s[t.id];if(!i)return this.network.getBoundingBox(t.id);const n={left:i.x-32,right:i.x+32,top:i.y-32,bottom:i.y+60};if(!r)return n;const o="Area"===t.group?`${t.label} ${this.collapsedAreas.has(null!==(e=t.area_id)&&void 0!==e?e:"")?"▸":"▾"}`:ai(t.label);r.save(),r.font="bold 14px system-ui, sans-serif";const a=o.split("\n"),l=Math.max(...a.map((t=>r.measureText(t).width)))/2;return r.restore(),n.left=Math.min(n.left,i.x-l),n.right=Math.max(n.right,i.x+l),n.bottom=Math.max(n.bottom,i.y+32+14*(a.length+1)),n})),n=e.findIndex((t=>"Area"===t.group)),a=e[n],l=a&&s[a.id],h=i.filter(((t,e)=>e!==n));if(l&&h.length&&!this.areaDrag&&"vertical"===this.orientation){const t=(Math.min(...h.map((t=>t.left)))+Math.max(...h.map((t=>t.right))))/2,e=t-l.x;Math.abs(e)>.01&&(this.network.moveNode(a.id,t,l.y),this.areaPositions[a.id]={x:t,y:l.y},i[n].left+=e,i[n].right+=e)}return{left:Math.min(...i.map((t=>t.left)))-18,right:Math.max(...i.map((t=>t.right)))+18,top:Math.min(...i.map((t=>t.top)))-18,bottom:Math.max(...i.map((t=>t.bottom)))+18}}))}drawAreaGroups(t){const e=this.areaBounds(t);if(!e.length||!this.network)return;const i=getComputedStyle(this).getPropertyValue("--primary-text-color").trim()||this.textColor;t.save();for(const n of e)t.beginPath(),t.roundRect(n.left,n.top,n.right-n.left,n.bottom-n.top,14),t.fillStyle=i,t.globalAlpha=.04,t.fill(),t.strokeStyle=i,t.lineWidth=1/this.network.getScale(),t.globalAlpha=.22,t.stroke();t.restore()}positionAreaIcons(){var t,e;if(!this.network||"area"!==(null===(t=this.config)||void 0===t?void 0:t.group_by))return;const i=this.network.getPositions(),n=64*this.network.getScale();null===(e=this.shadowRoot)||void 0===e||e.querySelectorAll(".area-icons ha-icon").forEach((t=>{const e=i[Number(t.dataset.node)];if(!e)return;const o=this.network.canvasToDOM(e);t.style.left=`${o.x}px`,t.style.top=`${o.y}px`,t.style.width=`${n}px`,t.style.height=`${n}px`,t.style.setProperty("--mdc-icon-size",`${n}px`),t.style.setProperty("--ha-icon-size",`${n}px`)}))}cancelDeviceInfo(){clearTimeout(this.deviceTapTimer),this.deviceTapTimer=void 0,this.infoRequest++,this.selectedEntity=void 0}closeDeviceInfo(t=!0){var e;this.cancelDeviceInfo(),this.selected=void 0;const i=this.infoReturnView;this.infoReturnView=void 0,t&&(null===(e=this.network)||void 0===e||e.unselectAll(),i&&this.network&&(this.zoomReturnView=i.zoomReturnView,this.network.moveTo({position:i.position,scale:i.scale,animation:!1})))}deviceClick(t){clearTimeout(this.deviceTapTimer),void 0!==t?this.deviceTapTimer=setTimeout((()=>{var e,i;const n=null===(e=this.mapData)||void 0===e?void 0:e.nodes.find((e=>e.id===t));"Area"===(null==n?void 0:n.group)?this.toggleArea(null!==(i=n.area_id)&&void 0!==i?i:""):this.showDeviceDetails(t)}),300):this.closeDeviceInfo()}toggleArea(t){var e;this.closeDeviceInfo(!1),this.areaPositions=Object.assign(Object.assign({},this.areaPositions),null===(e=this.network)||void 0===e?void 0:e.getPositions()),this.collapsedAreas.has(t)?this.collapsedAreas.delete(t):this.collapsedAreas.add(t),this.drawNetwork(!0)}async deviceHold(t){var e,i;this.closeDeviceInfo();const n=null===(e=this.zigbeeData)||void 0===e?void 0:e.nodes.find((e=>e.id===t));if(!n||!this.hass)return;const o=this.infoRequest;try{const t=await k4(this.hass,n,null===(i=this.config)||void 0===i?void 0:i.hub);t&&o===this.infoRequest&&this.isConnected&&Gn(this,"hass-more-info",{entityId:t})}catch(t){}}showDeviceDetails(t){void 0!==t?(!this.infoReturnView&&this.network&&(this.infoReturnView={position:this.network.getViewPosition(),scale:this.network.getScale(),zoomReturnView:this.zoomReturnView}),this.cancelDeviceInfo(),this.selected=t,void 0!==t&&this.openDeviceInfo(t,this.infoRequest)):this.closeDeviceInfo()}async openDeviceInfo(t,e){var i,n;const o=null===(i=this.zigbeeData)||void 0===i?void 0:i.nodes.find((e=>e.id===t));if(o&&this.hass)try{const i=await k4(this.hass,o,null===(n=this.config)||void 0===n?void 0:n.hub);i&&e===this.infoRequest&&this.isConnected&&this.selected===t&&(this.selectedEntity=i)}catch(t){}}toggleDeviceZoom(t,e){if(!this.network)return;const i=!window.matchMedia("(prefers-reduced-motion: reduce)").matches&&{duration:250,easingFunction:"easeInOutQuad"};if(this.zoomReturnView)return this.network.moveTo(Object.assign(Object.assign({},this.zoomReturnView),{animation:i})),void(this.zoomReturnView=void 0);if(!(void 0!==t||e&&Number.isFinite(e.x)&&Number.isFinite(e.y)))return;this.zoomReturnView={position:this.network.getViewPosition(),scale:this.network.getScale()};const n=Math.max(2*this.zoomReturnView.scale,1.25);void 0!==t?this.network.focus(t,{scale:n,locked:!1,animation:i}):this.network.moveTo({position:e,scale:n,animation:i})}focusAboveInfo(){var t,e,i;if(!(null===(t=this.config)||void 0===t?void 0:t.map_only)||void 0===this.selected||!this.network)return;const n=null===(e=this.shadowRoot)||void 0===e?void 0:e.getElementById("zigbee-network"),o=null===(i=this.shadowRoot)||void 0===i?void 0:i.querySelector("footer.map-info");if(!n||!o||o.hidden)return;const r=n.getBoundingClientRect(),s=Math.min(r.bottom,o.getBoundingClientRect().top-12);s<=r.top||this.network.focus(this.selected,{scale:this.network.getScale(),offset:{x:0,y:(s-r.top-r.height)/2},locked:!1,animation:!1})}zoomStep(t){this.network&&(this.prepareGestureZoom(),this.network.moveTo({position:this.network.getViewPosition(),scale:Math.min(10,Math.max(.01,this.network.getScale()*t)),animation:!1}))}prepareGestureZoom(){var t;this.network&&(this.closeDeviceInfo(!1),null!==(t=this.zoomReturnView)&&void 0!==t||(this.zoomReturnView={position:this.network.getViewPosition(),scale:this.network.getScale()}))}touchZoomStart(t){t.touches.length>=2&&this.prepareGestureZoom()}panZoomedView(t){if(t.ctrlKey||t.metaKey)return void this.prepareGestureZoom();if(t.stopPropagation(),!this.network||!this.zoomReturnView)return;t.preventDefault();const e=t.currentTarget,i=this.network.getScale(),n=this.network.getViewPosition(),o=1===t.deltaMode?16:2===t.deltaMode?e.clientWidth:1,r=1===t.deltaMode?16:2===t.deltaMode?e.clientHeight:1,s=t.shiftKey&&0===t.deltaX?t.deltaY*o:t.deltaX*o,a=t.shiftKey&&0===t.deltaX?0:t.deltaY*r;this.network.moveTo({position:{x:n.x+s/i,y:n.y+a/i},scale:i,animation:!1})}fitNetwork(){var t,e,i;if(this.zoomReturnView=void 0,!this.network)return;const n=null===(t=this.shadowRoot)||void 0===t?void 0:t.getElementById("zigbee-network");if(!n||!n.clientWidth||!n.clientHeight)return;this.network.redraw();const o=function(t,e,i,n=8){const o=t.filter((t=>Object.values(t).every(Number.isFinite)));if(!o.length||e<=2*n||i<=2*n)return;const r=Math.min(...o.map((t=>t.left))),s=Math.max(...o.map((t=>t.right))),a=Math.min(...o.map((t=>t.top))),l=Math.max(...o.map((t=>t.bottom))),h={x:(r+s)/2,y:(a+l)/2},c=2*Math.max(Math.abs(r-h.x),Math.abs(s-h.x)),d=2*Math.max(Math.abs(a-h.y),Math.abs(l-h.y));return{position:h,scale:Math.min((e-2*n)/Math.max(c,1),(i-2*n)/Math.max(d,1))}}([...(null!==(i=null===(e=this.visibleData)||void 0===e?void 0:e.nodes)&&void 0!==i?i:[]).map((t=>this.network.getBoundingBox(t.id))),...this.areaBounds()],n.clientWidth,n.clientHeight);o&&this.network.moveTo(Object.assign(Object.assign({},o),{animation:!1}))}hoverLink(t){var e;this.hoveredEdge!==t&&(this.hoveredEdge=t,this.showLabels||null===(e=this.network)||void 0===e||e.redraw())}drawLinkLabels(t){var e,i,n;if(!this.showLabels&&void 0===this.hoveredEdge||!this.network||!this.zigbeeData)return;const o=this.network,r=null===(e=this.shadowRoot)||void 0===e?void 0:e.getElementById("zigbee-network");if(!r)return;const s=o.getScale(),a=o.getPositions(),l=this.visibleData.nodes.map((t=>{const e=o.getBoundingBox(t.id),i=o.canvasToDOM({x:e.left,y:e.top}),n=o.canvasToDOM({x:e.right,y:e.bottom});return{left:i.x,top:i.y,right:n.x,bottom:n.y}})),h=(null===(i=this.config)||void 0===i?void 0:i.map_only)?null===(n=this.shadowRoot)||void 0===n?void 0:n.querySelector("footer.map-info"):void 0;if(h&&!h.hidden){const t=r.getBoundingClientRect(),e=h.getBoundingClientRect();l.push({left:e.left-t.left,right:e.right-t.left,top:e.top-t.top,bottom:e.bottom-t.top})}t.save(),t.font=14/s+"px system-ui, sans-serif";const c=[];for(const e of this.visibleData.edges){if(!e.label||!this.showLabels&&e.id!==this.hoveredEdge)continue;if(!a[e.from]||!a[e.to])continue;const i=F4(e.label,this.hass);c.push({id:e.id,text:i,width:t.measureText(i).width*s,from:o.canvasToDOM(a[e.from]),to:o.canvasToDOM(a[e.to])})}const d=function(t,e,i,n,o){const r=[];for(const s of t){let t;for(const a of[0,14,-14,26,-26,40,-40]){for(const l of[.5,.4,.6,.3,.7,.2,.8]){const h=U4(s.from,s.to,l,o),c=U4(s.from,s.to,l-.01,o),d=U4(s.from,s.to,l+.01,o),u=d.x-c.x,f=d.y-c.y,p=Math.hypot(u,f)||1,v={x:h.x-f/p*a,y:h.y+u/p*a},g={left:v.x-s.width/2-6,right:v.x+s.width/2+6,top:v.y-13,bottom:v.y+13};if(!(g.left<4||g.top<4||g.right>i-4||g.bottom>n-4||[...e,...r].some((t=>L4(g,t))))){t=Object.assign(Object.assign({},g),{id:s.id,text:s.text,anchor:h,center:v});break}}if(t)break}t&&r.push(t)}return r}(c,l,r.clientWidth,r.clientHeight,"vertical"===this.orientation),u=getComputedStyle(this),f=t=>u.getPropertyValue(t).trim(),p=f("--ha-tooltip-background-color")||f("--ha-color-surface-default")||f("--card-background-color")||"#fff",v=f("--ha-tooltip-text-color")||f("--primary-text-color")||this.textColor,g=parseFloat(f("--ha-tooltip-border-radius")||f("--ha-border-radius-md"))||4;t.textAlign="center",t.textBaseline="middle";for(const e of d){const i=o.DOMtoCanvas(e.center),n=o.DOMtoCanvas(e.anchor),r=o.DOMtoCanvas({x:e.left,y:e.top});t.strokeStyle=this.textColor,t.lineWidth=.5/s,t.beginPath(),t.moveTo(n.x,n.y),t.lineTo(i.x,i.y),t.stroke(),t.fillStyle=p,t.beginPath(),t.roundRect(r.x,r.y,(e.right-e.left)/s,(e.bottom-e.top)/s,Math.min(g,(e.bottom-e.top)/2)/s),t.fill(),t.fillStyle=v,t.fillText(e.text,i.x,i.y)}t.restore()}toggleLabels(){this.showLabels=!this.showLabels,this.drawNetwork(!0),this.saveLayoutClick(!0)}tidyLayout(){var t,e,i,n;this.zigbeeData&&(this.mapData=C4(null!==(t=this.mapData)&&void 0!==t?t:this.zigbeeData,this.orientation,null===(e=this.network)||void 0===e?void 0:e.getPositions(),null===(i=this.config)||void 0===i?void 0:i.group_by),this.areaPositions={},"area"!==(null===(n=this.config)||void 0===n?void 0:n.group_by)&&(this.zigbeeData=this.mapData),this.closeDeviceInfo(!1),this.areaDrag=void 0,this.drawNetwork(),this.spaceRenderedAreas(),this.fitNetwork())}spaceRenderedAreas(){var t,e;if(!this.network||"area"!==(null===(t=this.config)||void 0===t?void 0:t.group_by)||"pie"!==this.orientation)return;this.network.redraw();const i=this.visibleData,n=this.network.getPositions(),o=i.nodes.map((t=>Object.assign(Object.assign({},t),n[t.id]))),r=[...new Set(i.nodes.filter((t=>"Area"===t.group)).map((t=>{var e;return null!==(e=t.area_id)&&void 0!==e?e:""})))],s=this.areaBounds(),a=new Map(r.map(((t,e)=>[t,s[e]])));li(o,new Set(i.edges.map((t=>t.to))),(t=>{var e;const i=t[0],o=n[i.id],r=i.x-o.x,s=i.y-o.y,l="Controller"===i.group?this.network.getBoundingBox(i.id):a.get(null!==(e=i.area_id)&&void 0!==e?e:"");return{left:l.left+r,right:l.right+r,top:l.top+s,bottom:l.bottom+s}}));for(const t of o){if(t.x===n[t.id].x&&t.y===n[t.id].y)continue;this.network.moveNode(t.id,t.x,t.y),this.areaPositions[t.id]={x:t.x,y:t.y};const i=null===(e=this.mapData)||void 0===e?void 0:e.nodes.find((e=>e.id===t.id));i&&(i.x=t.x,i.y=t.y)}this.network.redraw()}get layoutKey(){var t,e,i,n,o,r,s;const a=`wiser-zigbee-layout:${JSON.stringify([location.pathname,null!==(e=null===(t=this.config)||void 0===t?void 0:t.hub)&&void 0!==e?e:"",null!==(n=null===(i=this.config)||void 0===i?void 0:i.name)&&void 0!==n?n:"Wiser Zigbee Network",null!==(r=null===(o=this.config)||void 0===o?void 0:o.layout_id)&&void 0!==r?r:""])}`,l="pie"===this.orientation?`${a}:pie`:"vertical"===this.orientation?`${a}:horizontal`:a;return"area"===(null===(s=this.config)||void 0===s?void 0:s.group_by)?`${l}:area-topology`:l}validPosition(t){return t&&Number.isFinite(t.x)&&Number.isFinite(t.y)?{x:t.x,y:t.y}:void 0}currentPositions(){var t,e;if(!this.network)return;const i={};for(const n of null!==(e=null===(t=this.mapData)||void 0===t?void 0:t.nodes)&&void 0!==e?e:[])i[n.id]={x:n.x,y:n.y};return Object.assign(Object.assign(Object.assign({},i),this.areaPositions),this.network.getPositions())}prepareConfirmation(t,e){var i,n;return function(t,e){if(!t)return()=>{};const i=t.ownerDocument,n=t.getBoundingClientRect(),o=getComputedStyle(t),r=["--ha-tooltip-background-color","--ha-tooltip-text-color","--ha-color-surface-default","--primary-text-color","--ha-font-family-body","--ha-tooltip-border-radius","--ha-border-radius-md"].map((t=>[t,o.getPropertyValue(t)]));return()=>{const t=i.createElement("div"),o=i.createElement("span"),s=i.createElement("ha-tooltip"),a=`wiser-confirm-${Math.random().toString(36).slice(2)}`;t.style.cssText=`position:fixed;left:${n.left}px;top:${n.top}px;width:${n.width}px;height:${n.height}px;pointer-events:none;z-index:1000`,r.forEach((([e,i])=>{i&&t.style.setProperty(e,i)})),o.id=a,o.style.cssText="display:block;width:100%;height:100%",s.for=a,s.trigger="manual",s.setAttribute("placement","bottom"),s.textContent=e,s.setAttribute("role","status"),t.append(o,s),i.body.append(t),s.open=!0,setTimeout((()=>t.remove()),2500)}}(null!==(n=null===(i=this.shadowRoot)||void 0===i?void 0:i.querySelector(`[data-action="${t}"]`))&&void 0!==n?n:null,this.t(e))}async copyLayout(){var t,e,i,n,r,s,a,l,h,c,d,u,f,p;const v=this.prepareConfirmation("common.copy","common.copied"),g=this.currentPositions();var y;if(g)try{const m=(y={name:null!==(e=null===(t=this.config)||void 0===t?void 0:t.name)&&void 0!==e?e:this.t("card.title"),auto_update:null===(n=null===(i=this.config)||void 0===i?void 0:i.auto_update)||void 0===n||n,theme_mode:this.themeMode,map_only:null!==(s=null===(r=this.config)||void 0===r?void 0:r.map_only)&&void 0!==s&&s,show_device_list:null===(l=null===(a=this.config)||void 0===a?void 0:a.show_device_list)||void 0===l||l,show_labels:this.showLabels,magnifier:null!==(c=null===(h=this.config)||void 0===h?void 0:h.magnifier)&&void 0!==c&&c,link_status:null!==(u=null===(d=this.config)||void 0===d?void 0:d.link_status)&&void 0!==u?u:"links",map_height:this.mapHeight,orientation:this.orientation,group_by:null!==(p=null===(f=this.config)||void 0===f?void 0:f.group_by)&&void 0!==p?p:"none",layout_data:g},Ye(Xe(y),{schema:Ke,noRefs:!0,lineWidth:-1,quotingType:'"'}));await async function(t){var e,i;if(o(),null===(e=navigator.clipboard)||void 0===e?void 0:e.writeText)try{return await navigator.clipboard.writeText(t),void o(t)}catch(t){}const n=document.createElement("textarea");n.value=t,n.readOnly=!0,n.style.cssText="position:fixed;top:0;left:0;opacity:0;pointer-events:none";const r=document.activeElement;try{if(document.body.appendChild(n),n.focus({preventScroll:!0}),n.select(),!document.execCommand("copy"))throw new Error("Clipboard copy failed");o(t)}finally{n.remove(),null===(i=null==r?void 0:r.focus)||void 0===i||i.call(r,{preventScroll:!0})}}(m),this.layoutStatus="",v()}catch(t){this.layoutStatus="layout.copy_error"}}async pasteLayout(t){var e,o;if(this.pastingSettings||this.savingConfig||!this.suppliedConfig)return;const r=this.suppliedConfig;if(this.pastingSettings=!0,void 0===t)try{t=await async function(){try{return await navigator.clipboard.readText()}catch(t){let e=!1;try{const t=sessionStorage.getItem(n);if(e=!0,null!==t)return t}catch(t){}if(!e&&void 0!==i)return i;throw t}}()}catch(t){return this.pasteError="",this.pasteDialogOpen=!0,this.pastingSettings=!1,await this.updateComplete,void(null===(o=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector("#settings-paste"))||void 0===o||o.focus())}let s;try{s=function(t){if(t.length>1048576)throw new Error("Text too large");return Xe(qe(t,{schema:Ke}))}(t)}catch(t){return this.layoutStatus="layout.paste_error",this.pasteError="layout.paste_error",void(this.pastingSettings=!1)}try{if(this.suppliedConfig!==r||!this.isConnected)return;const t=await ni(this,r,Object.assign(Object.assign({},s),{layout_orientation:void 0,layout_group_by:void 0}));if(this.suppliedConfig!==r||!this.isConnected)return;this.setConfig(t),this.layoutStatus="common.saved",this.pasteDialogOpen=!1,this.pasteError=""}catch(t){this.layoutStatus="layout.paste_save_error",this.pasteError="layout.paste_save_error"}finally{this.pastingSettings=!1}}pasteSettingsDialog(){return qi`{this.pasteDialogOpen=!1}} + @close-dialog=${()=>{this.pasteDialogOpen=!1}} + > +

${this.t("layout.paste_hint")}

+ + ${this.pasteError?qi`

${this.t(this.pasteError)}

`:""} +
+ {this.pasteDialogOpen=!1}}>${this.t("panel.cancel")} + {var t,e,i;this.pasteLayout(null!==(i=null===(e=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("#settings-paste"))||void 0===e?void 0:e.value)&&void 0!==i?i:"")}}>${this.t("common.save")} +
+
`}settingsTransferControl(){var t,e;const i=`${this.t("common.copy")} / ${this.t("common.paste")}`;return qi`{"copy"===t.detail.item.value?this.copyLayout():"paste"===t.detail.item.value&&this.pasteLayout()}} + > + + + ${this.t("common.copy")} + + + ${this.t("common.paste")} + + `}async saveLayoutClick(t=!1){var e,i,n,o,r,s,a,l;if(this.pastingSettings)return;const h=this.currentPositions();if(!h||!this.config)return;const c=t?()=>{}:this.prepareConfirmation("card.save_layout","common.saved");try{t||localStorage.setItem(this.layoutKey,JSON.stringify(h)),localStorage.setItem(`${this.layoutKey}:labels`,JSON.stringify(this.showLabels)),localStorage.setItem(`${this.layoutKey}:map-only`,JSON.stringify(null!==(e=this.config.map_only)&&void 0!==e&&e)),this.layoutStatus=""}catch(t){this.layoutStatus="layout.storage_error"}if(t||g4(this))Gn(this,"wiser-zigbee-save-layout",{layout_data:h,show_labels:this.showLabels,map_only:null!==(s=this.config.map_only)&&void 0!==s&&s,magnifier:null!==(a=this.config.magnifier)&&void 0!==a&&a,preferences_only:t,hub:this.config.hub,name:this.config.name,orientation:this.orientation,layout_id:this.config.layout_id,group_by:null!==(l=this.config.group_by)&&void 0!==l?l:"none"}),t||this.layoutStatus||c();else{if(this.savingConfig||!this.suppliedConfig)return;this.savingConfig=!0;try{this.suppliedConfig=await ni(this,this.suppliedConfig,{show_labels:this.showLabels,magnifier:null!==(i=this.config.magnifier)&&void 0!==i&&i,map_only:null!==(n=this.config.map_only)&&void 0!==n&&n,layout_data:h,orientation:this.orientation,group_by:null!==(o=this.config.group_by)&&void 0!==o?o:"none",layout_orientation:void 0,layout_group_by:void 0}),this.config=Object.assign(Object.assign({},this.suppliedConfig),{auto_update:null===(r=this.suppliedConfig.auto_update)||void 0===r||r}),this.layoutStatus="",c()}catch(t){this.layoutStatus="layout.config_save_error"}finally{this.savingConfig=!1}}}renderZigbeeDetails(t){var e,i,n,o;const r=this.selectedEntity?null===(i=null===(e=this.hass)||void 0===e?void 0:e.states[this.selectedEntity])||void 0===i?void 0:i.attributes:void 0,s=null===(o=null===(n=this.zigbeeData)||void 0===n?void 0:n.edges.find((e=>e.from===t.id)))||void 0===o?void 0:o.to,a=E4(null==r?void 0:r.device_reception_RSSI,null==r?void 0:r.device_reception_LQI),l=E4(null==r?void 0:r.controller_reception_RSSI,null==r?void 0:r.controller_reception_LQI),h=[["zigbee.type",t.group],["zigbee.node",t.id],["zigbee.parent",s],["zigbee.channel",null==r?void 0:r.zigbee_channel],["zigbee.signal",(null==r?void 0:r.displayed_signal_strength)?P4(r.displayed_signal_strength,this.hass):void 0],["zigbee.device_rssi",null==a.rssi?void 0:`${a.rssi} dBm`],["zigbee.device_lqi",a.lqi],["zigbee.hub_rssi",null==l.rssi?void 0:`${l.rssi} dBm`],["zigbee.hub_lqi",l.lqi]];return qi`
+ ${h.filter((([,t])=>null!=t)).map((([t,e])=>qi`
${this.t(t)}${e}
`))} -
`}toggleViewMode(){this.config&&(this.config=Object.assign(Object.assign({},this.config),{map_only:!this.config.map_only}),this.saveLayoutClick(!0))}async openMagnifierMenu(t){var e;clearTimeout(this.magnifierHoldTimer),this.magnifierHeld=!0;const i=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector("#magnifier-menu");i&&(await i.updateComplete,i.anchorElement=t.querySelector("ha-icon-button"),i.open=!0)}magnifierControl(){var t,e;return X``}toggleViewMode(){this.config&&(this.config=Object.assign(Object.assign({},this.config),{map_only:!this.config.map_only}),this.saveLayoutClick(!0))}async openMagnifierMenu(t){var e;clearTimeout(this.magnifierHoldTimer),this.magnifierHeld=!0;const i=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector("#magnifier-menu");i&&(await i.updateComplete,i.anchorElement=t.querySelector("ha-icon-button"),i.open=!0)}magnifierControl(){var t,e;return qi`{if(!this.network||0!==t.button)return;clearTimeout(this.magnifierHoldTimer),this.magnifierHeld=!1;const e=t.currentTarget;this.magnifierHoldTimer=setTimeout((()=>{this.openMagnifierMenu(e)}),500)}} @pointerup=${()=>clearTimeout(this.magnifierHoldTimer)} @pointerleave=${()=>clearTimeout(this.magnifierHoldTimer)} @@ -198,11 +235,11 @@ function xG(){return xG=Object.assign||function(t){for(var e=1;e${this.layoutIcon("editor.magnifier","M9.5 3a6.5 6.5 0 1 0 3.98 11.64L19.85 21 21 19.85l-6.36-6.37A6.5 6.5 0 0 0 9.5 3m0 2a4.5 4.5 0 1 1 0 9 4.5 4.5 0 0 1 0-9m-1 1v2.5H6V10h2.5v2.5H10V10h2.5V8.5H10V6Z",(()=>{var t;this.config=Object.assign(Object.assign({},this.config),{magnifier:!(null===(t=this.config)||void 0===t?void 0:t.magnifier)}),this.magnifier.hide(),this.saveLayoutClick(!0)}),null!==(e=null===(t=this.config)||void 0===t?void 0:t.magnifier)&&void 0!==e&&e)} {this.magnifier.setZoom(Number(t.detail.item.value)),this.requestUpdate()}} - @wa-after-hide=${()=>{var t,e,i;const o=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("#magnifier-menu");(null==o?void 0:o.anchorElement)&&(o.anchorElement.selected=null!==(i=null===(e=this.config)||void 0===e?void 0:e.magnifier)&&void 0!==i&&i)}} + @wa-after-hide=${()=>{var t,e,i;const n=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("#magnifier-menu");(null==n?void 0:n.anchorElement)&&(n.anchorElement.selected=null!==(i=null===(e=this.config)||void 0===e?void 0:e.magnifier)&&void 0!==i&&i)}} >
- ${[2,3,4].map((t=>X`qi`${t}×`))}
@@ -219,18 +256,18 @@ function xG(){return xG=Object.assign||function(t){for(var e=1;e${this.magnifier.size} px
- `}layoutIcon(t,e,i,o,n=!this.network){const r=this.t(t),s=null!=o?o:"common.refresh"===t?this.loading:this.activeIcon===t;return X``}layoutIcon(t,e,i,n,o=!this.network){const r=this.t(t),s=null!=n?n:"common.refresh"===t?this.loading:this.activeIcon===t;return qi`{n||("editor.magnifier"===t&&this.magnifierHeld?this.magnifierHeld=!1:(void 0===o&&"common.refresh"!==t&&(clearTimeout(this.activeIconTimer),this.activeIcon=t,this.activeIconTimer=setTimeout((()=>{this.activeIcon=void 0}),500)),i()))}} - >`}render(){var t,e,i,o,n,r,s,a,l,h,c,d,u,f,p,v,g,y,m,b;const w=null!==(e=null===(t=this.zigbeeData)||void 0===t?void 0:t.nodes)&&void 0!==e?e:[],A=null!==(o=null===(i=this.zigbeeData)||void 0===i?void 0:i.edges)&&void 0!==o?o:[],E=w.find((t=>t.id===this.selected));return X`{o||("editor.magnifier"===t&&this.magnifierHeld?this.magnifierHeld=!1:(void 0===n&&"common.refresh"!==t&&(clearTimeout(this.activeIconTimer),this.activeIcon=t,this.activeIconTimer=setTimeout((()=>{this.activeIcon=void 0}),500)),i()))}} + >`}render(){var t,e,i,n,o,r,s,a,l,h,c,d,u,f,p,v,g,y,m,b;const w=null!==(e=null===(t=this.zigbeeData)||void 0===t?void 0:t.nodes)&&void 0!==e?e:[],A=null!==(n=null===(i=this.zigbeeData)||void 0===i?void 0:i.edges)&&void 0!==n?n:[],k=w.find((t=>t.id===this.selected));return qi`
WISER · ZIGBEE
@@ -247,19 +284,19 @@ function xG(){return xG=Object.assign||function(t){for(var e=1;ethis.toggleLabels()),this.showLabels)} ${this.magnifierControl()} ${this.layoutIcon("card.show_detailed_view","M3 3H21V21H3V3M5 5V7H19V5H5M5 9V19H19V9H5Z",(()=>this.toggleViewMode()),!(null!==(s=null===(r=this.config)||void 0===r?void 0:r.map_only)&&void 0!==s&&s),!this.config)} - ${this.layoutIcon("common.copy","M19 21H8V7H19M19 5H8A2 2 0 0 0 6 7V21A2 2 0 0 0 8 23H19A2 2 0 0 0 21 21V7A2 2 0 0 0 19 5M16 1H4A2 2 0 0 0 2 3V17H4V3H16Z",(()=>{this.copyLayout()}))} + ${this.settingsTransferControl()} ${this.layoutIcon("card.save_layout","M17,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V7L17,3M12,19A3,3 0 0,1 9,16A3,3 0 0,1 12,13A3,3 0 0,1 15,16A3,3 0 0,1 12,19M15,9H5V5H15V9Z",(()=>this.saveLayoutClick()))}
- ${this.layoutStatus?X`

+ ${this.layoutStatus?qi`

${this.t(this.layoutStatus)}

`:""}
- ${""===(null===(l=this.config)||void 0===l?void 0:l.name)?"":X`

${null!==(c=null===(h=this.config)||void 0===h?void 0:h.name)&&void 0!==c?c:this.t("card.title")}

`} + ${""===(null===(l=this.config)||void 0===l?void 0:l.name)?"":qi`

${null!==(c=null===(h=this.config)||void 0===h?void 0:h.name)&&void 0!==c?c:this.t("card.title")}

`}

- ${z3("devices",w.length,this.hass)} - · ${z3("connections",A.length,this.hass)} + ${z4("devices",w.length,this.hass)} + · ${z4("connections",A.length,this.hass)}

@@ -275,9 +312,9 @@ function xG(){return xG=Object.assign||function(t){for(var e=1;e
- ${"area"===(null===(f=this.config)||void 0===f?void 0:f.group_by)?X` + ${"area"===(null===(f=this.config)||void 0===f?void 0:f.group_by)?qi`
- ${E?X`
- ${this.deviceName(E)} ${function(t,e,i,o=!1){return X` + ${this.deviceName(k)} ${function(t,e,i,n=!1){return qi`${t}`}(this.t("common.close"),(()=>{this.closeDeviceInfo()}))}
- ${this.renderZigbeeDetails(E)} - ${A.filter((t=>t.from===E.id||t.to===E.id)).map((t=>X`
+ ${this.renderZigbeeDetails(k)} + ${A.filter((t=>t.from===k.id||t.to===k.id)).map((t=>qi`
${this.deviceName(w.find((e=>e.id===(t.from===E.id?t.to:t.from))))}${P3(t.label,this.hass)} -
`))}`:X`

${this.t("card.hint")}

`} - ${(null===(m=this.config)||void 0===m?void 0:m.map_only)||!1===(null===(b=this.config)||void 0===b?void 0:b.show_device_list)?"":(k=this.t("layout.device_list"),C=X` ${w.map((t=>X`
- ${this.deviceName(t)} ${A.filter((e=>e.from===t.id)).map((t=>X`
+ >${this.deviceName(w.find((e=>e.id===(t.from===k.id?t.to:t.from))))}${P4(t.label,this.hass)} +
`))}`:qi`

${this.t("card.hint")}

`} + ${(null===(m=this.config)||void 0===m?void 0:m.map_only)||!1===(null===(b=this.config)||void 0===b?void 0:b.show_device_list)?"":(E=this.t("layout.device_list"),C=qi` ${w.map((t=>qi`
+ ${this.deviceName(t)} ${A.filter((e=>e.from===t.id)).map((t=>qi`
→ ${this.deviceName(w.find((e=>e.id===t.to)))}${P3(t.label,this.hass)}${P4(t.label,this.hass)}
`))} -
`))}`,X``))}`,qi`
${C}
`)}
-
`;var k,C}}return Q3.panelApiVersion=1,Q3.styles=wt` + ${this.pasteSettingsDialog()}`;var E,C}}return Q4.panelApiVersion=1,Q4.styles=mn` + ${yn(Fn)} :host { display: block; min-width: 0; @@ -339,7 +377,7 @@ function xG(){return xG=Object.assign||function(t){for(var e=1;e Date: Sat, 19 Sep 2026 11:33:57 +0100 Subject: [PATCH 020/154] Automate local card builds and enforce published assets for releases --- .github/workflows/publish.yml | 15 +--- README.md | 14 +++- scripts/build.py | 71 +++++++++++++++++ scripts/fetch_card_releases.py | 55 ++++++++----- tests/test_build.py | 138 +++++++++++++++++++++++++++++++++ 5 files changed, 258 insertions(+), 35 deletions(-) create mode 100644 scripts/build.py create mode 100644 tests/test_build.py diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 1f057e6d..f000cc71 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -28,34 +28,27 @@ jobs: - name: Test packaging and sidebar integration run: | python -m unittest discover -s tests -p test_card_releases.py + python -m unittest discover -s tests -p test_build.py python -m unittest discover -s tests -p 'test_*sidebar.py' python -m unittest discover -s tests -p 'test_*version.py' - - name: Stage integration - run: | - mkdir -p dist/wiser - cp -a custom_components/wiser/. dist/wiser/ - - name: Fetch card release assets - if: github.event_name != 'push' + - name: Build integration with published card releases env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CARD_CHANNEL: ${{ github.event_name == 'release' && (github.event.release.prerelease && 'dev' || 'stable') || inputs.channel || 'dev' }} SCHEDULE_REPOSITORY: ${{ vars.WISER_SCHEDULE_CARD_REPOSITORY || 'andyblac/wiser-schedule-card' }} ZIGBEE_REPOSITORY: ${{ vars.WISER_ZIGBEE_CARD_REPOSITORY || 'andyblac/wiser-zigbee-card' }} run: >- - python scripts/fetch_card_releases.py + python scripts/build.py --release --channel "$CARD_CHANNEL" --schedule-repository "$SCHEDULE_REPOSITORY" --zigbee-repository "$ZIGBEE_REPOSITORY" - - name: Package integration - working-directory: dist/wiser - run: zip -r ../wiser.zip . -x '*/__pycache__/*' '*.pyc' - name: Upload test artifact uses: actions/upload-artifact@v4 with: name: wiser-package path: | dist/wiser.zip - dist/wiser/frontend/card-releases.json + dist/card-releases.json if-no-files-found: error publish: diff --git a/README.md b/README.md index 0884efed..8108088c 100755 --- a/README.md +++ b/README.md @@ -222,17 +222,23 @@ A full change log can be seen on our wiki [here](https://github.com/asantaga/wis The sidebar panel is built together with the schedule card in the `wiser-schedule-card` repository. The integration distributes that matching bundle; it does not maintain a separate panel JavaScript source. -### Packaging published cards +### Building the integration -The Publish workflow downloads compiled card assets from `andyblac/wiser-schedule-card` and `andyblac/wiser-zigbee-card` into the integration's `frontend` directory in a temporary staging copy. It does not change the tracked card files or build branch source. +Run `python3 scripts/build.py` to create `dist/wiser.zip`. For each card, the build automatically uses the compiled bundle in a sibling repository (`../wiser-schedule-card/dist/wiser-schedule-card.js` or `../wiser-zigbee-card/dist/wiser-zigbee-card.js`). Build the card in its own repository first to include source changes. Use `--local-root /path/to/repositories` if those repositories are elsewhere. + +If a local bundle is missing, the build downloads the corresponding GitHub release asset. It never falls back to the integration's old bundled copy. Development builds use local bundles first, with the `dev` release channel as fallback. An invalid local bundle fails the build. + +Release builds always use published GitHub assets, even when local bundles exist. Run `python3 scripts/build.py --release --channel dev` for a prerelease build or `python3 scripts/build.py --release --channel stable` for a stable release build. Selecting `--channel stable` also enforces release-only assets without requiring `--release`. Failed release downloads fail the build; they never fall back to local bundles. + +The Publish workflow always passes `--release`, so it ignores any local card builds and downloads compiled assets from `andyblac/wiser-schedule-card` and `andyblac/wiser-zigbee-card`. Packaging uses a temporary staging copy and does not change tracked card files. - Pushes to `test-build` and prereleases select the newest published prerelease of each card, falling back to its newest stable release if no prerelease exists. - Stable integration releases select only stable card releases. - Manual workflow runs let you test either channel and produce a downloadable `wiser-package` artifact, without publishing a release. -Each card release must have its compiled `wiser-schedule-card.js` or `wiser-zigbee-card.js` attached. Missing releases or assets fail the build instead of silently shipping old files. The schedule asset must include the sidebar panel when packaging a panel-enabled integration. The ZIP includes `frontend/card-releases.json` recording the exact tags, asset IDs, download URLs, and SHA-256 digests used. Repository variables `WISER_SCHEDULE_CARD_REPOSITORY` and `WISER_ZIGBEE_CARD_REPOSITORY` can override the source repositories. +Each card release must have its compiled `wiser-schedule-card.js` or `wiser-zigbee-card.js` attached. Missing releases or assets fail the build instead of silently shipping old files. Each card asset must include its sidebar panel when packaging a panel-enabled integration. The ZIP includes `frontend/card-releases.json` recording local paths or release tags, asset IDs and download URLs, plus SHA-256 digests. A copy is also written to `dist/card-releases.json`. Repository variables `WISER_SCHEDULE_CARD_REPOSITORY` and `WISER_ZIGBEE_CARD_REPOSITORY` can override the source repositories. -To preview selection without changing files: +To preview GitHub release selection without changing files: ```sh python3 scripts/fetch_card_releases.py --channel dev --plan diff --git a/scripts/build.py b/scripts/build.py new file mode 100644 index 00000000..23d03b83 --- /dev/null +++ b/scripts/build.py @@ -0,0 +1,71 @@ +"""Package Wiser with local development cards or published release assets.""" + +import argparse +import json +from pathlib import Path +import shutil +import tempfile +from zipfile import ZIP_DEFLATED, ZipFile + +from fetch_card_releases import CARD_REPOSITORIES, fetch_cards + +ROOT = Path(__file__).resolve().parents[1] + + +def build(source, output, local_root, channel, repositories, release=False): + """Stage a fresh integration and replace the ZIP only after a successful build.""" + # Stable builds and explicit releases must never package local card builds. + if release or channel == "stable": + local_root = None + output.parent.mkdir(parents=True, exist_ok=True) + with tempfile.TemporaryDirectory(dir=output.parent) as temporary: + staging = Path(temporary) / "wiser" + shutil.copytree( + source, staging, + ignore=shutil.ignore_patterns("__pycache__", "*.pyc", ".DS_Store"), + ) + report = fetch_cards( + channel, staging / "frontend", repositories, local_root=local_root + ) + archive_path = Path(temporary) / "wiser.zip" + with ZipFile(archive_path, "w", compression=ZIP_DEFLATED) as archive: + for path in sorted(staging.rglob("*")): + if path.is_file(): + archive.write(path, path.relative_to(staging)) + with ZipFile(archive_path) as archive: + if archive.testzip() is not None: + raise ValueError("Package integrity check failed") + archive_path.replace(output) + shutil.copyfile( + staging / "frontend/card-releases.json", + output.parent / "card-releases.json", + ) + return report + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--channel", choices=["dev", "stable"], default="dev") + parser.add_argument("--release", action="store_true", + help="Use only GitHub release assets, including for the dev channel") + parser.add_argument("--local-root", type=Path, default=ROOT.parent, + help="Directory containing sibling card repositories") + parser.add_argument("--output", type=Path, default=ROOT / "dist/wiser.zip") + parser.add_argument("--schedule-repository", default=CARD_REPOSITORIES["schedule"]) + parser.add_argument("--zigbee-repository", default=CARD_REPOSITORIES["zigbee"]) + args = parser.parse_args() + try: + report = build( + ROOT / "custom_components/wiser", args.output, args.local_root, + args.channel, + {"schedule": args.schedule_repository, "zigbee": args.zigbee_repository}, + release=args.release, + ) + except Exception as error: + parser.exit(1, f"Build failed: {error}\n") + print(json.dumps(report, indent=2)) + print(f"Built {args.output.resolve()}") + + +if __name__ == "__main__": + main() diff --git a/scripts/fetch_card_releases.py b/scripts/fetch_card_releases.py index c2255dfb..66123468 100644 --- a/scripts/fetch_card_releases.py +++ b/scripts/fetch_card_releases.py @@ -71,29 +71,44 @@ def download_asset(repository, asset): return contents, digest -def fetch_cards(channel, output_dir, repositories, plan=False): - selections = [] - # Resolve every release before downloading or replacing any assets. - for card, repository in repositories.items(): - release = select_release(list_releases(repository), channel) - filename = f"wiser-{card}-card.js" - asset = select_asset(release, filename) - selections.append((repository, release, asset)) +def fetch_cards(channel, output_dir, repositories, plan=False, local_root=None): report = [] payloads = {} - for repository, release, asset in selections: - record = { - "repository": repository, "tag": release["tag_name"], - "prerelease": release["prerelease"], "asset": asset["name"], - "asset_id": asset["id"], "url": asset["browser_download_url"], - } + # Resolve and validate every source before replacing any staged assets. + for card, repository in repositories.items(): + filename = f"wiser-{card}-card.js" + local = ( + Path(local_root) / repository.rsplit("/", 1)[-1] / "dist" / filename + if local_root is not None else None + ) + if local is not None and local.is_file(): + contents = local.read_bytes() + record = { + "repository": repository, "source": "local", "asset": filename, + "path": str(local.resolve()), + "digest": "sha256:" + sha256(contents).hexdigest(), + } + else: + release = select_release(list_releases(repository), channel) + asset = select_asset(release, filename) + record = { + "repository": repository, "source": "release", + "tag": release["tag_name"], "prerelease": release["prerelease"], + "asset": filename, "asset_id": asset["id"], + "url": asset["browser_download_url"], + } + if not plan: + contents, record["digest"] = download_asset(repository, asset) if not plan: - contents, digest = download_asset(repository, asset) - # The integration's dedicated panel must have a matching card build. - if asset["name"] == "wiser-schedule-card.js" and (output_dir / "schedules_sidebar.py").exists() and b"wiser-schedules-panel" not in contents: - raise ValueError("Selected schedule card does not include the sidebar panel required by this integration") - payloads[asset["name"]] = contents - record["digest"] = digest + if not contents or contents.lstrip().lower().startswith((b" Date: Sat, 19 Sep 2026 11:46:56 +0100 Subject: [PATCH 021/154] Register custom Wiser Zigbee sidebar icon --- custom_components/wiser/frontend/__init__.py | 5 +++ .../wiser/frontend/wiser-icons.js | 9 +++++ .../wiser/frontend/zigbee_sidebar.py | 2 +- tests/test_sidebar_icons.py | 34 +++++++++++++++++++ tests/test_zigbee_sidebar.py | 1 + 5 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 custom_components/wiser/frontend/wiser-icons.js create mode 100644 tests/test_sidebar_icons.py diff --git a/custom_components/wiser/frontend/__init__.py b/custom_components/wiser/frontend/__init__.py index 52b545fd..d8f7229f 100644 --- a/custom_components/wiser/frontend/__init__.py +++ b/custom_components/wiser/frontend/__init__.py @@ -7,6 +7,7 @@ from pathlib import Path from urllib.parse import parse_qs, urlsplit +from homeassistant.components.frontend import add_extra_js_url from homeassistant.components.http import StaticPathConfig from homeassistant.components.lovelace import MODE_STORAGE, LovelaceData from homeassistant.const import MAJOR_VERSION, MINOR_VERSION @@ -77,6 +78,10 @@ def __init__(self, hass: HomeAssistant) -> None: async def async_register(self): """Register view_assist path.""" await self._async_register_path() + icon_version = await self.hass.async_add_executor_job( + card_version, Path(__file__).parent / "wiser-icons.js" + ) + add_extra_js_url(self.hass, f"{URL_BASE}/wiser-icons.js?v={icon_version}") if self.lovelace and self.resource_mode == MODE_STORAGE: diff --git a/custom_components/wiser/frontend/wiser-icons.js b/custom_components/wiser/frontend/wiser-icons.js new file mode 100644 index 00000000..2be7ccc3 --- /dev/null +++ b/custom_components/wiser/frontend/wiser-icons.js @@ -0,0 +1,9 @@ +// Wiser sidebar icons. Loaded globally so icons work before a card is opened. +(() => { + const path = "M11.1000 5.0000L11.1000 8.0000A.9 .9 0 0 0 12.9000 8.0000L12.9000 5.0000A.9 .9 0 0 0 11.1000 5.0000Z M5.1364 19.6364L8.1364 16.6364A.9 .9 0 0 0 6.8636 15.3636L3.8636 18.3636A.9 .9 0 0 0 5.1364 19.6364Z M20.1364 18.3636L17.1364 15.3636A.9 .9 0 0 0 15.8636 16.6364L18.8636 19.6364A.9 .9 0 0 0 20.1364 18.3636Z M7.0699 12.6966L12.5699 8.1966A.9 .9 0 0 0 11.4301 6.8034L5.9301 11.3034A.9 .9 0 0 0 7.0699 12.6966Z M11.4301 8.1966L16.9301 12.6966A.9 .9 0 0 0 18.0699 11.3034L12.5699 6.8034A.9 .9 0 0 0 11.4301 8.1966Z M7.1000 11.0000L7.1000 17.0000A.9 .9 0 0 0 8.9000 17.0000L8.9000 11.0000A.9 .9 0 0 0 7.1000 11.0000Z M8.0000 17.9000L16.0000 17.9000A.9 .9 0 0 0 16.0000 16.1000L8.0000 16.1000A.9 .9 0 0 0 8.0000 17.9000Z M16.9000 17.0000L16.9000 11.0000A.9 .9 0 0 0 15.1000 11.0000L15.1000 17.0000A.9 .9 0 0 0 16.9000 17.0000Z M9.75 3.25a2.25 2.25 0 1 0 4.5 0a2.25 2.25 0 1 0-4.5 0Z M1.0 20.25a2.25 2.25 0 1 0 4.5 0a2.25 2.25 0 1 0-4.5 0Z M18.5 20.25a2.25 2.25 0 1 0 4.5 0a2.25 2.25 0 1 0-4.5 0Z"; + window.customIcons = window.customIcons || {}; + window.customIcons["wiser"] = { + getIcon: async (name) => name === "zigbee" ? { path, viewBox: "0 0 24 24" } : {}, + getIconList: async () => [{ name: "zigbee", keywords: ["wiser", "home", "network"] }], + }; +})(); diff --git a/custom_components/wiser/frontend/zigbee_sidebar.py b/custom_components/wiser/frontend/zigbee_sidebar.py index ec5cacfb..97180b5a 100644 --- a/custom_components/wiser/frontend/zigbee_sidebar.py +++ b/custom_components/wiser/frontend/zigbee_sidebar.py @@ -15,7 +15,7 @@ state_key=PANEL_STATE, component="wiser-zigbee-panel", title="Wiser Zigbee", - icon="mdi:zigbee", + icon="wiser:zigbee", filename="wiser-zigbee-card.js", enabled_option=CONF_SHOW_ZIGBEE_SIDEBAR, config_option=CONF_ZIGBEE_PANEL_CONFIG, diff --git a/tests/test_sidebar_icons.py b/tests/test_sidebar_icons.py new file mode 100644 index 00000000..f817c7a2 --- /dev/null +++ b/tests/test_sidebar_icons.py @@ -0,0 +1,34 @@ +"""Check custom sidebar icons load without opening a Lovelace dashboard.""" +import ast +from pathlib import Path +from types import SimpleNamespace +import unittest +from unittest.mock import AsyncMock, Mock + +ROOT = Path(__file__).resolve().parents[1] / "custom_components/wiser/frontend" + + +class SidebarIconsTest(unittest.IsolatedAsyncioTestCase): + async def test_icons_register_after_static_path_without_lovelace(self): + tree = ast.parse((ROOT / "__init__.py").read_text()) + cls = next(node for node in tree.body if isinstance(node, ast.ClassDef) and node.name == "JSModuleRegistration") + method = next(node for node in cls.body if isinstance(node, ast.AsyncFunctionDef) and node.name == "async_register") + register = Mock() + version = Mock(return_value="sha256-icons") + namespace = { + "__file__": str(ROOT / "__init__.py"), "Path": Path, + "card_version": version, "add_extra_js_url": register, + "URL_BASE": "/wiser", "MODE_STORAGE": "storage", + } + exec(compile(ast.Module(body=[method], type_ignores=[]), str(ROOT / "__init__.py"), "exec"), namespace) + host = SimpleNamespace( + hass=SimpleNamespace(async_add_executor_job=AsyncMock(side_effect=lambda fn, *args: fn(*args))), + lovelace=None, + _async_register_path=AsyncMock(), + _async_wait_for_lovelace_resources=AsyncMock(), + ) + register.side_effect = lambda *args: host._async_register_path.assert_awaited_once() + await namespace["async_register"](host) + version.assert_called_once_with(ROOT / "wiser-icons.js") + register.assert_called_once_with(host.hass, "/wiser/wiser-icons.js?v=sha256-icons") + host._async_wait_for_lovelace_resources.assert_not_awaited() diff --git a/tests/test_zigbee_sidebar.py b/tests/test_zigbee_sidebar.py index f88c1da1..8acceb80 100644 --- a/tests/test_zigbee_sidebar.py +++ b/tests/test_zigbee_sidebar.py @@ -84,6 +84,7 @@ async def test_enable_registers_dedicated_panel_once(self): args = self.custom.async_register_panel.call_args.kwargs self.assertEqual(args["frontend_url_path"], "wiser-zigbee-panel") self.assertEqual(args["webcomponent_name"], "wiser-zigbee-panel") + self.assertEqual(args["sidebar_icon"], "wiser:zigbee") self.assertEqual(args["config"]["hubs"], ["hub"]) self.assertEqual(args["config"]["card_url"], "/wiser/wiser-zigbee-card.js?v=4.5.6-beta.2") From 3c4ad906e9cb25eae00dce51bad9bb4e205baf58 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Sat, 19 Sep 2026 12:41:11 +0100 Subject: [PATCH 022/154] Preview stable release packaging on frontend-panels pushes --- .github/workflows/publish.yml | 6 +++--- README.md | 9 ++++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f000cc71..6fa9793b 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -4,7 +4,7 @@ on: release: types: [published] push: - branches: [test-build] + branches: [test-build, frontend-panels] workflow_dispatch: inputs: channel: @@ -34,7 +34,7 @@ jobs: - name: Build integration with published card releases env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - CARD_CHANNEL: ${{ github.event_name == 'release' && (github.event.release.prerelease && 'dev' || 'stable') || inputs.channel || 'dev' }} + CARD_CHANNEL: ${{ github.event_name == 'release' && (github.event.release.prerelease && 'dev' || 'stable') || inputs.channel || (github.ref_name == 'frontend-panels' && 'stable' || 'dev') }} SCHEDULE_REPOSITORY: ${{ vars.WISER_SCHEDULE_CARD_REPOSITORY || 'andyblac/wiser-schedule-card' }} ZIGBEE_REPOSITORY: ${{ vars.WISER_ZIGBEE_CARD_REPOSITORY || 'andyblac/wiser-zigbee-card' }} run: >- @@ -42,7 +42,7 @@ jobs: --channel "$CARD_CHANNEL" --schedule-repository "$SCHEDULE_REPOSITORY" --zigbee-repository "$ZIGBEE_REPOSITORY" - - name: Upload test artifact + - name: Upload release package for inspection uses: actions/upload-artifact@v4 with: name: wiser-package diff --git a/README.md b/README.md index 8108088c..2cbebc64 100755 --- a/README.md +++ b/README.md @@ -232,9 +232,12 @@ Release builds always use published GitHub assets, even when local bundles exist The Publish workflow always passes `--release`, so it ignores any local card builds and downloads compiled assets from `andyblac/wiser-schedule-card` and `andyblac/wiser-zigbee-card`. Packaging uses a temporary staging copy and does not change tracked card files. -- Pushes to `test-build` and prereleases select the newest published prerelease of each card, falling back to its newest stable release if no prerelease exists. -- Stable integration releases select only stable card releases. -- Manual workflow runs let you test either channel and produce a downloadable `wiser-package` artifact, without publishing a release. +- Pushes to `frontend-panels` preview a stable release using only stable GitHub card releases. They run the same packaging job used by a real release and upload the resulting `wiser-package` artifact. The publish job is skipped. +- Pushes to `test-build` keep using the dev card release channel. +- Stable integration releases select only stable card releases. Prereleases select the newest published prerelease of each card, falling back to its newest stable release if no prerelease exists. +- Manual workflow runs keep their dev default and let you select either channel without publishing a release. + +To test the release workflow before merging into the release branch, commit your changes and push `frontend-panels`. Open **Actions → Publish**, select that push run, and download **wiser-package**. Inspect `card-releases.json` for the selected card releases and install the included `wiser.zip` on your test instance. The release attachment step uses this same ZIP artifact on actual release events. A later build may select newer card releases if they are published between the preview and the real release. Each card release must have its compiled `wiser-schedule-card.js` or `wiser-zigbee-card.js` attached. Missing releases or assets fail the build instead of silently shipping old files. Each card asset must include its sidebar panel when packaging a panel-enabled integration. The ZIP includes `frontend/card-releases.json` recording local paths or release tags, asset IDs and download URLs, plus SHA-256 digests. A copy is also written to `dist/card-releases.json`. Repository variables `WISER_SCHEDULE_CARD_REPOSITORY` and `WISER_ZIGBEE_CARD_REPOSITORY` can override the source repositories. From 359a231f3b07793fbf1088795a85485b8345a98f Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Sat, 19 Sep 2026 13:03:40 +0100 Subject: [PATCH 023/154] Document release builds in restored README --- README.md | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 2cbebc64..babf2006 100755 --- a/README.md +++ b/README.md @@ -13,8 +13,6 @@ For the latest version of the Wiser Home Assistant Platform please install via H **This integration requires a minimum HA version of 2025.5.** -To open the schedule editor in a dedicated sidebar panel, go to **Settings → Devices & services → Wiser → Configure → UI options** and enable **Show Wiser Schedules in sidebar**. The option is off by default. With multiple hubs, the panel shows schedules for each hub with this option enabled. Use the cog in the panel header to edit its display settings (administrators only). These are saved in the integration configuration for backups and are separate from the configuration of schedule cards on dashboards. - Detailed information about this integration has now been moved to our [Wiki pages](https://github.com/asantaga/wiserHomeAssistantPlatform/wiki) For more information checkout the AMAZING community thread available on @@ -220,29 +218,16 @@ For more information checkout the AMAZING community thread available on A full change log can be seen on our wiki [here](https://github.com/asantaga/wiserHomeAssistantPlatform/wiki/Full-Change-Log) -The sidebar panel is built together with the schedule card in the `wiser-schedule-card` repository. The integration distributes that matching bundle; it does not maintain a separate panel JavaScript source. - -### Building the integration - -Run `python3 scripts/build.py` to create `dist/wiser.zip`. For each card, the build automatically uses the compiled bundle in a sibling repository (`../wiser-schedule-card/dist/wiser-schedule-card.js` or `../wiser-zigbee-card/dist/wiser-zigbee-card.js`). Build the card in its own repository first to include source changes. Use `--local-root /path/to/repositories` if those repositories are elsewhere. - -If a local bundle is missing, the build downloads the corresponding GitHub release asset. It never falls back to the integration's old bundled copy. Development builds use local bundles first, with the `dev` release channel as fallback. An invalid local bundle fails the build. - -Release builds always use published GitHub assets, even when local bundles exist. Run `python3 scripts/build.py --release --channel dev` for a prerelease build or `python3 scripts/build.py --release --channel stable` for a stable release build. Selecting `--channel stable` also enforces release-only assets without requiring `--release`. Failed release downloads fail the build; they never fall back to local bundles. +## Building -The Publish workflow always passes `--release`, so it ignores any local card builds and downloads compiled assets from `andyblac/wiser-schedule-card` and `andyblac/wiser-zigbee-card`. Packaging uses a temporary staging copy and does not change tracked card files. +To build a stable release package, run: -- Pushes to `frontend-panels` preview a stable release using only stable GitHub card releases. They run the same packaging job used by a real release and upload the resulting `wiser-package` artifact. The publish job is skipped. -- Pushes to `test-build` keep using the dev card release channel. -- Stable integration releases select only stable card releases. Prereleases select the newest published prerelease of each card, falling back to its newest stable release if no prerelease exists. -- Manual workflow runs keep their dev default and let you select either channel without publishing a release. - -To test the release workflow before merging into the release branch, commit your changes and push `frontend-panels`. Open **Actions → Publish**, select that push run, and download **wiser-package**. Inspect `card-releases.json` for the selected card releases and install the included `wiser.zip` on your test instance. The release attachment step uses this same ZIP artifact on actual release events. A later build may select newer card releases if they are published between the preview and the real release. +```sh +python3 scripts/build.py --release --channel stable +``` -Each card release must have its compiled `wiser-schedule-card.js` or `wiser-zigbee-card.js` attached. Missing releases or assets fail the build instead of silently shipping old files. Each card asset must include its sidebar panel when packaging a panel-enabled integration. The ZIP includes `frontend/card-releases.json` recording local paths or release tags, asset IDs and download URLs, plus SHA-256 digests. A copy is also written to `dist/card-releases.json`. Repository variables `WISER_SCHEDULE_CARD_REPOSITORY` and `WISER_ZIGBEE_CARD_REPOSITORY` can override the source repositories. +For a prerelease package, use `--channel dev` instead. The build downloads published Schedules and Zigbee card assets from GitHub. Stable builds use stable card releases; prerelease builds use the newest published prerelease of each card, falling back to its newest stable release when none exists. -To preview GitHub release selection without changing files: +The output is `dist/wiser.zip`. The accompanying `dist/card-releases.json` records the card releases and checksums included in the package. Missing or invalid card assets fail the build. -```sh -python3 scripts/fetch_card_releases.py --channel dev --plan -``` +The **Publish** GitHub Actions workflow runs the same build and attaches `wiser.zip` when an integration release is published. Preview runs provide a downloadable **wiser-package** artifact without publishing a release. From 80ec445dffc9f698133f0f5a11542c40bc864604 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Sat, 19 Sep 2026 14:15:44 +0100 Subject: [PATCH 024/154] Clean up release workflow and sidebar formatting --- .github/workflows/publish.yml | 14 ++++++++------ .../wiser/frontend/schedules_sidebar.py | 2 -- custom_components/wiser/frontend/zigbee_sidebar.py | 1 - 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 6fa9793b..eed96f67 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -4,7 +4,7 @@ on: release: types: [published] push: - branches: [test-build, frontend-panels] + branches: [test-build] workflow_dispatch: inputs: channel: @@ -21,20 +21,22 @@ jobs: name: Build Wiser integration runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - uses: actions/checkout@v5 + - uses: actions/setup-python@v6 with: python-version: '3.13' - name: Test packaging and sidebar integration run: | python -m unittest discover -s tests -p test_card_releases.py python -m unittest discover -s tests -p test_build.py + python -m unittest discover -s tests -p test_ui_options.py + python -m unittest discover -s tests -p test_sidebar_icons.py python -m unittest discover -s tests -p 'test_*sidebar.py' python -m unittest discover -s tests -p 'test_*version.py' - name: Build integration with published card releases env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - CARD_CHANNEL: ${{ github.event_name == 'release' && (github.event.release.prerelease && 'dev' || 'stable') || inputs.channel || (github.ref_name == 'frontend-panels' && 'stable' || 'dev') }} + CARD_CHANNEL: ${{ github.event_name == 'release' && (github.event.release.prerelease && 'dev' || 'stable') || inputs.channel || 'dev' }} SCHEDULE_REPOSITORY: ${{ vars.WISER_SCHEDULE_CARD_REPOSITORY || 'andyblac/wiser-schedule-card' }} ZIGBEE_REPOSITORY: ${{ vars.WISER_ZIGBEE_CARD_REPOSITORY || 'andyblac/wiser-zigbee-card' }} run: >- @@ -43,7 +45,7 @@ jobs: --schedule-repository "$SCHEDULE_REPOSITORY" --zigbee-repository "$ZIGBEE_REPOSITORY" - name: Upload release package for inspection - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: wiser-package path: | @@ -59,7 +61,7 @@ jobs: permissions: contents: write steps: - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v6 with: name: wiser-package path: dist diff --git a/custom_components/wiser/frontend/schedules_sidebar.py b/custom_components/wiser/frontend/schedules_sidebar.py index 7ca17f4a..c10d3b25 100644 --- a/custom_components/wiser/frontend/schedules_sidebar.py +++ b/custom_components/wiser/frontend/schedules_sidebar.py @@ -19,7 +19,6 @@ config_option=CONF_SCHEDULES_PANEL_CONFIG, hub_error="Hub is not enabled in the schedules panel", setting_error="Invalid schedule card setting", - ) @@ -31,4 +30,3 @@ async def async_update_schedules_panel(hass): def save_schedules_panel_config(hass, configs): """Validate all submitted settings before updating integration options.""" save_panel_config(hass, _SCHEDULES_PANEL, configs) - diff --git a/custom_components/wiser/frontend/zigbee_sidebar.py b/custom_components/wiser/frontend/zigbee_sidebar.py index 97180b5a..607da209 100644 --- a/custom_components/wiser/frontend/zigbee_sidebar.py +++ b/custom_components/wiser/frontend/zigbee_sidebar.py @@ -21,7 +21,6 @@ config_option=CONF_ZIGBEE_PANEL_CONFIG, hub_error="Hub is not enabled in the zigbee panel", setting_error="Invalid Zigbee card setting", - ) From 336a7799bcc42dc2a5bdd2af41122067a94c8a51 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Sat, 19 Sep 2026 14:20:27 +0100 Subject: [PATCH 025/154] Add British English and correct integration translations --- custom_components/wiser/strings.json | 14 +- custom_components/wiser/translations/de.json | 46 +-- .../wiser/translations/en-GB.json | 372 ++++++++++++++++++ custom_components/wiser/translations/en.json | 16 +- custom_components/wiser/translations/fr.json | 50 +-- 5 files changed, 435 insertions(+), 63 deletions(-) create mode 100644 custom_components/wiser/translations/en-GB.json diff --git a/custom_components/wiser/strings.json b/custom_components/wiser/strings.json index 052be864..29d83d04 100755 --- a/custom_components/wiser/strings.json +++ b/custom_components/wiser/strings.json @@ -4,7 +4,7 @@ "step": { "user": { "title": "Wiser Heat Hub Setup", - "description": "Please enter the ip address and secret key obtained from the hub.", + "description": "Please enter the IP address and secret key obtained from the hub.", "data": { "host": "IP Address or Hostname", "port": "Port number", @@ -27,10 +27,10 @@ "not_wiser_hub": "The discovered device is not a Wiser Heat Hub." }, "error": { - "auth_failure": "Unable to authenticate with the Wiser Hub. Check the secret key and try again.", - "timeout_error": "Timed out trying to connect to the Wiser Hub. Check the IP address and try again.", - "timeout_error_discovery": "Timed out trying to connect to the Wiser Hub. Check your hub is still online and try again.", - "unknown": "Unknown error connecting to the Wiser hub. Please check the logs." + "auth_failure": "Unable to authenticate with the Wiser hub. Check the secret key and try again.", + "timeout_error": "Timed out trying to connect to the Wiser hub. Check the IP address and try again.", + "timeout_error_discovery": "Timed out trying to connect to the Wiser hub. Check that your hub is still online and try again.", + "unknown": "Unknown error connecting to the Wiser hub. Please check the logs." } }, "options": { @@ -67,12 +67,12 @@ "heating_boost_time": "Default Heating Boost Duration (mins)", "hotwater_boost_time": "Default Hot Water Boost Duration (mins)", "setpoint_mode": "Setpoint Mode", - "restore_manual_temp_option": "Use This Temperature If No Stored Manual Temperature" + "restore_manual_temp_option": "Use This Temperature If No Manual Temperature Is Stored" } }, "automation_params": { "title": "Wiser Integration Options", - "description": "Enable in-built automations", + "description": "Enable built-in automations", "sections": { "automations_passive_mode": { "name": "Passive Mode", diff --git a/custom_components/wiser/translations/de.json b/custom_components/wiser/translations/de.json index e7aaf3a3..880bbc80 100644 --- a/custom_components/wiser/translations/de.json +++ b/custom_components/wiser/translations/de.json @@ -3,21 +3,21 @@ "flow_title": "{name}", "step": { "user": { - "title": "Wiser Heat Hub Setup", - "description": "Bitte gib die IP-Adresse und API Schl\u00fcssel vom Wiser Heat Hub ein", + "title": "Wiser Heat Hub einrichten", + "description": "Bitte geben Sie die IP-Adresse und den geheimen Schlüssel des Wiser Heat Hubs ein.", "data": { - "host": "IP Adresse", + "host": "IP-Adresse oder Hostname", "port": "Portnummer", - "password": "API Schl\u00fcssel" + "password": "Geheimer Schlüssel" } }, "zeroconf_confirm": { - "title": "Wiser Heat Hub Setup ({name})", + "title": "Wiser Heat Hub einrichten ({name})", "description": "Bitte geben Sie den geheimen Schlüssel ein, den Sie vom Hub erhalten haben.", "data": { - "host": "IP Adresse", + "host": "IP-Adresse oder Hostname", "port": "Portnummer", - "password": "API Schl\u00fcssel" + "password": "Geheimer Schlüssel" } } }, @@ -27,20 +27,20 @@ "not_wiser_hub": "Das erkannte Gerät ist kein Wiser Heat Hub." }, "error": { - "auth_failure": "Authentifizierung mit Wiser Heat Hub fehlgeschlagen. Pr\u00fcfe den API Key und versuche es erneut.", - "timeout_error": "Timeout bei der Verbindung zum Wiser Heat Hub. Pr\u00fcfe die IP Adresse und versuche es erneut.", - "timeout_error_discovery": "Timeout bei der Verbindung zum Wiser Heat Hub. Überprüfen Sie, ob Ihr Hub noch online ist, und versuchen Sie es erneut.", + "auth_failure": "Authentifizierung beim Wiser Heat Hub fehlgeschlagen. Überprüfen Sie den geheimen Schlüssel und versuchen Sie es erneut.", + "timeout_error": "Zeitüberschreitung bei der Verbindung zum Wiser Heat Hub. Überprüfen Sie die IP-Adresse und versuchen Sie es erneut.", + "timeout_error_discovery": "Zeitüberschreitung bei der Verbindung zum Wiser Heat Hub. Überprüfen Sie, ob Ihr Hub noch online ist, und versuchen Sie es erneut.", "unknown": "Unbekannter Fehler beim Verbinden mit dem Wiser Heat Hub. Bitte überprüfen Sie die Protokolle." } }, "options": { "step": { "init": { - "title": "Wiser Integrationsoptionen", + "title": "Wiser-Integrationsoptionen", "description": "Wiser-Parameter ändern.", "menu_options": { "main_params": "Hauptparameter", - "automation_params": "Aktivieren Sie integrierte Automatisierungen", + "automation_params": "Automatisierungsparameter", "opentherm_sensors": "OpenTherm-Sensoren", "ui_options": "UI-Optionen" } @@ -57,21 +57,21 @@ } }, "main_params": { - "title": "Wiser Integrationsoptionen", + "title": "Wiser-Integrationsoptionen", "description": "Hauptparameter", "data": { - "host": "IP Adresse", + "host": "IP-Adresse oder Hostname", "port": "Portnummer", - "scan_interval": "Scan Intervall", - "heating_boost_temp": "Boost Temperatur", - "heating_boost_time": "Boost Dauer", - "hotwater_boost_time": "Standard-Warmwasser-Boost-Dauer", + "scan_interval": "Abfrageintervall (Sek.)", + "heating_boost_temp": "Standard-Heizungs-Boost-Temperatur (°C)", + "heating_boost_time": "Standard-Heizungs-Boost-Dauer (Min.)", + "hotwater_boost_time": "Standard-Warmwasser-Boost-Dauer (Min.)", "setpoint_mode": "Sollwert-Modus", "restore_manual_temp_option": "Verwenden Sie diese Temperatur, wenn keine gespeicherte manuelle Temperatur vorhanden ist" } }, "automation_params": { - "title": "Wiser Integrationsoptionen", + "title": "Wiser-Integrationsoptionen", "description": "Aktivieren Sie integrierte Automatisierungen", "sections": { "automations_passive_mode": { @@ -152,7 +152,7 @@ "boiler_hw_setpoint_transfer_enable": "Übertragung des Kessel-Warmwassersollwerts aktiviert", "boiler_hw_setpoint_upper_bound": "Obere Grenze des Kessel-Warmwassersollwerts", "hw_enabled": "Warmwasser aktiviert", - "hw_flow_setpoint": "Warmwasser-Durchflusssollwert" + "hw_flow_setpoint": "Warmwasser-Vorlaufsolltemperatur" } }, "opentherm_status": { @@ -341,7 +341,7 @@ "delta_t": { "name": "Delta-T" }, "estimated_boiler_output": { "name": "Geschätzte Kesselleistung" }, "hw_flow_rate": { "name": "Warmwasser-Durchfluss" }, - "hw_flow_setpoint": { "name": "Warmwasser-Durchflusssollwert" }, + "hw_flow_setpoint": { "name": "Warmwasser-Vorlaufsolltemperatur" }, "hw_temperature": { "name": "Warmwassertemperatur" }, "maximum_capacity_kw": { "name": "Maximale Kesselleistung" }, "minimum_modulation_level": { "name": "Minimale Modulationsstufe" }, @@ -365,8 +365,8 @@ "started_heating": "{entity_name} beginnt zu heizen", "stopped_heating": "{entity_name} stoppt die Heizung", "boosted": "{entity_name} wird verstärkt", - "target_temperature_increased": "{entity_name} zieltemperatur erhöht", - "target_temperature_decreased": "{entity_name} zieltemperatur gesenkt" + "target_temperature_increased": "Die Zieltemperatur von {entity_name} steigt", + "target_temperature_decreased": "Die Zieltemperatur von {entity_name} sinkt" } } } diff --git a/custom_components/wiser/translations/en-GB.json b/custom_components/wiser/translations/en-GB.json new file mode 100644 index 00000000..ac2de4cc --- /dev/null +++ b/custom_components/wiser/translations/en-GB.json @@ -0,0 +1,372 @@ +{ + "config": { + "flow_title": "{name}", + "step": { + "user": { + "title": "Wiser Heat Hub Setup", + "description": "Please enter the IP address and secret key obtained from the hub.", + "data": { + "host": "IP Address or Hostname", + "port": "Port number", + "password": "Secret Key" + } + }, + "zeroconf_confirm": { + "title": "Wiser Heat Hub Setup ({name})", + "description": "Please enter the secret key obtained from the hub.", + "data": { + "host": "IP Address or Hostname", + "port": "Port number", + "password": "Secret Key" + } + } + }, + "abort": { + "already_in_progress": "Wiser Heat Hub configuration is already in progress.", + "already_configured": "This device is already configured.", + "not_wiser_hub": "The discovered device is not a Wiser Heat Hub." + }, + "error": { + "auth_failure": "Unable to authenticate with the Wiser hub. Check the secret key and try again.", + "timeout_error": "Timed out trying to connect to the Wiser hub. Check the IP address and try again.", + "timeout_error_discovery": "Timed out trying to connect to the Wiser hub. Check that your hub is still online and try again.", + "unknown": "Unknown error connecting to the Wiser hub. Please check the logs." + } + }, + "options": { + "step": { + "init": { + "title": "Wiser Integration Options", + "description": "Select parameters to amend", + "menu_options": { + "main_params": "Main Parameters", + "automation_params": "Automation Parameters", + "opentherm_sensors": "OpenTherm sensors", + "ui_options": "UI options" + } + }, + "ui_options": { + "title": "UI options", + "data": { + "legacy_naming": "Legacy naming", + "show_schedules_sidebar": "Show Wiser Schedules in sidebar", + "show_zigbee_sidebar": "Show Wiser Zigbee in sidebar" + }, + "data_description": { + "legacy_naming": "Include room names in Wiser device names. If enabled, using Home Assistant to regenerate entity IDs with the default format in Settings → System → Entity ID format (Home Assistant 2026.8 and later) will duplicate area names when the area and Wiser room names match. Changing this option does not rename existing entity IDs." + } + }, + "main_params": { + "title": "Wiser Integration Options", + "description": "Main Parameters", + "data": { + "host": "IP Address or Hostname", + "port": "Port number", + "scan_interval": "Scan Interval (secs)", + "heating_boost_temp": "Default Heating Boost Temperature (°C)", + "heating_boost_time": "Default Heating Boost Duration (mins)", + "hotwater_boost_time": "Default Hot Water Boost Duration (mins)", + "setpoint_mode": "Setpoint Mode", + "restore_manual_temp_option": "Use This Temperature If No Manual Temperature Is Stored" + } + }, + "automation_params": { + "title": "Wiser Integration Options", + "description": "Enable built-in automations", + "sections": { + "automations_passive_mode": { + "name": "Passive Mode", + "description": "Enable passive TRV capability. Each room needs to be enabled for it to function.", + "data": { + "automations_passive_mode": "Passive Mode", + "passive_mode_temperature_increments": "Passive Mode Temperature Increments" + } + }, + "hotwater_climate": { + "name": "Hot Water Climate Control", + "description": "Enable hot-water climate control. See the wiki for details.", + "data": { + "hotwater_climate": "Enable the climate entity", + "experimental_mode": "Enable experimental working mode", + "hotwater_auto_mode": "Hot Water Auto Mode", + "hotwater_heat_mode": "Hot Water Heat Mode", + "hotwater_boost_mode": "Hot Water Boost Mode", + "hotwater_sensor_entity_id": "Hot Water Temperature Sensor" + } + } + } + }, + "opentherm_sensors": { + "title": "OpenTherm sensors", + "description": "Choose a category of detected OpenTherm attributes.", + "menu_options": { + "opentherm_readings": "Readings", + "opentherm_central_heating": "Central heating", + "opentherm_hot_water": "Hot water", + "opentherm_status": "Status and diagnostics" + } + }, + "opentherm_readings": { + "title": "OpenTherm readings", + "description": "Choose which detected OpenTherm readings are exposed as sensor entities.", + "data": { + "ch_flow_temperature": "Boiler flow temperature", + "ch_pressure_bar": "CH pressure", + "ch_return_temperature": "Boiler return temperature", + "delta_t": "Delta-T", + "boiler_exhaust_temperature": "Boiler exhaust temperature", + "estimated_boiler_output": "Estimated boiler output", + "hw_flow_rate": "Hot water flow rate", + "hw_temperature": "Hot water temperature", + "maximum_capacity_kw": "Maximum boiler capacity", + "minimum_modulation_level": "Minimum modulation level", + "relative_modulation_level": "Relative modulation level", + "room_temperature": "Room temperature" + } + }, + "opentherm_central_heating": { + "title": "OpenTherm central heating", + "description": "Choose which detected central-heating attributes are exposed as entities.", + "data": { + "boiler_ch_max_setpoint_read_write": "Boiler CH maximum setpoint read/write", + "boiler_ch_max_setpoint_transfer_enable": "Boiler CH maximum setpoint transfer enabled", + "boiler_ch_setpoint": "Boiler CH setpoint", + "boiler_ch_setpoint_lower_bound": "Boiler CH setpoint lower bound", + "boiler_ch_setpoint_upper_bound": "Boiler CH setpoint upper bound", + "ch_flow_active_lower_setpoint": "CH flow active lower setpoint", + "ch_flow_active_upper_setpoint": "CH flow active upper setpoint", + "ch1_flow_enabled": "CH1 flow enabled", + "ch1_flow_setpoint": "CH1 flow setpoint", + "ch2_flow_enabled": "CH2 flow enabled", + "ch2_flow_setpoint": "CH2 flow setpoint", + "room_setpoint": "Room setpoint" + } + }, + "opentherm_hot_water": { + "title": "OpenTherm hot water", + "description": "Choose which detected hot-water attributes are exposed as entities.", + "data": { + "boiler_hw_setpoint": "Boiler hot water setpoint", + "boiler_hw_setpoint_lower_bound": "Boiler hot water setpoint lower bound", + "boiler_hw_setpoint_read_write": "Boiler hot water setpoint read/write", + "boiler_hw_setpoint_transfer_enable": "Boiler hot water setpoint transfer enabled", + "boiler_hw_setpoint_upper_bound": "Boiler hot water setpoint upper bound", + "hw_enabled": "Hot water enabled", + "hw_flow_setpoint": "Hot water flow setpoint" + } + }, + "opentherm_status": { + "title": "OpenTherm status and diagnostics", + "description": "Choose which detected status and diagnostic attributes are exposed as sensor entities.", + "data": { + "boiler_fault": "Boiler fault", + "central_heating_active": "Central heating active", + "central_heating_2_active": "Central heating 2 active", + "connection_status": "Connection status", + "coprocessor_update_status": "OpenTherm coprocessor update status", + "coprocessor_version": "OpenTherm coprocessor version", + "cooling_active": "Cooling active", + "diagnostic_event": "Diagnostic event", + "flame_active": "Flame active", + "flame_statistics": "Flame statistics", + "hot_water_active": "Hot water active", + "operating_mode": "Operating mode", + "slave_status": "OpenTherm slave status", + "tracked_room_id": "Tracked room ID" + } + } + }, + "abort": { + "opentherm_not_available": "OpenTherm data is not available for this Wiser hub." + } + }, + "services": { + "set_opentherm_parameter": { + "name": "Set OpenTherm parameter", + "description": "Changes a supported OpenTherm temperature parameter on the Wiser hub.", + "fields": { + "parameter": { + "name": "Parameter", + "description": "OpenTherm temperature parameter to change. The required API endpoint is selected automatically." + }, + "temperature": { + "name": "Temperature", + "description": "Use a temperature within the limits reported by your boiler." + }, + "hub": { + "name": "Wiser hub", + "description": "Only select a hub when you have multiple Wiser hubs." + } + } + } + }, + "selector": { + "opentherm_parameter": { + "options": { + "chFlowActiveLowerSetpoint": "Active central-heating lower setpoint", + "chFlowActiveUpperSetpoint": "Active central-heating upper setpoint", + "dhwFlowSetpoint": "Hub hot-water flow setpoint", + "dhwSetpoint": "Boiler hot-water setpoint", + "maxChSetpoint": "Boiler maximum central-heating setpoint" + } + } + }, + "exceptions": { + "opentherm_temperature_required": { "message": "Please provide an OpenTherm temperature." }, + "opentherm_hub_not_found": { "message": "The specified Wiser hub was not found." }, + "opentherm_hub_not_loaded": { "message": "The specified Wiser hub is not loaded." }, + "opentherm_hub_required": { "message": "Please select a Wiser hub when more than one hub is configured." }, + "opentherm_not_supported": { "message": "This hub does not have OpenTherm functionality." }, + "opentherm_invalid_parameter": { "message": "The OpenTherm parameter or value is invalid: {error}" }, + "opentherm_write_failed": { "message": "Unable to set OpenTherm parameter {parameter}: {error}" }, + "opentherm_confirmation_failed": { "message": "OpenTherm parameter {parameter} did not remain at {requested} °C after one retry and the {window}-second confirmation window. Wiser reports {reported} °C. No further retry will be sent." }, + "opentherm_retry_failed": { "message": "OpenTherm parameter {parameter} did not remain at {requested} °C, and its retry could not be sent: {error}. Wiser reports {reported} °C. No further retry will be sent." }, + "opentherm_notification_title": { "message": "Wiser OpenTherm command" } + }, + "entity": { + "climate": { + "heating": { + "name": "Heating" + }, + "floor_temperature": { "name": "Floor temperature" } + }, + "number": { + "away_mode_target_temperature": { "name": "Away mode target temperature" }, + "floor_temperature_offset": { "name": "Floor temperature offset" }, + "indoor_discomfort_temperature": { "name": "Indoor discomfort temperature" }, + "outdoor_discomfort_temperature": { "name": "Outdoor discomfort temperature" } + }, + "select": { + "mode": { "name": "Mode" }, + "power_on_behavior": { "name": "Power-on behaviour" }, + "led_indicator": { "name": "LED indicator" } + }, + "button": { + "boost_all_heating": { "name": "Boost all heating" }, + "cancel_all_heating_overrides": { "name": "Cancel all heating overrides" }, + "boost_hot_water": { "name": "Boost hot water" }, + "cancel_hot_water_overrides": { "name": "Cancel hot water overrides" }, + "toggle_hot_water": { "name": "Toggle hot water" }, + "moment": { "name": "Moment: {name}" } + }, + "switch": { + "valve_protection": { "name": "Valve protection" }, + "eco_mode": { "name": "Eco mode" }, + "away_mode_affects_hot_water": { "name": "Away mode affects hot water" }, + "comfort_mode": { "name": "Comfort mode" }, + "away_mode": { "name": "Away mode" }, + "daylight_saving": { "name": "Daylight saving" }, + "summer_comfort_enabled": { "name": "Summer comfort enabled" }, + "window_detection": { "name": "Window detection" }, + "include_in_summer_comfort": { "name": "Include in summer comfort" }, + "device_lock": { "name": "Device lock" }, + "identify": { "name": "Identify" }, + "outlet": { "name": "Socket" }, + "away_mode_turns_off": { "name": "Away mode turns off" }, + "away_mode_closes": { "name": "Away mode closes" }, + "passive_mode": { "name": "Passive mode" }, + "respect_summer_comfort": { "name": "Respect summer comfort" }, + "interacts_with_room_climate": { "name": "Interacts with room climate" }, + "humidity_interacts_with_room_climate": { "name": "Humidity interacts with room climate" }, + "temperature_interacts_with_room_climate": { "name": "Temperature interacts with room climate" }, + "illuminance_interacts_with_room_climate": { "name": "Illuminance interacts with room climate" }, + "sensor_interacts_with_room_climate": { "name": "{sensor} interacts with room climate" }, + "manual_heat": { "name": "Manual heat" }, + "hot_water": { "name": "Hot water" } + }, + "binary_sensor": { + "summer_discomfort_prevention": { "name": "Summer discomfort prevention" }, + "summer_comfort_available": { "name": "Summer comfort available" }, + "pcm_device_limit_reached": { "name": "PCM device limit reached" }, + "smoke_alarm": { "name": "Smoke alarm" }, + "heat_alarm": { "name": "Heat alarm" }, + "tamper_alarm": { "name": "Tamper alarm" }, + "fault_warning": { "name": "Fault warning" }, + "remote_alarm": { "name": "Remote alarm" }, + "battery_defect": { "name": "Battery defect" }, + "controllable": { "name": "Controllable" }, + "pcm_mode": { "name": "PCM mode" }, + "window_detection_active": { "name": "Window detection active" }, + "is_dimmable": { "name": "Dimmable" }, + "is_led_indicator_supported": { "name": "LED indicator supported" }, + "is_output_mode_supported": { "name": "Output mode supported" }, + "is_power_on_behaviour_supported": { "name": "Power-on behaviour supported" }, + "is_tilt_supported": { "name": "Tilt supported" }, + "is_open": { "name": "Open" }, + "is_closed": { "name": "Closed" }, + "active": { "name": "Active" }, + "boiler_ch_max_setpoint_read_write": { "name": "Boiler CH maximum setpoint read/write" }, + "boiler_ch_max_setpoint_transfer_enable": { "name": "Boiler CH maximum setpoint transfer enabled" }, + "boiler_fault": { "name": "Boiler fault" }, + "boiler_hw_setpoint_read_write": { "name": "Boiler hot water setpoint read/write" }, + "boiler_hw_setpoint_transfer_enable": { "name": "Boiler hot water setpoint transfer enabled" }, + "central_heating_2_active": { "name": "Central heating 2 active" }, + "central_heating_active": { "name": "Central heating active" }, + "ch1_flow_enabled": { "name": "CH1 flow enabled" }, + "ch2_flow_enabled": { "name": "CH2 flow enabled" }, + "cooling_active": { "name": "Cooling active" }, + "diagnostic_event": { "name": "Diagnostic event" }, + "flame_active": { "name": "Flame active" }, + "hot_water_active": { "name": "Hot water active" }, + "hw_enabled": { "name": "Hot water enabled" } + }, + "sensor": { + "signal": { "name": "Signal" }, + "cloud": { "name": "Cloud" }, + "heating_operation_mode": { "name": "Heating operation mode" }, + "heating": { "name": "Heating" }, + "heating_channel": { "name": "Heating channel {channel}" }, + "hot_water": { "name": "Hot water" }, + "hot_water_operation_mode": { "name": "Hot water operation mode" }, + "target_temperature": { "name": "Target temperature" }, + "floor_temperature": { "name": "Floor temperature" }, + "boiler_flow_temperature": { "name": "Boiler flow temperature" }, + "boiler_return_temperature": { "name": "Boiler return temperature" }, + "flame_statistics": { "name": "Flame statistics" }, + "boiler_ch_setpoint": { "name": "Boiler CH setpoint" }, + "boiler_ch_setpoint_lower_bound": { "name": "Boiler CH setpoint lower bound" }, + "boiler_ch_setpoint_upper_bound": { "name": "Boiler CH setpoint upper bound" }, + "boiler_exhaust_temperature": { "name": "Boiler exhaust temperature" }, + "boiler_hw_setpoint": { "name": "Boiler hot water setpoint" }, + "boiler_hw_setpoint_lower_bound": { "name": "Boiler hot water setpoint lower bound" }, + "boiler_hw_setpoint_upper_bound": { "name": "Boiler hot water setpoint upper bound" }, + "ch1_flow_setpoint": { "name": "CH1 flow setpoint" }, + "ch2_flow_setpoint": { "name": "CH2 flow setpoint" }, + "ch_flow_active_lower_setpoint": { "name": "CH flow active lower setpoint" }, + "ch_flow_active_upper_setpoint": { "name": "CH flow active upper setpoint" }, + "ch_pressure_bar": { "name": "CH pressure" }, + "connection_status": { "name": "Connection status" }, + "coprocessor_update_status": { "name": "OpenTherm coprocessor update status" }, + "coprocessor_version": { "name": "OpenTherm coprocessor version" }, + "delta_t": { "name": "Delta-T" }, + "estimated_boiler_output": { "name": "Estimated boiler output" }, + "hw_flow_rate": { "name": "Hot water flow rate" }, + "hw_flow_setpoint": { "name": "Hot water flow setpoint" }, + "hw_temperature": { "name": "Hot water temperature" }, + "maximum_capacity_kw": { "name": "Maximum boiler capacity" }, + "minimum_modulation_level": { "name": "Minimum modulation level" }, + "operating_mode": { "name": "Operating mode" }, + "relative_modulation_level": { "name": "Relative modulation level" }, + "room_setpoint": { "name": "Room setpoint" }, + "room_temperature": { "name": "Room temperature" }, + "slave_status": { "name": "OpenTherm slave status" }, + "tracked_room_id": { "name": "Tracked room ID" }, + "heating_demand": { "name": "Heating demand" }, + "heating_demand_channel": { "name": "Heating demand channel {channel}" }, + "hot_water_demand": { "name": "Hot water demand" }, + "total_energy": { "name": "Total energy" }, + "energy_delivered": { "name": "Energy delivered" }, + "energy_received": { "name": "Energy received" }, + "equipment_power": { "name": "Equipment power" } + } + }, + "device_automation": { + "trigger_type": { + "started_heating": "{entity_name} starts heating", + "stopped_heating": "{entity_name} stops heating", + "boosted": "{entity_name} is boosted", + "target_temperature_increased": "{entity_name} target temperature increased", + "target_temperature_decreased": "{entity_name} target temperature decreased" + } + } +} diff --git a/custom_components/wiser/translations/en.json b/custom_components/wiser/translations/en.json index 449f4077..7b15cc2e 100755 --- a/custom_components/wiser/translations/en.json +++ b/custom_components/wiser/translations/en.json @@ -4,7 +4,7 @@ "step": { "user": { "title": "Wiser Heat Hub Setup", - "description": "Please enter the ip address and secret key obtained from the hub.", + "description": "Please enter the IP address and secret key obtained from the hub.", "data": { "host": "IP Address or Hostname", "port": "Port number", @@ -13,7 +13,7 @@ }, "zeroconf_confirm": { "title": "Wiser Heat Hub Setup ({name})", - "description": "Please enter the secret key obtained from the hub", + "description": "Please enter the secret key obtained from the hub.", "data": { "host": "IP Address or Hostname", "port": "Port number", @@ -27,10 +27,10 @@ "not_wiser_hub": "The discovered device is not a Wiser Heat Hub." }, "error": { - "auth_failure": "Unable to authenticate with the Wiser Hub. Check the secret key and try again.", - "timeout_error": "Timed out trying to connect to the Wiser Hub. Check the IP address and try again.", - "timeout_error_discovery": "Timed out trying to connect to the Wiser Hub. Check your hub is still online and try again.", - "unknown": "Unknown error connecting to the Wiser hub. Please check the logs." + "auth_failure": "Unable to authenticate with the Wiser hub. Check the secret key and try again.", + "timeout_error": "Timed out trying to connect to the Wiser hub. Check the IP address and try again.", + "timeout_error_discovery": "Timed out trying to connect to the Wiser hub. Check that your hub is still online and try again.", + "unknown": "Unknown error connecting to the Wiser hub. Please check the logs." } }, "options": { @@ -67,12 +67,12 @@ "heating_boost_time": "Default Heating Boost Duration (mins)", "hotwater_boost_time": "Default Hot Water Boost Duration (mins)", "setpoint_mode": "Setpoint Mode", - "restore_manual_temp_option": "Use This Temperature If No Stored Manual Temperature" + "restore_manual_temp_option": "Use This Temperature If No Manual Temperature Is Stored" } }, "automation_params": { "title": "Wiser Integration Options", - "description": "Enable in-built automations", + "description": "Enable built-in automations", "sections": { "automations_passive_mode": { "name": "Passive Mode", diff --git a/custom_components/wiser/translations/fr.json b/custom_components/wiser/translations/fr.json index 9ae09dc5..428362f8 100644 --- a/custom_components/wiser/translations/fr.json +++ b/custom_components/wiser/translations/fr.json @@ -4,20 +4,20 @@ "step": { "user": { "title": "Configuration de la Box Wiser", - "description": "Entrez l'adresse IP et la clé secrète SVP.", + "description": "Veuillez saisir l’adresse IP et la clé secrète obtenue auprès de la box Wiser.", "data": { - "host": "Adresse IP ou nom d'hote", + "host": "Adresse IP ou nom d’hôte", "port": "Numéro de port", - "password": "Clé Secrète" + "password": "Clé secrète" } }, "zeroconf_confirm": { "title": "Configuration de la Box Wiser ({name})", "description": "Entrez la clé secrète obtenue de la Box Wiser.", "data": { - "host": "Adresse IP ou nom d'hote", + "host": "Adresse IP ou nom d’hôte", "port": "Numéro de port", - "password": "Clé Secrète" + "password": "Clé secrète" } } }, @@ -27,16 +27,16 @@ "not_wiser_hub": "L’appareil détecté n’est pas une passerelle Wiser." }, "error": { - "auth_failure": "Authentification après de la Wiser Box impossible. Controlez la clé secrète et rééssayez.", - "timeout_error": "Timed out de la connection à la Box Wiser. Controlez l'adresse IP et rééssayez.", - "timeout_error_discovery": "Timed out de la connection à la Box Wiser. Vérifiez que votre Box Wiser est toujours en ligne et rééssayer.", - "unknown": "Erreur inconnue lors de la connexion à la Box Wiser. Controlez les logs, SVP." + "auth_failure": "Impossible de s’authentifier auprès de la box Wiser. Vérifiez la clé secrète et réessayez.", + "timeout_error": "Le délai de connexion à la box Wiser a expiré. Vérifiez l’adresse IP et réessayez.", + "timeout_error_discovery": "Le délai de connexion à la box Wiser a expiré. Vérifiez que votre box Wiser est toujours en ligne et réessayez.", + "unknown": "Erreur inconnue lors de la connexion à la box Wiser. Veuillez consulter les journaux." } }, "options": { "step": { "init": { - "title": "Wiser possibilités d'intégration", + "title": "Options de l’intégration Wiser", "description": "Réglages des paramètres Wiser.", "menu_options": { "main_params": "Paramètres principaux", @@ -57,21 +57,21 @@ } }, "main_params": { - "title": "Wiser possibilités d'intégration", + "title": "Options de l’intégration Wiser", "description": "Paramètres principaux", "data": { - "host": "Adresse IP ou nom d'hote", + "host": "Adresse IP ou nom d’hôte", "port": "Numéro de port", - "scan_interval": " Période d'acquisition", - "heating_boost_temp": "Défault temperature de boost chauffage", - "heating_boost_time": "Défault durée de boost chauffage", - "hotwater_boost_time": "Défault durée de boost eau chaude", - "setpoint_mode": "Mode de fonctionnement consigne", - "restore_manual_temp_option": "Utilisez cette température si aucune température manuelle stockée" + "scan_interval": "Intervalle d’actualisation (s)", + "heating_boost_temp": "Température de boost du chauffage par défaut (°C)", + "heating_boost_time": "Durée de boost du chauffage par défaut (min)", + "hotwater_boost_time": "Durée de boost de l’eau chaude par défaut (min)", + "setpoint_mode": "Mode de consigne", + "restore_manual_temp_option": "Utiliser cette température si aucune température manuelle n’est enregistrée" } }, "automation_params": { - "title": "Wiser possibilités d'intégration", + "title": "Options de l’intégration Wiser", "description": "Activer les automatisations intégrées", "sections": { "automations_passive_mode": { @@ -152,7 +152,7 @@ "boiler_hw_setpoint_transfer_enable": "Transfert de la consigne d’eau chaude activé", "boiler_hw_setpoint_upper_bound": "Limite supérieure de la consigne d’eau chaude", "hw_enabled": "Eau chaude activée", - "hw_flow_setpoint": "Consigne de débit d’eau chaude" + "hw_flow_setpoint": "Consigne de température de départ d’eau chaude" } }, "opentherm_status": { @@ -341,7 +341,7 @@ "delta_t": { "name": "Delta-T" }, "estimated_boiler_output": { "name": "Puissance estimée de la chaudière" }, "hw_flow_rate": { "name": "Débit d’eau chaude" }, - "hw_flow_setpoint": { "name": "Consigne de débit d’eau chaude" }, + "hw_flow_setpoint": { "name": "Consigne de température de départ d’eau chaude" }, "hw_temperature": { "name": "Température de l’eau chaude" }, "maximum_capacity_kw": { "name": "Puissance maximale de la chaudière" }, "minimum_modulation_level": { "name": "Niveau minimal de modulation" }, @@ -362,11 +362,11 @@ }, "device_automation": { "trigger_type": { - "started_heating": "{entity_name} chauffe démarrée", - "stopped_heating": "{entity_name} chauffe arrêté", + "started_heating": "{entity_name} commence à chauffer", + "stopped_heating": "{entity_name} cesse de chauffer", "boosted": "{entity_name} est boosté", - "target_temperature_increased": "{entity_name} température cible a diminué", - "target_temperature_decreased": "{entity_name} température cible augmentée" + "target_temperature_increased": "La température cible de {entity_name} augmente", + "target_temperature_decreased": "La température cible de {entity_name} diminue" } } } From ef205f21f52f4215e8204d736918d4ad72742198 Mon Sep 17 00:00:00 2001 From: asantaga Date: Sat, 19 Sep 2026 23:06:12 +0100 Subject: [PATCH 026/154] documentation for 4.0.0-rc1 --- README.md | 45 ++++++++++++++++++++++----- custom_components/wiser/const.py | 2 +- custom_components/wiser/manifest.json | 2 +- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index babf2006..ac200d02 100755 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Wiser Home Assistant Integration v3.4.21b0 +# Wiser Home Assistant Integration v4.0.0-rc1 [![hacs_badge](https://img.shields.io/badge/HACS-Default-orange.svg?style=for-the-badge)](https://github.com/hacs/integration) [![downloads](https://shields.io/github/downloads/asantaga/wiserHomeAssistantPlatform/latest/total?style=for-the-badge)](https://github.com/asantaga/wiserHomeAssistantPlatform) @@ -18,6 +18,19 @@ Detailed information about this integration has now been moved to our [Wiki page For more information checkout the AMAZING community thread available on [https://community.home-assistant.io/t/drayton-wiser-home-assistant-integration/80965](https://community.home-assistant.io/t/drayton-wiser-home-assistant-integration/80965) +## What's New in 4.0? + +This is a big release with a lot of bug fixes and changes. +- Entity and device naming now follows new Home Assistant conventions, where devices are associated with areas. Existing installations keep their current names automatically via the Legacy naming option - turn it off to adopt the new names +- New Wiser devices are assigned to Home Assistant areas matching your Wiser rooms +- Configurable OpenTherm monitoring and controls +- Brand new UI for Wiser Schedules and Wiser Zigbee, including optional sidebar panels +- Multiple bug fixes + +Huge thanks to [@andyblac](https://github.com/andyblac) and [@lgo44](https://github.com/LGO44) for this release + +See the change log for the full list of breaking changes before upgrading. + ## What's New in 3.4? - Added support for v2 hub @@ -30,14 +43,30 @@ For more information checkout the AMAZING community thread available on ## Change log -- v3.4.21b0 - - Added a Hot Water on/off switch entity - issue [#626](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/626). +- v4.0.0-rc1 + - **Breaking change:** the device registry is restructured. The separate virtual controller device is merged into the physical hub device, and Wiser room devices move to stable identifiers. In both cases the old device is removed and its entities are reassigned to the surviving device. Entity IDs and history are preserved, but anything that targets a Wiser *device* rather than an entity - device-based automations and scripts, or dashboard cards pointing at a device - needs repointing - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693). + - **Breaking change:** entity unique IDs migrate to deterministic UUIDv5. The migration runs automatically on upgrade and renames registry entries in place, so entity IDs, history, and customisations are preserved. Every target is checked before any change is applied, so it cannot partially apply, but it aborts if it finds a unique ID collision - take a backup before upgrading - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693). + - Entity naming now follows Home Assistant conventions, using `has_entity_name` so Home Assistant composes each displayed name from the device name plus the entity name. Existing entity IDs are not renamed. A new **Legacy naming** option controls whether Wiser room names are included in device names; it is switched on automatically for existing installations, so your device names stay as they are unless you turn it off. New installations on Home Assistant 2026.8 and later default it to off - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693), PR [#700](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/700). + - Wiser devices are now placed in Home Assistant areas matching their Wiser room, creating the area if it does not exist. This applies only to devices that have no area yet, so any area you assigned manually is left untouched - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693), PR [#700](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/700). + - Added configurable OpenTherm monitoring and controls, including relative modulation, a Delta-T sensor, expanded telemetry, and categorized diagnostics - PR [#697](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/697). + - Added a configurable Wiser Schedules sidebar panel - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). + - Added a Wiser Zigbee sidebar panel with a custom sidebar icon - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). + - Added a Hot Water on/off switch entity - issue [#626](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/626), PR [#682](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/682). - Added a UFH controller measured-temperature sensor - issue [#628](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/628). - - Fixed multi-gang dimmer lights breaking select, binary_sensor, switch, and sensor entities - issue [#681](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/681). - - Preserved light entities across the multi-gang unique_id migration - issue [#681](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/681). - - Added optimistic light state for instant UI feedback on toggles, kept stable across rapid repeated toggles. - - Fixed the device signal sensor to emit once per physical device instead of once per light channel on multi-gang dimmers. - - Fix for issue [#662](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/662). + - Added optimistic light state for instant UI feedback on toggles, kept stable across rapid repeated toggles - PR [#684](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/684). + - Added British English translations and corrected the German, French, and English integration translations - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). + - Reintroduced the previous Power and Energy entities, corrected equipment data naming on v2 hubs, and added an active state for the window/door sensor - issue [#677](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/677), PR [#690](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/690). + - Sidebar panel visibility is now configured through the integration's UI options - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). + - Card versions are now detected from the installed card bundles instead of being pinned in the integration, so card updates no longer need an integration release - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). + - Fixed multi-gang dimmer lights breaking select, binary_sensor, switch, and sensor entities - issue [#681](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/681), PR [#683](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/683). + - Preserved light entities across the multi-gang unique_id migration - issue [#681](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/681), PR [#683](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/683). + - Fixed the device signal sensor to emit once per physical device instead of once per light channel on multi-gang dimmers - issue [#681](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/681), PR [#683](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/683). + - Fixed the room **Window Detection Active** binary sensor being presented as a physical window sensor. It carried a `window` device class, so Home Assistant displayed it as Open/Closed as though it reported a real window, when it actually reports whether the room's window-detection feature is switched on. It now shows a plain on/off state. The underlying state values are unchanged, so automations that test for `on`/`off` keep working - only the displayed wording and icon change - PR [#703](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/703). + - Fixed away mode and frost protection reporting distinct target temperatures, and the frost protection target now honours the configured value - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693). + - Fixed the hot water switch to report against the hub as its parent device - PR [#704](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/704). + - Fixed a Zigbee sidebar route conflict that could stop the integration setting up - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). + - Fixed the boiler capacity and estimated boiler output sensors to use a gas burner icon - PR [#701](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/701). + - Fix for issue [#662](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/662) - PR [#680](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/680). - v3.4.20 - Added equipment data to smart plugs, heating actuators, and PowerTag E devices. diff --git a/custom_components/wiser/const.py b/custom_components/wiser/const.py index eb56a676..10db8e02 100755 --- a/custom_components/wiser/const.py +++ b/custom_components/wiser/const.py @@ -7,7 +7,7 @@ from enum import StrEnum -VERSION = "3.4.21b0" +VERSION = "4.0.0-rc1" DOMAIN = "wiser" CONF_LEGACY_NAMING = "legacy_naming" DATA_WISER_CONFIG = "wiser_config" diff --git a/custom_components/wiser/manifest.json b/custom_components/wiser/manifest.json index 10ef6ff3..be87b184 100755 --- a/custom_components/wiser/manifest.json +++ b/custom_components/wiser/manifest.json @@ -19,7 +19,7 @@ "requirements": [ "aioWiserHeatAPI==1.7.3" ], - "version": "3.4.21b0", + "version": "4.0.0-rc1", "zeroconf": [ { "type": "_http._tcp.local.", From 2ff55bdc8353c784f0f53dcc16db8f27b4221e30 Mon Sep 17 00:00:00 2001 From: asantaga Date: Sat, 19 Sep 2026 23:16:22 +0100 Subject: [PATCH 027/154] documentation for 4.0.0-rc1 pt2 --- README.md | 213 +++--------------------------------------------------- 1 file changed, 10 insertions(+), 203 deletions(-) diff --git a/README.md b/README.md index ac200d02..ef504541 100755 --- a/README.md +++ b/README.md @@ -29,7 +29,14 @@ This is a big release with a lot of bug fixes and changes. Huge thanks to [@andyblac](https://github.com/andyblac) and [@lgo44](https://github.com/LGO44) for this release -See the change log for the full list of breaking changes before upgrading. +### Breaking changes in 4.0 + +**Take a backup before upgrading.** + +- **The device registry is restructured.** The separate virtual controller device is merged into the physical hub device, and Wiser room devices move to stable identifiers. Entity IDs and history are preserved, but anything that targets a Wiser *device* rather than an entity - device-based automations and scripts, or dashboard cards pointing at a device - needs repointing. +- **Entity unique IDs migrate to deterministic UUIDv5.** The migration runs automatically on upgrade and renames registry entries in place, so entity IDs, history, and customisations are preserved. It cannot partially apply, but it aborts if it finds a unique ID collision. + +See the [change log](CHANGELOG.md) for the full list of changes in this release. ## What's New in 3.4? @@ -43,209 +50,9 @@ See the change log for the full list of breaking changes before upgrading. ## Change log -- v4.0.0-rc1 - - **Breaking change:** the device registry is restructured. The separate virtual controller device is merged into the physical hub device, and Wiser room devices move to stable identifiers. In both cases the old device is removed and its entities are reassigned to the surviving device. Entity IDs and history are preserved, but anything that targets a Wiser *device* rather than an entity - device-based automations and scripts, or dashboard cards pointing at a device - needs repointing - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693). - - **Breaking change:** entity unique IDs migrate to deterministic UUIDv5. The migration runs automatically on upgrade and renames registry entries in place, so entity IDs, history, and customisations are preserved. Every target is checked before any change is applied, so it cannot partially apply, but it aborts if it finds a unique ID collision - take a backup before upgrading - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693). - - Entity naming now follows Home Assistant conventions, using `has_entity_name` so Home Assistant composes each displayed name from the device name plus the entity name. Existing entity IDs are not renamed. A new **Legacy naming** option controls whether Wiser room names are included in device names; it is switched on automatically for existing installations, so your device names stay as they are unless you turn it off. New installations on Home Assistant 2026.8 and later default it to off - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693), PR [#700](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/700). - - Wiser devices are now placed in Home Assistant areas matching their Wiser room, creating the area if it does not exist. This applies only to devices that have no area yet, so any area you assigned manually is left untouched - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693), PR [#700](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/700). - - Added configurable OpenTherm monitoring and controls, including relative modulation, a Delta-T sensor, expanded telemetry, and categorized diagnostics - PR [#697](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/697). - - Added a configurable Wiser Schedules sidebar panel - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). - - Added a Wiser Zigbee sidebar panel with a custom sidebar icon - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). - - Added a Hot Water on/off switch entity - issue [#626](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/626), PR [#682](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/682). - - Added a UFH controller measured-temperature sensor - issue [#628](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/628). - - Added optimistic light state for instant UI feedback on toggles, kept stable across rapid repeated toggles - PR [#684](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/684). - - Added British English translations and corrected the German, French, and English integration translations - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). - - Reintroduced the previous Power and Energy entities, corrected equipment data naming on v2 hubs, and added an active state for the window/door sensor - issue [#677](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/677), PR [#690](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/690). - - Sidebar panel visibility is now configured through the integration's UI options - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). - - Card versions are now detected from the installed card bundles instead of being pinned in the integration, so card updates no longer need an integration release - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). - - Fixed multi-gang dimmer lights breaking select, binary_sensor, switch, and sensor entities - issue [#681](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/681), PR [#683](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/683). - - Preserved light entities across the multi-gang unique_id migration - issue [#681](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/681), PR [#683](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/683). - - Fixed the device signal sensor to emit once per physical device instead of once per light channel on multi-gang dimmers - issue [#681](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/681), PR [#683](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/683). - - Fixed the room **Window Detection Active** binary sensor being presented as a physical window sensor. It carried a `window` device class, so Home Assistant displayed it as Open/Closed as though it reported a real window, when it actually reports whether the room's window-detection feature is switched on. It now shows a plain on/off state. The underlying state values are unchanged, so automations that test for `on`/`off` keep working - only the displayed wording and icon change - PR [#703](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/703). - - Fixed away mode and frost protection reporting distinct target temperatures, and the frost protection target now honours the configured value - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693). - - Fixed the hot water switch to report against the hub as its parent device - PR [#704](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/704). - - Fixed a Zigbee sidebar route conflict that could stop the integration setting up - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). - - Fixed the boiler capacity and estimated boiler output sensors to use a gas burner icon - PR [#701](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/701). - - Fix for issue [#662](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/662) - PR [#680](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/680). - -- v3.4.20 - - Added equipment data to smart plugs, heating actuators, and PowerTag E devices. - - Added LED-indicator support for on/off and dimmable lights. - - Added seasonal-comfort controls, including the target lift for shutters. - - Added an option to hide the hot-water schedule in the Wiser Schedule Card. - - Fixed the controller signal sensor to use the HeatHub name - issue [#639](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/639). - - Fixed schedule deletion and schedule-name inputs on current Home Assistant releases - issue [#461](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/461). - -- v3.4.19 - - Fixed: Breaking change in HA 2026.2 causes integration not to load - issue [#643](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/643) - - Fixed: V2 hubs with firmware lower than 4.42.23 cannot connect on https - -- v3.4.18 - - Fixed no long term stats for temp/humidity sensors issue [#598](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/598) - - Fixed deprecated ZeroconfServiceInfo - issue [#612](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/612) - - Fixed error 500 when selecting integration config - issue [#613](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/613) - - Fixed unable to create new schedule card - issue [#616](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/616) - - Fixed schedule card badges are misaligned - issue [#615](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/615) - - Changed: Communication to v2 hub now uses https over internal network - - Bumped schedule card to v1.5.0 - - Bumped api to v1.7.0 - -- v3.4.17 - - Fixed hot water climate does not respect away mode - issue [#579](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/579) - - Fixed deprecation error sets option flow config_entry explicitly - issue [#595](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/595) - - Fixed schedule card unable to edit - issue [#607](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/607) - -- v3.4.16 - - Fix incorrect identifer on hub device - - Fix deprecation warning for access to lovelace resource parameters - - Fix error on unloading services for hubs without hot water control - - Fix deprecation warning for ZeroconfServiceInfo - - Bump api to v1.6.6 to support SSL for future firmware - -- v3.4.15 - - Added experimental hw climate mode to operate differently. See wiki for details - - Changed min/max hw climate temp range from 40-80C to 10-80C - issue [#545](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/545) - - Fixed issue whereby hw climate errors if temp sensor not available after HA start - issue [#541](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/541) - - Fixed issue whereby hw climate config requires some entry in the temp sensor select option, even if not enabled - issue [#544](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/544) - - Fixed issue whereby hw min does not change when setting both via service call if temps are 1C or less different - issue [#547](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/547) - -- v3.4.14 - - Fixed issue causing integration not to load in some circumstances due to failed config entry migration - issue #539 - - Added binary sensor active state sensor - -- v3.4.13 - - Added support for PowerTag C - issue #528 - - BREAKING CHANGE - refactored HW climate automation - issues #481, #490. See wiki for updated instructions - - Added illuminance, humidity and temp sensors to devices with threshold sensors - issue #531 - - Added support for 2 gang light switch - issue #529 - - Added interacts with room climate switch to supported devices - - Fixed support for Binary sensors with threshold sensors - issue #530 - - Fixed incompatibility with Python3.13 and HA2024.12 - issue #535 - - Fixed events not correctly firing for climate changes - issue #526 - - Fixed error when saving schedule with an off slot - issue #536 - - Changed all hot water related sensors to now belong to a hot water device - - Bumped aiowiserheatapi to v1.6.3 - -- v3.4.12 - - Fixed issue assigning schedules with non ascii characters in name - issue #509 - - Fixed error when using HotWater climate automation - issue #517 - - Fixed wiser http path not registering - issue #521 - - Fixed issue causing integration to fail loading with BoilerInterface - issue #523 - - Added support for ButtonPanel (Wiser Odace) - issue #524 - - Bump api to v1.5.19 to resolve issues #509, #523, #524 - -- v3.4.11 - - Bump api to v1.5.18 to reduce Payload not completed errors - - Fix typo in dimable light color mode - issue #518 - -- v3.4.10 - - Fixed error loading sensors - issue #513 - -- v3.4.9 (Pulled) - - Fixed smoke alarm naming issue - issue #496 - - Set humidity to Unavailable if no value - issue #503 - - Add support for BoilerInterface - issue #499 - - Add support for WindowDoorSensor for v2 hub - - Add support for CFMT device for v2 hub - issue #507 - -- v3.4.8 - - Fix deprecation warning no waiting on setups - [#485](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/485) - - Fix color mode issue - [#479](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/479) - - Added smoke alarm sensors - [#457](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/457) - - Fixed missing save layout button in zigbee card - [#488](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/488) - -- v3.4.7 - - Bump api to v1.5.14 to improve handling of hub connection errors - - Fix - improve handling of hub update failures - [#434](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/434) - - Fix - set entity values to unknown if not provided in the hub update - [#471](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/471) - - Fix - removed use of async_add_job - [#463](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/463) - - Fix - add color modes to lights - [#458](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/458) - - Fix - use default boost temp with presets - [#467](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/467) - - Add ability to unassign a schedule via the assign schedule service - [#470](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/470) - -- v3.4.6 - - Bump api to v1.5.13 to improve retry handling to include hub conneciton error - - Prevent entities going unavailable if hub update failed - - Fix issue with floor temp offset slider not loading - - Fix hass.components.websocket_api deprecation warning in HA 2024.3 (issue [#455](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/455)) - - Fix unique ids not unique error when changing configuration options - - Add new automation to control hot water with a climate entity and an external temperature sensor on your water tank by @markchalloner. See wiki for more info. - -- v3.4.5 - - Bump api to v1.5.12 to improve performance of improved retry handling - - Fixed issue caused by v3.4.4 that heating actuators and power tags error on load (issue [#449](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/449), [#450](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/450)) - - Fixed error setting up integration in config flow caused by session parameter being passed when no longer required (issue [#446](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/446)) - - Fixed issue on 3 channel hubs with Heating sensor names - - Fixed issue with signal sensor showing unknown on startup until first refresh - - Changed preset icon to HA standard - -- v3.4.4 - - Bump api to v1.5.11 - - Improved api retry handling for inconsitant errors coming from the hub causing errors in the log and entities to go unavailable (issues [#434](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/434), #436, #439) - - Fixed Validation of translation placeholders error for German language (issue [#434](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/434) - - Fixed diagnostic download failure (issue [#444](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/444)) - - Fixed error with wall plugs not providing power data (issue [#446](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/446)) - - Set state of target temp sensors to Unavailable when the climate HVAC mode is off (issue [#447](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/447), #378) - - Added ability to set a different IP port for hub - PR#430 - thanks @simick - - Enabled statistics on batteries - PR#445 - thanks @msalway - - Added number_of_trvs, number_of_trvs_locked and is_roomstat_locked attributes to climate entities (issue [#374](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/374)) - -- v3.4.3 - - Fixed Warning error in logs caused by new HA2024.2 requirement to explicity support Turn On/Off for climate entities (issue [#435](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/435)) - - Bump api to v1.5.7 to fix issue setting lower target temp when in passive mode - -- v3.4.2 - - Reverted to using aiohttp for communication and resolved issues caused by HA2023.12 - - Bumped api to v1.5.5 - - Fixed issue where hub communication would error due to command characters in payload (issue [#418](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/418)) - - Updated schedule card to allow hiding of hot water schedule (issue [#415](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/415)) - - Included version in card resources to improve updating of new versions - - Added more v2 hub features and attributes - - Improved error handling/logging when hub offline and command is issued - -- v3.4.1 - - Corrected error deleting schedule - - Handle space at end of secret key and prevent error (issue [#409](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/409)) - - Updated schedule card to v1.3.2 - fixed some UI bugs, added ability to hide info and assignments via config (issue [#404](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/404)) - -- v3.4.0beta - - Fixed issue in HA 2023.12 with errors reading hub - - Add PowerTagE support (v2 hub) - - Add tilt functions for shutters (v2 hub) - - Fixed issue whereby non ASCII chars are removed in device/room names - issues #396 - -- v3.3.11 - - Add check for overrides to prevent turning off away modewhen selecting cancel overrides when none exist (Wiser hub bug) - - Correct sensor device class and native values to fix history not displaying issue in HA 2023.11 - -- v3.3.10 - - bump api to v1.3.8 to fix passive mode error if room trv/roomstat goes offline - - make battery sensor unavailable if no battery info provided by hub (previously showed 0%) - - add uptime and last reset reason to Hub signal sensor - - make LTS sensors normal sensors instead of diagnostic sensors so they show in Area card - issue #381 - - save schedule service will now create directory for file if it doesn't exist - - correct relative modulation level magnitude - -- v3.3.9 - - bump api to v1.3.5 to fix warning regarding async not awaited on extra config - -- v3.3.8 - - Fix extra key issue preventing loading on HA 2023.8.0 and above - -- v3.3.7 - - Fix issue with zigbee card unable to save layout in stack card - - Updated libraries for schedule card to fix security vulnerabilities - - Fix colours missing on on/off schedule in schedule card - - Minor UI improvements in schedule card - -- v3.3.6 - - Improved Zigbee network card - -- v3.3.5 - - Fix for eroneous current temp if lost signal with TRV - issue #369 - - Reduced log error level for failed update form hub to warning +See [CHANGELOG.md](CHANGELOG.md) for the full release history. -A full change log can be seen on our wiki [here](https://github.com/asantaga/wiserHomeAssistantPlatform/wiki/Full-Change-Log) +Releases before v3.3.5 are listed on our wiki [here](https://github.com/asantaga/wiserHomeAssistantPlatform/wiki/Full-Change-Log). ## Building From 4d6e29bee64cc9ebbbf726e5c4c7d5e7408e02e1 Mon Sep 17 00:00:00 2001 From: asantaga Date: Sat, 19 Sep 2026 23:16:31 +0100 Subject: [PATCH 028/154] documentation for 4.0.0-rc1 pt2 --- CHANGELOG.md | 247 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..f9daeb98 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,247 @@ +# Changelog + +All notable changes to the Wiser Home Assistant integration, newest release first. + +For releases before v3.3.5, see the [Full Change Log](https://github.com/asantaga/wiserHomeAssistantPlatform/wiki/Full-Change-Log) on our wiki. + +## v4.0.0-rc1 + +### Breaking changes + +- The device registry is restructured. The separate virtual controller device is merged into the physical hub device, and Wiser room devices move to stable identifiers. In both cases the old device is removed and its entities are reassigned to the surviving device. Entity IDs and history are preserved, but anything that targets a Wiser *device* rather than an entity - device-based automations and scripts, or dashboard cards pointing at a device - needs repointing - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693). +- Entity unique IDs migrate to deterministic UUIDv5. The migration runs automatically on upgrade and renames registry entries in place, so entity IDs, history, and customisations are preserved. Every target is checked before any change is applied, so it cannot partially apply, but it aborts if it finds a unique ID collision - take a backup before upgrading - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693). + +### Added + +- Added configurable OpenTherm monitoring and controls, including relative modulation, a Delta-T sensor, expanded telemetry, and categorized diagnostics - PR [#697](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/697). +- Added a configurable Wiser Schedules sidebar panel - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). +- Added a Wiser Zigbee sidebar panel with a custom sidebar icon - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). +- Added a Hot Water on/off switch entity - issue [#626](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/626), PR [#682](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/682). +- Added a UFH controller measured-temperature sensor - issue [#628](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/628). +- Added optimistic light state for instant UI feedback on toggles, kept stable across rapid repeated toggles - PR [#684](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/684). +- Added British English translations and corrected the German, French, and English integration translations - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). + +### Changed + +- Entity naming now follows Home Assistant conventions, using `has_entity_name` so Home Assistant composes each displayed name from the device name plus the entity name. Existing entity IDs are not renamed. A new **Legacy naming** option controls whether Wiser room names are included in device names; it is switched on automatically for existing installations, so your device names stay as they are unless you turn it off. New installations on Home Assistant 2026.8 and later default it to off - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693), PR [#700](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/700). +- Wiser devices are now placed in Home Assistant areas matching their Wiser room, creating the area if it does not exist. This applies only to devices that have no area yet, so any area you assigned manually is left untouched - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693), PR [#700](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/700). +- Sidebar panel visibility is now configured through the integration's UI options - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). +- Card versions are now detected from the installed card bundles instead of being pinned in the integration, so card updates no longer need an integration release - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). + +### Fixed + +- Reintroduced the previous Power and Energy entities, corrected equipment data naming on v2 hubs, and added an active state for the window/door sensor - issue [#677](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/677), PR [#690](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/690). +- Fixed multi-gang dimmer lights breaking select, binary_sensor, switch, and sensor entities - issue [#681](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/681), PR [#683](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/683). +- Preserved light entities across the multi-gang unique_id migration - issue [#681](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/681), PR [#683](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/683). +- Fixed the device signal sensor to emit once per physical device instead of once per light channel on multi-gang dimmers - issue [#681](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/681), PR [#683](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/683). +- Fixed the room **Window Detection Active** binary sensor being presented as a physical window sensor. It carried a `window` device class, so Home Assistant displayed it as Open/Closed as though it reported a real window, when it actually reports whether the room's window-detection feature is switched on. It now shows a plain on/off state. The underlying state values are unchanged, so automations that test for `on`/`off` keep working - only the displayed wording and icon change - PR [#703](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/703). +- Fixed away mode and frost protection reporting distinct target temperatures, and the frost protection target now honours the configured value - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693). +- Fixed the hot water switch to report against the hub as its parent device - PR [#704](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/704). +- Fixed a Zigbee sidebar route conflict that could stop the integration setting up - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). +- Fixed the boiler capacity and estimated boiler output sensors to use a gas burner icon - PR [#701](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/701). +- Fix for issue [#662](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/662) - PR [#680](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/680). + +## v3.4.20 + +- Added equipment data to smart plugs, heating actuators, and PowerTag E devices. +- Added LED-indicator support for on/off and dimmable lights. +- Added seasonal-comfort controls, including the target lift for shutters. +- Added an option to hide the hot-water schedule in the Wiser Schedule Card. +- Fixed the controller signal sensor to use the HeatHub name - issue [#639](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/639). +- Fixed schedule deletion and schedule-name inputs on current Home Assistant releases - issue [#461](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/461). + +## v3.4.19 + +- Fixed: Breaking change in HA 2026.2 causes integration not to load - issue [#643](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/643) +- Fixed: V2 hubs with firmware lower than 4.42.23 cannot connect on https + +## v3.4.18 + +- Fixed no long term stats for temp/humidity sensors issue [#598](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/598) +- Fixed deprecated ZeroconfServiceInfo - issue [#612](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/612) +- Fixed error 500 when selecting integration config - issue [#613](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/613) +- Fixed unable to create new schedule card - issue [#616](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/616) +- Fixed schedule card badges are misaligned - issue [#615](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/615) +- Changed: Communication to v2 hub now uses https over internal network +- Bumped schedule card to v1.5.0 +- Bumped api to v1.7.0 + +## v3.4.17 + +- Fixed hot water climate does not respect away mode - issue [#579](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/579) +- Fixed deprecation error sets option flow config_entry explicitly - issue [#595](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/595) +- Fixed schedule card unable to edit - issue [#607](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/607) + +## v3.4.16 + +- Fix incorrect identifer on hub device +- Fix deprecation warning for access to lovelace resource parameters +- Fix error on unloading services for hubs without hot water control +- Fix deprecation warning for ZeroconfServiceInfo +- Bump api to v1.6.6 to support SSL for future firmware + +## v3.4.15 + +- Added experimental hw climate mode to operate differently. See wiki for details +- Changed min/max hw climate temp range from 40-80C to 10-80C - issue [#545](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/545) +- Fixed issue whereby hw climate errors if temp sensor not available after HA start - issue [#541](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/541) +- Fixed issue whereby hw climate config requires some entry in the temp sensor select option, even if not enabled - issue [#544](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/544) +- Fixed issue whereby hw min does not change when setting both via service call if temps are 1C or less different - issue [#547](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/547) + +## v3.4.14 + +- Fixed issue causing integration not to load in some circumstances due to failed config entry migration - issue #539 +- Added binary sensor active state sensor + +## v3.4.13 + +- Added support for PowerTag C - issue #528 +- BREAKING CHANGE - refactored HW climate automation - issues #481, #490. See wiki for updated instructions +- Added illuminance, humidity and temp sensors to devices with threshold sensors - issue #531 +- Added support for 2 gang light switch - issue #529 +- Added interacts with room climate switch to supported devices +- Fixed support for Binary sensors with threshold sensors - issue #530 +- Fixed incompatibility with Python3.13 and HA2024.12 - issue #535 +- Fixed events not correctly firing for climate changes - issue #526 +- Fixed error when saving schedule with an off slot - issue #536 +- Changed all hot water related sensors to now belong to a hot water device +- Bumped aiowiserheatapi to v1.6.3 + +## v3.4.12 + +- Fixed issue assigning schedules with non ascii characters in name - issue #509 +- Fixed error when using HotWater climate automation - issue #517 +- Fixed wiser http path not registering - issue #521 +- Fixed issue causing integration to fail loading with BoilerInterface - issue #523 +- Added support for ButtonPanel (Wiser Odace) - issue #524 +- Bump api to v1.5.19 to resolve issues #509, #523, #524 + +## v3.4.11 + +- Bump api to v1.5.18 to reduce Payload not completed errors +- Fix typo in dimable light color mode - issue #518 + +## v3.4.10 + +- Fixed error loading sensors - issue #513 + +## v3.4.9 (Pulled) + +- Fixed smoke alarm naming issue - issue #496 +- Set humidity to Unavailable if no value - issue #503 +- Add support for BoilerInterface - issue #499 +- Add support for WindowDoorSensor for v2 hub +- Add support for CFMT device for v2 hub - issue #507 + +## v3.4.8 + +- Fix deprecation warning no waiting on setups - [#485](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/485) +- Fix color mode issue - [#479](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/479) +- Added smoke alarm sensors - [#457](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/457) +- Fixed missing save layout button in zigbee card - [#488](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/488) + +## v3.4.7 + +- Bump api to v1.5.14 to improve handling of hub connection errors +- Fix - improve handling of hub update failures - [#434](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/434) +- Fix - set entity values to unknown if not provided in the hub update - [#471](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/471) +- Fix - removed use of async_add_job - [#463](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/463) +- Fix - add color modes to lights - [#458](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/458) +- Fix - use default boost temp with presets - [#467](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/467) +- Add ability to unassign a schedule via the assign schedule service - [#470](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/470) + +## v3.4.6 + +- Bump api to v1.5.13 to improve retry handling to include hub conneciton error +- Prevent entities going unavailable if hub update failed +- Fix issue with floor temp offset slider not loading +- Fix hass.components.websocket_api deprecation warning in HA 2024.3 (issue [#455](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/455)) +- Fix unique ids not unique error when changing configuration options +- Add new automation to control hot water with a climate entity and an external temperature sensor on your water tank by @markchalloner. See wiki for more info. + +## v3.4.5 + +- Bump api to v1.5.12 to improve performance of improved retry handling +- Fixed issue caused by v3.4.4 that heating actuators and power tags error on load (issue [#449](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/449), [#450](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/450)) +- Fixed error setting up integration in config flow caused by session parameter being passed when no longer required (issue [#446](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/446)) +- Fixed issue on 3 channel hubs with Heating sensor names +- Fixed issue with signal sensor showing unknown on startup until first refresh +- Changed preset icon to HA standard + +## v3.4.4 + +- Bump api to v1.5.11 +- Improved api retry handling for inconsitant errors coming from the hub causing errors in the log and entities to go unavailable (issues [#434](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/434), #436, #439) +- Fixed Validation of translation placeholders error for German language (issue [#434](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/434) +- Fixed diagnostic download failure (issue [#444](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/444)) +- Fixed error with wall plugs not providing power data (issue [#446](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/446)) +- Set state of target temp sensors to Unavailable when the climate HVAC mode is off (issue [#447](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/447), #378) +- Added ability to set a different IP port for hub - PR#430 - thanks @simick +- Enabled statistics on batteries - PR#445 - thanks @msalway +- Added number_of_trvs, number_of_trvs_locked and is_roomstat_locked attributes to climate entities (issue [#374](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/374)) + +## v3.4.3 + +- Fixed Warning error in logs caused by new HA2024.2 requirement to explicity support Turn On/Off for climate entities (issue [#435](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/435)) +- Bump api to v1.5.7 to fix issue setting lower target temp when in passive mode + +## v3.4.2 + +- Reverted to using aiohttp for communication and resolved issues caused by HA2023.12 +- Bumped api to v1.5.5 +- Fixed issue where hub communication would error due to command characters in payload (issue [#418](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/418)) +- Updated schedule card to allow hiding of hot water schedule (issue [#415](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/415)) +- Included version in card resources to improve updating of new versions +- Added more v2 hub features and attributes +- Improved error handling/logging when hub offline and command is issued + +## v3.4.1 + +- Corrected error deleting schedule +- Handle space at end of secret key and prevent error (issue [#409](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/409)) +- Updated schedule card to v1.3.2 - fixed some UI bugs, added ability to hide info and assignments via config (issue [#404](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/404)) + +## v3.4.0beta + +- Fixed issue in HA 2023.12 with errors reading hub +- Add PowerTagE support (v2 hub) +- Add tilt functions for shutters (v2 hub) +- Fixed issue whereby non ASCII chars are removed in device/room names - issues #396 + +## v3.3.11 + +- Add check for overrides to prevent turning off away modewhen selecting cancel overrides when none exist (Wiser hub bug) +- Correct sensor device class and native values to fix history not displaying issue in HA 2023.11 + +## v3.3.10 + +- bump api to v1.3.8 to fix passive mode error if room trv/roomstat goes offline +- make battery sensor unavailable if no battery info provided by hub (previously showed 0%) +- add uptime and last reset reason to Hub signal sensor +- make LTS sensors normal sensors instead of diagnostic sensors so they show in Area card - issue #381 +- save schedule service will now create directory for file if it doesn't exist +- correct relative modulation level magnitude + +## v3.3.9 + +- bump api to v1.3.5 to fix warning regarding async not awaited on extra config + +## v3.3.8 + +- Fix extra key issue preventing loading on HA 2023.8.0 and above + +## v3.3.7 + +- Fix issue with zigbee card unable to save layout in stack card +- Updated libraries for schedule card to fix security vulnerabilities +- Fix colours missing on on/off schedule in schedule card +- Minor UI improvements in schedule card + +## v3.3.6 + +- Improved Zigbee network card + +## v3.3.5 + +- Fix for eroneous current temp if lost signal with TRV - issue #369 +- Reduced log error level for failed update form hub to warning From e55031ddf016ca5589633e9e72726d081f16cbc6 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Sun, 20 Sep 2026 10:06:49 +0100 Subject: [PATCH 029/154] Add independent frontend card update entities --- .github/workflows/publish.yml | 3 + custom_components/wiser/__init__.py | 2 + custom_components/wiser/const.py | 1 + custom_components/wiser/frontend/__init__.py | 47 ++- .../wiser/frontend/card_files.py | 72 +++++ custom_components/wiser/frontend/panel.py | 10 +- custom_components/wiser/strings.json | 4 + custom_components/wiser/translations/de.json | 4 + .../wiser/translations/en-GB.json | 4 + custom_components/wiser/translations/en.json | 4 + custom_components/wiser/translations/fr.json | 4 + custom_components/wiser/update.py | 240 +++++++++++++++ tests/requirements.txt | 3 + tests/test_card_updates.py | 281 ++++++++++++++++++ tests/test_schedules_sidebar.py | 5 + tests/test_zigbee_sidebar.py | 5 + 16 files changed, 673 insertions(+), 16 deletions(-) create mode 100644 custom_components/wiser/frontend/card_files.py create mode 100644 custom_components/wiser/update.py create mode 100644 tests/requirements.txt create mode 100644 tests/test_card_updates.py diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index eed96f67..e59b6da2 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -25,10 +25,13 @@ jobs: - uses: actions/setup-python@v6 with: python-version: '3.13' + - name: Install test dependencies + run: python -m pip install -r tests/requirements.txt - name: Test packaging and sidebar integration run: | python -m unittest discover -s tests -p test_card_releases.py python -m unittest discover -s tests -p test_build.py + python -m unittest discover -s tests -p test_card_updates.py python -m unittest discover -s tests -p test_ui_options.py python -m unittest discover -s tests -p test_sidebar_icons.py python -m unittest discover -s tests -p 'test_*sidebar.py' diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index ae71be7b..31ca0564 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -58,6 +58,7 @@ from .services import async_setup_services from .frontend.zigbee_sidebar import async_update_zigbee_panel from .websockets import async_register_websockets +from .update import async_unload_card_updates _LOGGER = logging.getLogger(__name__) @@ -391,6 +392,7 @@ async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry): _LOGGER.debug("Unload integration") if unload_ok: + await async_unload_card_updates(hass, config_entry) hass.data[DOMAIN].pop(config_entry.entry_id) await async_update_schedules_panel(hass) update_hub_device_names(hass) diff --git a/custom_components/wiser/const.py b/custom_components/wiser/const.py index 10db8e02..aad1203e 100755 --- a/custom_components/wiser/const.py +++ b/custom_components/wiser/const.py @@ -38,6 +38,7 @@ "number", "light", "cover", + "update", ] DATA = "data" UPDATE_TRACK = "update_track" diff --git a/custom_components/wiser/frontend/__init__.py b/custom_components/wiser/frontend/__init__.py index d8f7229f..816f5d22 100644 --- a/custom_components/wiser/frontend/__init__.py +++ b/custom_components/wiser/frontend/__init__.py @@ -1,4 +1,4 @@ -"""View Assist Javascript module registration.""" +"""Register Wiser frontend resources and independently updated card bundles.""" from hashlib import sha256 import re @@ -14,6 +14,8 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.event import async_call_later +from .card_files import CARD_CACHE, CARD_CACHE_URL, resolve_card + from ..const import JSMODULES, URL_BASE # noqa: TID252 _LOGGER = logging.getLogger(__name__) @@ -61,6 +63,13 @@ def card_version(path: Path) -> str: return f"sha256-{sha256(contents).hexdigest()[:16]}" +async def async_card_resource(hass, filename): + """Resolve the active card path, cache-busted URL, and version off the loop.""" + return await hass.async_add_executor_job( + resolve_card, hass.config.path(), filename, card_version + ) + + class JSModuleRegistration: """Register Javascript modules.""" @@ -68,9 +77,12 @@ def __init__(self, hass: HomeAssistant) -> None: """Initialise.""" self.hass = hass self.lovelace: LovelaceData = self.hass.data.get("lovelace") + if self.lovelace is None: + self.resource_mode = None + return # Fix for change to name of mode to reousrce_mode in 2026.2 - if MAJOR_VERSION >= 2026 and MINOR_VERSION >= 2: + if (MAJOR_VERSION, MINOR_VERSION) >= (2026, 2): self.resource_mode = self.lovelace.resource_mode else: self.resource_mode = self.lovelace.mode @@ -90,6 +102,17 @@ async def async_register(self): # install card resources async def _async_register_path(self): """Register resource path if not already registered.""" + cache = Path(self.hass.config.path(CARD_CACHE)) + await self.hass.async_add_executor_job(lambda: cache.mkdir(parents=True, exist_ok=True)) + if not self.hass.data.get("wiser_card_cache_registered"): + try: + await self.hass.http.async_register_static_paths( + [StaticPathConfig(CARD_CACHE_URL, cache, False)] + ) + except RuntimeError: + # Another hub may have registered the shared path during setup. + _LOGGER.debug("Card cache path already registered") + self.hass.data["wiser_card_cache_registered"] = True try: await self.hass.http.async_register_static_paths( [StaticPathConfig(URL_BASE, Path(__file__).parent, False)] @@ -127,17 +150,20 @@ async def _async_register_modules(self): for module in JSMODULES: url = f"{URL_BASE}/{module.get('filename')}" - version = await self.hass.async_add_executor_job( - card_version, Path(__file__).parent / module["filename"] - ) + _, active_url, version = await async_card_resource(self.hass, module["filename"]) card_registered = False for resource in resources: - if self._get_resource_path(resource["url"]) == url: + if ( + self._get_resource_path(resource["url"]) == url + or self._get_resource_path(resource["url"]).startswith( + f"{CARD_CACHE_URL}/{Path(module['filename']).stem}-" + ) + ): card_registered = True # check version - if self._get_resource_version(resource["url"]) != version: + if resource["url"] != active_url: # Update card version _LOGGER.debug( "Updating %s to version %s", @@ -148,7 +174,7 @@ async def _async_register_modules(self): resource.get("id"), { "res_type": "module", - "url": url + "?v=" + version, + "url": active_url, }, ) # Remove old gzipped files @@ -167,7 +193,7 @@ async def _async_register_modules(self): version, ) await self.lovelace.resources.async_create_item( - {"res_type": "module", "url": url + "?v=" + version} + {"res_type": "module", "url": active_url} ) def _get_resource_path(self, url: str): @@ -185,6 +211,9 @@ async def async_unregister(self): resource for resource in self.lovelace.resources.async_items() if str(resource["url"]).startswith(url) + or str(resource["url"]).startswith( + f"{CARD_CACHE_URL}/{Path(module['filename']).stem}-" + ) ] for resource in wiser_resources: await self.lovelace.resources.async_delete_item(resource.get("id")) diff --git a/custom_components/wiser/frontend/card_files.py b/custom_components/wiser/frontend/card_files.py new file mode 100644 index 00000000..13425425 --- /dev/null +++ b/custom_components/wiser/frontend/card_files.py @@ -0,0 +1,72 @@ +"""Persistent, verified card overrides outside the integration installation.""" + +from hashlib import sha256 +import json +from pathlib import Path +import tempfile + +from awesomeversion import AwesomeVersion +from awesomeversion.exceptions import AwesomeVersionException + +from ..const import URL_BASE + +CARD_CACHE = ".storage/wiser_cards" +CARD_CACHE_URL = f"{URL_BASE}/cards" + + +def newer_version(candidate, installed): + """Compare semantic release versions without offering downgrades.""" + try: + return AwesomeVersion(candidate) > AwesomeVersion(installed) + except (AwesomeVersionException, ValueError, TypeError): + return False + + +def resolve_card(config_dir, filename, version_reader): + """Prefer a verified downloaded card only while newer than the bundled card.""" + bundled = Path(__file__).parent / filename + version = version_reader(bundled) + fallback = (bundled, f"{URL_BASE}/{filename}?v={version}", version) + directory = Path(config_dir) / CARD_CACHE + try: + record = json.loads((directory / f"{filename}.json").read_text()) + cached = directory / record["file"] + # Metadata must not redirect static serving outside the card cache. + digest = record["digest"] + expected = f"{Path(filename).stem}-{digest}.js" + if record["file"] != expected or len(digest) != 64 or any(c not in "0123456789abcdef" for c in digest): + return fallback + if not newer_version(record["version"], version): + return fallback + if sha256(cached.read_bytes()).hexdigest() != digest: + return fallback + return cached, f"{CARD_CACHE_URL}/{cached.name}?v={record['version']}", record["version"] + except (OSError, ValueError, KeyError, TypeError): + return fallback + + +def store_card(config_dir, filename, version, contents): + """Write immutable assets, then atomically switch the active metadata.""" + directory = Path(config_dir) / CARD_CACHE + directory.mkdir(parents=True, exist_ok=True) + digest = sha256(contents).hexdigest() + asset_name = f"{Path(filename).stem}-{digest}.js" + _atomic_write(directory / asset_name, contents) + metadata = {"file": asset_name, "version": version, "digest": digest} + _atomic_write(directory / f"{filename}.json", json.dumps(metadata).encode()) + + +def _atomic_write(path, contents): + """Keep the previous working file intact if a write fails.""" + with tempfile.NamedTemporaryFile(dir=path.parent, delete=False) as stream: + temporary = Path(stream.name) + try: + stream.write(contents) + stream.flush() + except BaseException: + temporary.unlink(missing_ok=True) + raise + try: + temporary.replace(path) + finally: + temporary.unlink(missing_ok=True) diff --git a/custom_components/wiser/frontend/panel.py b/custom_components/wiser/frontend/panel.py index 2fe395f9..19201a0f 100644 --- a/custom_components/wiser/frontend/panel.py +++ b/custom_components/wiser/frontend/panel.py @@ -4,12 +4,11 @@ import math from dataclasses import dataclass -from pathlib import Path from homeassistant.components import frontend, panel_custom -from . import card_version -from ..const import DATA, DOMAIN, URL_BASE +from . import async_card_resource +from ..const import DATA, DOMAIN @dataclass(frozen=True) @@ -49,10 +48,7 @@ async def async_update_panel(hass, panel): hass.data.pop(panel.state_key) return - version = await hass.async_add_executor_job( - card_version, Path(__file__).parent / panel.filename - ) - module_url = f"{URL_BASE}/{panel.filename}?v={version}" + _, module_url, _ = await async_card_resource(hass, panel.filename) state = { "hubs": [hub for hub, _ in entries], "card_configs": { diff --git a/custom_components/wiser/strings.json b/custom_components/wiser/strings.json index 29d83d04..441be7e9 100755 --- a/custom_components/wiser/strings.json +++ b/custom_components/wiser/strings.json @@ -224,6 +224,10 @@ "opentherm_notification_title": { "message": "Wiser OpenTherm command" } }, "entity": { + "update": { + "schedule_card": { "name": "Wiser Schedules Card" }, + "zigbee_card": { "name": "Wiser Zigbee Card" } + }, "climate": { "heating": { "name": "Heating" diff --git a/custom_components/wiser/translations/de.json b/custom_components/wiser/translations/de.json index 880bbc80..1e8c010a 100644 --- a/custom_components/wiser/translations/de.json +++ b/custom_components/wiser/translations/de.json @@ -224,6 +224,10 @@ "opentherm_notification_title": { "message": "Wiser-OpenTherm-Befehl" } }, "entity": { + "update": { + "schedule_card": { "name": "Wiser-Zeitplankarte" }, + "zigbee_card": { "name": "Wiser-Zigbee-Karte" } + }, "climate": { "heating": { "name": "Heizung" diff --git a/custom_components/wiser/translations/en-GB.json b/custom_components/wiser/translations/en-GB.json index ac2de4cc..9a84bef2 100644 --- a/custom_components/wiser/translations/en-GB.json +++ b/custom_components/wiser/translations/en-GB.json @@ -224,6 +224,10 @@ "opentherm_notification_title": { "message": "Wiser OpenTherm command" } }, "entity": { + "update": { + "schedule_card": { "name": "Wiser Schedules Card" }, + "zigbee_card": { "name": "Wiser Zigbee Card" } + }, "climate": { "heating": { "name": "Heating" diff --git a/custom_components/wiser/translations/en.json b/custom_components/wiser/translations/en.json index 7b15cc2e..737e882a 100755 --- a/custom_components/wiser/translations/en.json +++ b/custom_components/wiser/translations/en.json @@ -224,6 +224,10 @@ "opentherm_notification_title": { "message": "Wiser OpenTherm command" } }, "entity": { + "update": { + "schedule_card": { "name": "Wiser Schedules Card" }, + "zigbee_card": { "name": "Wiser Zigbee Card" } + }, "climate": { "heating": { "name": "Heating" diff --git a/custom_components/wiser/translations/fr.json b/custom_components/wiser/translations/fr.json index 428362f8..e8ff6c12 100644 --- a/custom_components/wiser/translations/fr.json +++ b/custom_components/wiser/translations/fr.json @@ -224,6 +224,10 @@ "opentherm_notification_title": { "message": "Commande OpenTherm Wiser" } }, "entity": { + "update": { + "schedule_card": { "name": "Carte des programmes Wiser" }, + "zigbee_card": { "name": "Carte Zigbee Wiser" } + }, "climate": { "heating": { "name": "Chauffage" diff --git a/custom_components/wiser/update.py b/custom_components/wiser/update.py new file mode 100644 index 00000000..b2085da8 --- /dev/null +++ b/custom_components/wiser/update.py @@ -0,0 +1,240 @@ +"""Offer independent, manually installed updates for the shared frontend cards.""" + +from __future__ import annotations + +import asyncio +from datetime import timedelta +from hashlib import sha256 +import logging +import re +from urllib.parse import urlsplit + +import aiohttp +from homeassistant.components.update import UpdateEntity, UpdateEntityFeature +from homeassistant.const import EntityCategory +from homeassistant.exceptions import HomeAssistantError +from homeassistant.helpers import entity_registry as er +from homeassistant.helpers.aiohttp_client import async_get_clientsession +from homeassistant.helpers.update_coordinator import CoordinatorEntity, DataUpdateCoordinator + +from .const import DOMAIN +from .frontend import JSModuleRegistration, async_card_resource +from .frontend.card_files import newer_version, store_card +from .frontend.schedules_sidebar import async_update_schedules_panel +from .frontend.zigbee_sidebar import async_update_zigbee_panel + +_LOGGER = logging.getLogger(__name__) +_MANAGER = "wiser_card_updates" +_MAX_DOWNLOAD = 20 * 1024 * 1024 +_CARDS = { + "schedule": ("andyblac/wiser-schedule-card", "wiser-schedule-card.js", "wiser-schedules-panel"), + "zigbee": ("andyblac/wiser-zigbee-card", "wiser-zigbee-card.js", "wiser-zigbee-panel"), +} + + +def _release_version(tag): + """Only accept stable semantic versions from published releases.""" + match = re.fullmatch(r"v?(\d+\.\d+\.\d+(?:\+[0-9A-Za-z.-]+)?)", tag) + if not match: + raise ValueError(f"Unsupported stable card release version: {tag}") + return match[1] + + +def _validate_release(card, release): + """Validate release metadata before exposing an installable update.""" + repository, filename, _ = _CARDS[card] + if release.get("draft") or release.get("prerelease") or not release.get("published_at"): + raise ValueError("Expected a published stable card release") + version = _release_version(release["tag_name"]) + assets = [asset for asset in release["assets"] if asset["name"] == filename and asset.get("state") == "uploaded"] + if len(assets) != 1: + raise ValueError(f"Release must include exactly one {filename}") + asset = assets[0] + url = urlsplit(asset["browser_download_url"]) + if url.scheme != "https" or url.netloc != "github.com" or not url.path.startswith(f"/{repository}/releases/download/"): + raise ValueError("Invalid card release download URL") + if not 100 <= asset["size"] <= _MAX_DOWNLOAD: + raise ValueError("Invalid card release asset size") + return {"version": version, "asset": asset, + "release_url": f"https://github.com/{repository}/releases/tag/{release['tag_name']}"} + + +def _validate_download(card, release, contents): + """Verify the file before changing the currently installed card.""" + _, filename, component = _CARDS[card] + asset = release["asset"] + if len(contents) != asset["size"]: + raise ValueError("Card download size does not match release metadata") + digest = "sha256:" + sha256(contents).hexdigest() + if asset.get("digest") and asset["digest"] != digest: + raise ValueError("Card download checksum does not match release metadata") + if contents.lstrip().lower().startswith((b" _MAX_DOWNLOAD: + raise ValueError("Card download exceeds size limit") + chunks.append(chunk) + contents = b"".join(chunks) + await self.hass.async_add_executor_job(_validate_download, card, release, contents) + await self.hass.async_add_executor_job( + store_card, self.hass.config.path(), filename, release["version"], contents + ) + state["installed"] = release["version"] + registration = JSModuleRegistration(self.hass) + await registration.async_register() + await async_update_schedules_panel(self.hass) + await async_update_zigbee_panel(self.hass) + except (aiohttp.ClientError, TimeoutError, OSError, ValueError) as err: + raise HomeAssistantError(f"Unable to install card update: {err}") from err + finally: + self.installing.discard(card) + self.async_update_listeners() + + +class WiserCardUpdate(CoordinatorEntity, UpdateEntity): + """A user-installed frontend card update, separate from hub firmware.""" + + _attr_supported_features = UpdateEntityFeature.INSTALL + _attr_entity_category = EntityCategory.CONFIG + _attr_has_entity_name = True + _attr_release_summary = "Refresh your browser after installation to load the updated card." + + def __init__(self, coordinator, card): + super().__init__(coordinator) + self.card = card + self._attr_unique_id = f"wiser_{card}_card_update" + self._attr_translation_key = f"{card}_card" + + @property + def available(self): + return super().available and self.coordinator.data.get(self.card, {}).get("release") is not None + + @property + def installed_version(self): + return self.coordinator.data.get(self.card, {}).get("installed") + + @property + def latest_version(self): + release = self.coordinator.data.get(self.card, {}).get("release") + return release["version"] if release else None + + @property + def release_url(self): + release = self.coordinator.data.get(self.card, {}).get("release") + return release["release_url"] if release else None + + @property + def in_progress(self): + return self.card in self.coordinator.installing + + def version_is_newer(self, latest_version, installed_version): + return newer_version(latest_version, installed_version) + + async def async_install(self, version, backup, **kwargs): + """Install only after an explicit Home Assistant update action.""" + await self.coordinator.install(self.card) diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 00000000..34f2539d --- /dev/null +++ b/tests/requirements.txt @@ -0,0 +1,3 @@ +# Runtime helpers used by card-update tests; Home Assistant itself is stubbed. +aiohttp>=3.11,<4 +awesomeversion>=24.6,<26 diff --git a/tests/test_card_updates.py b/tests/test_card_updates.py new file mode 100644 index 00000000..bdb97fdd --- /dev/null +++ b/tests/test_card_updates.py @@ -0,0 +1,281 @@ +"""Exercise persistent card installs and update entities without a running HA.""" + +import ast +from datetime import timedelta +from hashlib import sha256 +import importlib.util +import json +from pathlib import Path +import re +import sys +from tempfile import TemporaryDirectory +from types import ModuleType, SimpleNamespace +import unittest +from unittest.mock import AsyncMock, Mock, patch + +ROOT = Path(__file__).resolve().parents[1] / "custom_components/wiser" + + +def module(name, **attrs): + result = ModuleType(name) + result.__dict__.update(attrs) + return result + + +def load(name, path): + spec = importlib.util.spec_from_file_location(name, path) + result = importlib.util.module_from_spec(spec) + sys.modules[name] = result + spec.loader.exec_module(result) + return result + + +class Coordinator: + def __init__(self, hass, logger, **kwargs): + self.hass = hass + self.options = kwargs + self.data = {} + self.async_update_listeners = Mock() + self.async_shutdown = AsyncMock() + + async def async_refresh(self): + self.data = await self._async_update_data() + + +class CoordinatorEntity: + def __init__(self, coordinator): + self.coordinator = coordinator + + @property + def available(self): + return True + + +class CardUpdatesTest(unittest.IsolatedAsyncioTestCase): + def setUp(self): + self.temporary = TemporaryDirectory() + self.addCleanup(self.temporary.cleanup) + self.directory = Path(self.temporary.name) + self.registry = SimpleNamespace( + async_get_entity_id=Mock(return_value=None), async_update_entity=Mock() + ) + self.session = Mock() + self.registration = SimpleNamespace(async_register=AsyncMock()) + frontend = module("card_update_test.frontend", __path__=[str(ROOT / "frontend")]) + self.modules = patch.dict(sys.modules, { + "card_update_test": module("card_update_test", __path__=[str(ROOT)]), + "card_update_test.const": module("card_update_test.const", URL_BASE="/wiser", DOMAIN="wiser"), + "card_update_test.frontend": frontend, + "homeassistant": module("homeassistant"), + "homeassistant.components": module("homeassistant.components"), + "homeassistant.components.update": module("homeassistant.components.update", UpdateEntity=type("UpdateEntity", (), {}), UpdateEntityFeature=SimpleNamespace(INSTALL=1)), + "homeassistant.const": module("homeassistant.const", EntityCategory=SimpleNamespace(CONFIG="config")), + "homeassistant.exceptions": module("homeassistant.exceptions", HomeAssistantError=RuntimeError), + "homeassistant.helpers": module("homeassistant.helpers"), + "homeassistant.helpers.entity_registry": module("homeassistant.helpers.entity_registry", async_get=lambda _: self.registry), + "homeassistant.helpers.aiohttp_client": module("homeassistant.helpers.aiohttp_client", async_get_clientsession=lambda _: self.session), + "homeassistant.helpers.update_coordinator": module("homeassistant.helpers.update_coordinator", CoordinatorEntity=CoordinatorEntity, DataUpdateCoordinator=Coordinator), + "card_update_test.frontend.schedules_sidebar": module("card_update_test.frontend.schedules_sidebar", async_update_schedules_panel=AsyncMock()), + "card_update_test.frontend.zigbee_sidebar": module("card_update_test.frontend.zigbee_sidebar", async_update_zigbee_panel=AsyncMock()), + }) + self.modules.start() + self.addCleanup(self.modules.stop) + self.files = load("card_update_test.frontend.card_files", ROOT / "frontend/card_files.py") + self.version_reader = Mock(return_value="1.0.0") + async def resource(hass, filename): + return self.files.resolve_card(self.directory, filename, self.version_reader) + frontend.async_card_resource = resource + frontend.JSModuleRegistration = Mock(return_value=self.registration) + self.updates = load("card_update_test.update", ROOT / "update.py") + self.hass = SimpleNamespace( + data={}, config=SimpleNamespace(path=lambda *args: str(self.directory.joinpath(*args))), + async_add_executor_job=AsyncMock(side_effect=lambda fn, *args: fn(*args)), + ) + self.coordinator = self.updates.CardUpdateCoordinator(self.hass) + + def payload(self, card="zigbee", version="2.0.0"): + _, filename, component = self.updates._CARDS[card] + return (f"/*! WISER-CARD-VERSION {filename[:-3]} {version} */\n" + f"customElements.define('{component}', class extends HTMLElement {{}});").encode() + + def metadata(self, card="zigbee", version="2.0.0"): + contents = self.payload(card, version) + repo, filename, _ = self.updates._CARDS[card] + return { + "tag_name": f"v{version}", "published_at": "2026-09-20", "draft": False, "prerelease": False, + "assets": [{"name": filename, "state": "uploaded", "size": len(contents), + "digest": "sha256:" + sha256(contents).hexdigest(), + "browser_download_url": f"https://github.com/{repo}/releases/download/v{version}/{filename}"}], + } + + def response(self, *, json_data=None, contents=b"", error=None): + response = SimpleNamespace(raise_for_status=Mock(side_effect=error), json=AsyncMock(return_value=json_data)) + async def chunks(size): + yield contents + response.content = SimpleNamespace(iter_chunked=chunks) + context = type("ResponseContext", (), { + "__aenter__": AsyncMock(return_value=response), "__aexit__": AsyncMock(return_value=False) + })() + return context + + def test_persistent_cache_survives_restart_and_newer_bundle_takes_precedence(self): + contents = self.payload() + self.files.store_card(self.directory, "wiser-zigbee-card.js", "2.0.0", contents) + path, url, version = self.files.resolve_card(self.directory, "wiser-zigbee-card.js", self.version_reader) + self.assertEqual(path.read_bytes(), contents) + self.assertIn("/wiser/cards/", url) + self.assertEqual(version, "2.0.0") + self.version_reader.return_value = "3.0.0" + path, url, version = self.files.resolve_card(self.directory, "wiser-zigbee-card.js", self.version_reader) + self.assertEqual(path, ROOT / "frontend/wiser-zigbee-card.js") + self.assertEqual(version, "3.0.0") + + def test_corrupt_cache_falls_back_to_bundled_card(self): + self.files.store_card(self.directory, "wiser-zigbee-card.js", "2.0.0", self.payload()) + path, _, _ = self.files.resolve_card(self.directory, "wiser-zigbee-card.js", self.version_reader) + path.write_bytes(b"corrupt") + _, url, version = self.files.resolve_card(self.directory, "wiser-zigbee-card.js", self.version_reader) + self.assertEqual(url, "/wiser/wiser-zigbee-card.js?v=1.0.0") + self.assertEqual(version, "1.0.0") + + def test_failed_metadata_write_keeps_previous_version(self): + self.files.store_card(self.directory, "wiser-zigbee-card.js", "2.0.0", self.payload()) + original = self.files._atomic_write + def write(path, contents): + if path.suffix == ".json": + raise OSError("disk full") + original(path, contents) + with patch.object(self.files, "_atomic_write", side_effect=write): + with self.assertRaises(OSError): + self.files.store_card(self.directory, "wiser-zigbee-card.js", "3.0.0", self.payload(version="3.0.0")) + self.assertEqual(self.files.resolve_card(self.directory, "wiser-zigbee-card.js", self.version_reader)[2], "2.0.0") + + def test_stable_checks_do_not_offer_downgrades_or_unknown_versions(self): + self.assertTrue(self.files.newer_version("2.0.0", "2.0.0-rc1")) + self.assertFalse(self.files.newer_version("2.0.0", "3.0.0-dev.84")) + self.assertFalse(self.files.newer_version("2.0.0", "2.0.0")) + self.assertFalse(self.files.newer_version("2.0.0", "sha256-abcd")) + + def test_rejects_prereleases_and_foreign_download_urls(self): + for change in ("prerelease", "draft", "url", "size"): + metadata = self.metadata() + if change in ("prerelease", "draft"): + metadata[change] = True + elif change == "url": + metadata["assets"][0]["browser_download_url"] = "https://example.com/card.js" + else: + metadata["assets"][0]["size"] = 21 * 1024 * 1024 + with self.subTest(change=change), self.assertRaises(ValueError): + self.updates._validate_release("zigbee", metadata) + + def test_rejects_bad_checksum_and_wrong_version_or_panel(self): + release = self.updates._validate_release("zigbee", self.metadata()) + with self.assertRaises(ValueError): + self.updates._validate_download("zigbee", release, self.payload().replace(b"2.0.0", b"9.0.0")) + for contents in (self.payload(version="9.0.0"), self.payload().replace(b"wiser-zigbee-panel", b"other-widget-name")): + release["asset"]["digest"] = None + release["asset"]["size"] = len(contents) + with self.assertRaises(ValueError): + self.updates._validate_download("zigbee", release, contents) + + async def test_network_failure_does_not_block_other_card_or_hub_setup(self): + import aiohttp + self.session.get.side_effect = [self.response(error=aiohttp.ClientError("offline")), self.response(json_data=self.metadata())] + with self.assertLogs("card_update_test.update", level="WARNING"): + await self.coordinator.async_refresh() + self.assertIsNone(self.coordinator.data["schedule"]["release"]) + self.assertEqual(self.coordinator.data["zigbee"]["release"]["version"], "2.0.0") + self.assertEqual(self.coordinator.options["update_interval"], timedelta(hours=24)) + + async def test_check_does_not_install_until_user_requests_it(self): + self.session.get.return_value = self.response(json_data=self.metadata()) + state = await self.coordinator._check_card("zigbee") + self.assertFalse((self.directory / self.files.CARD_CACHE).exists()) + self.coordinator.data["zigbee"] = state + self.session.get.return_value = self.response(contents=self.payload()) + await self.coordinator.install("zigbee") + self.assertEqual(self.coordinator.data["zigbee"]["installed"], "2.0.0") + self.assertEqual(self.files.resolve_card(self.directory, "wiser-zigbee-card.js", self.version_reader)[2], "2.0.0") + self.registration.async_register.assert_awaited_once() + self.updates.async_update_schedules_panel.assert_awaited_once() + self.updates.async_update_zigbee_panel.assert_awaited_once() + self.assertFalse(self.coordinator.installing) + + async def test_invalid_download_keeps_existing_installation(self): + release = self.updates._validate_release("zigbee", self.metadata()) + self.coordinator.data["zigbee"] = {"installed": "1.0.0", "release": release} + self.session.get.return_value = self.response(contents=b"broken") + with self.assertRaisesRegex(RuntimeError, "Unable to install"): + await self.coordinator.install("zigbee") + self.assertEqual(self.coordinator.data["zigbee"]["installed"], "1.0.0") + self.assertFalse((self.directory / self.files.CARD_CACHE).exists()) + self.assertFalse(self.coordinator.installing) + self.registration.async_register.assert_not_awaited() + + async def test_multiple_hubs_share_entities_and_transfer_when_owner_unloads(self): + self.hass.data["wiser_card_updates"] = self.coordinator + self.coordinator.async_refresh = AsyncMock() + first, second = Mock(), Mock() + await self.updates.async_setup_entry(self.hass, SimpleNamespace(entry_id="first"), first) + await self.updates.async_setup_entry(self.hass, SimpleNamespace(entry_id="second"), second) + self.coordinator.async_refresh.assert_awaited_once() + self.assertEqual(len(first.call_args.args[0]), 2) + second.assert_not_called() + self.registry.async_get_entity_id.side_effect = lambda domain, platform, unique_id: f"update.{unique_id}" + await self.updates.async_unload_card_updates(self.hass, SimpleNamespace(entry_id="first")) + self.assertEqual(self.coordinator.owner, "second") + self.assertEqual(len(second.call_args.args[0]), 2) + self.assertEqual(self.registry.async_update_entity.call_args.kwargs["config_entry_id"], "second") + await self.updates.async_unload_card_updates(self.hass, SimpleNamespace(entry_id="second")) + self.coordinator.async_shutdown.assert_awaited_once() + self.assertNotIn("wiser_card_updates", self.hass.data) + + async def test_update_entity_delegates_manual_install_and_exposes_release(self): + self.coordinator.data["zigbee"] = {"installed": "1.0.0", "release": self.updates._validate_release("zigbee", self.metadata())} + entity = self.updates.WiserCardUpdate(self.coordinator, "zigbee") + self.assertTrue(entity.available) + self.assertEqual(entity.installed_version, "1.0.0") + self.assertEqual(entity.latest_version, "2.0.0") + self.assertIn("/releases/tag/v2.0.0", entity.release_url) + self.coordinator.install = AsyncMock() + await entity.async_install(None, False) + self.coordinator.install.assert_awaited_once_with("zigbee") + + async def test_lovelace_resource_moves_to_cached_url_without_duplicate(self): + tree = ast.parse((ROOT / "frontend/__init__.py").read_text()) + cls = next(node for node in tree.body if isinstance(node, ast.ClassDef) and node.name == "JSModuleRegistration") + active = "/wiser/cards/wiser-zigbee-card-abc.js?v=2.0.0" + resource = {"id": "card", "url": "/wiser/wiser-zigbee-card.js?v=1.0.0"} + resources = SimpleNamespace( + async_items=lambda: [resource], async_update_item=AsyncMock(), + async_create_item=AsyncMock(), async_delete_item=AsyncMock(), + ) + self.hass.data["lovelace"] = SimpleNamespace(mode="storage", resources=resources) + namespace = { + "HomeAssistant": object, "LovelaceData": object, "Path": Path, + "MAJOR_VERSION": 2025, "MINOR_VERSION": 5, + "MODE_STORAGE": "storage", "URL_BASE": "/wiser", + "CARD_CACHE_URL": "/wiser/cards", "_LOGGER": Mock(), + "JSMODULES": [{"filename": "wiser-zigbee-card.js", "name": "Zigbee"}], + "async_card_resource": AsyncMock(return_value=(None, active, "2.0.0")), + } + exec(compile(ast.Module(body=[cls], type_ignores=[]), "frontend/__init__.py", "exec"), namespace) + registration = namespace["JSModuleRegistration"](self.hass) + registration.async_remove_gzip_files = AsyncMock() + await registration._async_register_modules() + resources.async_update_item.assert_awaited_once_with("card", {"res_type": "module", "url": active}) + resources.async_create_item.assert_not_awaited() + resource["url"] = active + resources.async_update_item.reset_mock() + await registration._async_register_modules() + resources.async_update_item.assert_not_awaited() + resources.async_create_item.assert_not_awaited() + await registration.async_unregister() + resources.async_delete_item.assert_awaited_once_with("card") + + async def test_older_stable_release_is_not_installed_over_development_card(self): + self.version_reader.return_value = "3.0.0-dev.84" + self.coordinator.data["zigbee"] = {"release": self.updates._validate_release("zigbee", self.metadata())} + await self.coordinator.install("zigbee") + self.session.get.assert_not_called() + self.assertFalse((self.directory / self.files.CARD_CACHE).exists()) diff --git a/tests/test_schedules_sidebar.py b/tests/test_schedules_sidebar.py index 1a6dc563..42ac3786 100644 --- a/tests/test_schedules_sidebar.py +++ b/tests/test_schedules_sidebar.py @@ -29,6 +29,11 @@ def setUp(self): version_module = ModuleType("sidebar_test.frontend.schedule_version") self.version_reader = Mock(return_value="4.5.6-beta.2") version_module.card_version = self.version_reader + async def card_resource(hass, filename): + path = ROOT / "frontend" / filename + version = await hass.async_add_executor_job(self.version_reader, path) + return path, f"/wiser/{filename}?v={version}", version + version_module.async_card_resource = card_resource version_module.__path__ = [str(ROOT / "frontend")] constants.DATA = "data" constants.DOMAIN = "wiser" diff --git a/tests/test_zigbee_sidebar.py b/tests/test_zigbee_sidebar.py index 8acceb80..185974e1 100644 --- a/tests/test_zigbee_sidebar.py +++ b/tests/test_zigbee_sidebar.py @@ -27,6 +27,11 @@ def setUp(self): version_module = ModuleType("sidebar_test.frontend.zigbee_version") self.version_reader = Mock(return_value="4.5.6-beta.2") version_module.card_version = self.version_reader + async def card_resource(hass, filename): + path = ROOT / "frontend" / filename + version = await hass.async_add_executor_job(self.version_reader, path) + return path, f"/wiser/{filename}?v={version}", version + version_module.async_card_resource = card_resource version_module.__path__ = [str(ROOT / "frontend")] constants.DATA = "data" constants.DOMAIN = "wiser" From 62e59497d9fee353e1807d500438ee051003574d Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Sun, 20 Sep 2026 10:27:18 +0100 Subject: [PATCH 030/154] Fix card update refresh retries and prune old cached bundles --- custom_components/wiser/frontend/__init__.py | 7 +- .../wiser/frontend/card_files.py | 23 ++++- custom_components/wiser/update.py | 90 +++++++++++++------ tests/test_card_updates.py | 70 +++++++++++++++ 4 files changed, 156 insertions(+), 34 deletions(-) diff --git a/custom_components/wiser/frontend/__init__.py b/custom_components/wiser/frontend/__init__.py index 816f5d22..03616dda 100644 --- a/custom_components/wiser/frontend/__init__.py +++ b/custom_components/wiser/frontend/__init__.py @@ -81,21 +81,20 @@ def __init__(self, hass: HomeAssistant) -> None: self.resource_mode = None return - # Fix for change to name of mode to reousrce_mode in 2026.2 + # Fix for change to name of mode to resource_mode in 2026.2 if (MAJOR_VERSION, MINOR_VERSION) >= (2026, 2): self.resource_mode = self.lovelace.resource_mode else: self.resource_mode = self.lovelace.mode async def async_register(self): - """Register view_assist path.""" + """Register Wiser static paths, icons, and card resources.""" await self._async_register_path() icon_version = await self.hass.async_add_executor_job( card_version, Path(__file__).parent / "wiser-icons.js" ) add_extra_js_url(self.hass, f"{URL_BASE}/wiser-icons.js?v={icon_version}") - if self.lovelace and self.resource_mode == MODE_STORAGE: await self._async_wait_for_lovelace_resources() @@ -119,7 +118,7 @@ async def _async_register_path(self): ) _LOGGER.debug("Registered resource path from %s", Path(__file__).parent) except RuntimeError: - # Runtime error is likley this is already registered. + # Runtime error is likely this is already registered. _LOGGER.debug("Resource path already registered") async def _async_wait_for_lovelace_resources(self) -> None: diff --git a/custom_components/wiser/frontend/card_files.py b/custom_components/wiser/frontend/card_files.py index 13425425..51726959 100644 --- a/custom_components/wiser/frontend/card_files.py +++ b/custom_components/wiser/frontend/card_files.py @@ -2,7 +2,9 @@ from hashlib import sha256 import json +import logging from pathlib import Path +import re import tempfile from awesomeversion import AwesomeVersion @@ -10,6 +12,8 @@ from ..const import URL_BASE +_LOGGER = logging.getLogger(__name__) + CARD_CACHE = ".storage/wiser_cards" CARD_CACHE_URL = f"{URL_BASE}/cards" @@ -34,7 +38,11 @@ def resolve_card(config_dir, filename, version_reader): # Metadata must not redirect static serving outside the card cache. digest = record["digest"] expected = f"{Path(filename).stem}-{digest}.js" - if record["file"] != expected or len(digest) != 64 or any(c not in "0123456789abcdef" for c in digest): + if ( + record["file"] != expected + or len(digest) != 64 + or any(c not in "0123456789abcdef" for c in digest) + ): return fallback if not newer_version(record["version"], version): return fallback @@ -56,6 +64,19 @@ def store_card(config_dir, filename, version, contents): _atomic_write(directory / f"{filename}.json", json.dumps(metadata).encode()) +def prune_card_cache(config_dir, filename, keep_paths): + """Retain current and previous assets after a successful frontend refresh.""" + directory = Path(config_dir) / CARD_CACHE + pattern = re.compile(rf"{re.escape(Path(filename).stem)}-[0-9a-f]{{64}}\.js") + try: + for path in directory.iterdir(): + if pattern.fullmatch(path.name) and path not in keep_paths: + path.unlink(missing_ok=True) + except OSError as err: + # Cache housekeeping must not turn a successful installation into a failure. + _LOGGER.warning("Unable to clean up %s card cache: %s", filename, err) + + def _atomic_write(path, contents): """Keep the previous working file intact if a write fails.""" with tempfile.NamedTemporaryFile(dir=path.parent, delete=False) as stream: diff --git a/custom_components/wiser/update.py b/custom_components/wiser/update.py index b2085da8..4ebb2f8d 100644 --- a/custom_components/wiser/update.py +++ b/custom_components/wiser/update.py @@ -19,7 +19,7 @@ from .const import DOMAIN from .frontend import JSModuleRegistration, async_card_resource -from .frontend.card_files import newer_version, store_card +from .frontend.card_files import newer_version, prune_card_cache, store_card from .frontend.schedules_sidebar import async_update_schedules_panel from .frontend.zigbee_sidebar import async_update_zigbee_panel @@ -46,17 +46,27 @@ def _validate_release(card, release): if release.get("draft") or release.get("prerelease") or not release.get("published_at"): raise ValueError("Expected a published stable card release") version = _release_version(release["tag_name"]) - assets = [asset for asset in release["assets"] if asset["name"] == filename and asset.get("state") == "uploaded"] + assets = [ + asset for asset in release["assets"] + if asset["name"] == filename and asset.get("state") == "uploaded" + ] if len(assets) != 1: raise ValueError(f"Release must include exactly one {filename}") asset = assets[0] url = urlsplit(asset["browser_download_url"]) - if url.scheme != "https" or url.netloc != "github.com" or not url.path.startswith(f"/{repository}/releases/download/"): + if ( + url.scheme != "https" + or url.netloc != "github.com" + or not url.path.startswith(f"/{repository}/releases/download/") + ): raise ValueError("Invalid card release download URL") if not 100 <= asset["size"] <= _MAX_DOWNLOAD: raise ValueError("Invalid card release asset size") - return {"version": version, "asset": asset, - "release_url": f"https://github.com/{repository}/releases/tag/{release['tag_name']}"} + return { + "version": version, + "asset": asset, + "release_url": f"https://github.com/{repository}/releases/tag/{release['tag_name']}", + } def _validate_download(card, release, contents): @@ -111,13 +121,16 @@ class CardUpdateCoordinator(DataUpdateCoordinator): """Share one daily GitHub check and install lock across both cards and all hubs.""" def __init__(self, hass): - super().__init__(hass, _LOGGER, name="Wiser card updates", config_entry=None, - update_interval=timedelta(hours=24)) + super().__init__( + hass, _LOGGER, name="Wiser card updates", config_entry=None, + update_interval=timedelta(hours=24), + ) self.setup_lock = asyncio.Lock() self.install_lock = asyncio.Lock() self.entries = {} self.owner = None self.installing = set() + self.pending_refresh = {} self.data = {} def add_entities(self, entry_id): @@ -138,6 +151,8 @@ async def _async_update_data(self): async def _check_card(self, card): repository, filename, _ = _CARDS[card] _, _, installed = await async_card_resource(self.hass, filename) + if card in self.pending_refresh: + installed = self.pending_refresh[card][0] try: session = async_get_clientsession(self.hass) async with session.get( @@ -160,36 +175,53 @@ async def install(self, card): if not release: raise HomeAssistantError("No verified card release is available") _, filename, _ = _CARDS[card] - _, _, installed = await async_card_resource(self.hass, filename) - if not newer_version(release["version"], installed): + active_path, _, installed = await async_card_resource(self.hass, filename) + needs_download = newer_version(release["version"], installed) + if not needs_download and card not in self.pending_refresh: return self.installing.add(card) self.async_update_listeners() try: - session = async_get_clientsession(self.hass) - async with session.get( - release["asset"]["browser_download_url"], - timeout=aiohttp.ClientTimeout(total=120), - ) as response: - response.raise_for_status() - chunks = [] - size = 0 - async for chunk in response.content.iter_chunked(65536): - size += len(chunk) - if size > _MAX_DOWNLOAD: - raise ValueError("Card download exceeds size limit") - chunks.append(chunk) - contents = b"".join(chunks) - await self.hass.async_add_executor_job(_validate_download, card, release, contents) - await self.hass.async_add_executor_job( - store_card, self.hass.config.path(), filename, release["version"], contents - ) - state["installed"] = release["version"] + if needs_download: + session = async_get_clientsession(self.hass) + async with session.get( + release["asset"]["browser_download_url"], + timeout=aiohttp.ClientTimeout(total=120), + ) as response: + response.raise_for_status() + chunks = [] + size = 0 + async for chunk in response.content.iter_chunked(65536): + size += len(chunk) + if size > _MAX_DOWNLOAD: + raise ValueError("Card download exceeds size limit") + chunks.append(chunk) + contents = b"".join(chunks) + await self.hass.async_add_executor_job( + _validate_download, card, release, contents + ) + await self.hass.async_add_executor_job( + store_card, self.hass.config.path(), filename, + release["version"], contents, + ) + # Keep offering the update until every frontend registration succeeds. + # Retain the previous asset while a failed refresh can still reference it. + self.pending_refresh.setdefault(card, (installed, active_path)) registration = JSModuleRegistration(self.hass) await registration.async_register() await async_update_schedules_panel(self.hass) await async_update_zigbee_panel(self.hass) - except (aiohttp.ClientError, TimeoutError, OSError, ValueError) as err: + active_path, _, installed = await async_card_resource(self.hass, filename) + _, previous_path = self.pending_refresh.pop(card) + state["installed"] = installed + await self.hass.async_add_executor_job( + prune_card_cache, self.hass.config.path(), filename, + {active_path, previous_path}, + ) + except ( + aiohttp.ClientError, TimeoutError, OSError, ValueError, + RuntimeError, HomeAssistantError, + ) as err: raise HomeAssistantError(f"Unable to install card update: {err}") from err finally: self.installing.discard(card) diff --git a/tests/test_card_updates.py b/tests/test_card_updates.py index bdb97fdd..62e462dc 100644 --- a/tests/test_card_updates.py +++ b/tests/test_card_updates.py @@ -201,6 +201,76 @@ async def test_check_does_not_install_until_user_requests_it(self): self.updates.async_update_zigbee_panel.assert_awaited_once() self.assertFalse(self.coordinator.installing) + async def test_failed_frontend_refresh_can_retry_without_downloading_again(self): + for target in ( + self.registration.async_register, + self.updates.async_update_schedules_panel, + self.updates.async_update_zigbee_panel, + ): + with self.subTest(target=target): + self.files.store_card( + self.directory, "wiser-zigbee-card.js", "1.5.0", + self.payload(version="1.5.0"), + ) + previous, _, _ = self.files.resolve_card( + self.directory, "wiser-zigbee-card.js", self.version_reader + ) + release = self.updates._validate_release("zigbee", self.metadata()) + self.coordinator.data["zigbee"] = {"installed": "1.5.0", "release": release} + self.session.get.reset_mock() + self.session.get.return_value = self.response(contents=self.payload()) + target.side_effect = RuntimeError("frontend unavailable") + with self.assertRaisesRegex(RuntimeError, "Unable to install"): + await self.coordinator.install("zigbee") + self.assertEqual(self.coordinator.data["zigbee"]["installed"], "1.5.0") + self.assertTrue(previous.exists()) + self.assertFalse(self.coordinator.installing) + self.session.get.assert_called_once() + + # A scheduled release check must not hide the unfinished update. + self.session.get.return_value = self.response(json_data=self.metadata()) + self.coordinator.data["zigbee"] = await self.coordinator._check_card("zigbee") + self.assertEqual(self.coordinator.data["zigbee"]["installed"], "1.5.0") + self.session.get.reset_mock() + target.side_effect = None + await self.coordinator.install("zigbee") + self.session.get.assert_not_called() + self.assertEqual(self.coordinator.data["zigbee"]["installed"], "2.0.0") + self.assertFalse(self.coordinator.pending_refresh) + self.assertFalse(self.coordinator.installing) + self.assertTrue(previous.exists()) + + async def test_successful_updates_retain_only_current_and_previous_card_bundles(self): + filename = "wiser-zigbee-card.js" + cache = self.directory / self.files.CARD_CACHE + self.files.store_card(self.directory, "wiser-schedule-card.js", "2.0.0", self.payload("schedule")) + other_files = set(cache.iterdir()) + unrelated = cache / "wiser-zigbee-card-not-a-digest.js" + unrelated.write_text("unrelated") + for version in ("2.0.0", "3.0.0", "4.0.0"): + release = self.updates._validate_release("zigbee", self.metadata(version=version)) + self.coordinator.data["zigbee"] = {"release": release} + self.session.get.return_value = self.response(contents=self.payload(version=version)) + await self.coordinator.install("zigbee") + bundles = [p for p in cache.glob("wiser-zigbee-card-*.js") if p != unrelated] + self.assertEqual(len(bundles), 2) + self.assertEqual( + {re.search(rb"card (\S+) ", p.read_bytes())[1].decode() for p in bundles}, + {"3.0.0", "4.0.0"}, + ) + self.assertTrue(all(p.exists() for p in other_files | {unrelated})) + self.assertEqual(self.files.resolve_card(self.directory, filename, self.version_reader)[2], "4.0.0") + + async def test_cache_cleanup_failure_does_not_fail_installation(self): + release = self.updates._validate_release("zigbee", self.metadata()) + self.coordinator.data["zigbee"] = {"installed": "1.0.0", "release": release} + self.session.get.return_value = self.response(contents=self.payload()) + with patch.object(Path, "iterdir", side_effect=OSError("permission denied")): + with self.assertLogs("card_update_test.frontend.card_files", level="WARNING"): + await self.coordinator.install("zigbee") + self.assertEqual(self.coordinator.data["zigbee"]["installed"], "2.0.0") + self.assertFalse(self.coordinator.pending_refresh) + async def test_invalid_download_keeps_existing_installation(self): release = self.updates._validate_release("zigbee", self.metadata()) self.coordinator.data["zigbee"] = {"installed": "1.0.0", "release": release} From c2818e31fb1d93bfa2b60c23e22a5651d56ff7de Mon Sep 17 00:00:00 2001 From: Angelo Santagata Date: Sun, 20 Sep 2026 13:46:39 +0100 Subject: [PATCH 031/154] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ef504541..f84af2d8 100755 --- a/README.md +++ b/README.md @@ -31,12 +31,10 @@ Huge thanks to [@andyblac](https://github.com/andyblac) and [@lgo44](https://git ### Breaking changes in 4.0 -**Take a backup before upgrading.** +**Please Take a backup before upgrading.** - **The device registry is restructured.** The separate virtual controller device is merged into the physical hub device, and Wiser room devices move to stable identifiers. Entity IDs and history are preserved, but anything that targets a Wiser *device* rather than an entity - device-based automations and scripts, or dashboard cards pointing at a device - needs repointing. -- **Entity unique IDs migrate to deterministic UUIDv5.** The migration runs automatically on upgrade and renames registry entries in place, so entity IDs, history, and customisations are preserved. It cannot partially apply, but it aborts if it finds a unique ID collision. - -See the [change log](CHANGELOG.md) for the full list of changes in this release. +- If a device has been used in an automation then Home Assistant repairs should catch this and guide the user through the migration ## What's New in 3.4? @@ -44,6 +42,8 @@ See the [change log](CHANGELOG.md) for the full list of changes in this release. - Added support for many new v2 hub devices - Climate entity for controlling hot water with external tank temp sensor +See the [change log](CHANGELOG.md) for the full list of changes in this release. + ## Installing [![Open your Home Assistant instance and open a repository inside the Home Assistant Community Store.](https://my.home-assistant.io/badges/hacs_repository.svg)](https://my.home-assistant.io/redirect/hacs_repository/?owner=asantaga&repository=wiserHomeAssistantPlatform&category=integration) From 8876c8f4401a7ccebc3ff6cb30b865f3deb7f7df Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Mon, 21 Sep 2026 22:23:50 +0100 Subject: [PATCH 032/154] Count flame runtime from local midnight --- custom_components/wiser/sensor.py | 8 ++++---- tests/test_sensor.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index 7c838083..41f313bc 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -1417,7 +1417,7 @@ def icon(self): class WiserOpenThermFlameStatisticsSensor(WiserSensor): - """Rolling 24-hour runtime of the OpenTherm flame-active status.""" + """Today's runtime of the OpenTherm flame-active status, from local midnight.""" _attr_device_class = SensorDeviceClass.DURATION _attr_native_unit_of_measurement = UnitOfTime.HOURS @@ -1444,7 +1444,7 @@ def available(self): ) async def async_added_to_hass(self) -> None: - """Start the rolling history calculation after entities are registered.""" + """Start the daily history calculation after entities are registered.""" await super().async_added_to_hass() await self._async_setup_history() @@ -1484,9 +1484,9 @@ async def _async_setup_history(self, _now=None) -> None: self.hass, source_entity_id, [STATE_ON], - None, + Template("{{ today_at() }}", self.hass), Template("{{ now() }}", self.hass), - timedelta(hours=24), + None, timedelta(0), ) coordinator = HistoryStatsUpdateCoordinator( diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 81f20f56..79d8b8dc 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -713,7 +713,7 @@ def test_coprocessor_fields_are_diagnostic_sensors(self): class WiserOpenThermFlameStatisticsSensorTest(unittest.TestCase): - """Tests for the optional rolling flame-runtime entity.""" + """Tests for the optional daily flame-runtime entity.""" @classmethod def setUpClass(cls): From 3cb61bae0ef4f654359c47167bfc760137b96f27 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Sun, 27 Sep 2026 09:37:21 +0100 Subject: [PATCH 033/154] Remove bundled frontend card artifacts --- .../wiser/frontend/wiser-schedule-card.js | 2564 ----------------- .../wiser/frontend/wiser-zigbee-card.js | 658 ----- tests/test_frontend_version.py | 4 - tests/test_schedule_card_hide_hw_schedule.py | 12 +- tests/test_zigbee_version.py | 7 - 5 files changed, 1 insertion(+), 3244 deletions(-) delete mode 100644 custom_components/wiser/frontend/wiser-schedule-card.js delete mode 100644 custom_components/wiser/frontend/wiser-zigbee-card.js diff --git a/custom_components/wiser/frontend/wiser-schedule-card.js b/custom_components/wiser/frontend/wiser-schedule-card.js deleted file mode 100644 index 74fe1ace..00000000 --- a/custom_components/wiser/frontend/wiser-schedule-card.js +++ /dev/null @@ -1,2564 +0,0 @@ -function e(e,t,i,s){var o,a=arguments.length,r=a<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,i,s);else for(var n=e.length-1;n>=0;n--)(o=e[n])&&(r=(a<3?o(r):a>3?o(t,i,r):o(t,i))||r);return a>3&&r&&Object.defineProperty(t,i,r),r}function t(e){return t=>{customElements.get(e)||customElements.define(e,t)}} -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */"function"==typeof SuppressedError&&SuppressedError;const i=globalThis,s=i.ShadowRoot&&(void 0===i.ShadyCSS||i.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,o=Symbol(),a=new WeakMap;let r=class{constructor(e,t,i){if(this._$cssResult$=!0,i!==o)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=e,this.t=t}get styleSheet(){let e=this.o;const t=this.t;if(s&&void 0===e){const i=void 0!==t&&1===t.length;i&&(e=a.get(t)),void 0===e&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),i&&a.set(t,e))}return e}toString(){return this.cssText}};const n=(e,...t)=>{const i=1===e.length?e[0]:t.reduce((t,i,s)=>t+(e=>{if(!0===e._$cssResult$)return e.cssText;if("number"==typeof e)return e;throw Error("Value passed to 'css' function must be a 'css' function result: "+e+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+e[s+1],e[0]);return new r(i,e,o)},l=s?e=>e:e=>e instanceof CSSStyleSheet?(e=>{let t="";for(const i of e.cssRules)t+=i.cssText;return(e=>new r("string"==typeof e?e:e+"",void 0,o))(t)})(e):e,{is:d,defineProperty:c,getOwnPropertyDescriptor:h,getOwnPropertyNames:p,getOwnPropertySymbols:u,getPrototypeOf:m}=Object,g=globalThis,v=g.trustedTypes,y=v?v.emptyScript:"",_=g.reactiveElementPolyfillSupport,f=(e,t)=>e,b={toAttribute(e,t){switch(t){case Boolean:e=e?y:null;break;case Object:case Array:e=null==e?e:JSON.stringify(e)}return e},fromAttribute(e,t){let i=e;switch(t){case Boolean:i=null!==e;break;case Number:i=null===e?null:Number(e);break;case Object:case Array:try{i=JSON.parse(e)}catch(e){i=null}}return i}},w=(e,t)=>!d(e,t),x={attribute:!0,type:String,converter:b,reflect:!1,useDefault:!1,hasChanged:w}; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */Symbol.metadata??=Symbol("metadata"),g.litPropertyMetadata??=new WeakMap;let $=class extends HTMLElement{static addInitializer(e){this._$Ei(),(this.l??=[]).push(e)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(e,t=x){if(t.state&&(t.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(e)&&((t=Object.create(t)).wrapped=!0),this.elementProperties.set(e,t),!t.noAccessor){const i=Symbol(),s=this.getPropertyDescriptor(e,i,t);void 0!==s&&c(this.prototype,e,s)}}static getPropertyDescriptor(e,t,i){const{get:s,set:o}=h(this.prototype,e)??{get(){return this[t]},set(e){this[t]=e}};return{get:s,set(t){const a=s?.call(this);o?.call(this,t),this.requestUpdate(e,a,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)??x}static _$Ei(){if(this.hasOwnProperty(f("elementProperties")))return;const e=m(this);e.finalize(),void 0!==e.l&&(this.l=[...e.l]),this.elementProperties=new Map(e.elementProperties)}static finalize(){if(this.hasOwnProperty(f("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(f("properties"))){const e=this.properties,t=[...p(e),...u(e)];for(const i of t)this.createProperty(i,e[i])}const e=this[Symbol.metadata];if(null!==e){const t=litPropertyMetadata.get(e);if(void 0!==t)for(const[e,i]of t)this.elementProperties.set(e,i)}this._$Eh=new Map;for(const[e,t]of this.elementProperties){const i=this._$Eu(e,t);void 0!==i&&this._$Eh.set(i,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(e){const t=[];if(Array.isArray(e)){const i=new Set(e.flat(1/0).reverse());for(const e of i)t.unshift(l(e))}else void 0!==e&&t.push(l(e));return t}static _$Eu(e,t){const i=t.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof e?e.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(e=>this.enableUpdating=e),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(e=>e(this))}addController(e){(this._$EO??=new Set).add(e),void 0!==this.renderRoot&&this.isConnected&&e.hostConnected?.()}removeController(e){this._$EO?.delete(e)}_$E_(){const e=new Map,t=this.constructor.elementProperties;for(const i of t.keys())this.hasOwnProperty(i)&&(e.set(i,this[i]),delete this[i]);e.size>0&&(this._$Ep=e)}createRenderRoot(){const e=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return((e,t)=>{if(s)e.adoptedStyleSheets=t.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(const s of t){const t=document.createElement("style"),o=i.litNonce;void 0!==o&&t.setAttribute("nonce",o),t.textContent=s.cssText,e.appendChild(t)}})(e,this.constructor.elementStyles),e}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(e=>e.hostConnected?.())}enableUpdating(e){}disconnectedCallback(){this._$EO?.forEach(e=>e.hostDisconnected?.())}attributeChangedCallback(e,t,i){this._$AK(e,i)}_$ET(e,t){const i=this.constructor.elementProperties.get(e),s=this.constructor._$Eu(e,i);if(void 0!==s&&!0===i.reflect){const o=(void 0!==i.converter?.toAttribute?i.converter:b).toAttribute(t,i.type);this._$Em=e,null==o?this.removeAttribute(s):this.setAttribute(s,o),this._$Em=null}}_$AK(e,t){const i=this.constructor,s=i._$Eh.get(e);if(void 0!==s&&this._$Em!==s){const e=i.getPropertyOptions(s),o="function"==typeof e.converter?{fromAttribute:e.converter}:void 0!==e.converter?.fromAttribute?e.converter:b;this._$Em=s;const a=o.fromAttribute(t,e.type);this[s]=a??this._$Ej?.get(s)??a,this._$Em=null}}requestUpdate(e,t,i,s=!1,o){if(void 0!==e){const a=this.constructor;if(!1===s&&(o=this[e]),i??=a.getPropertyOptions(e),!((i.hasChanged??w)(o,t)||i.useDefault&&i.reflect&&o===this._$Ej?.get(e)&&!this.hasAttribute(a._$Eu(e,i))))return;this.C(e,t,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(e,t,{useDefault:i,reflect:s,wrapped:o},a){i&&!(this._$Ej??=new Map).has(e)&&(this._$Ej.set(e,a??t??this[e]),!0!==o||void 0!==a)||(this._$AL.has(e)||(this.hasUpdated||i||(t=void 0),this._$AL.set(e,t)),!0===s&&this._$Em!==e&&(this._$Eq??=new Set).add(e))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(e){Promise.reject(e)}const e=this.scheduleUpdate();return null!=e&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[e,t]of this._$Ep)this[e]=t;this._$Ep=void 0}const e=this.constructor.elementProperties;if(e.size>0)for(const[t,i]of e){const{wrapped:e}=i,s=this[t];!0!==e||this._$AL.has(t)||void 0===s||this.C(t,void 0,i,s)}}let e=!1;const t=this._$AL;try{e=this.shouldUpdate(t),e?(this.willUpdate(t),this._$EO?.forEach(e=>e.hostUpdate?.()),this.update(t)):this._$EM()}catch(t){throw e=!1,this._$EM(),t}e&&this._$AE(t)}willUpdate(e){}_$AE(e){this._$EO?.forEach(e=>e.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(e){return!0}update(e){this._$Eq&&=this._$Eq.forEach(e=>this._$ET(e,this[e])),this._$EM()}updated(e){}firstUpdated(e){}};$.elementStyles=[],$.shadowRootOptions={mode:"open"},$[f("elementProperties")]=new Map,$[f("finalized")]=new Map,_?.({ReactiveElement:$}),(g.reactiveElementVersions??=[]).push("2.1.2"); -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const S=globalThis,k=e=>e,C=S.trustedTypes,E=C?C.createPolicy("lit-html",{createHTML:e=>e}):void 0,A="$lit$",z=`lit$${Math.random().toFixed(9).slice(2)}$`,D="?"+z,T=`<${D}>`,M=document,N=()=>M.createComment(""),O=e=>null===e||"object"!=typeof e&&"function"!=typeof e,I=Array.isArray,L="[ \t\n\f\r]",P=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,R=/-->/g,H=/>/g,j=RegExp(`>|${L}(?:([^\\s"'>=/]+)(${L}*=${L}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),U=/'/g,V=/"/g,B=/^(?:script|style|textarea|title)$/i,W=(e=>(t,...i)=>({_$litType$:e,strings:t,values:i}))(1),q=Symbol.for("lit-noChange"),F=Symbol.for("lit-nothing"),Y=new WeakMap,J=M.createTreeWalker(M,129);function Z(e,t){if(!I(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==E?E.createHTML(t):t}const G=(e,t)=>{const i=e.length-1,s=[];let o,a=2===t?"":3===t?"":"",r=P;for(let t=0;t"===l[0]?(r=o??P,d=-1):void 0===l[1]?d=-2:(d=r.lastIndex-l[2].length,n=l[1],r=void 0===l[3]?j:'"'===l[3]?V:U):r===V||r===U?r=j:r===R||r===H?r=P:(r=j,o=void 0);const h=r===j&&e[t+1].startsWith("/>")?" ":"";a+=r===P?i+T:d>=0?(s.push(n),i.slice(0,d)+A+i.slice(d)+z+h):i+z+(-2===d?t:h)}return[Z(e,a+(e[i]||"")+(2===t?"":3===t?"":"")),s]};class K{constructor({strings:e,_$litType$:t},i){let s;this.parts=[];let o=0,a=0;const r=e.length-1,n=this.parts,[l,d]=G(e,t);if(this.el=K.createElement(l,i),J.currentNode=this.el.content,2===t||3===t){const e=this.el.content.firstChild;e.replaceWith(...e.childNodes)}for(;null!==(s=J.nextNode())&&n.length0){s.textContent=C?C.emptyScript:"";for(let i=0;iI(e)||"function"==typeof e?.[Symbol.iterator])(e)?this.k(e):this._(e)}O(e){return this._$AA.parentNode.insertBefore(e,this._$AB)}T(e){this._$AH!==e&&(this._$AR(),this._$AH=this.O(e))}_(e){this._$AH!==F&&O(this._$AH)?this._$AA.nextSibling.data=e:this.T(M.createTextNode(e)),this._$AH=e}$(e){const{values:t,_$litType$:i}=e,s="number"==typeof i?this._$AC(e):(void 0===i.el&&(i.el=K.createElement(Z(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===s)this._$AH.p(t);else{const e=new Q(s,this),i=e.u(this.options);e.p(t),this.T(i),this._$AH=e}}_$AC(e){let t=Y.get(e.strings);return void 0===t&&Y.set(e.strings,t=new K(e)),t}k(e){I(this._$AH)||(this._$AH=[],this._$AR());const t=this._$AH;let i,s=0;for(const o of e)s===t.length?t.push(i=new ee(this.O(N()),this.O(N()),this,this.options)):i=t[s],i._$AI(o),s++;s2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=F}_$AI(e,t=this,i,s){const o=this.strings;let a=!1;if(void 0===o)e=X(this,e,t,0),a=!O(e)||e!==this._$AH&&e!==q,a&&(this._$AH=e);else{const s=e;let r,n;for(e=o[0],r=0;r{const s=i?.renderBefore??t;let o=s._$litPart$;if(void 0===o){const e=i?.renderBefore??null;s._$litPart$=o=new ee(t.insertBefore(N(),e),e,void 0,i??{})}return o._$AI(e),o})(t,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return q}}le._$litElement$=!0,le.finalized=!0,ne.litElementHydrateSupport?.({LitElement:le});const de=ne.litElementPolyfillSupport;de?.({LitElement:le}),(ne.litElementVersions??=[]).push("4.2.2"); -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -const ce={attribute:!0,type:String,converter:b,reflect:!1,hasChanged:w},he=(e=ce,t,i)=>{const{kind:s,metadata:o}=i;let a=globalThis.litPropertyMetadata.get(o);if(void 0===a&&globalThis.litPropertyMetadata.set(o,a=new Map),"setter"===s&&((e=Object.create(e)).wrapped=!0),a.set(i.name,e),"accessor"===s){const{name:s}=i;return{set(i){const o=t.get.call(this);t.set.call(this,i),this.requestUpdate(s,o,e,!0,i)},init(t){return void 0!==t&&this.C(s,void 0,e,t),t}}}if("setter"===s){const{name:s}=i;return function(i){const o=this[s];t.call(this,i),this.requestUpdate(s,o,e,!0,i)}}throw Error("Unsupported decorator location: "+s)};function pe(e){return(t,i)=>"object"==typeof i?he(e,t,i):((e,t,i)=>{const s=t.hasOwnProperty(i);return t.constructor.createProperty(i,e),s?Object.getOwnPropertyDescriptor(t,i):void 0})(e,t,i)} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */function ue(e){return pe({...e,state:!0,attribute:!1})} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */var me,ge;!function(e){e.language="language",e.system="system",e.comma_decimal="comma_decimal",e.decimal_comma="decimal_comma",e.space_comma="space_comma",e.none="none"}(me||(me={})),function(e){e.language="language",e.system="system",e.am_pm="12",e.twenty_four="24"}(ge||(ge={}));var ve=function(e,t,i,s){s=s||{},i=null==i?{}:i;var o=new Event(t,{bubbles:void 0===s.bubbles||s.bubbles,cancelable:Boolean(s.cancelable),composed:void 0===s.composed||s.composed});return o.detail=i,e.dispatchEvent(o),o};const ye="2.0.0-dev.60",_e=86400;var fe,be,we;!function(e){e.Overview="OVERVIEW",e.RoomSchedule="ROOM_SCHEDULE",e.ScheduleEdit="SCHEDULE_EDIT",e.ScheduleCopy="SCHEDULE_COPY",e.ScheduleAdd="SCHEDULE_ADD",e.ScheduleRename="SCHEDULE_RENAME"}(fe||(fe={})),function(e){e.Heating="19",e.OnOff="Off",e.Lighting="0",e.Shutters="100"}(be||(be={})),function(e){e.Heating="°C",e.OnOff="",e.Lighting="%",e.Shutters="%"}(we||(we={}));const xe=["Heating","OnOff","Lighting","Shutters"],$e=["Lighting","Shutters"],Se=["Weekdays","Weekend"],ke=["Monday","Tuesday","Wednesday","Thursday","Friday"],Ce=["Saturday","Sunday"],Ee=ke.concat(Ce),Ae=["Sunrise","Sunset"];var ze;!function(e){e.Sunrise="3000",e.Sunset="4000"}(ze||(ze={}));var De={version:"Version",invalid_configuration:"Invalid configuration",no_schedules:"No Schedules Found",name_required:"Name is required",loading:"Loading schedules…",retry:"Try again",load_failed:"Unable to load schedules.",integration_unavailable:"The Wiser integration is not available."},Te={actions:{copy:"Copy",files:"Files",rename:"Rename",add:"Add",view:"View",add_schedule:"Add Schedule",export:"Export schedule",import:"Import schedule"},labels:{setting:"Setting",name:"Name",assigns:"Assigns",start:"Start",end:"End",to:"to"},days:{monday:"Monday",tuesday:"Tuesday",wednesday:"Wednesday",thursday:"Thursday",friday:"Friday",saturday:"Saturday",sunday:"Sunday",weekdays:"Weekdays",weekend:"Weekend",all:"All",short:{monday:"Mon",tuesday:"Tue",wednesday:"Wed",thursday:"Thu",friday:"Fri",saturday:"Sat",sunday:"Sun"}},headings:{schedule_actions:"Schedule Actions",schedule_type:"Schedule Type",schedule_id:"Schedule Id",schedule_name:"Schedule Name",schedule_assignment:"Room/Device Assignment",not_assigned:"(Not Assigned)",rename_schedule:"Rename Schedule",copy_schedule:"Copy Schedule",delete_schedule:"Delete Schedule"},helpers:{enter_new_name:"Enter the new name for the Schedule",select_copy_schedule:"Select the schedule to copy to",delete_schedule_confirm:"Are you sure you wish to delete the schedule",select_a_schedule:"Select a schedule to view",add_schedule:"Select the schedule type and enter a name for the schedule to create",add_schedule_name:"Enter a name for the new schedule",no_supported_types:"No compatible schedule types are available for this device."},rooms:{title:"Rooms",schedules:"Schedules",manage:"Manage schedules",back:"Back to home",missing:"This room or device is no longer available.",current:"Current schedule",unassigned:"No schedule assigned",choose:"Choose a schedule",no_schedules:"No compatible schedules available. Create one using + in the toolbar.",assigning:"Assigning…",assign:"Assign schedule",saved:"Schedule assigned.",view_schedule:"View / edit schedule",shared:"This schedule is shared. Editing its times affects every assigned room or device.",select:"Select a room to choose its schedule",empty:"No Wiser rooms found.",edit:"Edit schedule",save_edit:"Save schedule",cancel_edit:"Cancel editing",delete:"Delete schedule",available:"Available schedule",none:"No schedule",removed:"Schedule unassigned."},moments:{title:"Moments",heating:"Room heating",description:"Preset actions for your home. Use Home Assistant automations to run them on a schedule.",loading:"Loading Moments…",failed:"Moments could not be loaded. Registry access may be restricted for this account.",empty:"No enabled Wiser Moments found for this hub. Create Moments in the Wiser app.",open:"Open controls",unavailable:"Unavailable"},home:{title:"Home",heating:"Heating",hotwater:"Hot water",devices:"Lighting & devices",empty:"No scheduled Wiser rooms or devices found.",screen:"Home screen",no_schedules:"No schedules yet. Use + to create one.",assignments:"assigned",assign_devices:"Assigned rooms / devices",apply_devices:"Apply assignments",no_devices:"No compatible devices available.",schedules:"Schedules",overview:"Overview",overview_hint:"Planned schedule changes for each device, shown in the Home Assistant timezone.",schedule_name:"Schedule name",schedule_id:"Schedule ID",schedule_type:"Schedule type",next_day:"Next day",next_change:"Next change",next_setting:"Next scheduled setting",no_next_change:"No upcoming timed change available.",overview_details:"Overview Details",show:"Show",hide:"Hide",device_details:"Schedule details"},editor:{hub:"Wiser hub",permissions:"Permissions",appearance:"Appearance",display_only:"Read-only mode",admin_only:"Only admins can manage schedules",theme_colors:"Use theme colours",hide_card_borders:"Hide card borders",display_only_help:"Prevent schedule and heating changes, including for admins.",hide_card_background:"Hide card background"},heating:{status:"Schedule status",activity:"Heating",mode:"Heating mode",following:"Following schedule",auto:"Auto",manual:"Manual",off:"Off",override:"Temporary override",boost:"Boost active",away:"Away mode",comfort:"Comfort adjustment",eco:"EcoIQ adjustment",passive:"Passive mode",unknown:"Unknown",unavailable:"Status unavailable",unassigned:"No schedule assigned",heating:"Heating",idle:"Idle",resume:"Resume schedule",failed:"Unable to change heating mode."}},Me={common:De,wiser:Te},Ne={version:"Déclinaison",invalid_configuration:"Configuration Invalide",no_schedules:"Aucun Programme Trouvé",name_required:"Nom est obligatoire",loading:"Chargement des programmes…",retry:"Réessayer",load_failed:"Impossible de charger les programmes.",integration_unavailable:"L’intégration Wiser n’est pas disponible."},Oe={actions:{copy:"Copie",files:"Fichier",rename:"Renommer",add:"Ajouter",view:"Voir",add_schedule:"Ajouter un Programme",export:"Exporter le programme",import:"Importer un programme"},labels:{setting:"Paramètre",name:"Nom",assigns:"Attribuers",start:"Début",end:"Fin",to:"à"},days:{monday:"Lundi",tuesday:"Mardi",wednesday:"Mercredi",thursday:"Jeudi",friday:"Vendredi",saturday:"Samedi",sunday:"Dimanche",weekdays:"Lun à Ven",weekend:"Sam et Dim",all:"Toute",short:{monday:"Lun",tuesday:"Mar",wednesday:"Mer",thursday:"Jeu",friday:"Ven",saturday:"Sam",sunday:"Dim"}},headings:{schedule_actions:"Programmer des Actions",schedule_type:"Type de Programme",schedule_id:"Numéro de Programme",schedule_name:"Nom de Programme",schedule_assignment:"Attribuer de Programme",not_assigned:"(Non Attribué)",rename_schedule:"Renommer le Programme",copy_schedule:"Copier le Programme",delete_schedule:"Supprimer le Programme"},helpers:{enter_new_name:"Entrez un nom pour le Programme",select_copy_schedule:"Sélectionnez le calendrier ci-dessous pour le copier",delete_schedule_confirm:"Êtes-vous sûr de vouloir effacer ce programme",select_a_schedule:"Sélectionner un programme à afficher",add_schedule:"Sélectionnez le type de programme et entrez un nom pour la programme à créer",add_schedule_name:"Saisissez un nom pour le nouveau programme",no_supported_types:"Aucun type de programme compatible avec cet appareil."},rooms:{title:"Pièces",schedules:"Programmes",manage:"Gérer les programmes",back:"Retour à l’accueil",missing:"Cette pièce ou cet appareil n’est plus disponible.",current:"Programme actuel",unassigned:"Aucun programme attribué",choose:"Choisir un programme",no_schedules:"Aucun programme compatible. Créez-en un avec +.",assigning:"Attribution…",assign:"Attribuer le programme",saved:"Programme attribué.",view_schedule:"Voir / modifier le programme",shared:"Ce programme est partagé : les modifications affectent toutes les pièces et appareils associés.",select:"Sélectionnez une pièce pour choisir son programme",empty:"Aucune pièce Wiser trouvée.",edit:"Modifier le programme",save_edit:"Enregistrer le programme",cancel_edit:"Annuler les modifications",delete:"Supprimer le programme",available:"Programme disponible",none:"Aucun programme",removed:"Programme désaffecté."},moments:{title:"Moments",heating:"Chauffage des pièces",description:"Actions prédéfinies pour votre maison. Utilisez les automatisations Home Assistant pour les programmer.",loading:"Chargement des Moments…",failed:"Impossible de charger les Moments. L’accès aux registres peut être limité pour ce compte.",empty:"Aucun Moment Wiser activé pour ce hub. Créez des Moments dans l’application Wiser.",open:"Ouvrir les commandes",unavailable:"Indisponible"},home:{title:"Maison",heating:"Chauffage",hotwater:"Eau chaude",devices:"Éclairage et appareils",empty:"Aucune pièce ni appareil Wiser programmable trouvé.",screen:"Écran d’accueil",no_schedules:"Aucun programme. Utilisez + pour en créer un.",assignments:"affectations",assign_devices:"Pièces / appareils affectés",apply_devices:"Appliquer les affectations",no_devices:"Aucun appareil compatible disponible.",schedules:"Plannings",overview:"Vue d’ensemble",overview_hint:"Changements planifiés par appareil, dans le fuseau horaire de Home Assistant.",schedule_name:"Nom du planning",schedule_id:"ID du planning",schedule_type:"Type de planning",next_day:"Prochain jour",next_change:"Prochain changement",next_setting:"Prochaine consigne planifiée",no_next_change:"Aucun prochain changement horaire disponible.",overview_details:"Détails de la vue d’ensemble",show:"Afficher",hide:"Masquer",device_details:"Détails du planning"},editor:{hub:"Hub Wiser",permissions:"Autorisations",appearance:"Apparence",display_only:"Mode lecture seule",admin_only:"Seuls les administrateurs peuvent gérer les plannings",theme_colors:"Utiliser les couleurs du thème",hide_card_borders:"Masquer les bordures de la carte",display_only_help:"Empêcher les modifications des plannings et du chauffage, même pour les administrateurs.",hide_card_background:"Masquer le fond de la carte"},heating:{status:"État du planning",activity:"Chauffage",mode:"Mode de chauffage",following:"Suit le planning",auto:"Auto",manual:"Manuel",off:"Arrêt",override:"Dérogation temporaire",boost:"Boost actif",away:"Mode absence",comfort:"Ajustement Comfort",eco:"Ajustement EcoIQ",passive:"Mode passif",unknown:"Inconnu",unavailable:"État indisponible",unassigned:"Aucun planning attribué",heating:"En chauffe",idle:"Au repos",resume:"Reprendre le planning",failed:"Impossible de changer le mode de chauffage."}},Ie={common:Ne,wiser:Oe};const Le={en:Object.freeze({__proto__:null,common:De,default:Me,wiser:Te}),fr:Object.freeze({__proto__:null,common:Ne,default:Ie,wiser:Oe})},Pe={"wiser.heating.auto":"ui.common.auto","wiser.heating.unknown":"state.default.unknown","wiser.heating.mode":"ui.card.climate.mode","wiser.home.overview":"panel.states","wiser.home.show":"ui.common.show","wiser.home.hide":"ui.common.hide","wiser.actions.rename":"ui.common.rename","wiser.actions.copy":"ui.common.copy","wiser.actions.add":"ui.common.add","wiser.rooms.back":"ui.common.back","wiser.rooms.edit":"ui.common.edit","wiser.rooms.delete":"ui.common.delete","wiser.rooms.cancel_edit":"ui.common.cancel","wiser.rooms.save_edit":"ui.common.save"};function Re(e,t){const i=t.split(".").reduce((e,t)=>e&&"object"==typeof e?e[t]:void 0,Le[e]);return"string"==typeof i?i:void 0}function He(e,t="",i="",s){const o=Re((s||localStorage.getItem("selectedLanguage")||"en").replace(/['"]+/g,"").toLowerCase().split(/[-_]/)[0],e)||Re("en",e)||e;return t&&i?o.replace(t,i):o}function je(e,t,i="",s=""){var o;const a=Pe[t],r=a?null==e?void 0:e.localize(a):void 0;return r&&r!==a?i&&s?r.replace(i,s):r:He(t,i,s,(null===(o=null==e?void 0:e.locale)||void 0===o?void 0:o.language)||(null==e?void 0:e.language))}const Ue=n` - .tool { - color: var(--secondary-text-color); - } - .tool[aria-pressed='true'], - .tool:not(:disabled):hover { - color: var(--primary-color); - } - .tool:disabled { - color: var(--disabled-text-color); - opacity: 1; - } -`;let Ve=class extends le{constructor(){super(...arguments),this.editable=!1,this.assigned=!1,this.busy=!1,this.error=""}text(e){return je(this.hass,"wiser.heating."+e)}get entity(){var e;return this.entityId?null===(e=this.hass)||void 0===e?void 0:e.states[this.entityId]:void 0}get available(){return this.entity&&!["unknown","unavailable"].includes(this.entity.state)}get canResume(){var e,t,i;const s=null===(e=this.entity)||void 0===e?void 0:e.attributes;return this.assigned&&"auto"===(null===(t=this.entity)||void 0===t?void 0:t.state)&&((null==s?void 0:s.is_boosted)||(null==s?void 0:s.is_override))&&(null===(i=null==s?void 0:s.preset_modes)||void 0===i?void 0:i.includes("Cancel Overrides"))}async change(e){var t,i,s;if(!this.hass||!this.entityId||!this.editable||this.busy||!this.available)return;if(!["auto","heat","off"].includes(e)||!(null===(t=this.entity.attributes.hvac_modes)||void 0===t?void 0:t.includes(e))||"auto"===e&&!this.assigned)return;const o=this.entityId;this.busy=!0,this.error="";try{this.entity.state!==e&&await this.hass.callService("climate","set_hvac_mode",{entity_id:o,hvac_mode:e}),"auto"===e&&(null===(s=null===(i=this.entity)||void 0===i?void 0:i.attributes.preset_modes)||void 0===s?void 0:s.includes("Cancel Overrides"))&&(this.entity.attributes.is_override||this.entity.attributes.is_boosted)&&await this.hass.callService("climate","set_preset_mode",{entity_id:o,preset_mode:"Cancel Overrides"})}catch(e){this.error=e.message||this.text("failed")}finally{this.busy=!1}}render(){const e=this.entity;if(!this.hass)return W``;const t=null==e?void 0:e.attributes,i=null==t?void 0:t.target_temperature_origin,s=this.available?this.assigned?"off"===e.state?"off":"heat"===e.state?"manual":(null==t?void 0:t.is_passive)?"passive":(null==t?void 0:t.is_boosted)?"boost":(null==t?void 0:t.is_override)?"override":{FromSchedule:"following",FromAwayMode:"away",FromComfortMode:"comfort",FromEcoIQ:"eco",FromManualOverrideDuringAway:"away",FromBoostDuringAway:"away"}[i]||"unknown":"unassigned":"unavailable",o=((null==e?void 0:e.attributes.hvac_modes)||[]).filter(e=>["auto","heat","off"].includes(e)&&("auto"!==e||this.assigned));return W`
${this.text("status")}: ${this.text(s)}
- ${this.available?W`

${this.text("activity")}: ${!0===(null==t?void 0:t.is_heating)||"heating"===(null==t?void 0:t.hvac_action)?this.text("heating"):!1===(null==t?void 0:t.is_heating)||"idle"===(null==t?void 0:t.hvac_action)?this.text("idle"):this.text("unknown")}

`:""} - ${this.editable&&e?W`({value:e,label:this.text("heat"===e?"manual":e)}))}}} - .value=${e.state} - .required=${!0} - .disabled=${!this.available||this.busy} - @value-changed=${e=>{e.stopPropagation(),this.change(e.detail.value)}} - > - ${this.canResume?W`this.change("auto")}>${this.text("resume")}`:""}`:""} - ${this.error?W`

${this.error}

`:""}`}};Ve.styles=n` - :host { - display: block; - border-top: 1px solid var(--divider-color); - margin-top: 12px; - padding-top: 12px; - } - .status, - p { - font-size: inherit; - line-height: 1.5; - } - p { - margin: 8px 0; - color: var(--secondary-text-color); - } - ha-selector { - display: block; - margin-top: 12px; - max-width: 300px; - } - `,e([pe({attribute:!1})],Ve.prototype,"hass",void 0),e([pe()],Ve.prototype,"entityId",void 0),e([pe({type:Boolean})],Ve.prototype,"editable",void 0),e([pe({type:Boolean})],Ve.prototype,"assigned",void 0),e([ue()],Ve.prototype,"busy",void 0),e([ue()],Ve.prototype,"error",void 0),Ve=e([t("wiser-heating-status")],Ve);const Be=e=>e.callWS({type:"wiser/hubs"}),We=(e,t)=>e.callWS({type:"wiser/suntimes",hub:t}),qe=(e,t,i="")=>e.callWS({type:"wiser/schedules",hub:t,schedule_type:i}),Fe=(e,t,i,s)=>e.callWS({type:"wiser/schedule/id",hub:t,schedule_type:i,schedule_id:s}),Ye=(e,t)=>e.callWS({type:"wiser/rooms",hub:t}),Je=(e,t,i)=>e.callWS({type:"wiser/devices",device_type:i,hub:t}),Ze=(e,t,i,s,o,a=!1)=>e.callWS({type:"wiser/schedule/assign",hub:t,schedule_type:i,schedule_id:s,entity_id:o,remove:a});function Ge(e,t,i){ve(e,"show-dialog",{dialogTag:"wiser-dialog-error",dialogImport:()=>Promise.resolve().then(function(){return Xt}),dialogParams:{title:t,error:i}})}async function Ke(e,t){const[i,s,o]=await Promise.all([e.callWS({type:"config/entity_registry/list"}),e.callWS({type:"config/device_registry/list"}),t?Promise.resolve([t]):Be(e)]),a=new Set(s.filter(e=>e.identifiers.some(([e,i])=>"wiser"===e&&i===(t||o[0]))).map(e=>e.id)),r=new Set(s.filter(e=>e.via_device_id&&a.has(e.via_device_id)).map(e=>e.id));return i.filter(e=>"wiser"===e.platform&&e.entity_id.startsWith("climate.")&&!e.disabled_by&&e.device_id&&r.has(e.device_id)).map(e=>e.entity_id)}let Xe=class extends le{constructor(){super(...arguments),this.active="schedules",this.canAdd=!1}localize(e,t="",i=""){return je(this.hass,e,t,i)}render(){return W`${["schedules","overview"].map(e=>W``)}`}};Xe.styles=n` - :host { - display: inline-flex; - gap: 6px; - } - button { - display: grid; - place-items: center; - width: 44px; - height: 44px; - border: 1px solid transparent; - border-radius: 10px; - background: transparent; - color: var(--secondary-text-color); - cursor: pointer; - } - button[aria-pressed='true'] { - color: var(--primary-color); - background: var(--secondary-background-color); - border-color: var(--secondary-text-color); - } - button:disabled { - color: var(--disabled-text-color); - opacity: 1; - cursor: default; - } - button:not(:disabled):hover { - background: var(--secondary-background-color); - } - button:focus-visible { - outline: 2px solid var(--primary-color); - outline-offset: 2px; - } - ${Ue} - `,e([pe({attribute:!1})],Xe.prototype,"hass",void 0),e([pe()],Xe.prototype,"active",void 0),e([pe({type:Boolean})],Xe.prototype,"canAdd",void 0),Xe=e([t("wiser-home-navigation")],Xe);const Qe=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];let et=class extends le{render(){var e;const t=null===(e=this.config)||void 0===e?void 0:e.name;return W`
- ${t?W`

Wiser${"Wiser Schedule"!==t?W`${t}`:""}

`:""} -
-
`}};et.styles=n` - :host { - display: block; - margin-bottom: 20px; - } - header { - display: flex; - align-items: center; - flex-wrap: wrap; - gap: 12px; - min-height: 44px; - } - h2 { - display: flex; - align-items: center; - gap: 14px; - margin: 0; - min-width: 0; - line-height: 1.2; - } - .brand { - color: var(--wiser-brand-color, #279f43); - font-family: 'Arial Rounded MT Bold', 'Trebuchet MS', sans-serif; - font-size: calc(32px + 1pt); - font-weight: 700; - letter-spacing: -1.5px; - } - .title { - padding-inline-start: 14px; - border-inline-start: 1px solid var(--divider-color, #ddd); - color: var(--primary-text-color); - font-size: calc(15px + 1pt); - font-weight: 500; - overflow-wrap: anywhere; - } - .actions { - margin-inline-start: auto; - min-width: 0; - max-width: 100%; - } - `,e([pe({attribute:!1})],et.prototype,"config",void 0),et=e([t("wiser-card-header")],et);let tt=class extends le{constructor(){super(...arguments),this.hub="",this.entities=[],this.loading=!0,this.failed=!1,this.request=0}localize(e,t="",i=""){return je(this.hass,e,t,i)}updated(e){(e.has("hub")||e.has("hass")&&!e.get("hass"))&&this.load()}async load(){if(!this.hass)return;const e=++this.request;this.loading=!0,this.failed=!1;try{const[t,i,s]=await Promise.all([this.hass.callWS({type:"config/entity_registry/list"}),this.hass.callWS({type:"config/device_registry/list"}),this.hub?Promise.resolve([this.hub]):Be(this.hass)]);if(e!==this.request)return;const o=this.hub||s[0],a=new Set(i.filter(e=>e.identifiers.some(([e,t])=>"wiser"===e&&t===o)).map(e=>e.id));this.entities=t.filter(e=>{var t;return"wiser"===e.platform&&e.entity_id.startsWith("button.")&&!e.disabled_by&&!e.hidden_by&&e.device_id&&a.has(e.device_id)&&("moment"===e.translation_key||(null===(t=e.original_name)||void 0===t?void 0:t.startsWith("Moments "))||e.unique_id.includes("-button-Moments "))})}catch(t){e===this.request&&(this.entities=[],this.failed=!0)}finally{e===this.request&&(this.loading=!1)}}renderMoment(e){const t=this.hass.states[e.entity_id];return W``}render(){const e=this.entities.filter(e=>{var t;return null===(t=this.hass)||void 0===t?void 0:t.states[e.entity_id]});if(!this.loading&&!this.failed&&!e.length)return W``;let t;return t=this.loading?W`

${this.localize("wiser.moments.loading")}

`:this.failed?W`

${this.localize("wiser.moments.failed")}

- `:W`
${e.map(e=>this.renderMoment(e))}
`,W`
-

${this.localize("wiser.moments.title")}

-

${this.localize("wiser.moments.description")}

- ${t} -
`}};tt.styles=n` - :host { - display: block; - } - section { - margin-top: 24px; - padding-top: 20px; - border-top: 1px solid var(--divider-color, #ddd); - } - h3 { - font-size: calc(15px + 1pt); - font-weight: 600; - margin: 0 0 8px; - color: var(--primary-text-color); - } - p { - font-size: calc(14px + 1pt); - line-height: 1.5; - margin: 0 0 14px; - color: var(--secondary-text-color); - } - .moments { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(min(100%, 210px), 1fr)); - gap: 10px; - } - button { - font: inherit; - color: var(--primary-text-color); - border: 1px solid var(--divider-color, #ddd); - border-radius: 12px; - background: var(--card-background-color, white); - padding: 14px; - min-height: 44px; - cursor: pointer; - } - .moment { - display: flex; - align-items: center; - gap: 12px; - text-align: start; - } - .moment span:nth-child(2) { - flex: 1; - min-width: 0; - overflow-wrap: anywhere; - } - strong { - display: block; - font-size: calc(14px + 1pt); - font-weight: 500; - } - small { - display: block; - color: var(--secondary-text-color); - margin-top: 4px; - } - ha-icon { - color: var(--primary-color); - flex-shrink: 0; - } - button:hover { - border-color: var(--primary-color); - } - button:focus-visible { - outline: 2px solid var(--primary-color); - outline-offset: 3px; - } - `,e([pe({attribute:!1})],tt.prototype,"hass",void 0),e([pe({attribute:!1})],tt.prototype,"hub",void 0),e([ue()],tt.prototype,"entities",void 0),e([ue()],tt.prototype,"loading",void 0),e([ue()],tt.prototype,"failed",void 0),tt=e([t("wiser-moments")],tt);const it={GB:"uk",IE:"uk",MT:"uk",CY:"uk",SG:"uk",MY:"uk",HK:"uk",US:"us",CA:"us",MX:"us",AU:"au",NZ:"au",CN:"au",AR:"au",JP:"jp",CH:"ch",LI:"ch",IT:"it",FR:"fr",BE:"fr",PL:"fr",CZ:"fr",SK:"fr",DE:"de",AT:"de",NL:"de",ES:"de",PT:"de",SE:"de",NO:"de",FI:"de",IS:"de",GR:"de"};function st(e){const t=it[(null==e?void 0:e.trim().toUpperCase())||""];return t?`mdi:power-socket-${t}`:"mdi:power-plug"}let ot;function at(){return customElements.get("ha-selector")?Promise.resolve():(ot||(ot=(async()=>{var e;const t=window;if(!t.loadCardHelpers)throw new Error("Home Assistant controls are not available yet. Please retry.");const i=(await t.loadCardHelpers()).createCardElement({type:"entities",entities:[]}).constructor;if(await(null===(e=i.getConfigElement)||void 0===e?void 0:e.call(i)),!customElements.get("ha-selector"))throw new Error("Home Assistant controls could not be loaded. Please retry.")})().catch(e=>{throw ot=void 0,e})),ot)}const rt="a-f\\d",nt=`#?[${rt}]{3}[${rt}]?`,lt=`#?[${rt}]{6}([${rt}]{2})?`,dt=new RegExp(`[^#${rt}]`,"gi"),ct=new RegExp(`^${nt}$|^${lt}$`,"i");const ht=Math.trunc;function pt(e){return null!=e}function ut(e){if(function(e){return 6===(e=String(e).replace("#","")).length&&!isNaN(Number("0x"+e))}(e)){const t=function(e,t={}){if("string"!=typeof e||dt.test(e)||!ct.test(e))throw new TypeError("Expected a valid hex string");let i=1;8===(e=e.replace(/^#/,"")).length&&(i=Number.parseInt(e.slice(6,8),16)/255,e=e.slice(0,6)),4===e.length&&(i=Number.parseInt(e.slice(3,4).repeat(2),16)/255,e=e.slice(0,3)),3===e.length&&(e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]);const s=Number.parseInt(e,16),o=s>>16,a=s>>8&255,r=255&s,n="number"==typeof t.alpha?t.alpha:i;if("array"===t.format)return[o,a,r,n];if("css"===t.format)return`rgb(${o} ${a} ${r}${1===n?"":` / ${Number((100*n).toFixed(2))}%`})`;return{red:o,green:a,blue:r,alpha:n}}(e);return String(t.red+","+t.green+","+t.blue+","+t.alpha)}return"100,100,100"}function mt(e,t){return getComputedStyle(e).getPropertyValue(t).trim()}function gt(e,t,i){if("Unknown"==i)return"100,100,100";if("onoff"===t.toLowerCase())return ut(mt(e,"On"==i?"--green-color":"--red-color"));if(["lighting","shutters"].includes(t.toLowerCase()))return(0==(s=parseInt(i))?"50,50,50":ht(50+1.85*s)+","+ht(50+1.5*s)+",0")+",1";{if(-20==parseFloat(i))return"138, 138, 138";const e=45,t=-10,s=(parseFloat(i)-t)/(e-t);return 235+","+Math.floor(255*(1-s))+","+0+",1"}var s}function vt(e,t){return!t.display_only&&!!(t.admin_only&&e.user.is_admin||!t.admin_only)}function yt(e,t){return 0==e.slots.length||e.slots.length-1==t?"23:59":e.slots[t+1].Time}function _t(e,t,i){return-1==t?function(e,t){const i=[...Ee.slice(Ee.indexOf(e.day)),...Ee.slice(0,Ee.indexOf(e.day))].reverse();let s;for(s of i){const e=t.ScheduleData.filter(e=>e.day==s)[0];if(e&&e.slots.length>0)return e.slots[e.slots.length-1].Setpoint}return"Unknown"}(e,i):e.slots[t].Setpoint}function ft(e){const[t,i]=e.split(":");return 3600*+t+60*+i}const bt=e=>e.locale||{language:e.selectedLanguage,number_format:me.system,time_format:ge.system},wt=t=>{class i extends t{connectedCallback(){super.connectedCallback(),this.__checkSubscribed()}disconnectedCallback(){if(super.disconnectedCallback(),this.__unsubs){for(;this.__unsubs.length;){const e=this.__unsubs.pop();e instanceof Promise?e.then(e=>e()):pt(e)&&e()}this.__unsubs=void 0}}updated(e){super.updated(e),e.has("hass")&&this.__checkSubscribed()}hassSubscribe(){return[]}__checkSubscribed(){void 0===this.__unsubs&&this.isConnected&&void 0!==this.hass&&(this.__unsubs=this.hassSubscribe())}}return e([pe({attribute:!1})],i.prototype,"hass",void 0),i};async function xt(e){await e.updateComplete,e.isConnected&&e.dispatchEvent(new CustomEvent("wiser-view-ready",{bubbles:!0,composed:!0}))}let $t=class extends(wt(le)){constructor(){super(...arguments),this.climateEntities=[],this.now=new Date,this.expandedDevices={},this.target_type="heating",this.openCreatedEditor=!1,this.devices=[],this.rooms=[],this.schedules=[],this.loading=!0,this.loaded=!1,this.error="",this.saving=!1,this.selected="",this.saved=!1,this.editing=!1,this.editorSaving=!1,this.editorReady=!1,this.requestId=0}localize(e,t="",i=""){return je(this.hass,e,t,i)}connectedCallback(){super.connectedCallback(),this.clock=setInterval(()=>{this.now=new Date},3e4)}disconnectedCallback(){super.disconnectedCallback(),clearInterval(this.clock)}hassSubscribe(){return[this.hass.connection.subscribeMessage(e=>{"wiser_updated"!==e.event||this.config.hub&&e.hub!==this.config.hub||this.saving||this.editing||this.loadData()},{type:"wiser_updated"})]}updated(e){super.updated(e),(e.has("config")||e.has("room_id")||e.has("target_type")||e.has("hass")&&!e.get("hass"))&&(this.loaded=!1,this.selected="",this.saved=!1,this.loadData())}compatible(e){return this.schedules.filter(t=>"hotwater"===e?1e3===t.Id:1e3!==t.Id&&("heating"===e?t.Type:t.SubType||t.Type).toLowerCase()===e)}get target(){return"heating"===this.target_type?this.rooms.find(e=>e.Id===this.room_id):this.devices.find(e=>e.Id===this.room_id&&e.kind===this.target_type)}currentSchedule(e,t=this.target_type){return"hotwater"===t?this.schedules.find(e=>1e3===e.Id):this.compatible(t).find(t=>t.Assignments.some(t=>{var i,s;const o=t,a=null!==(i=o.id)&&void 0!==i?i:o.Id;return void 0!==a?String(a)===String(e.Id):(null!==(s=o.name)&&void 0!==s?s:o.Name)===e.Name}))}async loadData(){var e,t,i,s;if(!this.hass||!this.config)return;const o=++this.requestId;this.loading=!0,this.error="";try{await at();const[a,r,n,l,...d]=await Promise.all([Ye(this.hass,this.config.hub),qe(this.hass,this.config.hub),We(this.hass,this.config.hub).catch(()=>{}),Ke(this.hass,this.config.hub).catch(()=>[]),...["lighting","onoff","shutters"].map(e=>Je(this.hass,this.config.hub,e))]),c=await Promise.all(r.map(e=>Fe(this.hass,this.config.hub,e.Type,e.Id)));if(o!==this.requestId)return;this.rooms=[...a].sort((e,t)=>e.Name.localeCompare(t.Name)),this.schedules=c,this.sun=n,this.climateEntities=l,this.devices=d.reduce((e,t,i)=>e.concat(t.map(e=>Object.assign(Object.assign({},e),{kind:["lighting","onoff","shutters"][i]}))),[]),c.some(e=>1e3===e.Id)&&this.devices.unshift({Id:1e3,Name:this.localize("wiser.home.hotwater"),kind:"hotwater"}),this.loaded=!0;const h=this.target;if(h){const o=this.compatible(this.target_type);this.created_schedule&&o.some(e=>e.Id===this.created_schedule.Id&&e.Type===this.created_schedule.Type)?(this.selected=String(this.created_schedule.Id),this.openCreatedEditor=!0,this.dispatchEvent(new CustomEvent("createdScheduleOpened"))):"none"===this.selected||(o.length<=1?this.selected=String(null!==(t=null===(e=o[0])||void 0===e?void 0:e.Id)&&void 0!==t?t:""):o.some(e=>String(e.Id)===this.selected)||(this.selected=String(null!==(s=null===(i=this.currentSchedule(h))||void 0===i?void 0:i.Id)&&void 0!==s?s:"none")))}}catch(e){o===this.requestId&&(this.error=(null==e?void 0:e.message)||this.localize("common.load_failed"))}finally{o===this.requestId&&(this.loading=!1,await this.updateComplete,this.editor&&!this.editorReady||await xt(this))}}async assign(){const e=this.target,t="none"===this.selected,i=t&&e?this.currentSchedule(e):this.compatible(this.target_type).find(e=>String(e.Id)===this.selected);if("hotwater"!==this.target_type&&e&&i&&!this.saving&&vt(this.hass,this.config)){this.saving=!0,this.saved=!1,this.error="";try{await Ze(this.hass,this.config.hub,i.Type,i.Id,String(e.Id),t),await this.loadData(),this.saved=!this.error}catch(e){this.error=(null==e?void 0:e.message)||this.localize("common.load_failed")}finally{this.saving=!1,await xt(this)}}}get editor(){return this.renderRoot.querySelector("wiser-schedule-edit-card")}scheduleAction(e,t){this.dispatchEvent(new CustomEvent("scheduleAction",{detail:{schedule_type:e.Type,schedule_id:e.Id,action:t}}))}tool(e,t,i,s=!1){const o=this.localize(e);return W``}render(){var e;if(!this.hass||!this.config)return W``;const t=this.target,i=void 0!==this.room_id?W``:"";if(this.loading&&!this.loaded)return W`${i} -
${this.localize("common.loading")}
`;if(this.error)return W`${i} - - `;if(void 0!==this.room_id){if(!t)return W`${i} -
${this.localize("wiser.rooms.missing")}
`;const s=this.currentSchedule(t),o=this.compatible(this.target_type),a="hotwater"===this.target_type,r="none"===this.selected?void 0:o.find(e=>String(e.Id)===this.selected)||s,n=vt(this.hass,this.config),l=this.saving||this.editing||this.editorSaving;return W` - {var t,i;const s=e.target,o=null===(t=s.files)||void 0===t?void 0:t[0];s.value="",o&&(null===(i=this.editor)||void 0===i||i.importSchedule(o))}} - /> - -
- ${this.editing?W` - ${this.tool("wiser.rooms.cancel_edit","mdi:close",()=>{var e;return null===(e=this.editor)||void 0===e?void 0:e.cancelClick()},this.editorSaving)} - ${this.tool("wiser.rooms.save_edit","mdi:content-save",()=>{var e;null===(e=this.editor)||void 0===e||e.saveClick()},this.editorSaving)} - `:W` - ${this.tool("wiser.rooms.back","mdi:arrow-left",()=>this.dispatchEvent(new CustomEvent("roomsBack")),l)} - ${n&&r?this.tool("wiser.actions.export","mdi:download",()=>{var e;return null===(e=this.editor)||void 0===e?void 0:e.exportSchedule()},l||!this.editorReady):""} - ${n&&r?this.tool("wiser.actions.import","mdi:upload",()=>{var e;return null===(e=this.renderRoot.querySelector(".import-file"))||void 0===e?void 0:e.click()},l||!this.editorReady):""} - ${n&&r?W` - ${this.tool("wiser.rooms.edit","mdi:pencil",()=>{var e;return null===(e=this.editor)||void 0===e?void 0:e.editClick()},l||!this.editorReady)} - ${this.tool("wiser.actions.rename","mdi:form-textbox",()=>this.scheduleAction(r,"rename"),l)} - ${this.tool("wiser.actions.copy","mdi:content-copy",()=>this.scheduleAction(r,"copy"),l||a)} - ${this.tool("wiser.rooms.delete","mdi:delete-outline",()=>{var e;null===(e=this.editor)||void 0===e||e.deleteClick()},l||!this.editorReady||a)} - `:""} - ${n&&!a?W` - ${this.tool("wiser.actions.add_schedule","mdi:plus",()=>this.dispatchEvent(new CustomEvent("addScheduleClick")),l)} - ${this.tool("wiser.rooms.assign","mdi:check",()=>{this.assign()},l||!this.selected||("none"===this.selected?!s:this.selected===String(null==s?void 0:s.Id)))} - `:""} - `} -
-
-

${t.Name}

-

- ${this.localize("wiser.rooms.current")}: - ${null!==(e=null==s?void 0:s.Name)&&void 0!==e?e:this.localize("wiser.rooms.unassigned")} -

- ${n&&!a?W` - ${o.length>0?W`({value:String(e.Id),label:e.Name}))}}} - .value=${"none"===this.selected?void 0:this.selected||void 0} - .required=${!1} - .disabled=${l} - @value-changed=${e=>{e.stopPropagation(),l||null!=e.detail.value&&""!==e.detail.value&&!o.some(t=>String(t.Id)===e.detail.value)||(this.selected=e.detail.value||"none",this.saved=!1)}} - >`:1!==o.length||s?"":W`

- ${this.localize("wiser.rooms.available")}: ${o[0].Name} -

`} - ${o.length?"":W`

${this.localize("wiser.rooms.no_schedules")}

`} - `:""} - ${r?W` - {var t;this.editing=e.detail.editing,this.editorSaving=e.detail.saving,this.editorReady=e.detail.ready,this.openCreatedEditor&&e.detail.ready&&!e.detail.editing&&(this.openCreatedEditor=!1,null===(t=this.editor)||void 0===t||t.editClick())}} - @scheduleDeleted=${()=>{this.selected="",this.loadData()}} - > - - `:""} - ${this.saved?W`

${this.localize("none"===this.selected?"wiser.rooms.removed":"wiser.rooms.saved")}

`:""} - ${r&&r.Assignments.length>1?W`

${this.localize("wiser.rooms.shared")}

`:""} - ${this.saving?W`

${this.localize("wiser.rooms.assigning")}

`:""} - `}const s=[{title:"heating",items:this.rooms.map(e=>Object.assign(Object.assign({},e),{kind:"heating"}))},{title:"hotwater",items:this.devices.filter(e=>"hotwater"===e.kind)},{title:"devices",items:this.devices.filter(e=>"hotwater"!==e.kind)}];return W` - {if("overview"!==e.detail)return;e.stopPropagation();const t=Array.from(this.renderRoot.querySelectorAll(".details-toggle:not(:disabled)")),i=t.some(e=>"true"!==e.getAttribute("aria-expanded"));this.expandedDevices=Object.assign(Object.assign({},this.expandedDevices),t.reduce((e,t)=>(e[t.dataset.key]=i,e),{})),xt(this)}} - > -

${this.localize("wiser.home.overview")}

- ${"overview"!==this.config.home_screen||!1!==this.config.overview_details?W`

${this.localize("wiser.home.overview_hint")}

`:""} - ${s.filter(e=>e.items.length).map(e=>W`
-

${this.localize("wiser.home."+e.title)}

-
${e.items.map(e=>this.renderDeviceOverview(e))}
-
`)} - ${this.rooms.length||this.devices.length?"":W`

${this.localize("wiser.home.empty")}

`} - - `}renderDeviceOverview(e){var t,i,s,o;const a=this.currentSchedule(e,e.kind),r=a?function(e,t,i,s){var o;const a=new Intl.DateTimeFormat("en-GB",{timeZone:i,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1}).formatToParts(t),r=e=>{var t;return Number(null===(t=a.find(t=>t.type===e))||void 0===t?void 0:t.value)},n=Date.UTC(r("year"),r("month")-1,r("day")),l=3600*r("hour")+60*r("minute")+r("second");for(let t=0;t<=7;t++){const i=new Date(n+864e5*t),a=Qe[i.getUTCDay()],r=((null===(o=e.ScheduleData.find(e=>e.day.toLowerCase()===a.toLowerCase()))||void 0===o?void 0:o.slots)||[]).map(e=>{var o;let r=e.Time;if("sunrise"===r.toLowerCase()||"sunset"===r.toLowerCase()){const e="sunrise"===r.toLowerCase()?null==s?void 0:s.Sunrises:null==s?void 0:s.Sunsets;r=(null===(o=null==e?void 0:e.find(e=>e.day.toLowerCase()===a.toLowerCase()))||void 0===o?void 0:o.time)||""}const n=/^(\d{1,2}):(\d{2})(?::(\d{2}))?$/.exec(r);if(!n)return;const[,d,c,h="0"]=n,p=3600*Number(d)+60*Number(c)+Number(h);return Number(d)>23||Number(c)>59||Number(h)>59||!t&&p<=l?void 0:{day:a,date:i.toISOString().slice(0,10),time:`${d.padStart(2,"0")}:${c}`,setpoint:e.Setpoint,seconds:p}}).filter(e=>Boolean(e)).sort((e,t)=>e.seconds-t.seconds);if(r.length)return r[0]}}(a,this.now,this.hass.config.time_zone||"UTC",this.sun):void 0,n=r?`${r.setpoint}${"heating"===e.kind?"°C":["lighting","shutters"].includes(e.kind)?"%":""}`:"",l=`${e.kind}-${e.Id}`,d=null!==(t=this.expandedDevices[l])&&void 0!==t?t:"overview"!==this.config.home_screen||!1!==this.config.overview_details,c=(e,t)=>W`
-
${this.localize("wiser.home."+e)}
-
${t}
-
`;return W`
-
- - -
- ${a?W`
-
- ${c("schedule_name",a.Name)}${c("schedule_id",a.Id)} - ${c("schedule_type",a.SubType||a.Type)} - ${r?W`${c("next_day",this.localize("wiser.days."+r.day.toLowerCase()))}${c("next_change",new Intl.DateTimeFormat((null===(o=this.hass.locale)||void 0===o?void 0:o.language)||"en",{year:"numeric",month:"short",day:"numeric",timeZone:"UTC"}).format(new Date(r.date+"T00:00:00Z"))+" · "+r.time)}${c("next_setting",n)}`:W`

${this.localize("wiser.home.no_next_change")}

`} -
- ${"heating"===e.kind?this.renderHeating(e,!0):""} -
`:"heating"===e.kind?W`
- ${this.renderHeating(e,!1)} -
`:""} -
`}renderHeating(e,t){return W`{var s;return(null===(s=e.states[t])||void 0===s?void 0:s.attributes.name)===i});return 1===s.length?s[0]:void 0}(this.hass,this.climateEntities,e.Name)} - .editable=${vt(this.hass,this.config)} - .assigned=${t} - >`}};$t.styles=n` - .device-heading { - display: flex; - align-items: center; - gap: 8px; - } - .device-heading .details-toggle { - flex: 0 0 44px; - padding: 0; - width: 44px; - border: 0; - background: transparent; - color: var(--primary-color); - } - .device-heading .overview-device { - border: 0; - background: transparent; - padding: 8px; - min-width: 0; - } - .overview-grid { - align-items: start; - display: grid; - grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); - gap: 12px; - } - .device-overview { - border: 1px solid var(--divider-color); - border-radius: 14px; - padding: 16px; - background: var(--card-background-color); - min-width: 0; - } - .overview-device { - display: flex; - align-items: center; - gap: 12px; - width: 100%; - text-align: start; - } - .device-summary { - display: flex; - flex-direction: column; - gap: 4px; - min-width: 0; - } - .device-summary { - flex: 1; - overflow-wrap: anywhere; - } - .overview-device ha-icon { - color: var(--primary-color); - } - dl { - margin: 12px 0 0; - } - dl > div { - display: flex; - justify-content: space-between; - gap: 16px; - padding: 8px 0; - } - dt { - color: var(--secondary-text-color); - } - dd { - margin: 0; - text-align: end; - overflow-wrap: anywhere; - } - - :host { - display: block; - color: var(--primary-text-color); - } - section + section { - margin-top: 24px; - padding-top: 20px; - border-top: 1px solid var(--divider-color, #ddd); - } - .room-heading { - display: flex; - flex-wrap: wrap; - align-items: center; - justify-content: space-between; - gap: 12px; - } - .tools { - display: flex; - flex-wrap: wrap; - gap: 6px; - margin-inline-start: auto; - } - .tool { - width: 44px; - padding: 0; - display: grid; - place-items: center; - color: var(--secondary-text-color); - } - .tool:disabled { - color: var(--disabled-text-color); - opacity: 1; - } - .tool:not(:disabled):hover { - color: var(--primary-color); - } - - h3 { - margin: 16px 0 8px; - font-size: calc(22px + 1pt); - } - .section-heading { - font-size: calc(15px + 1pt); - font-weight: 600; - margin: 0 0 8px; - } - .intro, - .secondary { - color: var(--secondary-text-color); - font-size: calc(14px + 1pt); - line-height: 1.5; - } - .intro { - margin: 0 0 16px; - } - button, - select { - font: inherit; - color: var(--primary-text-color); - border: 1px solid var(--divider-color, #ddd); - border-radius: 12px; - background: var(--card-background-color, white); - min-height: 44px; - padding: 10px 14px; - } - button { - cursor: pointer; - } - button:disabled { - opacity: 0.5; - cursor: default; - } - button:not(:disabled):hover { - border-color: var(--primary-color); - } - button:focus-visible, - select:focus-visible { - outline: 2px solid var(--primary-color); - outline-offset: 3px; - } - .back { - border: 0; - background: none; - color: var(--primary-color); - padding-inline-start: 0; - } - .schedule-picker { - display: block; - width: 100%; - max-width: 420px; - margin: 20px 0 12px; - } - label { - display: grid; - gap: 8px; - margin: 20px 0 12px; - font-size: calc(14px + 1pt); - } - select { - width: 100%; - box-sizing: border-box; - } - .primary { - background: var(--primary-color); - color: var(--text-primary-color, white); - border-color: transparent; - } - .schedule-link { - margin-top: 24px; - border-top: 1px solid var(--divider-color, #ddd); - padding-top: 16px; - } - .status { - padding: 24px; - border-radius: 12px; - background: var(--secondary-background-color); - color: var(--secondary-text-color); - } - ${Ue} - `,e([pe({attribute:!1})],$t.prototype,"config",void 0),e([ue()],$t.prototype,"climateEntities",void 0),e([ue()],$t.prototype,"sun",void 0),e([ue()],$t.prototype,"now",void 0),e([ue()],$t.prototype,"expandedDevices",void 0),e([pe({attribute:!1})],$t.prototype,"room_id",void 0),e([pe({attribute:!1})],$t.prototype,"target_type",void 0),e([pe({attribute:!1})],$t.prototype,"created_schedule",void 0),e([ue()],$t.prototype,"devices",void 0),e([ue()],$t.prototype,"rooms",void 0),e([ue()],$t.prototype,"schedules",void 0),e([ue()],$t.prototype,"loading",void 0),e([ue()],$t.prototype,"loaded",void 0),e([ue()],$t.prototype,"error",void 0),e([ue()],$t.prototype,"saving",void 0),e([ue()],$t.prototype,"selected",void 0),e([ue()],$t.prototype,"saved",void 0),e([ue()],$t.prototype,"editing",void 0),e([ue()],$t.prototype,"editorSaving",void 0),e([ue()],$t.prototype,"editorReady",void 0),$t=e([t("wiser-room-schedules")],$t);let St=class extends(wt(le)){constructor(){super(...arguments),this.schedules=[],this.loading=!0,this.error="",this.request=0}localize(e,t="",i=""){return je(this.hass,e,t,i)}hassSubscribe(){return[this.hass.connection.subscribeMessage(e=>{"wiser_updated"!==e.event||this.config.hub&&e.hub!==this.config.hub||this.load()},{type:"wiser_updated"})]}updated(e){super.updated(e),(e.has("config")||e.has("hass")&&!e.get("hass"))&&this.load()}async load(){if(!this.hass||!this.config)return;const e=++this.request;this.error="";try{const t=await qe(this.hass,this.config.hub);e===this.request&&(this.schedules=[...t].sort((e,t)=>e.Name.localeCompare(t.Name)))}catch(t){e===this.request&&(this.error=t.message||this.localize("common.load_failed"))}finally{e===this.request&&(this.loading=!1,await xt(this))}}render(){return this.hass?W` - - -

${this.localize("wiser.rooms.schedules")}

- ${this.error?W`

${this.error}

- `:this.loading?W`

${this.localize("common.loading")}

`:this.schedules.length?W`
- ${this.schedules.map(e=>W``)} -
`:W`

${this.localize("wiser.home.no_schedules")}

`} - `:W``}};St.styles=n` - :host { - display: block; - color: var(--primary-text-color); - } - .home-tools { - display: flex; - align-items: center; - flex-wrap: wrap; - gap: 6px; - } - .heading { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: 16px; - } - h3 { - margin: 0; - font-size: calc(15px + 1pt); - } - button { - font: inherit; - color: var(--primary-text-color); - background: var(--card-background-color); - border: 1px solid var(--divider-color); - border-radius: 12px; - padding: 14px; - min-height: 44px; - cursor: pointer; - } - button:focus-visible { - outline: 2px solid var(--primary-color); - outline-offset: 3px; - } - button:hover { - border-color: var(--primary-color); - } - ha-icon { - color: var(--primary-color); - flex-shrink: 0; - } - .tiles { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(min(100%, 210px), 1fr)); - gap: 10px; - } - .tiles.list { - grid-template-columns: 1fr; - } - .schedule-tile { - display: flex; - align-items: center; - gap: 12px; - text-align: start; - min-height: 82px; - } - .schedule-tile span:first-of-type { - flex: 1; - min-width: 0; - overflow-wrap: anywhere; - } - strong { - display: block; - font-weight: 500; - } - small { - display: block; - color: var(--secondary-text-color); - margin-top: 4px; - } - `,e([pe({attribute:!1})],St.prototype,"config",void 0),e([ue()],St.prototype,"schedules",void 0),e([ue()],St.prototype,"loading",void 0),e([ue()],St.prototype,"error",void 0),St=e([t("wiser-schedules-home")],St);const kt=n` - button { - font: inherit; - color: var(--primary-color, #16859a); - background: transparent; - border: 1px solid transparent; - border-radius: 10px; - min-height: 44px; - padding: 8px 14px; - margin: 3px 0; - cursor: pointer; - } - button:not(:disabled):hover { - background: var(--secondary-background-color, #eee); - } - button:disabled { - opacity: 0.45; - cursor: default; - } - button[appearance='filled'], - button.active { - background: var(--primary-color); - color: var(--text-primary-color, white); - } - button[variant='danger'] { - color: var(--error-color, #c33); - } - button:focus-visible, - input:focus-visible { - outline: 2px solid var(--primary-color); - outline-offset: 3px; - } - input { - font: inherit; - accent-color: var(--primary-color); - } - input[type='text'] { - box-sizing: border-box; - width: 100%; - min-height: 44px; - border: 1px solid var(--divider-color, #aaa); - border-radius: 10px; - padding: 10px 12px; - background: var(--card-background-color, white); - color: var(--primary-text-color); - } - input[type='checkbox'] { - width: 22px; - height: 22px; - } - input[type='range'] { - width: 100%; - min-height: 44px; - } - label.schedule-name { - display: grid; - gap: 8px; - } - progress { - width: 36px; - height: 6px; - accent-color: var(--primary-color); - } - button svg { - width: 24px; - height: 24px; - fill: currentColor; - pointer-events: none; - } -`,Ct=n` - ${kt} - :host { - display: block; - color: var(--primary-text-color); - } - ha-textfield { - width: 100%; - } - ha-button { - margin: 3px 0; - } - .card-actions { - margin-top: 20px; - } - ha-button:focus-visible { - outline: 2px solid var(--primary-color); - outline-offset: 3px; - } - - .card-header { - display: flex; - justify-content: space-between; - } - .card-header .name { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - display: flex; - } - .card-header ha-switch { - padding: 5px; - } - .card-header ha-icon-button { - position: absolute; - right: 6px; - top: 6px; - } - .card-content { - flex: 1; - } - .card-content > *:first-child { - margin-top: 0; - } - .card-content > *:last-child { - margin-bottom: 0; - } - div.text-field, - div.secondary { - color: var(--secondary-text-color); - } - .disabled { - color: var(--disabled-text-color); - } - div.header { - color: var(--secondary-text-color); - text-transform: uppercase; - font-weight: 500; - font-size: calc(12px + 1pt); - margin: 20px 0px 0px 0px; - display: flex; - flex-direction: row; - } - div.header .switch { - text-transform: none; - font-weight: normal; - font-size: calc(14px + 1pt); - display: flex; - flex-grow: 1; - justify-content: flex-end; - } - div.header ha-switch { - display: flex; - align-self: center; - margin: 0px 8px; - line-height: 24px; - } - mwc-button { - margin: 2px 0px; - } - mwc-button.active { - background: var(--primary-color); - --mdc-theme-primary: var(--text-primary-color); - border-radius: 4px; - } - mwc-button ha-icon { - margin-right: 11px; - } - mwc-button.warning { - --mdc-theme-primary: var(--error-color); - } - div.checkbox-container { - display: grid; - grid-template-columns: max-content 1fr max-content; - grid-template-rows: min-content; - grid-template-areas: 'checkbox slider value'; - grid-gap: 0px 10px; - } - div.checkbox-container div.checkbox { - grid-area: checkbox; - display: flex; - align-items: center; - } - div.checkbox-container div.slider { - grid-area: slider; - display: flex; - align-items: center; - } - div.checkbox-container div.value { - grid-area: value; - min-width: 40px; - display: flex; - align-items: center; - } - a { - color: var(--primary-color); - } - a:visited { - color: var(--accent-color); - } -`;let Et=class extends le{localize(e,t="",i=""){return je(this.hass,e,t,i)}async showDialog(e){this._params=e,await this.updateComplete}async closeDialog(){const e=this._params;this._params=void 0,null==e||e.cancel()}render(){var e;return this._params?W` - -
- ${this.localize("wiser.helpers.delete_schedule_confirm")+" "+this._params.name+"?"} -
-
- ${this.hass.localize("ui.common.cancel")} - ${this.hass.localize("ui.common.delete")} -
-
- `:W``}confirmClick(){const e=this._params;this._params=void 0,null==e||e.confirm()}cancelClick(){this.closeDialog()}static get styles(){return n` - .actions { - display: flex; - justify-content: flex-end; - gap: 8px; - padding-top: 16px; - } - div.wrapper { - color: var(--primary-text-color); - } - `}};e([pe({attribute:!1})],Et.prototype,"hass",void 0),e([ue()],Et.prototype,"_params",void 0),Et=e([t("wiser-dialog-delete-confirm")],Et);var At=Object.freeze({__proto__:null,get DialogDeleteConfirm(){return Et}});function zt(e){if(e.match(/^([0-9:]+)$/)){const t=e.split(":").map(Number);return 3600*t[0]+60*t[1]+(t[2]||0)}const t=new Date(e);return 3600*t.getHours()+60*t.getMinutes()+t.getSeconds()}function Dt(e){const t=Math.floor(e/3600);e-=3600*t;const i=Math.floor(e/60);e-=60*i;const s=Math.round(e);return String(t%24).padStart(2,"0")+":"+String(i).padStart(2,"0")+":"+String(s).padStart(2,"0")}function Tt(e){const t=Math.floor(e/3600);e-=3600*t;const i=Math.floor(e/60);return String(t%24).padStart(2,"0")+":"+String(i).padStart(2,"0")}function Mt(e,t,i={wrapAround:!0}){let s=e>=0?Math.floor(e/3600):Math.ceil(e/3600),o=Math.floor((e-3600*s)/60);o%t!=0&&(o=Math.round(o/t)*t),o>=60?(s++,o-=60):o<0&&(s--,o+=60),i.wrapAround&&(s>=24?s-=24:s<0&&(s+=24));const a=3600*s+60*o;if(i.maxHours){if(a>3600*i.maxHours)return 3600*i.maxHours;if(a<3600*-i.maxHours)return 3600*-i.maxHours}return a}var Nt=/d{1,4}|M{1,4}|YY(?:YY)?|S{1,3}|Do|ZZ|Z|([HhMsDm])\1?|[aA]|"[^"]*"|'[^']*'/g,Ot=/\[([^]*?)\]/gm;function It(e,t){for(var i=[],s=0,o=e.length;s3?0:(e-e%10!=10?1:0)*e%10]}}),Ut=function(e,t){for(void 0===t&&(t=2),e=String(e);e.length0?"-":"+")+Ut(100*Math.floor(Math.abs(t)/60)+Math.abs(t)%60,4)},Z:function(e){var t=e.getTimezoneOffset();return(t>0?"-":"+")+Ut(Math.floor(Math.abs(t)/60),2)+":"+Ut(Math.abs(t)%60,2)}},Bt={default:"ddd MMM DD YYYY HH:mm:ss",shortDate:"M/D/YY",mediumDate:"MMM D, YYYY",longDate:"MMMM D, YYYY",fullDate:"dddd, MMMM D, YYYY",isoDate:"YYYY-MM-DD",isoDateTime:"YYYY-MM-DDTHH:mm:ssZ",shortTime:"HH:mm",mediumTime:"HH:mm:ss",longTime:"HH:mm:ss.SSS"},Wt=function(e,t,i){if(void 0===t&&(t=Bt.default),void 0===i&&(i={}),"number"==typeof e&&(e=new Date(e)),"[object Date]"!==Object.prototype.toString.call(e)||isNaN(e.getTime()))throw new Error("Invalid Date pass to format");var s=[];t=(t=Bt[t]||t).replace(Ot,function(e,t){return s.push(t),"@@@"});var o=Lt(Lt({},jt),i);return(t=t.replace(Nt,function(t){return Vt[t](e,o)})).replace(/@@@/g,function(){return s.shift()})};const qt=e=>{if(e.time_format===ge.language||e.time_format===ge.system){const t=e.time_format===ge.language?e.language:void 0,i=(new Date).toLocaleString(t);return i.includes("AM")||i.includes("PM")}return e.time_format===ge.am_pm};function Ft(e,t,i){return i===ge.am_pm||!i&&t.time_format===ge.am_pm?Wt(e,"h:mm A"):i===ge.twenty_four||!i&&t.time_format===ge.twenty_four?Wt(e,"shortTime"):(()=>{try{(new Date).toLocaleTimeString("i")}catch(e){return"RangeError"===e.name}return!1})()?e.toLocaleTimeString(t.language,{hour:"numeric",minute:"2-digit",hour12:qt(t)}):qt(t)?Ft(e,t,ge.am_pm):Ft(e,t,ge.twenty_four)}function Yt(e){const t=new Date,i=(e||"").match(/^([0-9]{4})-([0-9]{2})-([0-9]{2})/);null!==i&&t.setFullYear(Number(i[1]),Number(i[2])-1,Number(i[3]));const s=(e||"").match(/([0-9]{2}):([0-9]{2})(:([0-9]{2}))?$/);return null!==s&&t.setHours(Number(s[1]),Number(s[2]),s.length>4?Number(s[4]):t.getSeconds()),t}let Jt=class extends le{constructor(){super(...arguments),this.min=0,this.max=255,this.step=1,this.scaleFactor=1,this.unit="",this.optional=!1,this.disabled=!1,this._displayedValue=0}set value(e){e=isNaN(e)?this.min:this._roundedValue(e/this.scaleFactor),this._displayedValue=e}render(){return W` -
-
${this.getCheckbox()}
-
${this.getSlider()}
-
${this._displayedValue}${this.unit}
-
- `}getSlider(){return W``}getCheckbox(){return this.optional?W` - - `:W``}_toggleChecked(e){const t=e.target.checked;this.disabled=!t;const i=this.disabled?null:this._scaledValue(this._displayedValue);ve(this,"value-changed",{value:i})}_updateValue(e){let t=Number(e.target.value);this._displayedValue=t,t=this._scaledValue(this._displayedValue),ve(this,"value-changed",{value:t})}_roundedValue(e){return e=Math.round(e/this.step)*this.step,(e=parseFloat(e.toPrecision(12)))>this.max?e=this.max:e${this.renderTimes()}
`}renderTimes(){if(this.hass){const e=parseFloat(getComputedStyle(this).getPropertyValue("width"))||460,t=[1,2,3,4,6,8,12],i=qt(bt(this.hass))?55:40;let s=Math.ceil(24/(e/i));for(;!t.includes(s);)s++;const o=[0,...Array.from(Array(24/s-1).keys()).map(e=>(e+1)*s),24];return o.map(e=>{const t=0==e||24==e,i=t?s/48*100:s/24*100;return W` -
- ${t?"":Ft(Yt(Dt(3600*e)),bt(this.hass))} -
- `})}return W``}static get styles(){return n` - :host { - display: block; - max-width: 100%; - overflow: hidden; - } - div.outer { - width: 100%; - overflow-x: hidden; - overflow-y: hidden; - border-radius: 5px; - } - div.time-wrapper { - white-space: nowrap; - transition: - width 0.2s cubic-bezier(0.17, 0.67, 0.83, 0.67), - margin 0.2s cubic-bezier(0.17, 0.67, 0.83, 0.67); - overflow: auto; - } - div.time-wrapper div { - float: left; - display: flex; - position: relative; - height: 25px; - line-height: 25px; - font-size: calc(12px + 1pt); - text-align: center; - align-content: center; - align-items: center; - justify-content: center; - } - div.time-wrapper div.time:before { - content: ' '; - background: var(--disabled-text-color); - position: absolute; - left: 0px; - top: 0px; - width: 1px; - height: 5px; - margin-left: 50%; - margin-top: 0px; - } - @keyframes fadeIn { - 99% { - visibility: hidden; - } - 100% { - visibility: visible; - } - } - `}};e([pe({attribute:!1})],Zt.prototype,"hass",void 0),Zt=e([t("wiser-time-bar")],Zt);let Gt=class extends le{localize(e,t="",i=""){return je(this.hass,e,t,i)}constructor(){super(),this.editMode=!1,this._activeSlot=-99,this._activeDay="",this._show_short_days=!1,this.schedule_type=xe[0],this.activeMarker=0,this.isDragging=!1,this.currentTime=0,this.timer=0,this.timeout=0,this.zoomFactor=1,this.rangeMin=0,this.rangeMax=_e,this.stepSize=5,this.initialise()}async initialise(){return this.schedule&&(this.schedule_type=this.schedule.Type),!0}shouldUpdate(){return this.editMode||(this._activeSlot=-99,this._activeDay=""),!0}render(){const e=parseFloat(getComputedStyle(this).getPropertyValue("width"));return this._show_short_days=e<500,this.hass&&this.config&&this.suntimes&&this.schedule?W` -
- ${Ee.map(e=>this.renderDay(this.schedule.ScheduleData.filter(t=>t.day==e)[0]?this.schedule.ScheduleData.filter(t=>t.day==e)[0]:{day:e,slots:[]}))} -
-
 
- -
-
-
- ${this.editMode&&$e.includes(this.schedule_type)?this.renderSpecialTimeButtons():null} - ${this.editMode?this.renderAddDeleteButtons():null} - ${this.editMode?this.renderSetPointControl():null} - ${this.editMode?this.renderCopyDay():null} - `:W``}renderDay(e){return W` -
- ${this.computeDayLabel(e.day)} -
-
- ${e.slots.length>0?e.slots.map((t,i)=>this.renderSlot(t,i,e)):this.renderEmptySlot({Time:"23:59",Setpoint:"0",SpecialTime:""},-1,e,!0)} -
-
-
- `}renderEmptySlot(e,t,i,s=!1){const o="00:00",a=e.Time,r=_t(i,t,this.schedule),n=parseFloat(getComputedStyle(this).getPropertyValue("width")),l=this.config.theme_colors?"rgba(var(--rgb-primary-color), 0.7)":"rgba("+gt(this,this.schedule_type,r)+")",d=(ft(a)-ft(o))/_e*100,c=this.localize("wiser.labels.start")+" - "+o+"\n"+this.localize("wiser.labels.end")+" - "+a+"\n"+this.localize("wiser.labels.setting")+" - "+this.computeSetpointLabel(r),h=d/100*n<35?"setpoint rotate":"setpoint";return W` - - `}renderSlot(e,t,i){const s=e.Time,o=yt(i,t),a=e.Setpoint,r=(ft(o)-ft(s))/_e*100,n=this.config.theme_colors?"rgba(var(--rgb-primary-color), 0.7)":"rgba("+gt(this,this.schedule_type,a)+")",l=r/100*parseFloat(getComputedStyle(this).getPropertyValue("width"))<35?"setpoint rotate":"setpoint",d=this.localize("wiser.labels.start")+" - "+(e.SpecialTime?e.SpecialTime+" ("+s+")":s)+"\n"+this.localize("wiser.labels.end")+" - "+o+"\n"+this.localize("wiser.labels.setting")+" - "+this.computeSetpointLabel(a);return W` - ${0==t&&"00:00"!=s&&"0:00"!=s?this.renderEmptySlot(e,-1,i,!1):""} -
-
- ${this.computeSetpointLabel(a)} -
- ${this._activeSlot==t&&this._activeDay==i.day?W` - ${zt(i.slots[t].Time)>0?this.renderBoundaryHandle(i,t,!1):""} - ${t - `}renderBoundaryHandle(e,t,i){return W` -
-
- e.stopPropagation()} - @mousedown=${this._handleTouchStart} - @touchstart=${this._handleTouchStart} - > -
-
- ${this.renderTooltip(e,t,i)} - `}renderSpecialTimeButtons(){const e=this._activeDay?this.schedule.ScheduleData.filter(e=>e.day==this._activeDay)[0].slots[this._activeSlot]:null;return W` -
-
 
-
-
Set Special Time
- - -
-
- `}renderAddDeleteButtons(){let e=0;return this.schedule.ScheduleData.filter(e=>e.day==this._activeDay).length>0&&(e=this._activeDay?this.schedule.ScheduleData.filter(e=>e.day==this._activeDay)[0].slots.length:0),W` -
-
 
-
- - -
-
- `}renderSetPointControl(){let e={};return this.editMode?(this.schedule.ScheduleData.filter(e=>e.day==this._activeDay).length>0&&(e=this._activeDay?this.schedule.ScheduleData.filter(e=>e.day==this._activeDay)[0].slots:{}),"Heating"==this.schedule_type?W` -
-
-
${this._show_short_days?"Temp":"Temperature"}
-
- - =0?parseFloat(e[this._activeSlot].Setpoint):0} - unit="°C" - .optional=${!1} - .disabled=${this._activeSlot<0} - @value-changed=${e=>{this._updateSetPoint(Number(e.detail.value))}} - > - -
-
-
- `:"OnOff"==this.schedule_type?W` -
-
 
-
-
-
State
-
- Off - =0&&"On"==e[this._activeSlot].Setpoint} - .disabled=${this._activeSlot<0} - @change=${()=>"On"==e[this._activeSlot].Setpoint?this._updateSetPoint("Off"):this._updateSetPoint("On")} - /> - On -
-
-
-
- `:["Lighting","Shutters"].includes(this.schedule_type)?W` -
-
 
-
-
Level
-
- =0?parseFloat(e[this._activeSlot].Setpoint):0} - unit="%" - .optional=${!1} - .disabled=${this._activeSlot<0} - @value-changed=${e=>{this._updateSetPoint(Number(e.detail.value))}} - > - -
-
-
- `:W``):W``}renderCopyDay(){return W` -
-
 
-
-
- ${this._activeDay?this.localize("wiser.actions.copy")+" "+this.localize("wiser.days."+this._activeDay.toLowerCase())+" "+this.localize("wiser.labels.to"):this.localize("wiser.actions.copy")+" "+this.localize("wiser.labels.to")} -
-
- ${Ee.concat(Se).concat("All").map(e=>this.renderCopyToButton(e))} -
-
-
- `}renderCopyToButton(e){return W` - - `}renderTooltip(e,t,i=!1){const s=e.slots,o=Ae.includes(s[t].SpecialTime);return W` -
-
- ${o?W` - - ${s[t].SpecialTime} - `:Ft(Yt(Dt(zt(s[t].Time))),bt(this.hass))} -
-
- `}_slotClick(e){const t=e.currentTarget;if(t.id){const e=t.id.split("|")[0],i=t.id.split("|")[1];i!=this._activeSlot||e!=this._activeDay?(this._activeSlot=parseInt(i),this._activeDay=e):(this._activeSlot=-99,this._activeDay="");const s=new CustomEvent("slotClicked",{detail:{day:this._activeDay,slot:this._activeSlot}});this.dispatchEvent(s)}}_copyDay(e){const t=e.currentTarget,i=JSON.stringify(this.schedule.ScheduleData[Ee.indexOf(this._activeDay)].slots);Ee.includes(t.id)?this.schedule.ScheduleData[Ee.indexOf(t.id)].slots=JSON.parse(i):t.id==Se[0]?ke.map(e=>{this.schedule.ScheduleData[Ee.indexOf(e)].slots=JSON.parse(i)}):t.id==Se[1]?Ce.map(e=>{this.schedule.ScheduleData[Ee.indexOf(e)].slots=JSON.parse(i)}):"All"==t.id&&Ee.map(e=>{this.schedule.ScheduleData[Ee.indexOf(e)].slots=JSON.parse(i)}),this.requestUpdate()}_updateSetPoint(e){this.schedule.ScheduleData[Ee.indexOf(this._activeDay)].slots=Object.assign(this.schedule.ScheduleData[Ee.indexOf(this._activeDay)].slots,{[this._activeSlot]:Object.assign(Object.assign({},this.schedule.ScheduleData[Ee.indexOf(this._activeDay)].slots[this._activeSlot]),{Setpoint:e})});const t=new CustomEvent("scheduleChanged",{detail:{schedule:this.schedule}});this.dispatchEvent(t),this.requestUpdate()}getSunTime(e,t){return t==Ae[0]?this.suntimes.Sunrises[Ee.indexOf(e)].time:this.suntimes.Sunsets[Ee.indexOf(e)].time}convertScheduleDay(e){const t=e.slots.map(t=>Ae.includes(t.SpecialTime)?{Time:this.getSunTime(e.day,t.SpecialTime),Setpoint:t.Setpoint,SpecialTime:t.SpecialTime}:{Time:t.Time,Setpoint:t.Setpoint,SpecialTime:t.SpecialTime}).sort((e,t)=>parseInt(e.Time.replace(":",""))JSON.stringify(e))),s=Array.from(i).map(e=>JSON.parse(e));return{day:e.day,slots:s}}_setSpecialTime(e){const t=e.currentTarget.id.replace(/\w\S*/g,e=>e.charAt(0).toUpperCase()+e.substr(1).toLowerCase());this._activeDay&&this._activeSlot>=0&&(this.schedule.ScheduleData[Ee.indexOf(this._activeDay)].slots[this._activeSlot].SpecialTime!=t&&(this.schedule.ScheduleData[Ee.indexOf(this._activeDay)].slots=Object.assign(this.schedule.ScheduleData[Ee.indexOf(this._activeDay)].slots,{[this._activeSlot]:Object.assign(Object.assign({},this.schedule.ScheduleData[Ee.indexOf(this._activeDay)].slots[this._activeSlot]),{SpecialTime:t,Time:this.getSunTime(this._activeDay,t)})})),this.schedule.ScheduleData[Ee.indexOf(this._activeDay)]=this.convertScheduleDay(this.schedule.ScheduleData[Ee.indexOf(this._activeDay)]),this.schedule.ScheduleData[Ee.indexOf(this._activeDay)].slots.forEach((e,i)=>{e.SpecialTime==t&&(this._activeSlot=i)}),this.requestUpdate())}_addSlot(){if(this._activeSlot<-1)return;const e=Ee.indexOf(this._activeDay);if(this._activeSlot<0)this.schedule.ScheduleData[e].slots=[{Time:Tt(zt("06:00")),Setpoint:be[this.schedule_type],SpecialTime:""}],this._activeSlot=0;else{const t=this.schedule.ScheduleData[e].slots[this._activeSlot];let i=zt(t.Time),s=zt(yt(this.schedule.ScheduleData[e],this._activeSlot));se.day==this._activeDay)[0].slots;const s=e.currentTarget;let o=s;for(;!o.classList.contains("outer");)o=o.parentElement;const a=parseFloat(getComputedStyle(o).getPropertyValue("width")),r=_e/(this.rangeMax-this.rangeMin)*a,n=-(-this.rangeMin/(this.rangeMax-this.rangeMin)*a)/r*_e;let l=s;for(;!l.classList.contains("slot");)l=l.parentElement;const d=l,c=Number(s.dataset.boundary);if(!Number.isInteger(c)||c<0||c>=i.length)return;const h=c>0?zt(i[c-1].Time)+60*this.stepSize:0,p=c{let s;s="undefined"!=typeof TouchEvent&&e instanceof TouchEvent?e.changedTouches[0].pageX:e.pageX;let o=s-u.left;o>a-1&&(o=a-1),o<-18&&(o=-18);let l=Math.round(o/r*_e+n);lp&&(l=p),this.currentTime=l,l=Math.round(l)>=_e?_e:Mt(l,this.stepSize);const d=Tt(l);d!=yt(this.schedule.ScheduleData[t],c)&&(i=Object.assign(i,{[c]:Object.assign(Object.assign({},i[c]),{Time:d,SpecialTime:""})}),this.requestUpdate())};const g=()=>{window.removeEventListener("mousemove",m),window.removeEventListener("touchmove",m),window.removeEventListener("mouseup",g),window.removeEventListener("touchend",g),window.removeEventListener("blur",g),m=()=>{},setTimeout(()=>{this.isDragging=!1},100),s.blur();const e=new CustomEvent("scheduleChanged",{detail:{schedule:this.schedule}});this.dispatchEvent(e)};window.addEventListener("mouseup",g),window.addEventListener("touchend",g),window.addEventListener("blur",g),window.addEventListener("mousemove",m),window.addEventListener("touchmove",m)}computeDayLabel(e){return W` -
- ${this._show_short_days?this.localize("wiser.days.short."+e.toLowerCase()):this.localize("wiser.days."+e.toLowerCase())} -
- `}computeSetpointLabel(e){return"Unknown"==e?e:"Heating"==this.schedule_type&&-20==e?"Off":e+we[this.schedule_type]}static get styles(){return n` - ${kt} - :host { - display: block; - max-width: 100%; - } - div.outer { - width: 100%; - overflow: visible; - } - div.wrapper, - div.time-wrapper { - white-space: nowrap; - transition: - width 0.2s cubic-bezier(0.17, 0.67, 0.83, 0.67), - margin 0.2s cubic-bezier(0.17, 0.67, 0.83, 0.67); - display: flex; - } - div.sub-section { - display: flex; - justify-content: center; - width: 100%; - } - .special-times { - justify-content: flex-end; - line-height: 40px; - padding: 0 5px; - text-transform: uppercase; - font-size: calc(13px + 1pt); - } - .temperature-row { - display: flex; - justify-content: center; - width: 100%; - padding-top: 10px; - } - .temperature-controls { - display: flex; - align-items: center; - justify-content: center; - flex-wrap: wrap; - gap: 8px; - width: min(100%, 540px); - } - .temperature-input { - display: flex; - align-items: center; - flex: 1 1 240px; - min-width: 0; - max-width: 400px; - } - .temperature-input wiser-variable-slider { - min-width: 0; - } - .section-header { - color: var(--primary-text-color); - text-transform: uppercase; - font-weight: 500; - font-size: calc(var(--material-small-font-size, 12px) + 1pt); - padding: 5px 10px; - } - .slot { - float: left; - background: rgba(var(--rgb-primary-color), 0.7); - height: 60px; - box-sizing: border-box; - transition: background 0.1s cubic-bezier(0.17, 0.67, 0.83, 0.67); - position: relative; - height: 40px; - line-height: 40px; - font-size: calc(10px + 1pt); - text-align: center; - } - .slot:first-child { - border-radius: 5px 0 0 5px; - } - .slot:last-child { - border-radius: 0 5px 5px 0; - } - .slot:only-child { - border-radius: 5px; - } - .slot.previous { - cursor: default; - } - .slot.selected { - background: rgba(52, 143, 255, 1); - } - .setpoint { - z-index: 3; - position: relative; - text-align: center; - } - .slotoverlay { - position: absolute; - display: hidden; - width: 100%; - height: 100%; - top: 0; - left: 0; - right: 0; - bottom: 0; - /*background-color: rgba(0,0,0,0.5);*/ - z-index: 2; - } - div.slot.selectable { - cursor: pointer; - } - - .previous { - display: block; - background: repeating-linear-gradient( - 135deg, - rgba(0, 0, 0, 0), - rgba(0, 0, 0, 0) 5px, - rgba(255, 255, 255, 0.2) 5px, - rgba(255, 255, 255, 0.2) 10px - ); - border-radius: 5px 0 0 5px; - } - .previous.selected { - border: 2px solid var(--primary-color); - } - .previous.selected.theme-colors { - border: 2px solid var(--warning-color); - } - .wrapper.selectable .slot:hover { - background: rgba(var(--rgb-primary-color), 0.85); - } - .slot:not(:first-child) { - border-left: 1px solid var(--card-background-color); - } - .slot.active { - background: rgba(var(--rgb-accent-color), 0.7); - } - .slot.noborder { - border: none; - } - .wrapper.selectable .slot.active:hover { - background: rgba(var(--rgb-accent-color), 0.85); - } - .wrapper .day.short { - max-width: 50px; - } - .wrapper .day { - line-height: 42px; - float: left; - width: 20%; - max-width: 100px; - } - .wrapper .schedule { - position: relative; - width: 100%; - height: 40px; - border-radius: 5px; - overflow: auto; - margin-bottom: 2px; - display: flex; - } - .setpoint.rotate { - z-index: 3; - transform: rotate(-90deg); - position: absolute; - top: 20px; - height: 0px !important; - width: 100%; - overflow: visible !important; - } - div.time-wrapper div { - float: left; - display: flex; - position: relative; - height: 25px; - line-height: 25px; - font-size: calc(12px + 1pt); - text-align: center; - align-content: center; - align-items: center; - justify-content: center; - } - div.time-wrapper div.time:before { - content: ' '; - background: var(--disabled-text-color); - position: absolute; - left: 0px; - top: 0px; - width: 1px; - height: 5px; - margin-left: 50%; - margin-top: 0px; - } - .slot span { - font-size: calc(10px + 1pt); - color: var(--text-primary-color); - height: 100%; - display: flex; - align-content: center; - align-items: center; - justify-content: center; - transition: margin 0.2s cubic-bezier(0.17, 0.67, 0.83, 0.67); - word-break: nowrap; - white-space: normal; - overflow: hidden; - line-height: 1em; - } - div.handle { - position: absolute; - top: 0; - left: 0; - height: 100%; - width: 36px; - transform: translateX(-50%); - display: grid; - place-items: center; - z-index: 5; - } - div.handle.end-handle { - left: 100%; - } - div.tooltip-container.end-time { - left: 100%; - } - div.button-holder { - line-height: 0; - background: var(--card-background-color); - border: 1px solid var(--divider-color); - border-radius: 50%; - width: 32px; - height: 32px; - display: grid; - place-items: center; - } - ha-icon-button.time-handle { - display: flex; - align-items: center; - justify-content: center; - line-height: 0; - --ha-button-height: 32px; - --wa-form-control-height: 32px; - --ha-icon-button-padding-inline: 0px; - --mdc-icon-button-size: 32px; - --mdc-icon-size: 24px; - --ha-icon-button-size: 32px; - width: 32px; - height: 32px; - margin: 0; - padding: 0; - color: var(--primary-color); - cursor: ew-resize; - touch-action: none; - } - div.tooltip-container { - position: absolute; - margin-top: 0; - margin-left: -40px; - width: 80px; - height: 0px; - text-align: center; - line-height: 35px; - z-index: 3; - top: -48px; - } - - div.tooltip-container.visible { - display: block; - } - div.tooltip-container.left { - margin-left: -80px; - text-align: right; - } - div.tooltip-container.right { - margin-left: 0px; - text-align: left; - } - div.tooltip { - display: inline-flex; - margin: 0px auto; - border-radius: 5px; - color: var(--text-primary-color); - font-size: calc(18px + 1pt); - font-weight: 600; - font-variant-numeric: tabular-nums; - white-space: nowrap; - padding: 4px 10px; - text-align: center; - line-height: 28px; - z-index: 5; - transition: all 0.1s ease-in; - transform-origin: center bottom; - --tooltip-color: var(--primary-color); - background: var(--primary-color); - } - div.tooltip.active { - --tooltip-color: rgba(var(--rgb-accent-color), 0.7); - } - div.tooltip-container.left div.tooltip { - transform-origin: right bottom; - } - div.tooltip-container.right div.tooltip { - transform-origin: left bottom; - } - div.tooltip-container.center div.tooltip:before { - content: ' '; - width: 0px; - height: 0px; - border-left: 6px solid transparent; - border-right: 6px solid transparent; - border-top: 10px solid var(--primary-color); - position: absolute; - margin-top: 36px; - margin-left: calc(50% - 6px); - top: 0px; - left: 0px; - } - div.tooltip-container.left div.tooltip:before { - content: ' '; - border-top: 10px solid transparent; - border-bottom: 10px solid transparent; - border-right: 8px solid var(--tooltip-color); - opacity: 1; - position: absolute; - margin-top: 15px; - margin-left: calc(100% - 8px); - left: 0px; - top: 0px; - width: 0px; - height: 0px; - } - div.tooltip-container.right div.tooltip:before { - content: ' '; - border-top: 10px solid transparent; - border-bottom: 10px solid transparent; - border-left: 8px solid var(--tooltip-color); - opacity: 1; - position: absolute; - margin-top: 15px; - margin-left: 0px; - left: 0px; - top: 0px; - width: 0px; - height: 0px; - } - div.tooltip ha-icon { - --mdc-icon-size: 18px; - } - - mwc-button.state-button { - padding: 0px 10px; - margin: 0 2px; - max-width: 100px; - } - - mwc-button.warning { - --mdc-theme-primary: var(--error-color); - } - mwc-button.warning .mdc-button .mdc-button__label { - color: var(--primary-text-color); - } - mwc-button.right { - float: right; - } - ha-icon-button { - --mdc-icon-button-size: 36px; - margin-top: -6px; - margin-left: -6px; - } - @keyframes fadeIn { - 99% { - visibility: hidden; - } - 100% { - visibility: visible; - } - } - - mwc-button ha-icon { - margin-right: 2px; - } - mwc-button.active { - background: var(--primary-color); - --mdc-theme-primary: var(--text-primary-color); - border-radius: 4px; - } - ha-icon-button.set-off-button { - margin-left: 0px; - } - .sub-heading { - padding: 0px 10px 0px 10px; - font-weight: 500; - } - `}};e([pe({attribute:!1})],Gt.prototype,"hass",void 0),e([pe({attribute:!1})],Gt.prototype,"config",void 0),e([pe({attribute:!1})],Gt.prototype,"schedule",void 0),e([pe({attribute:!1})],Gt.prototype,"suntimes",void 0),e([pe({attribute:!1})],Gt.prototype,"editMode",void 0),e([ue()],Gt.prototype,"_activeSlot",void 0),e([ue()],Gt.prototype,"_activeDay",void 0),e([ue()],Gt.prototype,"_show_short_days",void 0),e([ue()],Gt.prototype,"rangeMin",void 0),e([ue()],Gt.prototype,"rangeMax",void 0),e([ue()],Gt.prototype,"stepSize",void 0),e([function(e){return(t,i)=>{const s="function"==typeof t?t:t[i];Object.assign(s,e)}}({passive:!0})],Gt.prototype,"_handleTouchStart",null),Gt=e([t("wiser-schedule-slot-editor")],Gt);let Kt=class extends le{async showDialog(e){this._params=e,await this.updateComplete}async closeDialog(){this._params=void 0}render(){var e;return this._params?W` - -
${this._params.error||""}
-
- ${this.hass.localize("ui.dialogs.generic.ok")} -
-
- `:W``}static get styles(){return n` - .actions { - display: flex; - justify-content: flex-end; - gap: 8px; - padding-top: 16px; - } - div.wrapper { - color: var(--primary-text-color); - } - `}};e([pe({attribute:!1})],Kt.prototype,"hass",void 0),e([ue()],Kt.prototype,"_params",void 0),Kt=e([t("wiser-dialog-error")],Kt);var Xt=Object.freeze({__proto__:null,get DialogError(){return Kt}});let Qt=class extends(wt(le)){constructor(){var e;super(...arguments),this.schedule_id=0,this.use_heat_colors=!0,this.embedded=!1,this.assignmentSelection=[],this.assigningDevices=!1,this.rooms=[],this.entities=[],this._activeSlot=null,this._activeDay=null,this.editMode=!1,this._current_user=null===(e=this.hass)||void 0===e?void 0:e.user,this._assigning_in_progress=0,this._save_in_progress=!1,this.stepSize=5}localize(e,t="",i=""){return je(this.hass,e,t,i)}async initialise(){return await this._isComponentLoaded()&&(this.component_loaded=!0,await this.loadData()),!0}hassSubscribe(){return this.initialise(),[this.hass.connection.subscribeMessage(e=>this.handleUpdate(e),{type:"wiser_updated"})]}async handleUpdate(e){this.assigningDevices||this.config.hub&&e.hub!=this.config.hub||"wiser_updated"!=e.event||await this.loadData()}async _isComponentLoaded(){return Boolean(this.hass&&this.config&&this.hass.config.components.includes("wiser"))}getSunTime(e,t){return t==Ae[0]?this.suntimes.Sunrises[Ee.indexOf(e)].time:this.suntimes.Sunsets[Ee.indexOf(e)].time}convertLoadedSchedule(e){const t=e.ScheduleData.map(e=>this.convertLoadedScheduleDay(e));return e.ScheduleData=t,e}convertLoadedScheduleDay(e){const t=e.slots.map(t=>Ae.includes(t.Time)?{Time:this.getSunTime(e.day,t.Time),Setpoint:t.Setpoint,SpecialTime:t.Time}:{Time:t.Time,Setpoint:t.Setpoint,SpecialTime:""}).sort((e,t)=>parseInt(e.Time.replace(":",""))JSON.stringify(e))),s=Array.from(i).map(e=>JSON.parse(e));return{day:e.day,slots:s}}convertScheduleForSaving(e){const t=e.ScheduleData.map(e=>this.convertScheduleDayForSaving(e));return e.ScheduleData=t,e}convertScheduleDayForSaving(e){const t=e.slots.map(e=>Ae.includes(e.SpecialTime)?{Time:e.SpecialTime,Setpoint:e.Setpoint,SpecialTime:e.SpecialTime}:{Time:e.Time,Setpoint:e.Setpoint,SpecialTime:""}).sort((e,t)=>e.Time.replace(":","")JSON.stringify(e))),s=Array.from(i).map(e=>JSON.parse(e));return{day:e.day,slots:s}}async loadData(){this.error=void 0,this.embedded||await at(),this.schedule_type&&this.schedule_id&&!this.editMode&&(await We(this.hass,this.config.hub).then(e=>{this.suntimes=e}).catch(e=>{this.error=e}),await Fe(this.hass,this.config.hub,this.schedule_type,this.schedule_id).then(e=>{this.schedule=this.convertLoadedSchedule(e)}).catch(e=>{this.schedule=void 0,this.error=e}),this.schedule&&await this.get_entity_list(this.hass,this.config.hub).then(e=>{this.entities=e,this.assignmentSelection=e.filter(e=>this.isAssigned(e)).map(e=>String(e.Id))}).catch(e=>{this.error=e})),await xt(this)}async get_entity_list(e,t){return 1e3===this.schedule.Id?[]:"heating"==this.schedule.Type.toLowerCase()?await Ye(e,t):await Je(e,t,this.schedule.SubType||this.schedule.Type)}shouldUpdate(e){return!(!e.has("hass")&&!e.has("component_loaded"))||(e.has("schedule_id")||e.has("schedule_type")||e.has("config")||e.has("editMode")?(this.loadData(),!0):!!(e.has("schedule")||e.has("entities")||e.has("editMode")||e.has("_assigning_in_progress")||e.has("_save_in_progress")||e.has("assignmentSelection")||e.has("assigningDevices")||e.has("error")&&pt(this.error)))}updated(e){super.updated(e),this.embedded&&this.dispatchEvent(new CustomEvent("editor-state",{detail:{editing:this.editMode,saving:this._save_in_progress,ready:Boolean(this.schedule&&this.schedule.Id===this.schedule_id&&this.suntimes&&!this.error)}}))}render(){return this.hass&&this.config&&this.component_loaded?pt(this.error)?W`
${this.error.message}
`:this.schedule&&this.entities&&this.suntimes?W` -
- ${this.embedded?"":this.renderToolbar()} - ${this.embedded||1e3===this.schedule.Id?"":this.renderScheduleAssignment(this.entities,this.schedule.Assignments)} -
-
-
- -
-
-
-
- `:W``:W``}isAssigned(e){var t;return Boolean(null===(t=this.schedule)||void 0===t?void 0:t.Assignments.some(t=>{var i,s;const o=t,a=null!==(i=o.id)&&void 0!==i?i:o.Id;return void 0!==a?String(a)===String(e.Id):(null!==(s=o.name)&&void 0!==s?s:o.Name)===e.Name}))}renderScheduleAssignment(e,t){if(this.schedule&&!this.editMode&&1e3!==this.schedule.Id)return vt(this.hass,this.config)?W`
- ({value:String(e.Id),label:e.Name}))}}} - .value=${this.assignmentSelection} - .required=${!1} - .disabled=${this.assigningDevices||!e.length} - @value-changed=${t=>{var i;if(t.stopPropagation(),this.assigningDevices)return;const s=null!==(i=t.detail.value)&&void 0!==i?i:[];Array.isArray(s)&&s.every(t=>e.some(e=>String(e.Id)===t))&&(this.assignmentSelection=s)}} - > - ${e.length?"":W`

${this.localize("wiser.home.no_devices")}

`} -
`:W`

- ${e.filter(e=>this.isAssigned(e)).map(e=>e.Name).join(", ")||this.localize("wiser.headings.not_assigned")} -

`}async applyDeviceAssignments(){if(!this.schedule||this.assigningDevices||this.editMode||1e3===this.schedule.Id||!vt(this.hass,this.config))return;const e=(this.entities||[]).filter(e=>this.isAssigned(e)!==this.assignmentSelection.includes(String(e.Id)));this.assigningDevices=!0;try{for(const t of e)await Ze(this.hass,this.config.hub,this.schedule.Type,this.schedule.Id,String(t.Id),!this.assignmentSelection.includes(String(t.Id)));await this.loadData()}catch(e){await this.loadData(),Ge(this,"Schedule assignment",e.message||this.localize("common.load_failed"))}finally{this.assigningDevices=!1}}renderEntityButton(e,t){return W` - - `}tool(e,t,i,s=!1){return W``}renderToolbar(){const e=vt(this.hass,this.config),t=this.assigningDevices||this._save_in_progress,i=1e3===this.schedule.Id,s=(this.entities||[]).some(e=>this.isAssigned(e)!==this.assignmentSelection.includes(String(e.Id)));return W` {var t;const i=e.target,s=null===(t=i.files)||void 0===t?void 0:t[0];i.value="",s&&this.importSchedule(s)}} - /> - - - -

${this.schedule.Name}

`}async entityAssignmentClick(e){var t;const i=e.currentTarget;if(!this._assigning_in_progress&&!this.editMode&&1e3!==(null===(t=this.schedule)||void 0===t?void 0:t.Id)&&vt(this.hass,this.config)){this._assigning_in_progress=parseInt(i.id);try{await Ze(this.hass,this.config.hub,this.schedule_type,this.schedule_id,i.id,i.classList.contains("active")),await this.loadData()}catch(e){Ge(this,"Schedule assignment",e.message||this.localize("common.load_failed"))}finally{this._assigning_in_progress=0}}}backClick(){const e=new CustomEvent("backClick");this.dispatchEvent(e)}editClick(){this.schedule&&this.schedule.Id===this.schedule_id&&vt(this.hass,this.config)&&(this._tempSchedule=JSON.parse(JSON.stringify(this.schedule)),this.editMode=!this.editMode)}copyClick(){const e=new CustomEvent("copyClick");this.dispatchEvent(e)}exportSchedule(){if(!this.schedule)return;const e=this.convertScheduleForSaving(JSON.parse(JSON.stringify(this.schedule))),t={format:"wiser-schedule",version:1,schedule:{Name:e.Name,Type:e.Type,SubType:e.SubType,ScheduleData:e.ScheduleData}},i=URL.createObjectURL(new Blob([JSON.stringify(t,null,2)],{type:"application/json"})),s=document.createElement("a");s.href=i,s.download=`${e.Name.replace(/[^a-z0-9_-]/gi,"_")||"schedule"}.json`,s.click(),setTimeout(()=>URL.revokeObjectURL(i),1e3)}async importSchedule(e){if(this.schedule&&!this.editMode&&vt(this.hass,this.config))try{if(e.size>1048576)throw new Error("Schedule file is too large.");const t=function(e,t){var i;const s=JSON.parse(e);if("wiser-schedule"!==s.format||1!==s.version)throw new Error("Unsupported schedule file.");const o=s.schedule,a=(t.SubType||t.Type).toLowerCase();if(!o||(null===(i=o.SubType||o.Type)||void 0===i?void 0:i.toLowerCase())!==a)throw new Error("This file is for a different schedule type.");if(!Array.isArray(o.ScheduleData)||7!==o.ScheduleData.length)throw new Error("The file must contain all seven days.");const r=new Set;let n=0;const l=o.ScheduleData.map(e=>{if(!Ee.includes(e.day)||r.has(e.day)||!Array.isArray(e.slots)||e.slots.length>24)throw new Error("Invalid schedule days or slots.");r.add(e.day);const t=new Set;return{day:e.day,slots:e.slots.map(e=>{const i=Ae.includes(e.Time);if(!i&&!/^([01]\d|2[0-3]):[0-5]\d$/.test(e.Time)||i&&!["lighting","shutters"].includes(a)||t.has(e.Time))throw new Error("Invalid or duplicate slot time.");t.add(e.Time);const s=String(e.Setpoint),o=Number(s);if(!("heating"===a?Number.isFinite(o)&&(-20===o||o>=5&&o<=30):["lighting","shutters"].includes(a)?Number.isFinite(o)&&o>=0&&o<=100:["On","Off"].includes(s)))throw new Error("Invalid schedule setting.");return n++,{Time:e.Time,Setpoint:s,SpecialTime:i?e.Time:""}})}});if(!n)throw new Error("The schedule has no time slots.");return Object.assign(Object.assign({},t),{ScheduleData:l})}(await e.text(),this.schedule);this._tempSchedule=this.convertLoadedSchedule(t),this.editMode=!0}catch(e){Ge(this,"Import schedule",e.message)}}filesClick(){const e=new CustomEvent("filesClick");this.dispatchEvent(e)}async renameScheduleClick(){const e=new CustomEvent("renameClick");this.dispatchEvent(e)}async deleteClick(e){if(!vt(this.hass,this.config))return;const t=(null==e?void 0:e.target)||this;if(await new Promise(e=>{ve(t,"show-dialog",{dialogTag:"wiser-dialog-delete-confirm",dialogImport:()=>Promise.resolve().then(function(){return At}),dialogParams:{cancel:()=>{e(!1)},confirm:()=>{e(!0)},name:this.schedule.Name}})})){this.schedule_id=0,await(i=this.hass,s=this.config.hub,o=this.schedule.Type,a=this.schedule.Id,i.callWS({type:"wiser/schedule/delete",hub:s,schedule_type:o,schedule_id:a}));const e=new CustomEvent("scheduleDeleted");this.dispatchEvent(e)}var i,s,o,a}cancelClick(){this.editMode=!1}validateSchedule(e){return e.ScheduleData.map(e=>e.slots).map(e=>e.length>0).includes(!0)}async saveClick(){if(!this._save_in_progress&&this._tempSchedule&&vt(this.hass,this.config)){this._save_in_progress=!0;try{if(this.validateSchedule(this._tempSchedule)){const e=JSON.parse(JSON.stringify(this._tempSchedule)),t=$e.includes(this.schedule_type)?this.convertScheduleForSaving(e):e;await((e,t,i,s,o)=>e.callWS({type:"wiser/schedule/save",hub:t,schedule_type:i,schedule_id:s,schedule:o}))(this.hass,this.config.hub,this.schedule_type,this.schedule_id,t),this.editMode=!1}else Ge(this,"Error Saving Schedule","The schedule you are trying to save has no time slots.")}catch(e){Ge(this,"Error Saving Schedule",(null==e?void 0:e.message)||this.localize("common.load_failed"))}finally{this._save_in_progress=!1}}}scheduleChanged(e){this._tempSchedule=e.detail.schedule,this.render()}static get styles(){return n` - ${Ct} - .schedule-heading { - display: flex; - flex-wrap: wrap; - align-items: center; - justify-content: space-between; - gap: 12px; - } - .schedule-title { - margin: 16px 0 8px; - font-size: calc(22px + 1pt); - } - .tools { - display: flex; - flex-wrap: wrap; - gap: 6px; - margin-inline-start: auto; - } - .tool { - width: 44px; - height: 44px; - padding: 0; - display: grid; - place-items: center; - color: var(--secondary-text-color); - } - .tool:disabled { - color: var(--disabled-text-color); - opacity: 1; - } - .tool:not(:disabled):hover { - color: var(--primary-color); - } - - .device-assignment { - max-width: 420px; - margin: 20px 0; - display: grid; - gap: 8px; - } - .device-assignment button { - justify-self: start; - } - :host { - display: block; - max-width: 100%; - } - div.outer { - width: 100%; - overflow-x: hidden; - overflow-y: hidden; - border-radius: 5px; - } - div.wrapper, - div.time-wrapper { - white-space: nowrap; - transition: - width 0.2s cubic-bezier(0.17, 0.67, 0.83, 0.67), - margin 0.2s cubic-bezier(0.17, 0.67, 0.83, 0.67); - } - div.assignment-wrapper, - div.actions-wrapper { - border-top: 1px solid var(--divider-color, #e8e8e8); - padding: 5px 0px; - min-height: 40px; - } - div.mode { - position: absolute; - right: 10px; - top: 64px; - background: var(--primary-color); - padding: 2px 10px; - border-radius: 20px; - font-size: smaller; - color: var(--app-header-text-color); - } - div.action-buttons { - display: flow-root; - } - span.assignment-label { - color: var(--primary-color); - text-transform: uppercase; - font-weight: 500; - font-size: calc(var(--material-small-font-size, 12px) + 1pt); - padding: 5px 10px; - } - .slot { - float: left; - background: rgba(var(--rgb-primary-color), 0.7); - height: 60px; - cursor: pointer; - box-sizing: border-box; - transition: background 0.1s cubic-bezier(0.17, 0.67, 0.83, 0.67); - position: relative; - height: 40px; - line-height: 40px; - font-size: calc(10px + 1pt); - text-align: center; - overflow: hidden; - } - .slot.previous { - cursor: default; - } - .slot.selected { - background: rgba(52, 143, 255, 1); - } - .setpoint { - z-index: 3; - position: relative; - text-align: center; - } - .slotoverlay { - position: absolute; - display: hidden; - width: 100%; - height: 100%; - top: 0; - left: 0; - right: 0; - bottom: 0; - /*background-color: rgba(0,0,0,0.5);*/ - z-index: 2; - cursor: pointer; - } - .previous { - display: block; - background: repeating-linear-gradient( - 135deg, - rgba(0, 0, 0, 0), - rgba(0, 0, 0, 0) 5px, - rgba(255, 255, 255, 0.2) 5px, - rgba(255, 255, 255, 0.2) 10px - ); - } - .wrapper.selectable .slot:hover { - background: rgba(var(--rgb-primary-color), 0.85); - } - .slot:not(:first-child) { - border-left: 1px solid var(--card-background-color); - } - .slot:not(:last-child) { - border-right: 1px solid var(--card-background-color); - } - .slot.active { - background: rgba(var(--rgb-accent-color), 0.7); - } - .slot.noborder { - border: none; - } - .wrapper.selectable .slot.active:hover { - background: rgba(var(--rgb-accent-color), 0.85); - } - .wrapper .days .day { - line-height: 42px; - float: left; - width: 100%; - } - .wrapper .schedules { - position: relative; - padding-top: 30px; - width: 100%; - } - .wrapper .schedules .slots { - height: 40px; - border-radius: 5px; - overflow: auto; - margin-bottom: 2px; - display: flex; - } - - .setpoint.rotate { - z-index: 3; - transform: rotate(-90deg); - position: absolute; - top: 20px; - height: 0px !important; - width: 100%; - overflow: visible !important; - } - div.schedule-action-wrapper { - display: flex; - justify-content: center; - flex-wrap: wrap; - gap: 8px; - } - div.time-wrapper div { - float: left; - display: flex; - position: relative; - height: 25px; - line-height: 25px; - font-size: calc(12px + 1pt); - text-align: center; - align-content: center; - align-items: center; - justify-content: center; - flex-wrap: wrap; - gap: 8px; - } - div.time-wrapper div.time:before { - content: ' '; - background: var(--disabled-text-color); - position: absolute; - left: 0px; - top: 0px; - width: 1px; - height: 5px; - margin-left: 50%; - margin-top: 0px; - } - .slot span { - font-size: calc(10px + 1pt); - color: var(--text-primary-color); - height: 100%; - display: flex; - align-content: center; - align-items: center; - justify-content: center; - transition: margin 0.2s cubic-bezier(0.17, 0.67, 0.83, 0.67); - word-break: nowrap; - white-space: normal; - overflow: hidden; - line-height: 1em; - } - div.handle { - display: flex; - height: 100%; - width: 36px; - margin-left: -19px; - margin-bottom: -60px; - align-content: center; - align-items: center; - justify-content: center; - } - div.button-holder { - background: var(--card-background-color); - border-radius: 50%; - width: 24px; - height: 24px; - display: flex; - visibility: hidden; - animation: 0.2s fadeIn; - animation-fill-mode: forwards; - } - .schedule-action-button { - flex: 1 1 100px; - padding: 0 5px; - } - ha-icon-button { - --mdc-icon-button-size: 36px; - margin-top: -6px; - margin-left: -6px; - } - @keyframes fadeIn { - 99% { - visibility: hidden; - } - 100% { - visibility: visible; - } - } - .card-header ha-icon-button { - position: absolute; - right: 6px; - top: 6px; - } - .sub-heading { - padding-bottom: 10px; - font-weight: 500; - } - span.waiting { - position: absolute; - height: 28px; - width: 100%; - margin: 4px; - } - div.schedule-info { - margin: 3px 0; - } - ${Ue} - `}};e([pe({attribute:!1})],Qt.prototype,"config",void 0),e([pe({attribute:!1})],Qt.prototype,"schedule_id",void 0),e([pe({attribute:!1})],Qt.prototype,"schedule_type",void 0),e([pe({attribute:!1})],Qt.prototype,"use_heat_colors",void 0),e([pe({attribute:!1})],Qt.prototype,"embedded",void 0),e([ue()],Qt.prototype,"assignmentSelection",void 0),e([ue()],Qt.prototype,"assigningDevices",void 0),e([ue()],Qt.prototype,"schedule",void 0),e([ue()],Qt.prototype,"rooms",void 0),e([ue()],Qt.prototype,"entities",void 0),e([ue()],Qt.prototype,"suntimes",void 0),e([ue()],Qt.prototype,"component_loaded",void 0),e([ue()],Qt.prototype,"_activeSlot",void 0),e([ue()],Qt.prototype,"_activeDay",void 0),e([ue()],Qt.prototype,"editMode",void 0),e([ue()],Qt.prototype,"_current_user",void 0),e([ue()],Qt.prototype,"_assigning_in_progress",void 0),e([ue()],Qt.prototype,"_save_in_progress",void 0),e([ue()],Qt.prototype,"error",void 0),Qt=e([t("wiser-schedule-edit-card")],Qt);let ei=class extends le{constructor(){super(...arguments),this.component_loaded=!1,this._saving=!1,this._schedule_types=[],this._schedule_info={Name:"",Type:""},this._loadError=""}localize(e,t="",i=""){return je(this.hass,e,t,i)}firstUpdated(){this.loadData().then(()=>{this.component_loaded=!0}).catch(e=>{this._loadError=(null==e?void 0:e.message)||this.localize("common.load_failed")}).then(()=>xt(this))}async loadData(){const e=await(t=this.hass,i=this.config.hub,t.callWS({type:"wiser/schedules/types",hub:i}));var t,i;if(this._schedule_types=e.filter(e=>!this.allowed_types||this.allowed_types.some(t=>t.toLowerCase()===e.toLowerCase())),this._schedule_info={Name:"",Type:this._schedule_types[0]||""},!this._schedule_types.length)throw new Error(this.localize("wiser.helpers.no_supported_types"))}render(){var e,t,i;return this.hass&&this.config?this._loadError?W`
${this._loadError}`:this.component_loaded?W` - - - -
-
${this.localize("wiser.actions.add_schedule")}
-
- ${this.localize(1===this._schedule_types.length?"wiser.helpers.add_schedule_name":"wiser.helpers.add_schedule")} -
- ${this._schedule_types.length>1?W`
${this._schedule_types.map((e,t)=>this.renderScheduleTypeButtons(e,t))}
`:""} - -
- `:W`
${this.localize("common.loading")}
`:W``}renderScheduleTypeButtons(e,t){return W` - - `}async confirmClick(){await this.createSchedule()}async createSchedule(){const e=this._schedule_info;if(this.hass&&this.config&&vt(this.hass,this.config)&&!this._saving&&(null==e?void 0:e.Name.trim())&&this._schedule_types.includes(e.Type)){this._saving=!0;try{const a=await qe(this.hass,this.config.hub,e.Type);await(t=this.hass,i=this.config.hub,s=e.Type,o=e.Name.trim(),t.callWS({type:"wiser/schedule/create",hub:i,schedule_type:s,name:o}));const r=(await qe(this.hass,this.config.hub,e.Type)).find(t=>t.Name===e.Name.trim()&&!a.some(e=>e.Id===t.Id&&e.Type===t.Type));r&&void 0!==this.assign_to&&await Ze(this.hass,this.config.hub,r.Type,r.Id,String(this.assign_to)),this.dispatchEvent(new CustomEvent("scheduleAdded",{detail:r}))}catch(e){this._loadError=(null==e?void 0:e.message)||this.localize("common.load_failed")}finally{this._saving=!1}var t,i,s,o}}cancelClick(){const e=new CustomEvent("backClick");this.dispatchEvent(e)}_valueChanged(e){const t=e.currentTarget;t.configValue&&(this._schedule_info=Object.assign(Object.assign({},this._schedule_info),{[t.configValue]:void 0!==t.checked?t.checked:t.value}))}static get styles(){return n` - ${Ct} - .header-actions { - display: flex; - flex-wrap: wrap; - justify-content: flex-end; - gap: 6px; - } - div.wrapper { - white-space: nowrap; - transition: - width 0.2s cubic-bezier(0.17, 0.67, 0.83, 0.67), - margin 0.2s cubic-bezier(0.17, 0.67, 0.83, 0.67); - overflow: auto; - } - div.wrapper { - color: var(--primary-text-color); - padding: 5px 0; - } - .schedule-type-select { - margin: 20px 0 0 0; - } - .schedule-name { - max-width: 420px; - display: grid; - gap: 8px; - color: var(--primary-text-color); - margin: 20px 0 0 0; - width: 100%; - } - input { - box-sizing: border-box; - width: 100%; - min-height: 44px; - padding: 10px 12px; - border: 1px solid var(--divider-color, #aaa); - border-radius: 10px; - background: var(--card-background-color, white); - color: var(--primary-text-color, #222); - font: inherit; - } - input:focus-visible { - outline: 2px solid var(--primary-color); - outline-offset: 2px; - } - ha-icon-button { - --mdc-icon-button-size: 36px; - margin-top: -6px; - margin-left: -6px; - } - .card-header ha-icon-button { - position: absolute; - right: 6px; - top: 6px; - } - mwc-button.active { - background: var(--primary-color); - --mdc-theme-primary: var(--text-primary-color); - border-radius: 4px; - } - `}};e([pe({attribute:!1})],ei.prototype,"hass",void 0),e([pe({attribute:!1})],ei.prototype,"config",void 0),e([pe({attribute:!1})],ei.prototype,"component_loaded",void 0),e([pe({attribute:!1})],ei.prototype,"allowed_types",void 0),e([pe({attribute:!1})],ei.prototype,"assign_to",void 0),e([ue()],ei.prototype,"_saving",void 0),e([ue()],ei.prototype,"_schedule_types",void 0),e([ue()],ei.prototype,"_schedule_info",void 0),e([ue()],ei.prototype,"_loadError",void 0),ei=e([t("wiser-schedule-add-card")],ei);let ti=class extends le{constructor(){super(...arguments),this.schedule_id=0,this.component_loaded=!1,this._copy_in_progress=0,this._schedule_list=[],this._loadError=""}localize(e,t="",i=""){return je(this.hass,e,t,i)}firstUpdated(){this.loadData().then(()=>{this.component_loaded=!0}).catch(e=>{this._loadError=(null==e?void 0:e.message)||this.localize("common.load_failed")}).then(()=>xt(this))}async loadData(){this.schedule=await Fe(this.hass,this.config.hub,this.schedule_type,this.schedule_id),this._schedule_list=await qe(this.hass,this.config.hub,this.schedule_type)}render(){return this.hass&&this.config?this._loadError?W`
${this._loadError}`:this.component_loaded&&this.schedule?W` - - - -
-
${this.localize("wiser.headings.copy_schedule")}
-
- ${this.localize("wiser.headings.schedule_type")}: ${this.schedule.Type} -
-
- ${this.localize("wiser.headings.schedule_id")}: ${this.schedule.Id} -
-
- ${this.localize("wiser.headings.schedule_name")}: ${this.schedule.Name} -
-
${this.localize("wiser.helpers.select_copy_schedule")}
-
- ${this._schedule_list.filter(e=>{var t;return e.Id!=(null===(t=this.schedule)||void 0===t?void 0:t.Id)}).map(e=>this.renderScheduleButtons(e))} -
-
- `:W`
${this.localize("common.loading")}
`:W``}renderScheduleButtons(e){return W` - - `}cancelClick(){const e=new CustomEvent("backClick",{detail:fe.ScheduleEdit});this.dispatchEvent(e)}async _copySchedule(e){const t=e.currentTarget;if(t.id){this._copy_in_progress=parseInt(t.id),await(i=this.hass,s=this.config.hub,o=this.schedule_type,a=this.schedule_id,r=parseInt(t.id),i.callWS({type:"wiser/schedule/copy",hub:s,schedule_type:o,schedule_id:a,to_schedule_id:r})),this._copy_in_progress=0;const e=new CustomEvent("scheduleCopied");this.dispatchEvent(e)}var i,s,o,a,r}static get styles(){return n` - ${Ct} - .header-actions { - display: flex; - flex-wrap: wrap; - justify-content: flex-end; - gap: 6px; - } - div.wrapper { - white-space: nowrap; - transition: - width 0.2s cubic-bezier(0.17, 0.67, 0.83, 0.67), - margin 0.2s cubic-bezier(0.17, 0.67, 0.83, 0.67); - overflow: auto; - } - div.card-actions { - border-top: 1px solid var(--divider-color, #e8e8e8); - padding: 5px 0px; - min-height: 40px; - } - div.wrapper { - color: var(--primary-text-color); - padding: 5px 0; - } - .schedule-type-select { - margin: 20px 0 0 0; - } - .schedule-name { - margin: 20px 0 0 0; - width: 100%; - } - .sub-heading { - padding-bottom: 10px; - font-weight: 500; - } - .schedule-button { - padding: 5px; - } - span.waiting { - position: absolute; - height: 28px; - width: 100%; - margin: 4px; - } - div.schedule-info { - margin: 3px 0; - } - `}};e([pe({attribute:!1})],ti.prototype,"hass",void 0),e([pe({attribute:!1})],ti.prototype,"config",void 0),e([pe({attribute:!1})],ti.prototype,"schedule_id",void 0),e([pe({attribute:!1})],ti.prototype,"schedule_type",void 0),e([ue()],ti.prototype,"schedule",void 0),e([ue()],ti.prototype,"component_loaded",void 0),e([ue()],ti.prototype,"_copy_in_progress",void 0),e([ue()],ti.prototype,"_schedule_list",void 0),e([ue()],ti.prototype,"_loadError",void 0),ti=e([t("wiser-schedule-copy-card")],ti);let ii=class extends le{constructor(){super(...arguments),this.component_loaded=!1,this._newScheduleName="",this._rename_in_progress=!1,this._loadError=""}localize(e,t="",i=""){return je(this.hass,e,t,i)}firstUpdated(){this.loadData().then(()=>{this.component_loaded=!0}).catch(e=>{this._loadError=(null==e?void 0:e.message)||this.localize("common.load_failed")}).then(()=>xt(this))}async loadData(){this._schedule=await Fe(this.hass,this.config.hub,this.schedule_type,this.schedule_id),this._newScheduleName=this._schedule.Name}render(){var e;return this.hass&&this.config?this._loadError?W`
${this._loadError}`:this.component_loaded?W` - - - -
-
${this.localize("wiser.headings.rename_schedule")}
-
${this.localize("wiser.helpers.enter_new_name")}
- -
- `:W`
${this.localize("common.loading")}
`:W``}async confirmClick(){await this.renameSchedule()}async renameSchedule(){var e,t,i,s,o;this._rename_in_progress=!0,await(e=this.hass,t=this.config.hub,i=this.schedule_type,s=this.schedule_id,o=this._newScheduleName,e.callWS({type:"wiser/schedule/rename",hub:t,schedule_type:i,schedule_id:s,schedule_name:o}));const a=new CustomEvent("scheduleRenamed");this.dispatchEvent(a),this._rename_in_progress=!1}cancelClick(){const e=new CustomEvent("backClick",{detail:fe.ScheduleEdit});this.dispatchEvent(e)}static get styles(){return n` - ${Ct} - .header-actions { - display: flex; - flex-wrap: wrap; - justify-content: flex-end; - gap: 6px; - } - div.wrapper { - white-space: nowrap; - transition: - width 0.2s cubic-bezier(0.17, 0.67, 0.83, 0.67), - margin 0.2s cubic-bezier(0.17, 0.67, 0.83, 0.67); - overflow: auto; - } - div.wrapper { - color: var(--primary-text-color); - padding: 5px 0; - } - .card-actions { - padding-top: 8px; - } - .schedule-type-select { - margin: 20px 0 0 0; - } - .schedule-name { - max-width: 420px; - margin: 20px 0 0 0; - width: 100%; - } - ha-icon-button { - --mdc-icon-button-size: 36px; - margin-top: -6px; - margin-left: -6px; - } - .card-header ha-icon-button { - position: absolute; - right: 6px; - top: 6px; - } - mwc-button.active { - background: var(--primary-color); - --mdc-theme-primary: var(--text-primary-color); - border-radius: 4px; - } - `}};e([pe({attribute:!1})],ii.prototype,"hass",void 0),e([pe({attribute:!1})],ii.prototype,"config",void 0),e([pe({attribute:!1})],ii.prototype,"component_loaded",void 0),e([pe({attribute:!1})],ii.prototype,"schedule_type",void 0),e([pe({attribute:!1})],ii.prototype,"schedule_id",void 0),e([ue()],ii.prototype,"_newScheduleName",void 0),e([ue()],ii.prototype,"_schedule",void 0),e([ue()],ii.prototype,"_rename_in_progress",void 0),e([ue()],ii.prototype,"_loadError",void 0),ii=e([t("wiser-schedule-rename-card")],ii);let si=class extends le{constructor(){super(...arguments),this._hubs=[],this._error="",this._requestId=0}localize(e,t="",i=""){return je(this.hass,e,t,i)}setConfig(e){this._config=Object.assign({},e)}updated(e){var t;const i=e.get("_config");(e.has("hass")&&!e.get("hass")||e.has("_config")&&(!i||i.hub!==(null===(t=this._config)||void 0===t?void 0:t.hub)))&&this.loadData()}async loadData(){if(!this.hass||!this._config)return;const e=++this._requestId;this._error="";try{await at();const t=await Be(this.hass);if(e!==this._requestId)return;this._hubs=t}catch(t){e===this._requestId&&(this._error=(null==t?void 0:t.message)||"Unable to load schedules.")}}change(e,t){if(!this._config)return;const i=Object.assign({},this._config);""===t?delete i[e]:i[e]=t,"home_screen"===e&&delete i.selected_schedule,"hub"===e&&delete i.selected_schedule,this._config=i,ve(this,"config-changed",{config:i})}toggle(e,t,i=!1){var s;return W``}render(){if(!this._config)return W``;const e=this._config;return W` -
-
- ${this.localize("wiser.home.screen")} - {e.stopPropagation(),["schedules","overview"].includes(e.detail.value)&&this.change("home_screen",e.detail.value)}} - > -
- ${"overview"===e.home_screen||"devices"===e.home_screen?W` -
- ${this.localize("wiser.home.overview_details")} - {e.stopPropagation(),["show","hide"].includes(e.detail.value)&&this.change("overview_details","show"===e.detail.value)}} - > -
- `:""} - ${this._hubs.length>1?W``:""} -
- ${this._error?W`
${this._error}
`:""} -
- ${this.localize("wiser.editor.permissions")} - ${this.toggle("display_only",this.localize("wiser.editor.display_only"))} -

${this.localize("wiser.editor.display_only_help")}

- ${this.toggle("admin_only",this.localize("wiser.editor.admin_only"),e.display_only)} -
-
- ${this.localize("wiser.editor.appearance")} - ${this.toggle("theme_colors",this.localize("wiser.editor.theme_colors"))} - ${this.toggle("hide_card_borders",this.localize("wiser.editor.hide_card_borders"))} - ${this.toggle("hide_card_background",this.localize("wiser.editor.hide_card_background"))} -
-
Wiser Schedule Card · ${ye}
- `}};si.styles=n` - .field-help { - color: var(--secondary-text-color); - font-size: 13px; - margin: 0 0 12px; - } - :host { - display: block; - color: var(--primary-text-color); - } - .home-screen { - display: flex; - align-items: center; - justify-content: space-between; - gap: 16px; - flex-wrap: wrap; - } - .home-screen ha-selector { - width: max-content; - margin-inline-start: auto; - display: flex; - justify-content: flex-end; - max-width: 100%; - } - .fields { - display: grid; - gap: 16px; - } - label { - display: grid; - gap: 8px; - font-size: calc(14px + 1pt); - } - input[type='text'], - select { - box-sizing: border-box; - width: 100%; - min-height: 44px; - border: 1px solid var(--divider-color, #ddd); - border-radius: 10px; - padding: 10px 12px; - background: var(--card-background-color, white); - color: var(--primary-text-color); - font: inherit; - } - fieldset { - border: 0; - border-top: 1px solid var(--divider-color, #ddd); - padding: 16px 0 0; - margin: 24px 0 0; - min-width: 0; - } - legend { - padding-right: 12px; - color: var(--secondary-text-color); - font-size: calc(13px + 1pt); - } - .toggle { - display: flex; - justify-content: space-between; - align-items: center; - gap: 16px; - min-height: 44px; - } - input[type='checkbox'] { - width: 20px; - height: 20px; - flex-shrink: 0; - accent-color: var(--primary-color); - } - input:focus-visible, - select:focus-visible { - outline: 2px solid var(--primary-color); - outline-offset: 2px; - } - .version { - margin-top: 24px; - color: var(--secondary-text-color); - font-size: calc(12px + 1pt); - } - `,e([pe({attribute:!1})],si.prototype,"hass",void 0),e([ue()],si.prototype,"_config",void 0),e([ue()],si.prototype,"_hubs",void 0),e([ue()],si.prototype,"_error",void 0),si=e([t("wiser-schedule-card-editor")],si);class oi extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this.shadowRoot.innerHTML='\n \n
\n

Wiser Schedules

\n \n \n
\n \n

Customize this panel. Dashboard cards keep their own settings.

\n
\n
\n Cancel\n Save\n
\n
\n

Loading Wiser schedules…

',this.shadowRoot.getElementById("menu").addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("hass-toggle-menu",{bubbles:!0,composed:!0}))}),this.shadowRoot.getElementById("settings").addEventListener("click",()=>this._openEditor()),this.shadowRoot.getElementById("cancel").addEventListener("click",()=>this._closeEditor()),this.shadowRoot.getElementById("save").addEventListener("click",()=>this._saveEditor()),this.shadowRoot.getElementById("editor-dialog").addEventListener("closed",()=>this._closeEditor()),this.shadowRoot.getElementById("editor-dialog").addEventListener("close-dialog",()=>this._closeEditor()),this._editors=[],this._cards=[],this._generation=0}set hass(e){this._hass=e;for(const t of this._cards)t.hass=e;for(const t of this._editors)t.hass=e;this.shadowRoot.getElementById("settings").hidden=!e?.user?.is_admin}set panel(e){const t=e.config;JSON.stringify(t)!==JSON.stringify(this._config)&&(this._config=t,this._loadCards())}_cardConfig(e){return{name:this._config.hubs.length>1?e:"Wiser Schedules",...this._config.card_configs?.[e],type:"custom:wiser-schedule-card",hub:e}}_closeEditor(){this.shadowRoot.getElementById("editor-dialog").open=!1,this._editors=[]}async _openEditor(){const e=this.shadowRoot.getElementById("editor-dialog");if(e.open||!this._cards.length||!this._hass?.user?.is_admin)return;const t=this.shadowRoot.getElementById("editors"),i=this.shadowRoot.getElementById("editor-error"),s=this.shadowRoot.getElementById("save");this._drafts={},this._editors=[],i.textContent="",t.replaceChildren(),s.disabled=!0,e.heading="Panel settings","headerTitle"in(customElements.get("ha-dialog")?.prototype||{})||this.shadowRoot.getElementById("editor-actions").removeAttribute("slot"),e.open=!0;try{if(!window.loadCardHelpers){const e=document.createElement("partial-panel-resolver"),t=e._getRoutes?.({lovelace:{component_name:"lovelace",url_path:"lovelace"}});await(t?.routes?.lovelace?.load?.())}const i=customElements.get("wiser-schedule-card");for(const s of this._config.hubs){const o=await i.getConfigElement();if(!e.open)return;const a=this._cardConfig(s);this._drafts[s]=a,o.hass=this._hass,o.setConfig({...a}),o.addEventListener("config-changed",e=>{e.stopPropagation(),this._drafts[s]={...e.detail.config}});const r=document.createElement("section"),n=document.createElement("h3");n.textContent=s,r.replaceChildren(...this._config.hubs.length>1?[n,o]:[o]),t.append(r),this._editors.push(o)}s.disabled=!1}catch(e){i.textContent="Unable to open the editor. Close this dialog and try again.",console.error("Unable to open Wiser editor",e)}}async _saveEditor(){const e=this.shadowRoot.getElementById("save");e.disabled=!0;try{await this._hass.callWS({type:"wiser/schedules_panel/configure",configs:this._drafts}),this._config={...this._config,card_configs:{...this._config.card_configs,...this._drafts}},this._closeEditor(),this._editors=[],this._loadCards()}catch(e){this.shadowRoot.getElementById("editor-error").textContent="Unable to save settings to Home Assistant. Please try again.",console.error("Unable to save Wiser panel settings",e)}finally{e.disabled=!1}}async _loadCards(){const e=++this._generation,t=this._config,i=this.shadowRoot.querySelector("main");try{const s=customElements.get("wiser-schedule-card");if(1!==s?.panelApiVersion)throw new Error("Wiser Schedules needs its matching schedule card build. Update the card resource and refresh the browser.");if(e!==this._generation)return;const o=t.hubs.map(e=>{const t=document.createElement("wiser-schedule-card");return t.setConfig(this._cardConfig(e)),t.hass=this._hass,t});this._cards=o,i.replaceChildren(...o),this.shadowRoot.getElementById("settings").disabled=!1}catch(t){if(e!==this._generation)return;this._cards=[],this.shadowRoot.getElementById("settings").disabled=!0;const s=document.createElement("p");s.setAttribute("role","alert"),s.textContent=t.message||"Unable to load Wiser schedules. Please try again.";const o=document.createElement("ha-button");o.textContent="Retry",o.addEventListener("click",()=>this._loadCards()),i.replaceChildren(s,o),console.error("Unable to load Wiser schedules",t)}}}customElements.get("wiser-schedules-panel")||customElements.define("wiser-schedules-panel",oi),console.info(`%c WISER-SCHEDULE-CARD \n%c ${He("common.version")} ${ye} `,"color: orange; font-weight: bold; background: black","color: white; font-weight: bold; background: dimgray"),window.customCards=window.customCards||[],window.customCards.some(e=>"wiser-schedule-card"===e.type)||window.customCards.push({type:"wiser-schedule-card",name:"Wiser Schedule Card",description:"A card to manage Wiser schedules",preview:!1});let ai=class extends le{constructor(){super(...arguments),this._view=fe.Overview,this.component_loaded=!1,this._schedule_id=0,this._schedule_type="heating",this._homeView="schedules",this._target_type="heating",this._returnView=fe.Overview}static async getConfigElement(){return document.createElement("wiser-schedule-card-editor")}static getStubConfig(){return{}}setConfig(e){var t;if(!e)throw new Error(He("common.invalid_configuration"));e.test_gui&&function(){var e=document.querySelector("home-assistant");if(e=(e=(e=(e=(e=(e=(e=(e=e&&e.shadowRoot)&&e.querySelector("home-assistant-main"))&&e.shadowRoot)&&e.querySelector("app-drawer-layout partial-panel-resolver"))&&e.shadowRoot||e)&&e.querySelector("ha-panel-lovelace"))&&e.shadowRoot)&&e.querySelector("hui-root")){var t=e.lovelace;return t.current_view=e.___curView,t}return null}().setEditMode(!0),this.config=Object.assign(Object.assign({name:"Wiser Schedule"},e),{home_screen:"devices"===e.home_screen?"overview":null!==(t=e.home_screen)&&void 0!==t?t:"schedules"})}set hass(e){this._hass=e}processConfigSchedule(){var e,t,i;(null===(e=this.config)||void 0===e?void 0:e.selected_schedule)?(this._schedule_type=null===(t=this.config)||void 0===t?void 0:t.selected_schedule.split("|")[0],this._schedule_id=parseInt(null===(i=this.config)||void 0===i?void 0:i.selected_schedule.split("|")[1]),this._view=fe.ScheduleEdit):(this._schedule_type="",this._schedule_id=0,this._view=fe.Overview)}getCardSize(){return 9}willUpdate(e){var t,i,s;if(e.has("config"))this.style.removeProperty("--wiser-view-min-height"),this._returnView=fe.Overview,this._homeView=(null===(t=this.config)||void 0===t?void 0:t.home_screen)||"schedules",this.processConfigSchedule();else if(e.has("_view")){const e=this.renderRoot.querySelector(".card-content");e&&this.style.setProperty("--wiser-view-min-height",`${e.getBoundingClientRect().height}px`)}this.component_loaded=null!==(s=null===(i=this._hass)||void 0===i?void 0:i.config.components.includes("wiser"))&&void 0!==s&&s}_viewReady(e){const t=this.renderRoot.querySelector(".card-content");e.target===(null==t?void 0:t.firstElementChild)&&this.style.removeProperty("--wiser-view-min-height")}render(){if(!this._hass||!this.config)return W``;const e=`${this.config.hide_card_borders?"border-width: 0px;":""}${this.config.hide_card_background?"background: transparent; box-shadow: none; backdrop-filter: none;":""}`;return this.component_loaded?this._view===fe.Overview&&"schedules"===this._homeView?W` -
{"schedules"!==e.detail&&"overview"!==e.detail||(this._homeView=e.detail)}} - > - {this._schedule_id=e.detail.Id,this._schedule_type=e.detail.Type,this._returnView=fe.Overview,this._view=fe.ScheduleEdit}} - >
`:this._view===fe.Overview||this._view===fe.RoomSchedule?W` -
{"schedules"!==e.detail&&"overview"!==e.detail||(this._homeView=e.detail)}} - > - {this._created_schedule=void 0}} - @roomClick=${e=>{this._room_id=e.detail.id,this._target_type=e.detail.kind,this._view=fe.RoomSchedule}} - @roomsBack=${()=>{this._view=fe.Overview}} - @scheduleAction=${e=>{this._schedule_id=e.detail.schedule_id,this._schedule_type=e.detail.schedule_type,this._returnView=fe.RoomSchedule,this._view="rename"===e.detail.action?fe.ScheduleRename:fe.ScheduleCopy}} - @addScheduleClick=${this._addScheduleClick} - > - -
-
`:this._view==fe.ScheduleEdit&&this._schedule_id?W` - -
{"schedules"!==e.detail&&"overview"!==e.detail||(this._homeView=e.detail)}} - > - -
-
- `:this._view==fe.ScheduleAdd?W` - -
{"schedules"!==e.detail&&"overview"!==e.detail||(this._homeView=e.detail)}} - > - -
-
- `:this._view==fe.ScheduleCopy?W` - -
{"schedules"!==e.detail&&"overview"!==e.detail||(this._homeView=e.detail)}} - > - -
-
- `:this._view==fe.ScheduleRename?W` - -
{"schedules"!==e.detail&&"overview"!==e.detail||(this._homeView=e.detail)}} - > - -
-
- `:W``:W`
${He("common.integration_unavailable")}
`}_addScheduleClick(){this._returnView=this._view,this._view=fe.ScheduleAdd}_renameClick(){this._view=fe.ScheduleRename}_editClick(){this._view=fe.ScheduleEdit}_copyClick(){this._view=fe.ScheduleCopy}_backClick(e){e.detail?this._view=e.detail===fe.ScheduleEdit&&this._returnView===fe.RoomSchedule?fe.RoomSchedule:e.detail:this._view=this._returnView}_scheduleDeleted(){this._view=this._returnView}_scheduleAdded(e){var t;if(this._created_schedule=e.detail,"schedules"===(null===(t=this.config)||void 0===t?void 0:t.home_screen)&&e.detail)return this._schedule_id=e.detail.Id,this._schedule_type=e.detail.Type,void(this._view=fe.ScheduleEdit);this._view=this._returnView}_scheduleCopied(){this._view=this._returnView===fe.RoomSchedule?fe.RoomSchedule:fe.ScheduleEdit}_scheduleRenamed(){this._view=this._returnView===fe.RoomSchedule?fe.RoomSchedule:fe.ScheduleEdit}};ai.panelApiVersion=1,ai.styles=n` - :host { - font-size: calc(14px + 1pt); - --mdc-typography-body1-font-size: calc(16px + 1pt); - --mdc-typography-subtitle1-font-size: calc(16px + 1pt); - --ha-font-size-m: calc(14px + 1pt); - display: block; - color: var(--primary-text-color); - } - ha-card { - overflow: hidden; - } - .card-header { - display: flex; - align-items: center; - gap: 12px; - min-height: 44px; - padding: 22px 20px 20px; - } - .brand-header { - display: flex; - align-items: center; - gap: 14px; - margin: 0; - min-width: 0; - line-height: 1.2; - } - .brand-name { - flex-shrink: 0; - color: var(--wiser-brand-color, #279f43); - font-family: 'Arial Rounded MT Bold', 'Trebuchet MS', sans-serif; - font-size: calc(32px + 1pt); - font-weight: 700; - letter-spacing: -1.5px; - } - .brand-title { - min-width: 0; - padding-inline-start: 14px; - border-inline-start: 1px solid var(--divider-color, #ddd); - color: var(--primary-text-color); - font-size: calc(15px + 1pt); - font-weight: 500; - line-height: 1.4; - overflow-wrap: anywhere; - } - .card-content { - box-sizing: border-box; - min-height: var(--wiser-view-min-height, 0px); - padding: 22px 20px 20px; - } - .status { - padding: 20px; - color: var(--secondary-text-color); - } - @media (max-width: 400px) { - .card-header { - padding: 18px 12px; - } - .brand-header { - gap: 12px; - } - .brand-title { - padding-inline-start: 12px; - } - .card-content { - padding: 18px 12px 12px; - } - } - `,e([pe({attribute:!1})],ai.prototype,"_hass",void 0),e([ue()],ai.prototype,"config",void 0),e([ue()],ai.prototype,"_view",void 0),e([ue()],ai.prototype,"component_loaded",void 0),e([ue()],ai.prototype,"_schedule_id",void 0),e([ue()],ai.prototype,"_schedule_type",void 0),e([ue()],ai.prototype,"_room_id",void 0),e([ue()],ai.prototype,"_homeView",void 0),e([ue()],ai.prototype,"_target_type",void 0),e([ue()],ai.prototype,"_created_schedule",void 0),ai=e([t("wiser-schedule-card")],ai);export{ai as WiserScheduleCard}; diff --git a/custom_components/wiser/frontend/wiser-zigbee-card.js b/custom_components/wiser/frontend/wiser-zigbee-card.js deleted file mode 100644 index 1983f24a..00000000 --- a/custom_components/wiser/frontend/wiser-zigbee-card.js +++ /dev/null @@ -1,658 +0,0 @@ -/*! WISER-CARD-VERSION wiser-zigbee-card 3.0.0-dev.84 */ -var wiserzigbeecard=function(t){"use strict";function e(t,e,i,n){var o,r=arguments.length,s=r<3?e:null===n?n=Object.getOwnPropertyDescriptor(e,i):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,i,n);else for(var a=t.length-1;a>=0;a--)(o=t[a])&&(s=(r<3?o(s):r>3?o(e,i,s):o(e,i))||s);return r>3&&s&&Object.defineProperty(e,i,s),s}let i;"function"==typeof SuppressedError&&SuppressedError;const n="wiser-zigbee:copied-settings";function o(t){i=t;try{void 0===t?sessionStorage.removeItem(n):sessionStorage.setItem(n,t)}catch(t){}} -/*! js-yaml 4.1.0 https://github.com/nodeca/js-yaml @license MIT */ -function r(t){return null==t}var s=function(t,e){var i,n="";for(i=0;ia&&(e=n-a+(r=" ... ").length),i-n>a&&(i=n+a-(s=" ...").length),{str:r+t.slice(e,i).replace(/\t/g,"→")+s,pos:n-e+r.length}}function p(t,e){return h.repeat(" ",e-t.length)+t}var v=function(t,e){if(e=Object.create(e||null),!t.buffer)return null;e.maxLength||(e.maxLength=79),"number"!=typeof e.indent&&(e.indent=1),"number"!=typeof e.linesBefore&&(e.linesBefore=3),"number"!=typeof e.linesAfter&&(e.linesAfter=2);for(var i,n=/\r?\n|\r|\0/g,o=[0],r=[],s=-1;i=n.exec(t.buffer);)r.push(i.index),o.push(i.index+i[0].length),t.position<=i.index&&s<0&&(s=o.length-2);s<0&&(s=o.length-1);var a,l,c="",d=Math.min(t.line+e.linesAfter,r.length).toString().length,u=e.maxLength-(e.indent+d+3);for(a=1;a<=e.linesBefore&&!(s-a<0);a++)l=f(t.buffer,o[s-a],r[s-a],t.position-(o[s]-o[s-a]),u),c=h.repeat(" ",e.indent)+p((t.line-a+1).toString(),d)+" | "+l.str+"\n"+c;for(l=f(t.buffer,o[s],r[s],t.position,u),c+=h.repeat(" ",e.indent)+p((t.line+1).toString(),d)+" | "+l.str+"\n",c+=h.repeat("-",e.indent+d+3+l.pos)+"^\n",a=1;a<=e.linesAfter&&!(s+a>=r.length);a++)l=f(t.buffer,o[s+a],r[s+a],t.position-(o[s]-o[s+a]),u),c+=h.repeat(" ",e.indent)+p((t.line+a+1).toString(),d)+" | "+l.str+"\n";return c.replace(/\n$/,"")},g=["kind","multi","resolve","construct","instanceOf","predicate","represent","representName","defaultStyle","styleAliases"],y=["scalar","sequence","mapping"];var m=function(t,e){if(e=e||{},Object.keys(e).forEach((function(e){if(-1===g.indexOf(e))throw new u('Unknown option "'+e+'" is met in definition of "'+t+'" YAML type.')})),this.options=e,this.tag=t,this.kind=e.kind||null,this.resolve=e.resolve||function(){return!0},this.construct=e.construct||function(t){return t},this.instanceOf=e.instanceOf||null,this.predicate=e.predicate||null,this.represent=e.represent||null,this.representName=e.representName||null,this.defaultStyle=e.defaultStyle||null,this.multi=e.multi||!1,this.styleAliases=function(t){var e={};return null!==t&&Object.keys(t).forEach((function(i){t[i].forEach((function(t){e[String(t)]=i}))})),e}(e.styleAliases||null),-1===y.indexOf(this.kind))throw new u('Unknown kind "'+this.kind+'" is specified for "'+t+'" YAML type.')};function b(t,e){var i=[];return t[e].forEach((function(t){var e=i.length;i.forEach((function(i,n){i.tag===t.tag&&i.kind===t.kind&&i.multi===t.multi&&(e=n)})),i[e]=t})),i}function w(t){return this.extend(t)}w.prototype.extend=function(t){var e=[],i=[];if(t instanceof m)i.push(t);else if(Array.isArray(t))i=i.concat(t);else{if(!t||!Array.isArray(t.implicit)&&!Array.isArray(t.explicit))throw new u("Schema.extend argument should be a Type, [ Type ], or a schema definition ({ implicit: [...], explicit: [...] })");t.implicit&&(e=e.concat(t.implicit)),t.explicit&&(i=i.concat(t.explicit))}e.forEach((function(t){if(!(t instanceof m))throw new u("Specified list of YAML types (or a single Type object) contains a non-Type object.");if(t.loadKind&&"scalar"!==t.loadKind)throw new u("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.");if(t.multi)throw new u("There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.")})),i.forEach((function(t){if(!(t instanceof m))throw new u("Specified list of YAML types (or a single Type object) contains a non-Type object.")}));var n=Object.create(w.prototype);return n.implicit=(this.implicit||[]).concat(e),n.explicit=(this.explicit||[]).concat(i),n.compiledImplicit=b(n,"implicit"),n.compiledExplicit=b(n,"explicit"),n.compiledTypeMap=function(){var t,e,i={scalar:{},sequence:{},mapping:{},fallback:{},multi:{scalar:[],sequence:[],mapping:[],fallback:[]}};function n(t){t.multi?(i.multi[t.kind].push(t),i.multi.fallback.push(t)):i[t.kind][t.tag]=i.fallback[t.tag]=t}for(t=0,e=arguments.length;t=0?"0b"+t.toString(2):"-0b"+t.toString(2).slice(1)},octal:function(t){return t>=0?"0o"+t.toString(8):"-0o"+t.toString(8).slice(1)},decimal:function(t){return t.toString(10)},hexadecimal:function(t){return t>=0?"0x"+t.toString(16).toUpperCase():"-0x"+t.toString(16).toUpperCase().slice(1)}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}}),B=new RegExp("^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");var z=/^[-+]?[0-9]+e/;var P=new m("tag:yaml.org,2002:float",{kind:"scalar",resolve:function(t){return null!==t&&!(!B.test(t)||"_"===t[t.length-1])},construct:function(t){var e,i;return i="-"===(e=t.replace(/_/g,"").toLowerCase())[0]?-1:1,"+-".indexOf(e[0])>=0&&(e=e.slice(1)),".inf"===e?1===i?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:".nan"===e?NaN:i*parseFloat(e,10)},predicate:function(t){return"[object Number]"===Object.prototype.toString.call(t)&&(t%1!=0||h.isNegativeZero(t))},represent:function(t,e){var i;if(isNaN(t))switch(e){case"lowercase":return".nan";case"uppercase":return".NAN";case"camelcase":return".NaN"}else if(Number.POSITIVE_INFINITY===t)switch(e){case"lowercase":return".inf";case"uppercase":return".INF";case"camelcase":return".Inf"}else if(Number.NEGATIVE_INFINITY===t)switch(e){case"lowercase":return"-.inf";case"uppercase":return"-.INF";case"camelcase":return"-.Inf"}else if(h.isNegativeZero(t))return"-0.0";return i=t.toString(10),z.test(i)?i.replace("e",".e"):i},defaultStyle:"lowercase"}),F=x.extend({implicit:[I,S,R,P]}),T=F,N=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),j=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$");var L=new m("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:function(t){return null!==t&&(null!==N.exec(t)||null!==j.exec(t))},construct:function(t){var e,i,n,o,r,s,a,l,h=0,c=null;if(null===(e=N.exec(t))&&(e=j.exec(t)),null===e)throw new Error("Date resolve error");if(i=+e[1],n=+e[2]-1,o=+e[3],!e[4])return new Date(Date.UTC(i,n,o));if(r=+e[4],s=+e[5],a=+e[6],e[7]){for(h=e[7].slice(0,3);h.length<3;)h+="0";h=+h}return e[9]&&(c=6e4*(60*+e[10]+ +(e[11]||0)),"-"===e[9]&&(c=-c)),l=new Date(Date.UTC(i,n,o,r,s,a,h)),c&&l.setTime(l.getTime()-c),l},instanceOf:Date,represent:function(t){return t.toISOString()}});var U=new m("tag:yaml.org,2002:merge",{kind:"scalar",resolve:function(t){return"<<"===t||null===t}}),Q="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r";var H=new m("tag:yaml.org,2002:binary",{kind:"scalar",resolve:function(t){if(null===t)return!1;var e,i,n=0,o=t.length,r=Q;for(i=0;i64)){if(e<0)return!1;n+=6}return n%8==0},construct:function(t){var e,i,n=t.replace(/[\r\n=]/g,""),o=n.length,r=Q,s=0,a=[];for(e=0;e>16&255),a.push(s>>8&255),a.push(255&s)),s=s<<6|r.indexOf(n.charAt(e));return 0===(i=o%4*6)?(a.push(s>>16&255),a.push(s>>8&255),a.push(255&s)):18===i?(a.push(s>>10&255),a.push(s>>2&255)):12===i&&a.push(s>>4&255),new Uint8Array(a)},predicate:function(t){return"[object Uint8Array]"===Object.prototype.toString.call(t)},represent:function(t){var e,i,n="",o=0,r=t.length,s=Q;for(e=0;e>18&63],n+=s[o>>12&63],n+=s[o>>6&63],n+=s[63&o]),o=(o<<8)+t[e];return 0===(i=r%3)?(n+=s[o>>18&63],n+=s[o>>12&63],n+=s[o>>6&63],n+=s[63&o]):2===i?(n+=s[o>>10&63],n+=s[o>>4&63],n+=s[o<<2&63],n+=s[64]):1===i&&(n+=s[o>>2&63],n+=s[o<<4&63],n+=s[64],n+=s[64]),n}}),V=Object.prototype.hasOwnProperty,W=Object.prototype.toString;var G=new m("tag:yaml.org,2002:omap",{kind:"sequence",resolve:function(t){if(null===t)return!0;var e,i,n,o,r,s=[],a=t;for(e=0,i=a.length;e>10),56320+(t-65536&1023))}for(var wt=new Array(256),At=new Array(256),kt=0;kt<256;kt++)wt[kt]=mt(kt)?1:0,At[kt]=mt(kt);function Et(t,e){this.input=t,this.filename=e.filename||null,this.schema=e.schema||J,this.onWarning=e.onWarning||null,this.legacy=e.legacy||!1,this.json=e.json||!1,this.listener=e.listener||null,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=t.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.firstTabInLine=-1,this.documents=[]}function Ct(t,e){var i={name:t.filename,buffer:t.input.slice(0,-1),position:t.position,line:t.line,column:t.position-t.lineStart};return i.snippet=v(i),new u(e,i)}function xt(t,e){throw Ct(t,e)}function It(t,e){t.onWarning&&t.onWarning.call(null,Ct(t,e))}var St={YAML:function(t,e,i){var n,o,r;null!==t.version&&xt(t,"duplication of %YAML directive"),1!==i.length&&xt(t,"YAML directive accepts exactly one argument"),null===(n=/^([0-9]+)\.([0-9]+)$/.exec(i[0]))&&xt(t,"ill-formed argument of the YAML directive"),o=parseInt(n[1],10),r=parseInt(n[2],10),1!==o&&xt(t,"unacceptable YAML version of the document"),t.version=i[0],t.checkLineBreaks=r<2,1!==r&&2!==r&&It(t,"unsupported YAML version of the document")},TAG:function(t,e,i){var n,o;2!==i.length&&xt(t,"TAG directive accepts exactly two arguments"),n=i[0],o=i[1],lt.test(n)||xt(t,"ill-formed tag handle (first argument) of the TAG directive"),X.call(t.tagMap,n)&&xt(t,'there is a previously declared suffix for "'+n+'" tag handle'),ht.test(o)||xt(t,"ill-formed tag prefix (second argument) of the TAG directive");try{o=decodeURIComponent(o)}catch(e){xt(t,"tag prefix is malformed: "+o)}t.tagMap[n]=o}};function Mt(t,e,i,n){var o,r,s,a;if(e1&&(t.result+=h.repeat("\n",e-1))}function Ft(t,e){var i,n,o=t.tag,r=t.anchor,s=[],a=!1;if(-1!==t.firstTabInLine)return!1;for(null!==t.anchor&&(t.anchorMap[t.anchor]=s),n=t.input.charCodeAt(t.position);0!==n&&(-1!==t.firstTabInLine&&(t.position=t.firstTabInLine,xt(t,"tab characters must not be used in indentation")),45===n)&&ft(t.input.charCodeAt(t.position+1));)if(a=!0,t.position++,Bt(t,!0,-1)&&t.lineIndent<=e)s.push(null),n=t.input.charCodeAt(t.position);else if(i=t.line,jt(t,e,tt,!1,!0),s.push(t.result),Bt(t,!0,-1),n=t.input.charCodeAt(t.position),(t.line===i||t.lineIndent>e)&&0!==n)xt(t,"bad indentation of a sequence entry");else if(t.lineIndente?v=1:t.lineIndent===e?v=0:t.lineIndente?v=1:t.lineIndent===e?v=0:t.lineIndente)&&(y&&(s=t.line,a=t.lineStart,l=t.position),jt(t,e,et,!0,o)&&(y?v=t.result:g=t.result),y||(Dt(t,u,f,p,v,g,s,a,l),p=v=g=null),Bt(t,!0,-1),h=t.input.charCodeAt(t.position)),(t.line===r||t.lineIndent>e)&&0!==h)xt(t,"bad indentation of a mapping entry");else if(t.lineIndent=0))break;0===o?xt(t,"bad explicit indentation width of a block scalar; it cannot be less than one"):l?xt(t,"repeat of an indentation width identifier"):(c=e+o-1,l=!0)}if(ut(r)){do{r=t.input.charCodeAt(++t.position)}while(ut(r));if(35===r)do{r=t.input.charCodeAt(++t.position)}while(!dt(r)&&0!==r)}for(;0!==r;){for(Rt(t),t.lineIndent=0,r=t.input.charCodeAt(t.position);(!l||t.lineIndentc&&(c=t.lineIndent),dt(r))d++;else{if(t.lineIndent0){for(o=s,r=0;o>0;o--)(s=vt(a=t.input.charCodeAt(++t.position)))>=0?r=(r<<4)+s:xt(t,"expected hexadecimal character");t.result+=bt(r),t.position++}else xt(t,"unknown escape sequence");i=n=t.position}else dt(a)?(Mt(t,i,n,!0),Pt(t,Bt(t,!1,e)),i=n=t.position):t.position===t.lineStart&&zt(t)?xt(t,"unexpected end of the document within a double quoted scalar"):(t.position++,n=t.position)}xt(t,"unexpected end of the stream within a double quoted scalar")}(t,f)?y=!0:!function(t){var e,i,n;if(42!==(n=t.input.charCodeAt(t.position)))return!1;for(n=t.input.charCodeAt(++t.position),e=t.position;0!==n&&!ft(n)&&!pt(n);)n=t.input.charCodeAt(++t.position);return t.position===e&&xt(t,"name of an alias node must contain at least one character"),i=t.input.slice(e,t.position),X.call(t.anchorMap,i)||xt(t,'unidentified alias "'+i+'"'),t.result=t.anchorMap[i],Bt(t,!0,-1),!0}(t)?function(t,e,i){var n,o,r,s,a,l,h,c,d=t.kind,u=t.result;if(ft(c=t.input.charCodeAt(t.position))||pt(c)||35===c||38===c||42===c||33===c||124===c||62===c||39===c||34===c||37===c||64===c||96===c)return!1;if((63===c||45===c)&&(ft(n=t.input.charCodeAt(t.position+1))||i&&pt(n)))return!1;for(t.kind="scalar",t.result="",o=r=t.position,s=!1;0!==c;){if(58===c){if(ft(n=t.input.charCodeAt(t.position+1))||i&&pt(n))break}else if(35===c){if(ft(t.input.charCodeAt(t.position-1)))break}else{if(t.position===t.lineStart&&zt(t)||i&&pt(c))break;if(dt(c)){if(a=t.line,l=t.lineStart,h=t.lineIndent,Bt(t,!1,-1),t.lineIndent>=e){s=!0,c=t.input.charCodeAt(t.position);continue}t.position=r,t.line=a,t.lineStart=l,t.lineIndent=h;break}}s&&(Mt(t,o,r,!1),Pt(t,t.line-a),o=r=t.position,s=!1),ut(c)||(r=t.position+1),c=t.input.charCodeAt(++t.position)}return Mt(t,o,r,!1),!!t.result||(t.kind=d,t.result=u,!1)}(t,f,_===i)&&(y=!0,null===t.tag&&(t.tag="?")):(y=!0,null===t.tag&&null===t.anchor||xt(t,"alias node should not have any properties")),null!==t.anchor&&(t.anchorMap[t.anchor]=t.result)):0===v&&(y=a&&Ft(t,p))),null===t.tag)null!==t.anchor&&(t.anchorMap[t.anchor]=t.result);else if("?"===t.tag){for(null!==t.result&&"scalar"!==t.kind&&xt(t,'unacceptable node kind for ! tag; it should be "scalar", not "'+t.kind+'"'),l=0,c=t.implicitTypes.length;l"),null!==t.result&&u.kind!==t.kind&&xt(t,"unacceptable node kind for !<"+t.tag+'> tag; it should be "'+u.kind+'", not "'+t.kind+'"'),u.resolve(t.result,t.tag)?(t.result=u.construct(t.result,t.tag),null!==t.anchor&&(t.anchorMap[t.anchor]=t.result)):xt(t,"cannot resolve a node with !<"+t.tag+"> explicit tag")}return null!==t.listener&&t.listener("close",t),null!==t.tag||null!==t.anchor||y}function Lt(t){var e,i,n,o,r=t.position,s=!1;for(t.version=null,t.checkLineBreaks=t.legacy,t.tagMap=Object.create(null),t.anchorMap=Object.create(null);0!==(o=t.input.charCodeAt(t.position))&&(Bt(t,!0,-1),o=t.input.charCodeAt(t.position),!(t.lineIndent>0||37!==o));){for(s=!0,o=t.input.charCodeAt(++t.position),e=t.position;0!==o&&!ft(o);)o=t.input.charCodeAt(++t.position);for(n=[],(i=t.input.slice(e,t.position)).length<1&&xt(t,"directive name must not be less than one character in length");0!==o;){for(;ut(o);)o=t.input.charCodeAt(++t.position);if(35===o){do{o=t.input.charCodeAt(++t.position)}while(0!==o&&!dt(o));break}if(dt(o))break;for(e=t.position;0!==o&&!ft(o);)o=t.input.charCodeAt(++t.position);n.push(t.input.slice(e,t.position))}0!==o&&Rt(t),X.call(St,i)?St[i](t,i,n):It(t,'unknown document directive "'+i+'"')}Bt(t,!0,-1),0===t.lineIndent&&45===t.input.charCodeAt(t.position)&&45===t.input.charCodeAt(t.position+1)&&45===t.input.charCodeAt(t.position+2)?(t.position+=3,Bt(t,!0,-1)):s&&xt(t,"directives end mark is expected"),jt(t,t.lineIndent-1,et,!1,!0),Bt(t,!0,-1),t.checkLineBreaks&&st.test(t.input.slice(r,t.position))&&It(t,"non-ASCII line breaks are interpreted as content"),t.documents.push(t.result),t.position===t.lineStart&&zt(t)?46===t.input.charCodeAt(t.position)&&(t.position+=3,Bt(t,!0,-1)):t.position=55296&&n<=56319&&e+1=56320&&i<=57343?1024*(n-55296)+i-56320+65536:n}function De(t){return/^\n* /.test(t)}var Re=1,Be=2,ze=3,Pe=4,Fe=5;function Te(t,e,i,n,o,r,s,a){var l,h=0,c=null,d=!1,u=!1,f=-1!==n,p=-1,v=function(t){return Ie(t)&&t!==Gt&&!xe(t)&&t!==oe&&t!==le&&t!==re&&t!==ne&&t!==ce&&t!==de&&t!==fe&&t!==ve&&t!==_t&&t!==te&&t!==ie&&t!==Jt&&t!==pe&&t!==se&&t!==ae&&t!==ee&&t!==Xt&&t!==$t&&t!==he&&t!==ue}(Oe(t,0))&&function(t){return!xe(t)&&t!==re}(Oe(t,t.length-1));if(e||s)for(l=0;l=65536?l+=2:l++){if(!Ie(h=Oe(t,l)))return Fe;v=v&&Me(h,c,a),c=h}else{for(l=0;l=65536?l+=2:l++){if((h=Oe(t,l))===qt)d=!0,f&&(u=u||l-p-1>n&&" "!==t[p+1],p=l);else if(!Ie(h))return Fe;v=v&&Me(h,c,a),c=h}u=u||f&&l-p-1>n&&" "!==t[p+1]}return d||u?i>9&&De(t)?Fe:s?r===Ae?Fe:Be:u?Pe:ze:!v||s||o(t)?r===Ae?Fe:Be:Re}function Ne(t,e,i,n,o){t.dump=function(){if(0===e.length)return t.quotingType===Ae?'""':"''";if(!t.noCompatMode&&(-1!==ye.indexOf(e)||me.test(e)))return t.quotingType===Ae?'"'+e+'"':"'"+e+"'";var r=t.indent*Math.max(1,i),s=-1===t.lineWidth?-1:Math.max(Math.min(t.lineWidth,40),t.lineWidth-r),a=n||t.flowLevel>-1&&i>=t.flowLevel;switch(Te(e,a,t.indent,s,(function(e){return function(t,e){var i,n;for(i=0,n=t.implicitTypes.length;i"+je(e,t.indent)+Le(Ee(function(t,e){var i,n,o=/(\n+)([^\n]*)/g,r=(a=t.indexOf("\n"),a=-1!==a?a:t.length,o.lastIndex=a,Ue(t.slice(0,a),e)),s="\n"===t[0]||" "===t[0];var a;for(;n=o.exec(t);){var l=n[1],h=n[2];i=" "===h[0],r+=l+(s||i||""===h?"":"\n")+Ue(h,e),s=i}return r}(e,s),r));case Fe:return'"'+function(t){for(var e,i="",n=0,o=0;o=65536?o+=2:o++)n=Oe(t,o),!(e=ge[n])&&Ie(n)?(i+=t[o],n>=65536&&(i+=t[o+1])):i+=e||be(n);return i}(e)+'"';default:throw new u("impossible error: invalid scalar style")}}()}function je(t,e){var i=De(t)?String(e):"",n="\n"===t[t.length-1];return i+(n&&("\n"===t[t.length-2]||"\n"===t)?"+":n?"":"-")+"\n"}function Le(t){return"\n"===t[t.length-1]?t.slice(0,-1):t}function Ue(t,e){if(""===t||" "===t[0])return t;for(var i,n,o=/ [^ ]/g,r=0,s=0,a=0,l="";i=o.exec(t);)(a=i.index)-r>e&&(n=s>r?s:a,l+="\n"+t.slice(r,n),r=n+1),s=a;return l+="\n",t.length-r>e&&s>r?l+=t.slice(r,s)+"\n"+t.slice(s+1):l+=t.slice(r),l.slice(1)}function Qe(t,e,i,n){var o,r,s,a="",l=t.tag;for(o=0,r=i.length;o tag resolver accepts not "'+l+'" style');n=a.represent[l](e,l)}t.dump=n}return!0}return!1}function Ve(t,e,i,n,o,r,s){t.tag=null,t.dump=i,He(t,i,!1)||He(t,i,!0);var a,l=Vt.call(t.dump),h=n;n&&(n=t.flowLevel<0||t.flowLevel>e);var c,d,f="[object Object]"===l||"[object Array]"===l;if(f&&(d=-1!==(c=t.duplicates.indexOf(i))),(null!==t.tag&&"?"!==t.tag||d||2!==t.indent&&e>0)&&(o=!1),d&&t.usedDuplicates[c])t.dump="*ref_"+c;else{if(f&&d&&!t.usedDuplicates[c]&&(t.usedDuplicates[c]=!0),"[object Object]"===l)n&&0!==Object.keys(t.dump).length?(!function(t,e,i,n){var o,r,s,a,l,h,c="",d=t.tag,f=Object.keys(i);if(!0===t.sortKeys)f.sort();else if("function"==typeof t.sortKeys)f.sort(t.sortKeys);else if(t.sortKeys)throw new u("sortKeys must be a boolean or a function");for(o=0,r=f.length;o1024)&&(t.dump&&qt===t.dump.charCodeAt(0)?h+="?":h+="? "),h+=t.dump,l&&(h+=Ce(t,e)),Ve(t,e+1,a,!0,l)&&(t.dump&&qt===t.dump.charCodeAt(0)?h+=":":h+=": ",c+=h+=t.dump));t.tag=d,t.dump=c||"{}"}(t,e,t.dump,o),d&&(t.dump="&ref_"+c+t.dump)):(!function(t,e,i){var n,o,r,s,a,l="",h=t.tag,c=Object.keys(i);for(n=0,o=c.length;n1024&&(a+="? "),a+=t.dump+(t.condenseFlow?'"':"")+":"+(t.condenseFlow?"":" "),Ve(t,e,s,!1,!1)&&(l+=a+=t.dump));t.tag=h,t.dump="{"+l+"}"}(t,e,t.dump),d&&(t.dump="&ref_"+c+" "+t.dump));else if("[object Array]"===l)n&&0!==t.dump.length?(t.noArrayIndent&&!s&&e>0?Qe(t,e-1,t.dump,o):Qe(t,e,t.dump,o),d&&(t.dump="&ref_"+c+t.dump)):(!function(t,e,i){var n,o,r,s="",a=t.tag;for(n=0,o=i.length;n",t.dump=a+" "+t.dump)}return!0}function We(t,e){var i,n,o=[],r=[];for(Ge(t,o,r),i=0,n=r.length;inull!==t&&"object"==typeof t&&!Array.isArray(t);function Xe(t){if(!Je(t))throw new Error("Invalid layout");const e={};for(const i of["auto_update","map_only","show_device_list","show_labels","magnifier"])if(i in t){if("boolean"!=typeof t[i])throw new Error(`Invalid ${i}`);e[i]=t[i]}if("name"in t){if("string"!=typeof t.name)throw new Error("Invalid name");e.name=t.name}if("map_height"in t){if(null!==t.map_height&&!(Number.isFinite(t.map_height)&&t.map_height>=100&&t.map_height<=2e3))throw new Error("Invalid map height");e.map_height=t.map_height}for(const[i,n]of Object.entries(Ze))if(i in t){if(!n.includes(t[i]))throw new Error(`Invalid ${i}`);e[i]=t[i]}if(!Je(t.layout_data))throw new Error("Missing layout");e.layout_data={};for(const[i,n]of Object.entries(t.layout_data)){if(!(/^-?\d+$/.test(i)&&Je(n)&&Number.isFinite(n.x)&&Number.isFinite(n.y)))throw new Error("Invalid position");e.layout_data[i]={x:n.x,y:n.y}}return e}const _e="wiser-zigbee-magnifier-size",$e="wiser-zigbee-magnifier-zoom";class ti{constructor(){this.zoom=2,this.size=180;try{const t=Number(localStorage.getItem($e));[2,3,4].includes(t)&&(this.zoom=t);const e=Number(localStorage.getItem(_e));e>=100&&e<=360&&(this.size=10*Math.round(e/10))}catch(t){}}setSize(t){if(Number.isFinite(t)){this.size=Math.max(100,Math.min(360,10*Math.round(t/10)));try{localStorage.setItem(_e,String(this.size))}catch(t){}this.refresh()}}setZoom(t){if([2,3,4].includes(t)){this.zoom=t;try{localStorage.setItem($e,String(t))}catch(t){}this.refresh()}}show(t,e){if("touch"===e.pointerType||e.buttons)return void this.hide();const i=t.getBoundingClientRect();this.map=t,this.point={x:(e.clientX-i.left)*t.clientWidth/(i.width||t.clientWidth),y:(e.clientY-i.top)*t.clientHeight/(i.height||t.clientHeight)},this.refresh()}refresh(){this.point&&void 0===this.frame&&(this.frame=requestAnimationFrame((()=>{this.frame=void 0,this.draw()})))}hide(){var t;void 0!==this.frame&&cancelAnimationFrame(this.frame),this.frame=void 0,this.point=void 0,null===(t=this.lens)||void 0===t||t.remove(),this.lens=void 0}draw(){var t;const e=this.map,i=this.point,n=null==e?void 0:e.querySelector("canvas");if(!((null==e?void 0:e.isConnected)&&i&&n&&e.clientWidth&&e.clientHeight))return void this.hide();this.lens||(this.lens=e.ownerDocument.createElement("div"),this.lens.className="map-magnifier",this.lens.setAttribute("aria-hidden","true"),this.lens.append(e.ownerDocument.createElement("canvas"),e.ownerDocument.createElement("div")),e.parentElement.append(this.lens));const o=function(t,e,i,n,o=2,r=180){const s=Math.min(r,i,n);return{size:s,left:Math.max(0,Math.min(i-s,t-s/2)),top:Math.max(0,Math.min(n-s,e-s/2)),imageX:s/2-t*o,imageY:s/2-e*o}}(i.x,i.y,e.clientWidth,e.clientHeight,this.zoom,this.size);this.lens.style.cssText=`left:${o.left}px;top:${o.top}px;width:${o.size}px;height:${o.size}px`;const r=this.lens.firstElementChild,s=(null===(t=e.ownerDocument.defaultView)||void 0===t?void 0:t.devicePixelRatio)||1;r.width=Math.round(o.size*s),r.height=Math.round(o.size*s),r.style.width=r.style.height=`${o.size}px`;const a=r.getContext("2d");if(!a)return;a.scale(s,s),a.drawImage(n,o.imageX,o.imageY,e.clientWidth*this.zoom,e.clientHeight*this.zoom);const l=this.lens.lastElementChild;l.className="magnifier-area-icons",l.style.transform=`translate(${o.imageX}px, ${o.imageY}px) scale(${this.zoom})`,l.replaceChildren(),e.parentElement.querySelectorAll(".area-icons ha-icon").forEach((t=>{const e=t.cloneNode(!1);e.icon=t.icon,l.append(e)}))}}function ei(t){var e,i;const n=Object.assign({},t);return(void 0!==n.layout_orientation&&n.layout_orientation!==(null!==(e=n.orientation)&&void 0!==e?e:"vertical")||void 0!==n.layout_group_by&&n.layout_group_by!==(null!==(i=n.group_by)&&void 0!==i?i:"none"))&&delete n.layout_data,delete n.show_layout_export,delete n.layout_orientation,delete n.layout_group_by,n}const ii=t=>JSON.stringify(t,((t,e)=>e&&"object"==typeof e&&!Array.isArray(e)?Object.keys(e).sort().reduce(((t,i)=>(t[i]=e[i],t)),{}):e));async function ni(t,e,i){var n,o,r,s,a,l;let h,c=t;for(;c;){if("wiser-zigbee-panel"===c.localName&&c.saveZigbeeCardConfig)return c.saveZigbeeCardConfig(t,ei(Object.assign(Object.assign({},e),i)));if(null===(n=c.lovelace)||void 0===n?void 0:n.saveConfig){h=c.lovelace;break}c=null!==(o=c.parentElement)&&void 0!==o?o:null===(r=c.getRootNode)||void 0===r?void 0:r.call(c).host}const d=null!==(s=null==h?void 0:h.rawConfig)&&void 0!==s?s:null==h?void 0:h.config;if(!h||"storage"!==h.mode||!d||d.strategy)throw new Error("Dashboard configuration is not editable");const u=[],f=(t,i)=>{if(t&&"object"==typeof t){t.type===e.type&&ii(t)===ii(e)&&u.push({value:t,path:i});for(const[e,n]of Object.entries(t))f(n,[...i,e])}};f(d,[]);const p=u.filter((t=>t.value===e)),v=p.length?p:u;if(1!==v.length)throw new Error("Cannot uniquely identify this card");const g=JSON.parse(JSON.stringify(d)),y=v[0].path;let m=g;for(const t of y.slice(0,-1))m=m[t];const b=ei(Object.assign(Object.assign({},v[0].value),i));m[y[y.length-1]]=b;const w=function(t){if(!t)return()=>{};const{scrollX:e,scrollY:i}=t,n=t.location.href;let o=!1,r=0,s=Date.now()+2500;const a=["wheel","touchstart","pointerdown","keydown","popstate","hashchange"],l=()=>{o=!0,t.cancelAnimationFrame(r),a.forEach((e=>t.removeEventListener(e,l,!0)))},h=()=>{o||Date.now()>=s||t.location.href!==n?l():(t.scrollX===e&&t.scrollY===i||t.scrollTo({left:e,top:i,behavior:"instant"}),r=t.requestAnimationFrame(h))};return a.forEach((e=>t.addEventListener(e,l,{capture:!0,passive:!0}))),r=t.requestAnimationFrame(h),()=>{s=Math.min(s,Date.now()+500)}}(null!==(l=null===(a=t.ownerDocument)||void 0===a?void 0:a.defaultView)&&void 0!==l?l:null);try{await h.saveConfig(g)}finally{w()}return b}const oi=new Map,ri=t=>t.replace(/&/g,"&").replace(/"/g,""").replace(/`:"";o="data:image/svg+xml,"+encodeURIComponent(`${r}`),oi.set(n,o)}return o}function ai(t){const e=t.match(/^([\s\S]*?)\n\s*\(([\s\S]*)\)\s*$/);if(!e)return t.replace(/\n/g," ").trim();const i=e[1].trim(),n=e[2].trim();return!n||/^no room$/i.test(n)?i:n}function li(t,e,i){var n,o;const r=new Map;for(const e of t.filter((t=>"Controller"!==t.group))){const t=null!==(n=e.area_id)&&void 0!==n?n:"";r.set(t,[...null!==(o=r.get(t))&&void 0!==o?o:[],e])}const s=t=>{var e;return null!==(e=null==i?void 0:i(t))&&void 0!==e?e:{left:Math.min(...t.map((t=>t.x-Math.max(40,4.5*t.label.length))))-18,right:Math.max(...t.map((t=>t.x+Math.max(40,4.5*t.label.length))))+18,top:Math.min(...t.map((t=>t.y-32)))-18,bottom:Math.max(...t.map((t=>t.y+60)))+18}},a=(t,e)=>Math.max(0,Math.min(t.right,e.right)-Math.max(t.left,e.left))*Math.max(0,Math.min(t.bottom,e.bottom)-Math.max(t.top,e.top)),l=new Map(t.map((t=>[t.id,{x:t.x,y:t.y}]))),h=[...r.values()];if(!t.length)return;const c=h.map(s);if(!c.length)return;const d=c.some(((t,e)=>c.slice(e+1).some((e=>a(t,e)>0)))),u=Math.min(...c.map((t=>t.left))),f=Math.max(...c.map((t=>t.right))),p=Math.min(...c.map((t=>t.top))),v=Math.max(...c.map((t=>t.bottom))),g=Math.max(480,Math.min(1200,Math.hypot(f-u,v-p)));for(let i=0;i<12;i++){let i=!1;for(const n of h){if(n.some((t=>e.has(t.id))))continue;const o=h.filter((t=>t!==n)).map(s),r=s(n),c=t=>o.reduce(((e,i)=>e+a(t,i)),0),u=t=>{const e=[...o,t];return(Math.max(...e.map((t=>t.right)))-Math.min(...e.map((t=>t.left))))*(Math.max(...e.map((t=>t.bottom)))-Math.min(...e.map((t=>t.top))))};let f=c(r),p=u(r),v={x:0,y:0};for(const e of o.filter((t=>d||a(r,t)>0))){const i=[{x:e.left-r.right-16,y:0},{x:e.right-r.left+16,y:0},{x:0,y:e.top-r.bottom-16},{x:0,y:e.bottom-r.top+16},{x:e.right-r.left+16,y:e.top-r.bottom-16},{x:e.left-r.right-16,y:e.top-r.bottom-16},{x:e.right-r.left+16,y:e.bottom-r.top+16},{x:e.left-r.right-16,y:e.bottom-r.top+16}].sort(((t,e)=>Math.hypot(t.x,t.y)-Math.hypot(e.x,e.y)));for(const e of i){if(n.some((t=>Math.hypot(t.x+e.x-l.get(t.id).x,t.y+e.y-l.get(t.id).y)>g)))continue;const i={left:r.left+e.x,right:r.right+e.x,top:r.top+e.y,bottom:r.bottom+e.y};if(t.some((t=>"Controller"===t.group&&a(i,s([t]))>0)))continue;const o=c(i),h=u(i);(ohi(e,!0,t))).join("|")} -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */const di=window,ui=di.ShadowRoot&&(void 0===di.ShadyCSS||di.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,fi=Symbol(),pi=new WeakMap;let vi=class{constructor(t,e,i){if(this._$cssResult$=!0,i!==fi)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(ui&&void 0===t){const i=void 0!==e&&1===e.length;i&&(t=pi.get(e)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&pi.set(e,t))}return t}toString(){return this.cssText}};const gi=ui?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new vi("string"==typeof t?t:t+"",void 0,fi))(e)})(t):t -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */;var yi;const mi=window,bi=mi.trustedTypes,wi=bi?bi.emptyScript:"",Ai=mi.reactiveElementPolyfillSupport,ki={toAttribute(t,e){switch(e){case Boolean:t=t?wi: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}},Ei=(t,e)=>e!==t&&(e==e||t==t),Ci={attribute:!0,type:String,converter:ki,reflect:!1,hasChanged:Ei},xi="finalized";let Ii=class extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(t){var e;this.finalize(),(null!==(e=this.h)&&void 0!==e?e:this.h=[]).push(t)}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach(((e,i)=>{const n=this._$Ep(i,e);void 0!==n&&(this._$Ev.set(n,i),t.push(n))})),t}static createProperty(t,e=Ci){if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){const i="symbol"==typeof t?Symbol():"__"+t,n=this.getPropertyDescriptor(t,i,e);void 0!==n&&Object.defineProperty(this.prototype,t,n)}}static getPropertyDescriptor(t,e,i){return{get(){return this[e]},set(n){const o=this[t];this[e]=n,this.requestUpdate(t,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||Ci}static finalize(){if(this.hasOwnProperty(xi))return!1;this[xi]=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),void 0!==t.h&&(this.h=[...t.h]),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,e=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const i of e)this.createProperty(i,t[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}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(gi(t))}else void 0!==t&&e.push(gi(t));return e}static _$Ep(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}_$Eu(){var t;this._$E_=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach((t=>t(this)))}addController(t){var e,i;(null!==(e=this._$ES)&&void 0!==e?e:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(i=t.hostConnected)||void 0===i||i.call(t))}removeController(t){var e;null===(e=this._$ES)||void 0===e||e.splice(this._$ES.indexOf(t)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach(((t,e)=>{this.hasOwnProperty(e)&&(this._$Ei.set(e,this[e]),delete this[e])}))}createRenderRoot(){var t;const e=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return((t,e)=>{ui?t.adoptedStyleSheets=e.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet)):e.forEach((e=>{const i=document.createElement("style"),n=di.litNonce;void 0!==n&&i.setAttribute("nonce",n),i.textContent=e.cssText,t.appendChild(i)}))})(e,this.constructor.elementStyles),e}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)}))}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)}))}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$EO(t,e,i=Ci){var n;const o=this.constructor._$Ep(t,i);if(void 0!==o&&!0===i.reflect){const r=(void 0!==(null===(n=i.converter)||void 0===n?void 0:n.toAttribute)?i.converter:ki).toAttribute(e,i.type);this._$El=t,null==r?this.removeAttribute(o):this.setAttribute(o,r),this._$El=null}}_$AK(t,e){var i;const n=this.constructor,o=n._$Ev.get(t);if(void 0!==o&&this._$El!==o){const t=n.getPropertyOptions(o),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(i=t.converter)||void 0===i?void 0:i.fromAttribute)?t.converter:ki;this._$El=o,this[o]=r.fromAttribute(e,t.type),this._$El=null}}requestUpdate(t,e,i){let n=!0;void 0!==t&&(((i=i||this.constructor.getPropertyOptions(t)).hasChanged||Ei)(this[t],e)?(this._$AL.has(t)||this._$AL.set(t,e),!0===i.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,i))):n=!1),!this.isUpdatePending&&n&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach(((t,e)=>this[e]=t)),this._$Ei=void 0);let e=!1;const i=this._$AL;try{e=this.shouldUpdate(i),e?(this.willUpdate(i),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)})),this.update(i)):this._$Ek()}catch(t){throw e=!1,this._$Ek(),t}e&&this._$AE(i)}willUpdate(t){}_$AE(t){var e;null===(e=this._$ES)||void 0===e||e.forEach((t=>{var e;return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)})),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return!0}update(t){void 0!==this._$EC&&(this._$EC.forEach(((t,e)=>this._$EO(e,this[e],t))),this._$EC=void 0),this._$Ek()}updated(t){}firstUpdated(t){}}; -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -var Si;Ii[xi]=!0,Ii.elementProperties=new Map,Ii.elementStyles=[],Ii.shadowRootOptions={mode:"open"},null==Ai||Ai({ReactiveElement:Ii}),(null!==(yi=mi.reactiveElementVersions)&&void 0!==yi?yi:mi.reactiveElementVersions=[]).push("1.6.3");const Mi=window,Oi=Mi.trustedTypes,Di=Oi?Oi.createPolicy("lit-html",{createHTML:t=>t}):void 0,Ri="$lit$",Bi=`lit$${(Math.random()+"").slice(9)}$`,zi="?"+Bi,Pi=`<${zi}>`,Fi=document,Ti=()=>Fi.createComment(""),Ni=t=>null===t||"object"!=typeof t&&"function"!=typeof t,ji=Array.isArray,Li="[ \t\n\f\r]",Ui=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Qi=/-->/g,Hi=/>/g,Vi=RegExp(`>|${Li}(?:([^\\s"'>=/]+)(${Li}*=${Li}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),Wi=/'/g,Gi=/"/g,Ki=/^(?:script|style|textarea|title)$/i,qi=(t=>(e,...i)=>({_$litType$:t,strings:e,values:i}))(1),Yi=Symbol.for("lit-noChange"),Zi=Symbol.for("lit-nothing"),Ji=new WeakMap,Xi=Fi.createTreeWalker(Fi,129,null,!1);function _i(t,e){if(!Array.isArray(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==Di?Di.createHTML(e):e}const $i=(t,e)=>{const i=t.length-1,n=[];let o,r=2===e?"":"",s=Ui;for(let e=0;e"===l[0]?(s=null!=o?o:Ui,h=-1):void 0===l[1]?h=-2:(h=s.lastIndex-l[2].length,a=l[1],s=void 0===l[3]?Vi:'"'===l[3]?Gi:Wi):s===Gi||s===Wi?s=Vi:s===Qi||s===Hi?s=Ui:(s=Vi,o=void 0);const d=s===Vi&&t[e+1].startsWith("/>")?" ":"";r+=s===Ui?i+Pi:h>=0?(n.push(a),i.slice(0,h)+Ri+i.slice(h)+Bi+d):i+Bi+(-2===h?(n.push(void 0),e):d)}return[_i(t,r+(t[i]||"")+(2===e?"":"")),n]};class tn{constructor({strings:t,_$litType$:e},i){let n;this.parts=[];let o=0,r=0;const s=t.length-1,a=this.parts,[l,h]=$i(t,e);if(this.el=tn.createElement(l,i),Xi.currentNode=this.el.content,2===e){const t=this.el.content,e=t.firstChild;e.remove(),t.append(...e.childNodes)}for(;null!==(n=Xi.nextNode())&&a.length0){n.textContent=Oi?Oi.emptyScript:"";for(let i=0;iji(t)||"function"==typeof(null==t?void 0: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!==Zi&&Ni(this._$AH)?this._$AA.nextSibling.data=t:this.$(Fi.createTextNode(t)),this._$AH=t}g(t){var e;const{values:i,_$litType$:n}=t,o="number"==typeof n?this._$AC(t):(void 0===n.el&&(n.el=tn.createElement(_i(n.h,n.h[0]),this.options)),n);if((null===(e=this._$AH)||void 0===e?void 0:e._$AD)===o)this._$AH.v(i);else{const t=new nn(o,this),e=t.u(this.options);t.v(i),this.$(e),this._$AH=t}}_$AC(t){let e=Ji.get(t.strings);return void 0===e&&Ji.set(t.strings,e=new tn(t)),e}T(t){ji(this._$AH)||(this._$AH=[],this._$AR());const e=this._$AH;let i,n=0;for(const o of t)n===e.length?e.push(i=new on(this.k(Ti()),this.k(Ti()),this,this.options)):i=e[n],i._$AI(o),n++;n2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=Zi}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(t,e=this,i,n){const o=this.strings;let r=!1;if(void 0===o)t=en(this,t,e,0),r=!Ni(t)||t!==this._$AH&&t!==Yi,r&&(this._$AH=t);else{const n=t;let s,a;for(t=o[0],s=0;snew gn("string"==typeof t?t:t+"",void 0,pn),mn=(t,...e)=>{const i=1===t.length?t[0]:e.reduce(((e,i,n)=>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[n+1]),t[0]);return new gn(i,t,pn)},bn=fn?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return yn(e)})(t):t -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */;var wn;const An=window,kn=An.trustedTypes,En=kn?kn.emptyScript:"",Cn=An.reactiveElementPolyfillSupport,xn={toAttribute(t,e){switch(e){case Boolean:t=t?En: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}},In=(t,e)=>e!==t&&(e==e||t==t),Sn={attribute:!0,type:String,converter:xn,reflect:!1,hasChanged:In},Mn="finalized";class On extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(t){var e;this.finalize(),(null!==(e=this.h)&&void 0!==e?e:this.h=[]).push(t)}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach(((e,i)=>{const n=this._$Ep(i,e);void 0!==n&&(this._$Ev.set(n,i),t.push(n))})),t}static createProperty(t,e=Sn){if(e.state&&(e.attribute=!1),this.finalize(),this.elementProperties.set(t,e),!e.noAccessor&&!this.prototype.hasOwnProperty(t)){const i="symbol"==typeof t?Symbol():"__"+t,n=this.getPropertyDescriptor(t,i,e);void 0!==n&&Object.defineProperty(this.prototype,t,n)}}static getPropertyDescriptor(t,e,i){return{get(){return this[e]},set(n){const o=this[t];this[e]=n,this.requestUpdate(t,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||Sn}static finalize(){if(this.hasOwnProperty(Mn))return!1;this[Mn]=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),void 0!==t.h&&(this.h=[...t.h]),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,e=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const i of e)this.createProperty(i,t[i])}return this.elementStyles=this.finalizeStyles(this.styles),!0}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(bn(t))}else void 0!==t&&e.push(bn(t));return e}static _$Ep(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}_$Eu(){var t;this._$E_=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach((t=>t(this)))}addController(t){var e,i;(null!==(e=this._$ES)&&void 0!==e?e:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(i=t.hostConnected)||void 0===i||i.call(t))}removeController(t){var e;null===(e=this._$ES)||void 0===e||e.splice(this._$ES.indexOf(t)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach(((t,e)=>{this.hasOwnProperty(e)&&(this._$Ei.set(e,this[e]),delete this[e])}))}createRenderRoot(){var t;const e=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return((t,e)=>{fn?t.adoptedStyleSheets=e.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet)):e.forEach((e=>{const i=document.createElement("style"),n=un.litNonce;void 0!==n&&i.setAttribute("nonce",n),i.textContent=e.cssText,t.appendChild(i)}))})(e,this.constructor.elementStyles),e}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostConnected)||void 0===e?void 0:e.call(t)}))}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostDisconnected)||void 0===e?void 0:e.call(t)}))}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$EO(t,e,i=Sn){var n;const o=this.constructor._$Ep(t,i);if(void 0!==o&&!0===i.reflect){const r=(void 0!==(null===(n=i.converter)||void 0===n?void 0:n.toAttribute)?i.converter:xn).toAttribute(e,i.type);this._$El=t,null==r?this.removeAttribute(o):this.setAttribute(o,r),this._$El=null}}_$AK(t,e){var i;const n=this.constructor,o=n._$Ev.get(t);if(void 0!==o&&this._$El!==o){const t=n.getPropertyOptions(o),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(i=t.converter)||void 0===i?void 0:i.fromAttribute)?t.converter:xn;this._$El=o,this[o]=r.fromAttribute(e,t.type),this._$El=null}}requestUpdate(t,e,i){let n=!0;void 0!==t&&(((i=i||this.constructor.getPropertyOptions(t)).hasChanged||In)(this[t],e)?(this._$AL.has(t)||this._$AL.set(t,e),!0===i.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,i))):n=!1),!this.isUpdatePending&&n&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach(((t,e)=>this[e]=t)),this._$Ei=void 0);let e=!1;const i=this._$AL;try{e=this.shouldUpdate(i),e?(this.willUpdate(i),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var e;return null===(e=t.hostUpdate)||void 0===e?void 0:e.call(t)})),this.update(i)):this._$Ek()}catch(t){throw e=!1,this._$Ek(),t}e&&this._$AE(i)}willUpdate(t){}_$AE(t){var e;null===(e=this._$ES)||void 0===e||e.forEach((t=>{var e;return null===(e=t.hostUpdated)||void 0===e?void 0:e.call(t)})),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return!0}update(t){void 0!==this._$EC&&(this._$EC.forEach(((t,e)=>this._$EO(e,this[e],t))),this._$EC=void 0),this._$Ek()}updated(t){}firstUpdated(t){}} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -var Dn,Rn;On[Mn]=!0,On.elementProperties=new Map,On.elementStyles=[],On.shadowRootOptions={mode:"open"},null==Cn||Cn({ReactiveElement:On}),(null!==(wn=An.reactiveElementVersions)&&void 0!==wn?wn:An.reactiveElementVersions=[]).push("1.6.3");class Bn extends On{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){var t,e;const i=super.createRenderRoot();return null!==(t=(e=this.renderOptions).renderBefore)&&void 0!==t||(e.renderBefore=i.firstChild),i}update(t){const e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=((t,e,i)=>{var n,o;const r=null!==(n=null==i?void 0:i.renderBefore)&&void 0!==n?n:e;let s=r._$litPart$;if(void 0===s){const t=null!==(o=null==i?void 0:i.renderBefore)&&void 0!==o?o:null;r._$litPart$=s=new on(e.insertBefore(Ti(),t),t,void 0,null!=i?i:{})}return s._$AI(t),s})(e,this.renderRoot,this.renderOptions)}connectedCallback(){var t;super.connectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!0)}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!1)}render(){return Yi}}Bn.finalized=!0,Bn._$litElement$=!0,null===(Dn=globalThis.litElementHydrateSupport)||void 0===Dn||Dn.call(globalThis,{LitElement:Bn});const zn=globalThis.litElementPolyfillSupport;function Pn(t){return"dark"===t||"light"===t?t:"auto"}null==zn||zn({LitElement:Bn}),(null!==(Rn=globalThis.litElementVersions)&&void 0!==Rn?Rn:globalThis.litElementVersions=[]).push("3.3.3");const Fn='\n :host([theme-mode="dark"]) {\n color-scheme: dark;\n --primary-text-color: #e1e1e1;\n --secondary-text-color: #9b9b9b;\n --disabled-text-color: #6f6f6f;\n --primary-background-color: #111111;\n --secondary-background-color: #202020;\n --card-background-color: #1c1c1c;\n --divider-color: rgba(225, 225, 225, 0.12);\n --app-header-background-color: #1c1c1c;\n --app-header-text-color: #e1e1e1;\n }\n :host([theme-mode="light"]) {\n color-scheme: light;\n --primary-text-color: #212121;\n --secondary-text-color: #727272;\n --disabled-text-color: #bdbdbd;\n --primary-background-color: #fafafa;\n --secondary-background-color: #e5e5e5;\n --card-background-color: #ffffff;\n --divider-color: rgba(0, 0, 0, 0.12);\n --app-header-background-color: #ffffff;\n --app-header-text-color: #212121;\n }\n :host([theme-mode="dark"]), :host([theme-mode="light"]) {\n --ha-card-background: var(--card-background-color);\n --ha-dialog-surface-background: var(--card-background-color);\n --ha-color-surface-default: var(--card-background-color);\n --ha-color-surface-raised: var(--card-background-color);\n --ha-color-text-primary: var(--primary-text-color);\n --ha-color-text-secondary: var(--secondary-text-color);\n --ha-color-text-disabled: var(--disabled-text-color);\n --ha-color-border-neutral-normal: var(--divider-color);\n --mdc-theme-surface: var(--card-background-color);\n --mdc-theme-on-surface: var(--primary-text-color);\n }\n',Tn=t=>null!=t?t:Zi -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */,Nn=(t,e)=>"method"===e.kind&&e.descriptor&&!("value"in e.descriptor)?{...e,finisher(i){i.createProperty(e.key,t)}}:{kind:"field",key:Symbol(),placement:"own",descriptor:{},originalKey:e.key,initializer(){"function"==typeof e.initializer&&(this[e.key]=e.initializer.call(this))},finisher(i){i.createProperty(e.key,t)}},jn=(t,e,i)=>{e.constructor.createProperty(i,t)}; -/** - * @license - * Copyright 2018 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */function Ln(t){return(e,i)=>void 0!==i?jn(t,e,i):Nn(t,e) -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */}function Un(t){return Ln({...t,state:!0})} -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -/** - * @license - * Copyright 2017 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */ -function Qn(t){return(({finisher:t,descriptor:e})=>(i,n)=>{var o;if(void 0===n){const n=null!==(o=i.originalKey)&&void 0!==o?o:i.key,r=null!=e?{kind:"method",placement:"prototype",key:n,descriptor:e(i.key)}:{...i,key:n};return null!=t&&(r.finisher=function(e){t(e,n)}),r}{const o=i.constructor;void 0!==e&&Object.defineProperty(i,n,e(n)),null==t||t(o,n)}})({finisher:(e,i)=>{Object.assign(e.prototype[i],t)}})} -/** - * @license - * Copyright 2021 Google LLC - * SPDX-License-Identifier: BSD-3-Clause - */var Hn,Vn,Wn;null===(Hn=window.HTMLSlotElement)||void 0===Hn||Hn.prototype.assignedElements,function(t){t.language="language",t.system="system",t.comma_decimal="comma_decimal",t.decimal_comma="decimal_comma",t.space_comma="space_comma",t.none="none"}(Vn||(Vn={})),function(t){t.language="language",t.system="system",t.am_pm="12",t.twenty_four="24"}(Wn||(Wn={}));var Gn=function(t,e,i,n){n=n||{},i=null==i?{}:i;var o=new Event(e,{bubbles:void 0===n.bubbles||n.bubbles,cancelable:Boolean(n.cancelable),composed:void 0===n.composed||n.composed});return o.detail=i,t.dispatchEvent(o),o -/** - * vis-data - * http://visjs.org/ - * - * Manage unstructured data using DataSet. Add, update, and remove data, and listen for changes in the data. - * - * @version 7.1.9 - * @date 2023-11-24T17:53:34.179Z - * - * @copyright (c) 2011-2017 Almende B.V, http://almende.com - * @copyright (c) 2017-2019 visjs contributors, https://github.com/visjs - * - * @license - * vis.js is dual licensed under both - * - * 1. The Apache 2.0 License - * http://www.apache.org/licenses/LICENSE-2.0 - * - * and - * - * 2. The MIT License - * http://opensource.org/licenses/MIT - * - * vis.js may be distributed under either license. - */};function Kn(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var qn="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function Yn(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var Zn={exports:{}},Jn=function(t){return t&&t.Math===Math&&t},Xn=Jn("object"==typeof globalThis&&globalThis)||Jn("object"==typeof window&&window)||Jn("object"==typeof self&&self)||Jn("object"==typeof qn&&qn)||function(){return this}()||qn||Function("return this")(),_n=function(t){try{return!!t()}catch(t){return!0}},$n=!_n((function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")})),to=$n,eo=Function.prototype,io=eo.apply,no=eo.call,oo="object"==typeof Reflect&&Reflect.apply||(to?no.bind(io):function(){return no.apply(io,arguments)}),ro=$n,so=Function.prototype,ao=so.call,lo=ro&&so.bind.bind(ao,ao),ho=ro?lo:function(t){return function(){return ao.apply(t,arguments)}},co=ho,uo=co({}.toString),fo=co("".slice),po=function(t){return fo(uo(t),8,-1)},vo=po,go=ho,yo=function(t){if("Function"===vo(t))return go(t)},mo="object"==typeof document&&document.all,bo={all:mo,IS_HTMLDDA:void 0===mo&&void 0!==mo},wo=bo.all,Ao=bo.IS_HTMLDDA?function(t){return"function"==typeof t||t===wo}:function(t){return"function"==typeof t},ko={},Eo=!_n((function(){return 7!==Object.defineProperty({},1,{get:function(){return 7}})[1]})),Co=$n,xo=Function.prototype.call,Io=Co?xo.bind(xo):function(){return xo.apply(xo,arguments)},So={},Mo={}.propertyIsEnumerable,Oo=Object.getOwnPropertyDescriptor,Do=Oo&&!Mo.call({1:2},1);So.f=Do?function(t){var e=Oo(this,t);return!!e&&e.enumerable}:Mo;var Ro,Bo,zo=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}},Po=_n,Fo=po,To=Object,No=ho("".split),jo=Po((function(){return!To("z").propertyIsEnumerable(0)}))?function(t){return"String"===Fo(t)?No(t,""):To(t)}:To,Lo=function(t){return null==t},Uo=Lo,Qo=TypeError,Ho=function(t){if(Uo(t))throw new Qo("Can't call method on "+t);return t},Vo=jo,Wo=Ho,Go=function(t){return Vo(Wo(t))},Ko=Ao,qo=bo.all,Yo=bo.IS_HTMLDDA?function(t){return"object"==typeof t?null!==t:Ko(t)||t===qo}:function(t){return"object"==typeof t?null!==t:Ko(t)},Zo={},Jo=Zo,Xo=Xn,_o=Ao,$o=function(t){return _o(t)?t:void 0},tr=function(t,e){return arguments.length<2?$o(Jo[t])||$o(Xo[t]):Jo[t]&&Jo[t][e]||Xo[t]&&Xo[t][e]},er=ho({}.isPrototypeOf),ir="undefined"!=typeof navigator&&String(navigator.userAgent)||"",nr=Xn,or=ir,rr=nr.process,sr=nr.Deno,ar=rr&&rr.versions||sr&&sr.version,lr=ar&&ar.v8;lr&&(Bo=(Ro=lr.split("."))[0]>0&&Ro[0]<4?1:+(Ro[0]+Ro[1])),!Bo&&or&&(!(Ro=or.match(/Edge\/(\d+)/))||Ro[1]>=74)&&(Ro=or.match(/Chrome\/(\d+)/))&&(Bo=+Ro[1]);var hr=Bo,cr=hr,dr=_n,ur=Xn.String,fr=!!Object.getOwnPropertySymbols&&!dr((function(){var t=Symbol("symbol detection");return!ur(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&cr&&cr<41})),pr=fr&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,vr=tr,gr=Ao,yr=er,mr=Object,br=pr?function(t){return"symbol"==typeof t}:function(t){var e=vr("Symbol");return gr(e)&&yr(e.prototype,mr(t))},wr=String,Ar=function(t){try{return wr(t)}catch(t){return"Object"}},kr=Ao,Er=Ar,Cr=TypeError,xr=function(t){if(kr(t))return t;throw new Cr(Er(t)+" is not a function")},Ir=xr,Sr=Lo,Mr=function(t,e){var i=t[e];return Sr(i)?void 0:Ir(i)},Or=Io,Dr=Ao,Rr=Yo,Br=TypeError,zr={exports:{}},Pr=Xn,Fr=Object.defineProperty,Tr=function(t,e){try{Fr(Pr,t,{value:e,configurable:!0,writable:!0})}catch(i){Pr[t]=e}return e},Nr="__core-js_shared__",jr=Xn[Nr]||Tr(Nr,{}),Lr=jr;(zr.exports=function(t,e){return Lr[t]||(Lr[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.33.2",mode:"pure",copyright:"© 2014-2023 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.33.2/LICENSE",source:"https://github.com/zloirock/core-js"});var Ur=zr.exports,Qr=Ho,Hr=Object,Vr=function(t){return Hr(Qr(t))},Wr=Vr,Gr=ho({}.hasOwnProperty),Kr=Object.hasOwn||function(t,e){return Gr(Wr(t),e)},qr=ho,Yr=0,Zr=Math.random(),Jr=qr(1..toString),Xr=function(t){return"Symbol("+(void 0===t?"":t)+")_"+Jr(++Yr+Zr,36)},_r=Ur,$r=Kr,ts=Xr,es=fr,is=pr,ns=Xn.Symbol,os=_r("wks"),rs=is?ns.for||ns:ns&&ns.withoutSetter||ts,ss=function(t){return $r(os,t)||(os[t]=es&&$r(ns,t)?ns[t]:rs("Symbol."+t)),os[t]},as=Io,ls=Yo,hs=br,cs=Mr,ds=function(t,e){var i,n;if("string"===e&&Dr(i=t.toString)&&!Rr(n=Or(i,t)))return n;if(Dr(i=t.valueOf)&&!Rr(n=Or(i,t)))return n;if("string"!==e&&Dr(i=t.toString)&&!Rr(n=Or(i,t)))return n;throw new Br("Can't convert object to primitive value")},us=TypeError,fs=ss("toPrimitive"),ps=function(t,e){if(!ls(t)||hs(t))return t;var i,n=cs(t,fs);if(n){if(void 0===e&&(e="default"),i=as(n,t,e),!ls(i)||hs(i))return i;throw new us("Can't convert object to primitive value")}return void 0===e&&(e="number"),ds(t,e)},vs=br,gs=function(t){var e=ps(t,"string");return vs(e)?e:e+""},ys=Yo,ms=Xn.document,bs=ys(ms)&&ys(ms.createElement),ws=function(t){return bs?ms.createElement(t):{}},As=ws,ks=!Eo&&!_n((function(){return 7!==Object.defineProperty(As("div"),"a",{get:function(){return 7}}).a})),Es=Eo,Cs=Io,xs=So,Is=zo,Ss=Go,Ms=gs,Os=Kr,Ds=ks,Rs=Object.getOwnPropertyDescriptor;ko.f=Es?Rs:function(t,e){if(t=Ss(t),e=Ms(e),Ds)try{return Rs(t,e)}catch(t){}if(Os(t,e))return Is(!Cs(xs.f,t,e),t[e])};var Bs=_n,zs=Ao,Ps=/#|\.prototype\./,Fs=function(t,e){var i=Ns[Ts(t)];return i===Ls||i!==js&&(zs(e)?Bs(e):!!e)},Ts=Fs.normalize=function(t){return String(t).replace(Ps,".").toLowerCase()},Ns=Fs.data={},js=Fs.NATIVE="N",Ls=Fs.POLYFILL="P",Us=Fs,Qs=xr,Hs=$n,Vs=yo(yo.bind),Ws=function(t,e){return Qs(t),void 0===e?t:Hs?Vs(t,e):function(){return t.apply(e,arguments)}},Gs={},Ks=Eo&&_n((function(){return 42!==Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype})),qs=Yo,Ys=String,Zs=TypeError,Js=function(t){if(qs(t))return t;throw new Zs(Ys(t)+" is not an object")},Xs=Eo,_s=ks,$s=Ks,ta=Js,ea=gs,ia=TypeError,na=Object.defineProperty,oa=Object.getOwnPropertyDescriptor,ra="enumerable",sa="configurable",aa="writable";Gs.f=Xs?$s?function(t,e,i){if(ta(t),e=ea(e),ta(i),"function"==typeof t&&"prototype"===e&&"value"in i&&aa in i&&!i[aa]){var n=oa(t,e);n&&n[aa]&&(t[e]=i.value,i={configurable:sa in i?i[sa]:n[sa],enumerable:ra in i?i[ra]:n[ra],writable:!1})}return na(t,e,i)}:na:function(t,e,i){if(ta(t),e=ea(e),ta(i),_s)try{return na(t,e,i)}catch(t){}if("get"in i||"set"in i)throw new ia("Accessors not supported");return"value"in i&&(t[e]=i.value),t};var la=Gs,ha=zo,ca=Eo?function(t,e,i){return la.f(t,e,ha(1,i))}:function(t,e,i){return t[e]=i,t},da=Xn,ua=oo,fa=yo,pa=Ao,va=ko.f,ga=Us,ya=Zo,ma=Ws,ba=ca,wa=Kr,Aa=function(t){var e=function(i,n,o){if(this instanceof e){switch(arguments.length){case 0:return new t;case 1:return new t(i);case 2:return new t(i,n)}return new t(i,n,o)}return ua(t,this,arguments)};return e.prototype=t.prototype,e},ka=function(t,e){var i,n,o,r,s,a,l,h,c,d=t.target,u=t.global,f=t.stat,p=t.proto,v=u?da:f?da[d]:(da[d]||{}).prototype,g=u?ya:ya[d]||ba(ya,d,{})[d],y=g.prototype;for(r in e)n=!(i=ga(u?r:d+(f?".":"#")+r,t.forced))&&v&&wa(v,r),a=g[r],n&&(l=t.dontCallGetSet?(c=va(v,r))&&c.value:v[r]),s=n&&l?l:e[r],n&&typeof a==typeof s||(h=t.bind&&n?ma(s,da):t.wrap&&n?Aa(s):p&&pa(s)?fa(s):s,(t.sham||s&&s.sham||a&&a.sham)&&ba(h,"sham",!0),ba(g,r,h),p&&(wa(ya,o=d+"Prototype")||ba(ya,o,{}),ba(ya[o],r,s),t.real&&y&&(i||!y[r])&&ba(y,r,s)))},Ea=ka,Ca=Eo,xa=Gs.f;Ea({target:"Object",stat:!0,forced:Object.defineProperty!==xa,sham:!Ca},{defineProperty:xa});var Ia=Zo.Object,Sa=Zn.exports=function(t,e,i){return Ia.defineProperty(t,e,i)};Ia.defineProperty.sham&&(Sa.sham=!0);var Ma=Zn.exports,Oa=Ma,Da=Yn(Oa),Ra=po,Ba=Array.isArray||function(t){return"Array"===Ra(t)},za=Math.ceil,Pa=Math.floor,Fa=Math.trunc||function(t){var e=+t;return(e>0?Pa:za)(e)},Ta=Fa,Na=function(t){var e=+t;return e!=e||0===e?0:Ta(e)},ja=Na,La=Math.min,Ua=function(t){return t>0?La(ja(t),9007199254740991):0},Qa=function(t){return Ua(t.length)},Ha=TypeError,Va=function(t){if(t>9007199254740991)throw Ha("Maximum allowed index exceeded");return t},Wa=gs,Ga=Gs,Ka=zo,qa=function(t,e,i){var n=Wa(e);n in t?Ga.f(t,n,Ka(0,i)):t[n]=i},Ya={};Ya[ss("toStringTag")]="z";var Za="[object z]"===String(Ya),Ja=Za,Xa=Ao,_a=po,$a=ss("toStringTag"),tl=Object,el="Arguments"===_a(function(){return arguments}()),il=Ja?_a:function(t){var e,i,n;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(i=function(t,e){try{return t[e]}catch(t){}}(e=tl(t),$a))?i:el?_a(e):"Object"===(n=_a(e))&&Xa(e.callee)?"Arguments":n},nl=Ao,ol=jr,rl=ho(Function.toString);nl(ol.inspectSource)||(ol.inspectSource=function(t){return rl(t)});var sl=ol.inspectSource,al=ho,ll=_n,hl=Ao,cl=il,dl=sl,ul=function(){},fl=[],pl=tr("Reflect","construct"),vl=/^\s*(?:class|function)\b/,gl=al(vl.exec),yl=!vl.test(ul),ml=function(t){if(!hl(t))return!1;try{return pl(ul,fl,t),!0}catch(t){return!1}},bl=function(t){if(!hl(t))return!1;switch(cl(t)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}try{return yl||!!gl(vl,dl(t))}catch(t){return!0}};bl.sham=!0;var wl=!pl||ll((function(){var t;return ml(ml.call)||!ml(Object)||!ml((function(){t=!0}))||t}))?bl:ml,Al=Ba,kl=wl,El=Yo,Cl=ss("species"),xl=Array,Il=function(t){var e;return Al(t)&&(e=t.constructor,(kl(e)&&(e===xl||Al(e.prototype))||El(e)&&null===(e=e[Cl]))&&(e=void 0)),void 0===e?xl:e},Sl=function(t,e){return new(Il(t))(0===e?0:e)},Ml=_n,Ol=hr,Dl=ss("species"),Rl=function(t){return Ol>=51||!Ml((function(){var e=[];return(e.constructor={})[Dl]=function(){return{foo:1}},1!==e[t](Boolean).foo}))},Bl=ka,zl=_n,Pl=Ba,Fl=Yo,Tl=Vr,Nl=Qa,jl=Va,Ll=qa,Ul=Sl,Ql=Rl,Hl=hr,Vl=ss("isConcatSpreadable"),Wl=Hl>=51||!zl((function(){var t=[];return t[Vl]=!1,t.concat()[0]!==t})),Gl=function(t){if(!Fl(t))return!1;var e=t[Vl];return void 0!==e?!!e:Pl(t)};Bl({target:"Array",proto:!0,arity:1,forced:!Wl||!Ql("concat")},{concat:function(t){var e,i,n,o,r,s=Tl(this),a=Ul(s,0),l=0;for(e=-1,n=arguments.length;ea;)if((o=r[a++])!=o)return!0}else for(;s>a;a++)if((t||a in r)&&r[a]===i)return t||a||0;return!t&&-1}},oh={includes:nh(!0),indexOf:nh(!1)},rh={},sh=Kr,ah=Go,lh=oh.indexOf,hh=rh,ch=ho([].push),dh=function(t,e){var i,n=ah(t),o=0,r=[];for(i in n)!sh(hh,i)&&sh(n,i)&&ch(r,i);for(;e.length>o;)sh(n,i=e[o++])&&(~lh(r,i)||ch(r,i));return r},uh=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],fh=dh,ph=uh,vh=Object.keys||function(t){return fh(t,ph)},gh=Eo,yh=Ks,mh=Gs,bh=Js,wh=Go,Ah=vh;Zl.f=gh&&!yh?Object.defineProperties:function(t,e){bh(t);for(var i,n=wh(e),o=Ah(e),r=o.length,s=0;r>s;)mh.f(t,i=o[s++],n[i]);return t};var kh,Eh=tr("document","documentElement"),Ch=Xr,xh=Ur("keys"),Ih=function(t){return xh[t]||(xh[t]=Ch(t))},Sh=Js,Mh=Zl,Oh=uh,Dh=rh,Rh=Eh,Bh=ws,zh="prototype",Ph="script",Fh=Ih("IE_PROTO"),Th=function(){},Nh=function(t){return"<"+Ph+">"+t+""},jh=function(t){t.write(Nh("")),t.close();var e=t.parentWindow.Object;return t=null,e},Lh=function(){try{kh=new ActiveXObject("htmlfile")}catch(t){}var t,e,i;Lh="undefined"!=typeof document?document.domain&&kh?jh(kh):(e=Bh("iframe"),i="java"+Ph+":",e.style.display="none",Rh.appendChild(e),e.src=String(i),(t=e.contentWindow.document).open(),t.write(Nh("document.F=Object")),t.close(),t.F):jh(kh);for(var n=Oh.length;n--;)delete Lh[zh][Oh[n]];return Lh()};Dh[Fh]=!0;var Uh=Object.create||function(t,e){var i;return null!==t?(Th[zh]=Sh(t),i=new Th,Th[zh]=null,i[Fh]=t):i=Lh(),void 0===e?i:Mh.f(i,e)},Qh={},Hh=dh,Vh=uh.concat("length","prototype");Qh.f=Object.getOwnPropertyNames||function(t){return Hh(t,Vh)};var Wh={},Gh=$l,Kh=Qa,qh=qa,Yh=Array,Zh=Math.max,Jh=function(t,e,i){for(var n=Kh(t),o=Gh(e,n),r=Gh(void 0===i?n:i,n),s=Yh(Zh(r-o,0)),a=0;om;m++)if((a||m in v)&&(f=g(u=v[m],m,p),t))if(e)w[m]=f;else if(f)switch(t){case 3:return!0;case 5:return u;case 6:return m;case 2:_c(w,u)}else switch(t){case 4:return!1;case 7:_c(w,u)}return r?-1:n||o?o:w}},td={forEach:$c(0),map:$c(1),filter:$c(2),some:$c(3),every:$c(4),find:$c(5),findIndex:$c(6),filterReject:$c(7)},ed=ka,id=Xn,nd=Io,od=ho,rd=Eo,sd=fr,ad=_n,ld=Kr,hd=er,cd=Js,dd=Go,ud=gs,fd=Yl,pd=zo,vd=Uh,gd=vh,yd=Qh,md=Wh,bd=ic,wd=ko,Ad=Gs,kd=Zl,Ed=So,Cd=oc,xd=sc,Id=Ur,Sd=rh,Md=Xr,Od=ss,Dd=ac,Rd=gc,Bd=Ac,zd=Dc,Pd=Kc,Fd=td.forEach,Td=Ih("hidden"),Nd="Symbol",jd="prototype",Ld=Pd.set,Ud=Pd.getterFor(Nd),Qd=Object[jd],Hd=id.Symbol,Vd=Hd&&Hd[jd],Wd=id.RangeError,Gd=id.TypeError,Kd=id.QObject,qd=wd.f,Yd=Ad.f,Zd=md.f,Jd=Ed.f,Xd=od([].push),_d=Id("symbols"),$d=Id("op-symbols"),tu=Id("wks"),eu=!Kd||!Kd[jd]||!Kd[jd].findChild,iu=function(t,e,i){var n=qd(Qd,e);n&&delete Qd[e],Yd(t,e,i),n&&t!==Qd&&Yd(Qd,e,n)},nu=rd&&ad((function(){return 7!==vd(Yd({},"a",{get:function(){return Yd(this,"a",{value:7}).a}})).a}))?iu:Yd,ou=function(t,e){var i=_d[t]=vd(Vd);return Ld(i,{type:Nd,tag:t,description:e}),rd||(i.description=e),i},ru=function(t,e,i){t===Qd&&ru($d,e,i),cd(t);var n=ud(e);return cd(i),ld(_d,n)?(i.enumerable?(ld(t,Td)&&t[Td][n]&&(t[Td][n]=!1),i=vd(i,{enumerable:pd(0,!1)})):(ld(t,Td)||Yd(t,Td,pd(1,{})),t[Td][n]=!0),nu(t,n,i)):Yd(t,n,i)},su=function(t,e){cd(t);var i=dd(e),n=gd(i).concat(cu(i));return Fd(n,(function(e){rd&&!nd(au,i,e)||ru(t,e,i[e])})),t},au=function(t){var e=ud(t),i=nd(Jd,this,e);return!(this===Qd&&ld(_d,e)&&!ld($d,e))&&(!(i||!ld(this,e)||!ld(_d,e)||ld(this,Td)&&this[Td][e])||i)},lu=function(t,e){var i=dd(t),n=ud(e);if(i!==Qd||!ld(_d,n)||ld($d,n)){var o=qd(i,n);return!o||!ld(_d,n)||ld(i,Td)&&i[Td][n]||(o.enumerable=!0),o}},hu=function(t){var e=Zd(dd(t)),i=[];return Fd(e,(function(t){ld(_d,t)||ld(Sd,t)||Xd(i,t)})),i},cu=function(t){var e=t===Qd,i=Zd(e?$d:dd(t)),n=[];return Fd(i,(function(t){!ld(_d,t)||e&&!ld(Qd,t)||Xd(n,_d[t])})),n};sd||(Hd=function(){if(hd(Vd,this))throw new Gd("Symbol is not a constructor");var t=arguments.length&&void 0!==arguments[0]?fd(arguments[0]):void 0,e=Md(t),i=function(t){var n=void 0===this?id:this;n===Qd&&nd(i,$d,t),ld(n,Td)&&ld(n[Td],e)&&(n[Td][e]=!1);var o=pd(1,t);try{nu(n,e,o)}catch(t){if(!(t instanceof Wd))throw t;iu(n,e,o)}};return rd&&eu&&nu(Qd,e,{configurable:!0,set:i}),ou(e,t)},Cd(Vd=Hd[jd],"toString",(function(){return Ud(this).tag})),Cd(Hd,"withoutSetter",(function(t){return ou(Md(t),t)})),Ed.f=au,Ad.f=ru,kd.f=su,wd.f=lu,yd.f=md.f=hu,bd.f=cu,Dd.f=function(t){return ou(Od(t),t)},rd&&xd(Vd,"description",{configurable:!0,get:function(){return Ud(this).description}})),ed({global:!0,constructor:!0,wrap:!0,forced:!sd,sham:!sd},{Symbol:Hd}),Fd(gd(tu),(function(t){Rd(t)})),ed({target:Nd,stat:!0,forced:!sd},{useSetter:function(){eu=!0},useSimple:function(){eu=!1}}),ed({target:"Object",stat:!0,forced:!sd,sham:!rd},{create:function(t,e){return void 0===e?vd(t):su(vd(t),e)},defineProperty:ru,defineProperties:su,getOwnPropertyDescriptor:lu}),ed({target:"Object",stat:!0,forced:!sd},{getOwnPropertyNames:hu}),Bd(),zd(Hd,Nd),Sd[Td]=!0;var du=fr&&!!Symbol.for&&!!Symbol.keyFor,uu=ka,fu=tr,pu=Kr,vu=Yl,gu=Ur,yu=du,mu=gu("string-to-symbol-registry"),bu=gu("symbol-to-string-registry");uu({target:"Symbol",stat:!0,forced:!yu},{for:function(t){var e=vu(t);if(pu(mu,e))return mu[e];var i=fu("Symbol")(e);return mu[e]=i,bu[i]=e,i}});var wu=ka,Au=Kr,ku=br,Eu=Ar,Cu=du,xu=Ur("symbol-to-string-registry");wu({target:"Symbol",stat:!0,forced:!Cu},{keyFor:function(t){if(!ku(t))throw new TypeError(Eu(t)+" is not a symbol");if(Au(xu,t))return xu[t]}});var Iu=ho([].slice),Su=Ba,Mu=Ao,Ou=po,Du=Yl,Ru=ho([].push),Bu=ka,zu=tr,Pu=oo,Fu=Io,Tu=ho,Nu=_n,ju=Ao,Lu=br,Uu=Iu,Qu=function(t){if(Mu(t))return t;if(Su(t)){for(var e=t.length,i=[],n=0;n=e.length)return t.target=void 0,wp(void 0,!0);switch(t.kind){case"keys":return wp(i,!1);case"values":return wp(e[i],!1)}return wp([i,e[i]],!1)}),"values"),yp.Arguments=yp.Array;var Cp={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0},xp=Xn,Ip=il,Sp=ca,Mp=ff,Op=ss("toStringTag");for(var Dp in Cp){var Rp=xp[Dp],Bp=Rp&&Rp.prototype;Bp&&Ip(Bp)!==Op&&Sp(Bp,Op,Dp),Mp[Dp]=Mp.Array}var zp=uf,Pp=ss,Fp=Gs.f,Tp=Pp("metadata"),Np=Function.prototype;void 0===Np[Tp]&&Fp(Np,Tp,{value:null}),gc("asyncDispose"),gc("dispose"),gc("metadata");var jp=zp,Lp=ho,Up=tr("Symbol"),Qp=Up.keyFor,Hp=Lp(Up.prototype.valueOf),Vp=Up.isRegisteredSymbol||function(t){try{return void 0!==Qp(Hp(t))}catch(t){return!1}};ka({target:"Symbol",stat:!0},{isRegisteredSymbol:Vp});for(var Wp=Ur,Gp=tr,Kp=ho,qp=br,Yp=ss,Zp=Gp("Symbol"),Jp=Zp.isWellKnownSymbol,Xp=Gp("Object","getOwnPropertyNames"),_p=Kp(Zp.prototype.valueOf),$p=Wp("wks"),tv=0,ev=Xp(Zp),iv=ev.length;tv=a?t?"":void 0:(n=uv(r,s))<55296||n>56319||s+1===a||(o=uv(r,s+1))<56320||o>57343?t?dv(r,s):n:t?fv(r,s,s+2):o-56320+(n-55296<<10)+65536}},vv={codeAt:pv(!1),charAt:pv(!0)}.charAt,gv=Yl,yv=Kc,mv=pp,bv=vp,wv="String Iterator",Av=yv.set,kv=yv.getterFor(wv);mv(String,"String",(function(t){Av(this,{type:wv,string:gv(t),index:0})}),(function(){var t,e=kv(this),i=e.string,n=e.index;return n>=i.length?bv(void 0,!0):(t=vv(i,n),e.index+=t.length,bv(t,!1))}));var Ev=ac.f("iterator"),Cv=Ev,xv=Yn(Cv);function Iv(t){return Iv="function"==typeof sv&&"symbol"==typeof xv?function(t){return typeof t}:function(t){return t&&"function"==typeof sv&&t.constructor===sv&&t!==sv.prototype?"symbol":typeof t},Iv(t)}var Sv=Yn(ac.f("toPrimitive"));function Mv(t){var e=function(t,e){if("object"!==Iv(t)||null===t)return t;var i=t[Sv];if(void 0!==i){var n=i.call(t,e||"default");if("object"!==Iv(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(t,"string");return"symbol"===Iv(e)?e:String(e)}function Ov(t,e){for(var i=0;i=0:a>l;l+=h)l in s&&(o=i(o,s[l],l,r));return o}},sg={left:rg(!1),right:rg(!0)},ag=_n,lg=function(t,e){var i=[][t];return!!i&&ag((function(){i.call(null,e||function(){return 1},1)}))},hg="process"===po(Xn.process),cg=sg.left;ka({target:"Array",proto:!0,forced:!hg&&hr>79&&hr<83||!lg("reduce")},{reduce:function(t){var e=arguments.length;return cg(this,t,e,e>1?arguments[1]:void 0)}});var dg=Kv("Array","reduce"),ug=er,fg=dg,pg=Array.prototype,vg=function(t){var e=t.reduce;return t===pg||ug(pg,t)&&e===pg.reduce?fg:e},gg=Yn(vg),yg=td.filter;ka({target:"Array",proto:!0,forced:!Rl("filter")},{filter:function(t){return yg(this,t,arguments.length>1?arguments[1]:void 0)}});var mg=Kv("Array","filter"),bg=er,wg=mg,Ag=Array.prototype,kg=function(t){var e=t.filter;return t===Ag||bg(Ag,t)&&e===Ag.filter?wg:e},Eg=Yn(kg),Cg=td.map;ka({target:"Array",proto:!0,forced:!Rl("map")},{map:function(t){return Cg(this,t,arguments.length>1?arguments[1]:void 0)}});var xg=Kv("Array","map"),Ig=er,Sg=xg,Mg=Array.prototype,Og=function(t){var e=t.map;return t===Mg||Ig(Mg,t)&&e===Mg.map?Sg:e},Dg=Yn(Og),Rg=Ba,Bg=Qa,zg=Va,Pg=Ws,Fg=function(t,e,i,n,o,r,s,a){for(var l,h,c=o,d=0,u=!!s&&Pg(s,a);d0&&Rg(l)?(h=Bg(l),c=Fg(t,e,l,h,c,r-1)-1):(zg(c+1),t[c]=l),c++),d++;return c},Tg=Fg,Ng=xr,jg=Vr,Lg=Qa,Ug=Sl;ka({target:"Array",proto:!0},{flatMap:function(t){var e,i=jg(this),n=Lg(i);return Ng(t),(e=Ug(i,0)).length=Tg(e,i,i,n,0,1,t,arguments.length>1?arguments[1]:void 0),e}}),Kv("Array","flatMap");var Qg=Io,Hg=Js,Vg=Mr,Wg=function(t,e,i){var n,o;Hg(t);try{if(!(n=Vg(t,"return"))){if("throw"===e)throw i;return i}n=Qg(n,t)}catch(t){o=!0,n=t}if("throw"===e)throw i;if(o)throw n;return Hg(n),i},Gg=Js,Kg=Wg,qg=ff,Yg=ss("iterator"),Zg=Array.prototype,Jg=function(t){return void 0!==t&&(qg.Array===t||Zg[Yg]===t)},Xg=il,_g=Mr,$g=Lo,ty=ff,ey=ss("iterator"),iy=function(t){if(!$g(t))return _g(t,ey)||_g(t,"@@iterator")||ty[Xg(t)]},ny=Io,oy=xr,ry=Js,sy=Ar,ay=iy,ly=TypeError,hy=function(t,e){var i=arguments.length<2?ay(t):e;if(oy(i))return ry(ny(i,t));throw new ly(sy(t)+" is not iterable")},cy=Ws,dy=Io,uy=Vr,fy=function(t,e,i,n){try{return n?e(Gg(i)[0],i[1]):e(i)}catch(e){Kg(t,"throw",e)}},py=Jg,vy=wl,gy=Qa,yy=qa,my=hy,by=iy,wy=Array,Ay=ss("iterator"),ky=!1;try{var Ey=0,Cy={next:function(){return{done:!!Ey++}},return:function(){ky=!0}};Cy[Ay]=function(){return this},Array.from(Cy,(function(){throw 2}))}catch(t){}var xy=function(t,e){try{if(!e&&!ky)return!1}catch(t){return!1}var i=!1;try{var n={};n[Ay]=function(){return{next:function(){return{done:i=!0}}}},t(n)}catch(t){}return i},Iy=function(t){var e=uy(t),i=vy(this),n=arguments.length,o=n>1?arguments[1]:void 0,r=void 0!==o;r&&(o=cy(o,n>2?arguments[2]:void 0));var s,a,l,h,c,d,u=by(e),f=0;if(!u||this===wy&&py(u))for(s=gy(e),a=i?new this(s):wy(s);s>f;f++)d=r?o(e[f],f):e[f],yy(a,f,d);else for(c=(h=my(e,u)).next,a=i?new this:[];!(l=dy(c,h)).done;f++)d=r?fy(h,o,[l.value,f],!0):l.value,yy(a,f,d);return a.length=f,a};ka({target:"Array",stat:!0,forced:!xy((function(t){Array.from(t)}))},{from:Iy});var Sy=Zo.Array.from,My=Yn(Sy),Oy=iy,Dy=Yn(Oy),Ry=Yn(Oy);ka({target:"Array",stat:!0},{isArray:Ba});var By=Zo.Array.isArray,zy=Yn(By);var Py=Eo,Fy=Ba,Ty=TypeError,Ny=Object.getOwnPropertyDescriptor,jy=Py&&!function(){if(void 0!==this)return!0;try{Object.defineProperty([],"length",{writable:!1}).length=1}catch(t){return t instanceof TypeError}}()?function(t,e){if(Fy(t)&&!Ny(t,"length").writable)throw new Ty("Cannot set read only .length");return t.length=e}:function(t,e){return t.length=e},Ly=Vr,Uy=Qa,Qy=jy,Hy=Va;ka({target:"Array",proto:!0,arity:1,forced:_n((function(){return 4294967297!==[].push.call({length:4294967296},1)}))||!function(){try{Object.defineProperty([],"length",{writable:!1}).push()}catch(t){return t instanceof TypeError}}()},{push:function(t){var e=Ly(this),i=Uy(e),n=arguments.length;Hy(i+n);for(var o=0;ot.length)&&(e=t.length);for(var i=0,n=new Array(e);i1?arguments[1]:void 0)};ka({target:"Array",proto:!0,forced:[].forEach!==Vm},{forEach:Vm});var Wm=Kv("Array","forEach"),Gm=il,Km=Kr,qm=er,Ym=Wm,Zm=Array.prototype,Jm={DOMTokenList:!0,NodeList:!0},Xm=function(t){var e=t.forEach;return t===Zm||qm(Zm,t)&&e===Zm.forEach||Km(Jm,Gm(t))?Ym:e},_m=Yn(Xm),$m=ka,tb=Ba,eb=ho([].reverse),ib=[1,2];$m({target:"Array",proto:!0,forced:String(ib)===String(ib.reverse())},{reverse:function(){return tb(this)&&(this.length=this.length),eb(this)}});var nb=Kv("Array","reverse"),ob=er,rb=nb,sb=Array.prototype,ab=function(t){var e=t.reverse;return t===sb||ob(sb,t)&&e===sb.reverse?rb:e},lb=ab,hb=Yn(lb),cb=Ar,db=TypeError,ub=function(t,e){if(!delete t[e])throw new db("Cannot delete property "+cb(e)+" of "+cb(t))},fb=ka,pb=Vr,vb=$l,gb=Na,yb=Qa,mb=jy,bb=Va,wb=Sl,Ab=qa,kb=ub,Eb=Rl("splice"),Cb=Math.max,xb=Math.min;fb({target:"Array",proto:!0,forced:!Eb},{splice:function(t,e){var i,n,o,r,s,a,l=pb(this),h=yb(l),c=vb(t,h),d=arguments.length;for(0===d?i=n=0:1===d?(i=0,n=h-c):(i=d-2,n=xb(Cb(gb(e),0),h-c)),bb(h+i-n),o=wb(l,n),r=0;rh-n+i;r--)kb(l,r-1)}else if(i>n)for(r=h-n;r>c;r--)a=r+i-1,(s=r+n-1)in l?l[a]=l[s]:kb(l,a);for(r=0;ro;)for(var a,l=Ub(arguments[o++]),h=r?Vb(Tb(l),r(l)):Tb(l),c=h.length,d=0;c>d;)a=h[d++],Bb&&!Pb(s,l,a)||(i[a]=l[a]);return i}:Qb,Gb=Wb;ka({target:"Object",stat:!0,arity:2,forced:Object.assign!==Gb},{assign:Gb});var Kb=Yn(Zo.Object.assign),qb=Vr,Yb=Mf,Zb=wf;ka({target:"Object",stat:!0,forced:_n((function(){Yb(1)})),sham:!Zb},{getPrototypeOf:function(t){return Yb(qb(t))}});var Jb=Zo.Object.getPrototypeOf;ka({target:"Object",stat:!0,sham:!Eo},{create:Uh});var Xb=Zo.Object,_b=function(t,e){return Xb.create(t,e)},$b=_b,tw=Yn($b),ew=Zo,iw=oo;ew.JSON||(ew.JSON={stringify:JSON.stringify});var nw=function(t,e,i){return iw(ew.JSON.stringify,null,arguments)},ow=Yn(nw),rw="function"==typeof Bun&&Bun&&"string"==typeof Bun.version,sw=TypeError,aw=function(t,e){if(ti,s=cw(n)?n:vw(n),a=r?fw(arguments,i):[],l=r?function(){hw(s,this,a)}:s;return e?t(l,o):t(l)}:t},mw=ka,bw=Xn,ww=yw(bw.setInterval,!0);mw({global:!0,bind:!0,forced:bw.setInterval!==ww},{setInterval:ww});var Aw=ka,kw=Xn,Ew=yw(kw.setTimeout,!0);Aw({global:!0,bind:!0,forced:kw.setTimeout!==Ew},{setTimeout:Ew});var Cw=Yn(Zo.setTimeout),xw={exports:{}};!function(t){function e(t){if(t)return function(t){return Object.assign(t,e.prototype),t._callbacks=new Map,t}(t);this._callbacks=new Map}e.prototype.on=function(t,e){const i=this._callbacks.get(t)??[];return i.push(e),this._callbacks.set(t,i),this},e.prototype.once=function(t,e){const i=(...n)=>{this.off(t,i),e.apply(this,n)};return i.fn=e,this.on(t,i),this},e.prototype.off=function(t,e){if(void 0===t&&void 0===e)return this._callbacks.clear(),this;if(void 0===e)return this._callbacks.delete(t),this;const i=this._callbacks.get(t);if(i){for(const[t,n]of i.entries())if(n===e||n.fn===e){i.splice(t,1);break}0===i.length?this._callbacks.delete(t):this._callbacks.set(t,i)}return this},e.prototype.emit=function(t,...e){const i=this._callbacks.get(t);if(i){const t=[...i];for(const i of t)i.apply(this,e)}return this},e.prototype.listeners=function(t){return this._callbacks.get(t)??[]},e.prototype.listenerCount=function(t){if(t)return this.listeners(t).length;let e=0;for(const t of this._callbacks.values())e+=t.length;return e},e.prototype.hasListeners=function(t){return this.listenerCount(t)>0},e.prototype.addEventListener=e.prototype.on,e.prototype.removeListener=e.prototype.off,e.prototype.removeEventListener=e.prototype.off,e.prototype.removeAllListeners=e.prototype.off,t.exports=e}(xw);var Iw,Sw=Yn(xw.exports); -/*! Hammer.JS - v2.0.17-rc - 2019-12-16 - * http://naver.github.io/egjs - * - * Forked By Naver egjs - * Copyright (c) hammerjs - * Licensed under the MIT license */ -function Mw(){return Mw=Object.assign||function(t){for(var e=1;e-1}var gA=function(){function t(t,e){this.manager=t,this.set(e)}var e=t.prototype;return e.set=function(t){t===Qw&&(t=this.compute()),Uw&&this.manager.element.style&&qw[t]&&(this.manager.element.style[Lw]=t),this.actions=t.toLowerCase().trim()},e.update=function(){this.set(this.manager.options.touchAction)},e.compute=function(){var t=[];return fA(this.manager.recognizers,(function(e){pA(e.options.enable,[e])&&(t=t.concat(e.getTouchAction()))})),function(t){if(vA(t,Ww))return Ww;var e=vA(t,Gw),i=vA(t,Kw);return e&&i?Ww:e||i?e?Gw:Kw:vA(t,Vw)?Vw:Hw}(t.join(" "))},e.preventDefaults=function(t){var e=t.srcEvent,i=t.offsetDirection;if(this.manager.session.prevented)e.preventDefault();else{var n=this.actions,o=vA(n,Ww)&&!qw[Ww],r=vA(n,Kw)&&!qw[Kw],s=vA(n,Gw)&&!qw[Gw];if(o){var a=1===t.pointers.length,l=t.distance<2,h=t.deltaTime<250;if(a&&l&&h)return}if(!s||!r)return o||r&&i&lA||s&&i&hA?this.preventSrc(e):void 0}},e.preventSrc=function(t){this.manager.session.prevented=!0,t.preventDefault()},t}();function yA(t,e){for(;t;){if(t===e)return!0;t=t.parentNode}return!1}function mA(t){var e=t.length;if(1===e)return{x:Fw(t[0].clientX),y:Fw(t[0].clientY)};for(var i=0,n=0,o=0;o=Tw(e)?t<0?oA:rA:e<0?sA:aA}function EA(t,e,i){return{x:e/t||0,y:i/t||0}}function CA(t,e){var i=t.session,n=e.pointers,o=n.length;i.firstInput||(i.firstInput=bA(e)),o>1&&!i.firstMultiple?i.firstMultiple=bA(e):1===o&&(i.firstMultiple=!1);var r=i.firstInput,s=i.firstMultiple,a=s?s.center:r.center,l=e.center=mA(n);e.timeStamp=Nw(),e.deltaTime=e.timeStamp-r.timeStamp,e.angle=AA(a,l),e.distance=wA(a,l),function(t,e){var i=e.center,n=t.offsetDelta||{},o=t.prevDelta||{},r=t.prevInput||{};e.eventType!==tA&&r.eventType!==eA||(o=t.prevDelta={x:r.deltaX||0,y:r.deltaY||0},n=t.offsetDelta={x:i.x,y:i.y}),e.deltaX=o.x+(i.x-n.x),e.deltaY=o.y+(i.y-n.y)}(i,e),e.offsetDirection=kA(e.deltaX,e.deltaY);var h,c,d=EA(e.deltaTime,e.deltaX,e.deltaY);e.overallVelocityX=d.x,e.overallVelocityY=d.y,e.overallVelocity=Tw(d.x)>Tw(d.y)?d.x:d.y,e.scale=s?(h=s.pointers,wA((c=n)[0],c[1],uA)/wA(h[0],h[1],uA)):1,e.rotation=s?function(t,e){return AA(e[1],e[0],uA)+AA(t[1],t[0],uA)}(s.pointers,n):0,e.maxPointers=i.prevInput?e.pointers.length>i.prevInput.maxPointers?e.pointers.length:i.prevInput.maxPointers:e.pointers.length,function(t,e){var i,n,o,r,s=t.lastInterval||e,a=e.timeStamp-s.timeStamp;if(e.eventType!==iA&&(a>$w||void 0===s.velocity)){var l=e.deltaX-s.deltaX,h=e.deltaY-s.deltaY,c=EA(a,l,h);n=c.x,o=c.y,i=Tw(c.x)>Tw(c.y)?c.x:c.y,r=kA(l,h),t.lastInterval=e}else i=s.velocity,n=s.velocityX,o=s.velocityY,r=s.direction;e.velocity=i,e.velocityX=n,e.velocityY=o,e.direction=r}(i,e);var u,f=t.element,p=e.srcEvent;yA(u=p.composedPath?p.composedPath()[0]:p.path?p.path[0]:p.target,f)&&(f=u),e.target=f}function xA(t,e,i){var n=i.pointers.length,o=i.changedPointers.length,r=e&tA&&n-o==0,s=e&(eA|iA)&&n-o==0;i.isFirst=!!r,i.isFinal=!!s,r&&(t.session={}),i.eventType=e,CA(t,i),t.emit("hammer.input",i),t.recognize(i),t.session.prevInput=i}function IA(t){return t.trim().split(/\s+/g)}function SA(t,e,i){fA(IA(e),(function(e){t.addEventListener(e,i,!1)}))}function MA(t,e,i){fA(IA(e),(function(e){t.removeEventListener(e,i,!1)}))}function OA(t){var e=t.ownerDocument||t;return e.defaultView||e.parentWindow||window}var DA=function(){function t(t,e){var i=this;this.manager=t,this.callback=e,this.element=t.element,this.target=t.options.inputTarget,this.domHandler=function(e){pA(t.options.enable,[t])&&i.handler(e)},this.init()}var e=t.prototype;return e.handler=function(){},e.init=function(){this.evEl&&SA(this.element,this.evEl,this.domHandler),this.evTarget&&SA(this.target,this.evTarget,this.domHandler),this.evWin&&SA(OA(this.element),this.evWin,this.domHandler)},e.destroy=function(){this.evEl&&MA(this.element,this.evEl,this.domHandler),this.evTarget&&MA(this.target,this.evTarget,this.domHandler),this.evWin&&MA(OA(this.element),this.evWin,this.domHandler)},t}();function RA(t,e,i){if(t.indexOf&&!i)return t.indexOf(e);for(var n=0;ni[e]})):n.sort()),n}var LA={touchstart:tA,touchmove:2,touchend:eA,touchcancel:iA},UA=function(t){function e(){var i;return e.prototype.evTarget="touchstart touchmove touchend touchcancel",(i=t.apply(this,arguments)||this).targetIds={},i}return Ow(e,t),e.prototype.handler=function(t){var e=LA[t.type],i=QA.call(this,t,e);i&&this.callback(this.manager,e,{pointers:i[0],changedPointers:i[1],pointerType:Xw,srcEvent:t})},e}(DA);function QA(t,e){var i,n,o=NA(t.touches),r=this.targetIds;if(e&(2|tA)&&1===o.length)return r[o[0].identifier]=!0,[o,o];var s=NA(t.changedTouches),a=[],l=this.target;if(n=o.filter((function(t){return yA(t.target,l)})),e===tA)for(i=0;i-1&&n.splice(t,1)}),WA)}}function KA(t,e){t&tA?(this.primaryTouch=e.changedPointers[0].identifier,GA.call(this,e)):t&(eA|iA)&&GA.call(this,e)}function qA(t){for(var e=t.srcEvent.clientX,i=t.srcEvent.clientY,n=0;n-1&&this.requireFail.splice(e,1),this},e.hasRequireFailures=function(){return this.requireFail.length>0},e.canRecognizeWith=function(t){return!!this.simultaneous[t.id]},e.emit=function(t){var e=this,i=this.state;function n(i){e.manager.emit(i,t)}i<8&&n(e.options.event+$A(i)),n(e.options.event),t.additionalEvent&&n(t.additionalEvent),i>=8&&n(e.options.event+$A(i))},e.tryEmit=function(t){if(this.canEmit())return this.emit(t);this.state=JA},e.canEmit=function(){for(var t=0;te.threshold&&o&e.direction},i.attrTest=function(t){return ik.prototype.attrTest.call(this,t)&&(2&this.state||!(2&this.state)&&this.directionTest(t))},i.emit=function(e){this.pX=e.deltaX,this.pY=e.deltaY;var i=nk(e.direction);i&&(e.additionalEvent=this.options.event+i),t.prototype.emit.call(this,e)},e}(ik),rk=function(t){function e(e){return void 0===e&&(e={}),t.call(this,Mw({event:"swipe",threshold:10,velocity:.3,direction:lA|hA,pointers:1},e))||this}Ow(e,t);var i=e.prototype;return i.getTouchAction=function(){return ok.prototype.getTouchAction.call(this)},i.attrTest=function(e){var i,n=this.options.direction;return n&(lA|hA)?i=e.overallVelocity:n&lA?i=e.overallVelocityX:n&hA&&(i=e.overallVelocityY),t.prototype.attrTest.call(this,e)&&n&e.offsetDirection&&e.distance>this.options.threshold&&e.maxPointers===this.options.pointers&&Tw(i)>this.options.velocity&&e.eventType&eA},i.emit=function(t){var e=nk(t.offsetDirection);e&&this.manager.emit(this.options.event+e,t),this.manager.emit(this.options.event,t)},e}(ik),sk=function(t){function e(e){return void 0===e&&(e={}),t.call(this,Mw({event:"pinch",threshold:0,pointers:2},e))||this}Ow(e,t);var i=e.prototype;return i.getTouchAction=function(){return[Ww]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.scale-1)>this.options.threshold||2&this.state)},i.emit=function(e){if(1!==e.scale){var i=e.scale<1?"in":"out";e.additionalEvent=this.options.event+i}t.prototype.emit.call(this,e)},e}(ik),ak=function(t){function e(e){return void 0===e&&(e={}),t.call(this,Mw({event:"rotate",threshold:0,pointers:2},e))||this}Ow(e,t);var i=e.prototype;return i.getTouchAction=function(){return[Ww]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.rotation)>this.options.threshold||2&this.state)},e}(ik),lk=function(t){function e(e){var i;return void 0===e&&(e={}),(i=t.call(this,Mw({event:"press",pointers:1,time:251,threshold:9},e))||this)._timer=null,i._input=null,i}Ow(e,t);var i=e.prototype;return i.getTouchAction=function(){return[Hw]},i.process=function(t){var e=this,i=this.options,n=t.pointers.length===i.pointers,o=t.distancei.time;if(this._input=t,!o||!n||t.eventType&(eA|iA)&&!r)this.reset();else if(t.eventType&tA)this.reset(),this._timer=setTimeout((function(){e.state=8,e.tryEmit()}),i.time);else if(t.eventType&eA)return 8;return JA},i.reset=function(){clearTimeout(this._timer)},i.emit=function(t){8===this.state&&(t&&t.eventType&eA?this.manager.emit(this.options.event+"up",t):(this._input.timeStamp=Nw(),this.manager.emit(this.options.event,this._input)))},e}(tk),hk={domEvents:!1,touchAction:Qw,enable:!0,inputTarget:null,inputClass:null,cssProps:{userSelect:"none",touchSelect:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}},ck=[[ak,{enable:!1}],[sk,{enable:!1},["rotate"]],[rk,{direction:lA}],[ok,{direction:lA},["swipe"]],[ek],[ek,{event:"doubletap",taps:2},["tap"]],[lk]];function dk(t,e){var i,n=t.element;n.style&&(fA(t.options.cssProps,(function(o,r){i=jw(n.style,r),e?(t.oldCssProps[i]=n.style[i],n.style[i]=o):n.style[i]=t.oldCssProps[i]||""})),e||(t.oldCssProps={}))}var uk=function(){function t(t,e){var i,n=this;this.options=Bw({},hk,e||{}),this.options.inputTarget=this.options.inputTarget||t,this.handlers={},this.session={},this.recognizers=[],this.oldCssProps={},this.element=t,this.input=new((i=this).options.inputClass||(Zw?TA:Jw?UA:Yw?YA:VA))(i,xA),this.touchAction=new gA(this,this.options.touchAction),dk(this,!0),fA(this.options.recognizers,(function(t){var e=n.add(new t[0](t[1]));t[2]&&e.recognizeWith(t[2]),t[3]&&e.requireFailure(t[3])}),this)}var e=t.prototype;return e.set=function(t){return Bw(this.options,t),t.touchAction&&this.touchAction.update(),t.inputTarget&&(this.input.destroy(),this.input.target=t.inputTarget,this.input.init()),this},e.stop=function(t){this.session.stopped=t?2:1},e.recognize=function(t){var e=this.session;if(!e.stopped){var i;this.touchAction.preventDefaults(t);var n=this.recognizers,o=e.curRecognizer;(!o||o&&8&o.state)&&(e.curRecognizer=null,o=null);for(var r=0;r\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",o=window.console&&(window.console.warn||window.console.log);return o&&o.call(window.console,n,i),t.apply(this,arguments)}}var yk=gk((function(t,e,i){for(var n=Object.keys(e),o=0;o=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function Ck(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i2)return Sk.apply(void 0,Om(n=[Ik(e[0],e[1])]).call(n,km(Dm(e).call(e,2))));var o=e[0],r=e[1];if(o instanceof Date&&r instanceof Date)return o.setTime(r.getTime()),o;var s,a=Ek(Nm(r));try{for(a.s();!(s=a.n()).done;){var l=s.value;Object.prototype.propertyIsEnumerable.call(r,l)&&(r[l]===xk?delete o[l]:null===o[l]||null===r[l]||"object"!=typeof o[l]||"object"!=typeof r[l]||jm(o[l])||jm(r[l])?o[l]=Mk(r[l]):o[l]=Sk(o[l],r[l]))}}catch(t){a.e(t)}finally{a.f()}return o}function Mk(t){return jm(t)?Dg(t).call(t,(function(t){return Mk(t)})):"object"==typeof t&&null!==t?t instanceof Date?new Date(t.getTime()):Sk({},t):t}function Ok(t){for(var e=0,i=Qm(t);e({set:t})}}()};function Rk(t){var e,i=this;this._cleanupQueue=[],this.active=!1,this._dom={container:t,overlay:document.createElement("div")},this._dom.overlay.classList.add("vis-overlay"),this._dom.container.appendChild(this._dom.overlay),this._cleanupQueue.push((function(){i._dom.overlay.parentNode.removeChild(i._dom.overlay)}));var n=Dk(this._dom.overlay);n.on("tap",$v(e=this._onTapOverlay).call(e,this)),this._cleanupQueue.push((function(){n.destroy()}));var o=["tap","doubletap","press","pinch","pan","panstart","panmove","panend"];_m(o).call(o,(function(t){n.on(t,(function(t){t.srcEvent.stopPropagation()}))})),document&&document.body&&(this._onClick=function(e){(function(t,e){for(;t;){if(t===e)return!0;t=t.parentNode}return!1})(e.target,t)||i.deactivate()},document.body.addEventListener("click",this._onClick),this._cleanupQueue.push((function(){document.body.removeEventListener("click",i._onClick)}))),this._escListener=function(t){("key"in t?"Escape"===t.key:27===t.keyCode)&&i.deactivate()}}Sw(Rk.prototype),Rk.current=null,Rk.prototype.destroy=function(){var t,e;this.deactivate();var i,n=Ek(hb(t=Rb(e=this._cleanupQueue).call(e,0)).call(t));try{for(n.s();!(i=n.n()).done;){(0,i.value)()}}catch(t){n.e(t)}finally{n.f()}},Rk.prototype.activate=function(){Rk.current&&Rk.current.deactivate(),Rk.current=this,this.active=!0,this._dom.overlay.style.display="none",this._dom.container.classList.add("vis-active"),this.emit("change"),this.emit("activate"),document.body.addEventListener("keydown",this._escListener)},Rk.prototype.deactivate=function(){this.active=!1,this._dom.overlay.style.display="block",this._dom.container.classList.remove("vis-active"),document.body.removeEventListener("keydown",this._escListener),this.emit("change"),this.emit("deactivate")},Rk.prototype._onTapOverlay=function(t){this.activate(),t.srcEvent.stopPropagation()};var Bk=wl,zk=Ar,Pk=TypeError,Fk=function(t){if(Bk(t))return t;throw new Pk(zk(t)+" is not a constructor")},Tk=ka,Nk=oo,jk=Hv,Lk=Fk,Uk=Js,Qk=Yo,Hk=Uh,Vk=_n,Wk=tr("Reflect","construct"),Gk=Object.prototype,Kk=[].push,qk=Vk((function(){function t(){}return!(Wk((function(){}),[],t)instanceof t)})),Yk=!Vk((function(){Wk((function(){}))})),Zk=qk||Yk;Tk({target:"Reflect",stat:!0,forced:Zk,sham:Zk},{construct:function(t,e){Lk(t),Uk(e);var i=arguments.length<3?t:Lk(arguments[2]);if(Yk&&!qk)return Wk(t,e,i);if(t===i){switch(e.length){case 0:return new t;case 1:return new t(e[0]);case 2:return new t(e[0],e[1]);case 3:return new t(e[0],e[1],e[2]);case 4:return new t(e[0],e[1],e[2],e[3])}var n=[null];return Nk(Kk,n,e),new(Nk(jk,t,n))}var o=i.prototype,r=Hk(Qk(o)?o:Gk),s=Nk(t,r,e);return Qk(s)?s:r}});var Jk=Yn(Zo.Reflect.construct),Xk=Yn(Zo.Object.getOwnPropertySymbols),_k={exports:{}},$k=ka,tE=_n,eE=Go,iE=ko.f,nE=Eo;$k({target:"Object",stat:!0,forced:!nE||tE((function(){iE(1)})),sham:!nE},{getOwnPropertyDescriptor:function(t,e){return iE(eE(t),e)}});var oE=Zo.Object,rE=_k.exports=function(t,e){return oE.getOwnPropertyDescriptor(t,e)};oE.getOwnPropertyDescriptor.sham&&(rE.sham=!0);var sE=Yn(_k.exports),aE=Tm,lE=Go,hE=ko,cE=qa;ka({target:"Object",stat:!0,sham:!Eo},{getOwnPropertyDescriptors:function(t){for(var e,i,n=lE(t),o=hE.f,r=aE(n),s={},a=0;r.length>a;)void 0!==(i=o(n,e=r[a++]))&&cE(s,e,i);return s}});var dE=Yn(Zo.Object.getOwnPropertyDescriptors),uE={exports:{}},fE=ka,pE=Eo,vE=Zl.f;fE({target:"Object",stat:!0,forced:Object.defineProperties!==vE,sham:!pE},{defineProperties:vE});var gE=Zo.Object,yE=uE.exports=function(t,e){return gE.defineProperties(t,e)};gE.defineProperties.sham&&(yE.sham=!0);var mE=Yn(uE.exports),bE=Yn(Ma);function wE(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}var AE=$b,kE=Yn(AE);ka({target:"Object",stat:!0},{setPrototypeOf:$f});var EE=Zo.Object.setPrototypeOf,CE=Yn(EE),xE=Yn(_v);function IE(t,e){var i;return IE=CE?xE(i=CE).call(i):function(t,e){return t.__proto__=e,t},IE(t,e)}var SE=Jb,ME=Yn(SE);function OE(t){var e;return OE=CE?xE(e=ME).call(e):function(t){return t.__proto__||ME(t)},OE(t)}var DE={exports:{}},RE={exports:{}};!function(t){var e=rv,i=Cv;function n(o){return t.exports=n="function"==typeof e&&"symbol"==typeof i?function(t){return typeof t}:function(t){return t&&"function"==typeof e&&t.constructor===e&&t!==e.prototype?"symbol":typeof t},t.exports.__esModule=!0,t.exports.default=t.exports,n(o)}t.exports=n,t.exports.__esModule=!0,t.exports.default=t.exports}(RE);var BE=RE.exports,zE=Xm,PE=Kr,FE=Tm,TE=ko,NE=Gs,jE=Yo,LE=ca,UE=Error,QE=ho("".replace),HE=String(new UE("zxcasd").stack),VE=/\n\s*at [^:]*:[^\n]*/,WE=VE.test(HE),GE=zo,KE=!_n((function(){var t=new Error("a");return!("stack"in t)||(Object.defineProperty(t,"stack",GE(1,7)),7!==t.stack)})),qE=ca,YE=function(t,e){if(WE&&"string"==typeof t&&!UE.prepareStackTrace)for(;e--;)t=QE(t,VE,"");return t},ZE=KE,JE=Error.captureStackTrace,XE=Ws,_E=Io,$E=Js,tC=Ar,eC=Jg,iC=Qa,nC=er,oC=hy,rC=iy,sC=Wg,aC=TypeError,lC=function(t,e){this.stopped=t,this.result=e},hC=lC.prototype,cC=function(t,e,i){var n,o,r,s,a,l,h,c=i&&i.that,d=!(!i||!i.AS_ENTRIES),u=!(!i||!i.IS_RECORD),f=!(!i||!i.IS_ITERATOR),p=!(!i||!i.INTERRUPTED),v=XE(e,c),g=function(t){return n&&sC(n,"normal",t),new lC(!0,t)},y=function(t){return d?($E(t),p?v(t[0],t[1],g):v(t[0],t[1])):p?v(t,g):v(t)};if(u)n=t.iterator;else if(f)n=t;else{if(!(o=rC(t)))throw new aC(tC(t)+" is not iterable");if(eC(o)){for(r=0,s=iC(t);s>r;r++)if((a=y(t[r]))&&nC(hC,a))return a;return new lC(!1)}n=oC(t,o)}for(l=u?t.next:n.next;!(h=_E(l,n)).done;){try{a=y(h.value)}catch(t){sC(n,"throw",t)}if("object"==typeof a&&a&&nC(hC,a))return a}return new lC(!1)},dC=Yl,uC=ka,fC=er,pC=Mf,vC=$f,gC=function(t,e,i){for(var n=FE(e),o=NE.f,r=TE.f,s=0;s2&&wC(i,arguments[2]);var o=[];return kC(t,IC,{that:o}),mC(i,"errors",o),i};vC?vC(SC,xC):gC(SC,xC,{name:!0});var MC=SC.prototype=yC(xC.prototype,{constructor:bC(1,SC),message:bC(1,""),name:bC(1,"AggregateError")});uC({global:!0,constructor:!0,arity:2},{AggregateError:SC});var OC,DC,RC,BC,zC=tr,PC=sc,FC=Eo,TC=ss("species"),NC=function(t){var e=zC(t);FC&&e&&!e[TC]&&PC(e,TC,{configurable:!0,get:function(){return this}})},jC=er,LC=TypeError,UC=function(t,e){if(jC(e,t))return t;throw new LC("Incorrect invocation")},QC=Js,HC=Fk,VC=Lo,WC=ss("species"),GC=function(t,e){var i,n=QC(t).constructor;return void 0===n||VC(i=QC(n)[WC])?e:HC(i)},KC=/(?:ipad|iphone|ipod).*applewebkit/i.test(ir),qC=Xn,YC=oo,ZC=Ws,JC=Ao,XC=Kr,_C=_n,$C=Eh,tx=Iu,ex=ws,ix=aw,nx=KC,ox=hg,rx=qC.setImmediate,sx=qC.clearImmediate,ax=qC.process,lx=qC.Dispatch,hx=qC.Function,cx=qC.MessageChannel,dx=qC.String,ux=0,fx={},px="onreadystatechange";_C((function(){OC=qC.location}));var vx=function(t){if(XC(fx,t)){var e=fx[t];delete fx[t],e()}},gx=function(t){return function(){vx(t)}},yx=function(t){vx(t.data)},mx=function(t){qC.postMessage(dx(t),OC.protocol+"//"+OC.host)};rx&&sx||(rx=function(t){ix(arguments.length,1);var e=JC(t)?t:hx(t),i=tx(arguments,1);return fx[++ux]=function(){YC(e,void 0,i)},DC(ux),ux},sx=function(t){delete fx[t]},ox?DC=function(t){ax.nextTick(gx(t))}:lx&&lx.now?DC=function(t){lx.now(gx(t))}:cx&&!nx?(BC=(RC=new cx).port2,RC.port1.onmessage=yx,DC=ZC(BC.postMessage,BC)):qC.addEventListener&&JC(qC.postMessage)&&!qC.importScripts&&OC&&"file:"!==OC.protocol&&!_C(mx)?(DC=mx,qC.addEventListener("message",yx,!1)):DC=px in ex("script")?function(t){$C.appendChild(ex("script"))[px]=function(){$C.removeChild(this),vx(t)}}:function(t){setTimeout(gx(t),0)});var bx={set:rx,clear:sx},wx=function(){this.head=null,this.tail=null};wx.prototype={add:function(t){var e={item:t,next:null},i=this.tail;i?i.next=e:this.head=e,this.tail=e},get:function(){var t=this.head;if(t)return null===(this.head=t.next)&&(this.tail=null),t.item}};var Ax,kx,Ex,Cx,xx,Ix=wx,Sx=/ipad|iphone|ipod/i.test(ir)&&"undefined"!=typeof Pebble,Mx=/web0s(?!.*chrome)/i.test(ir),Ox=Xn,Dx=Ws,Rx=ko.f,Bx=bx.set,zx=Ix,Px=KC,Fx=Sx,Tx=Mx,Nx=hg,jx=Ox.MutationObserver||Ox.WebKitMutationObserver,Lx=Ox.document,Ux=Ox.process,Qx=Ox.Promise,Hx=Rx(Ox,"queueMicrotask"),Vx=Hx&&Hx.value;if(!Vx){var Wx=new zx,Gx=function(){var t,e;for(Nx&&(t=Ux.domain)&&t.exit();e=Wx.get();)try{e()}catch(t){throw Wx.head&&Ax(),t}t&&t.enter()};Px||Nx||Tx||!jx||!Lx?!Fx&&Qx&&Qx.resolve?((Cx=Qx.resolve(void 0)).constructor=Qx,xx=Dx(Cx.then,Cx),Ax=function(){xx(Gx)}):Nx?Ax=function(){Ux.nextTick(Gx)}:(Bx=Dx(Bx,Ox),Ax=function(){Bx(Gx)}):(kx=!0,Ex=Lx.createTextNode(""),new jx(Gx).observe(Ex,{characterData:!0}),Ax=function(){Ex.data=kx=!kx}),Vx=function(t){Wx.head||Ax(),Wx.add(t)}}var Kx=Vx,qx=function(t){try{return{error:!1,value:t()}}catch(t){return{error:!0,value:t}}},Yx=Xn.Promise,Zx="object"==typeof Deno&&Deno&&"object"==typeof Deno.version,Jx=!Zx&&!hg&&"object"==typeof window&&"object"==typeof document,Xx=Xn,_x=Yx,$x=Ao,tI=Us,eI=sl,iI=ss,nI=Jx,oI=Zx,rI=hr,sI=_x&&_x.prototype,aI=iI("species"),lI=!1,hI=$x(Xx.PromiseRejectionEvent),cI=tI("Promise",(function(){var t=eI(_x),e=t!==String(_x);if(!e&&66===rI)return!0;if(!sI.catch||!sI.finally)return!0;if(!rI||rI<51||!/native code/.test(t)){var i=new _x((function(t){t(1)})),n=function(t){t((function(){}),(function(){}))};if((i.constructor={})[aI]=n,!(lI=i.then((function(){}))instanceof n))return!0}return!e&&(nI||oI)&&!hI})),dI={CONSTRUCTOR:cI,REJECTION_EVENT:hI,SUBCLASSING:lI},uI={},fI=xr,pI=TypeError,vI=function(t){var e,i;this.promise=new t((function(t,n){if(void 0!==e||void 0!==i)throw new pI("Bad Promise constructor");e=t,i=n})),this.resolve=fI(e),this.reject=fI(i)};uI.f=function(t){return new vI(t)};var gI,yI,mI=ka,bI=hg,wI=Xn,AI=Io,kI=oc,EI=Dc,CI=NC,xI=xr,II=Ao,SI=Yo,MI=UC,OI=GC,DI=bx.set,RI=Kx,BI=function(t,e){try{1===arguments.length?console.error(t):console.error(t,e)}catch(t){}},zI=qx,PI=Ix,FI=Kc,TI=Yx,NI=uI,jI="Promise",LI=dI.CONSTRUCTOR,UI=dI.REJECTION_EVENT,QI=FI.getterFor(jI),HI=FI.set,VI=TI&&TI.prototype,WI=TI,GI=VI,KI=wI.TypeError,qI=wI.document,YI=wI.process,ZI=NI.f,JI=ZI,XI=!!(qI&&qI.createEvent&&wI.dispatchEvent),_I="unhandledrejection",$I=function(t){var e;return!(!SI(t)||!II(e=t.then))&&e},tS=function(t,e){var i,n,o,r=e.value,s=1===e.state,a=s?t.ok:t.fail,l=t.resolve,h=t.reject,c=t.domain;try{a?(s||(2===e.rejection&&rS(e),e.rejection=1),!0===a?i=r:(c&&c.enter(),i=a(r),c&&(c.exit(),o=!0)),i===t.promise?h(new KI("Promise-chain cycle")):(n=$I(i))?AI(n,i,l,h):l(i)):h(r)}catch(t){c&&!o&&c.exit(),h(t)}},eS=function(t,e){t.notified||(t.notified=!0,RI((function(){for(var i,n=t.reactions;i=n.get();)tS(i,t);t.notified=!1,e&&!t.rejection&&nS(t)})))},iS=function(t,e,i){var n,o;XI?((n=qI.createEvent("Event")).promise=e,n.reason=i,n.initEvent(t,!1,!0),wI.dispatchEvent(n)):n={promise:e,reason:i},!UI&&(o=wI["on"+t])?o(n):t===_I&&BI("Unhandled promise rejection",i)},nS=function(t){AI(DI,wI,(function(){var e,i=t.facade,n=t.value;if(oS(t)&&(e=zI((function(){bI?YI.emit("unhandledRejection",n,i):iS(_I,i,n)})),t.rejection=bI||oS(t)?2:1,e.error))throw e.value}))},oS=function(t){return 1!==t.rejection&&!t.parent},rS=function(t){AI(DI,wI,(function(){var e=t.facade;bI?YI.emit("rejectionHandled",e):iS("rejectionhandled",e,t.value)}))},sS=function(t,e,i){return function(n){t(e,n,i)}},aS=function(t,e,i){t.done||(t.done=!0,i&&(t=i),t.value=e,t.state=2,eS(t,!0))},lS=function(t,e,i){if(!t.done){t.done=!0,i&&(t=i);try{if(t.facade===e)throw new KI("Promise can't be resolved itself");var n=$I(e);n?RI((function(){var i={done:!1};try{AI(n,e,sS(lS,i,t),sS(aS,i,t))}catch(e){aS(i,e,t)}})):(t.value=e,t.state=1,eS(t,!1))}catch(e){aS({done:!1},e,t)}}};LI&&(GI=(WI=function(t){MI(this,GI),xI(t),AI(gI,this);var e=QI(this);try{t(sS(lS,e),sS(aS,e))}catch(t){aS(e,t)}}).prototype,(gI=function(t){HI(this,{type:jI,done:!1,notified:!1,parent:!1,reactions:new PI,rejection:!1,state:0,value:void 0})}).prototype=kI(GI,"then",(function(t,e){var i=QI(this),n=ZI(OI(this,WI));return i.parent=!0,n.ok=!II(t)||t,n.fail=II(e)&&e,n.domain=bI?YI.domain:void 0,0===i.state?i.reactions.add(n):RI((function(){tS(n,i)})),n.promise})),yI=function(){var t=new gI,e=QI(t);this.promise=t,this.resolve=sS(lS,e),this.reject=sS(aS,e)},NI.f=ZI=function(t){return t===WI||undefined===t?new yI(t):JI(t)}),mI({global:!0,constructor:!0,wrap:!0,forced:LI},{Promise:WI}),EI(WI,jI,!1,!0),CI(jI);var hS=Yx,cS=dI.CONSTRUCTOR||!xy((function(t){hS.all(t).then(void 0,(function(){}))})),dS=Io,uS=xr,fS=uI,pS=qx,vS=cC;ka({target:"Promise",stat:!0,forced:cS},{all:function(t){var e=this,i=fS.f(e),n=i.resolve,o=i.reject,r=pS((function(){var i=uS(e.resolve),r=[],s=0,a=1;vS(t,(function(t){var l=s++,h=!1;a++,dS(i,e,t).then((function(t){h||(h=!0,r[l]=t,--a||n(r))}),o)})),--a||n(r)}));return r.error&&o(r.value),i.promise}});var gS=ka,yS=dI.CONSTRUCTOR;Yx&&Yx.prototype,gS({target:"Promise",proto:!0,forced:yS,real:!0},{catch:function(t){return this.then(void 0,t)}});var mS=Io,bS=xr,wS=uI,AS=qx,kS=cC;ka({target:"Promise",stat:!0,forced:cS},{race:function(t){var e=this,i=wS.f(e),n=i.reject,o=AS((function(){var o=bS(e.resolve);kS(t,(function(t){mS(o,e,t).then(i.resolve,n)}))}));return o.error&&n(o.value),i.promise}});var ES=Io,CS=uI;ka({target:"Promise",stat:!0,forced:dI.CONSTRUCTOR},{reject:function(t){var e=CS.f(this);return ES(e.reject,void 0,t),e.promise}});var xS=Js,IS=Yo,SS=uI,MS=function(t,e){if(xS(t),IS(e)&&e.constructor===t)return e;var i=SS.f(t);return(0,i.resolve)(e),i.promise},OS=ka,DS=Yx,RS=dI.CONSTRUCTOR,BS=MS,zS=tr("Promise"),PS=!RS;OS({target:"Promise",stat:!0,forced:true},{resolve:function(t){return BS(PS&&this===zS?DS:this,t)}});var FS=Io,TS=xr,NS=uI,jS=qx,LS=cC;ka({target:"Promise",stat:!0,forced:cS},{allSettled:function(t){var e=this,i=NS.f(e),n=i.resolve,o=i.reject,r=jS((function(){var i=TS(e.resolve),o=[],r=0,s=1;LS(t,(function(t){var a=r++,l=!1;s++,FS(i,e,t).then((function(t){l||(l=!0,o[a]={status:"fulfilled",value:t},--s||n(o))}),(function(t){l||(l=!0,o[a]={status:"rejected",reason:t},--s||n(o))}))})),--s||n(o)}));return r.error&&o(r.value),i.promise}});var US=Io,QS=xr,HS=tr,VS=uI,WS=qx,GS=cC,KS="No one promise resolved";ka({target:"Promise",stat:!0,forced:cS},{any:function(t){var e=this,i=HS("AggregateError"),n=VS.f(e),o=n.resolve,r=n.reject,s=WS((function(){var n=QS(e.resolve),s=[],a=0,l=1,h=!1;GS(t,(function(t){var c=a++,d=!1;l++,US(n,e,t).then((function(t){d||h||(h=!0,o(t))}),(function(t){d||h||(d=!0,s[c]=t,--l||r(new i(s,KS)))}))})),--l||r(new i(s,KS))}));return s.error&&r(s.value),n.promise}});var qS=ka,YS=Yx,ZS=_n,JS=tr,XS=Ao,_S=GC,$S=MS,tM=YS&&YS.prototype;qS({target:"Promise",proto:!0,real:!0,forced:!!YS&&ZS((function(){tM.finally.call({then:function(){}},(function(){}))}))},{finally:function(t){var e=_S(this,JS("Promise")),i=XS(t);return this.then(i?function(i){return $S(e,t()).then((function(){return i}))}:t,i?function(i){return $S(e,t()).then((function(){throw i}))}:t)}});var eM=Zo.Promise,iM=uI;ka({target:"Promise",stat:!0},{withResolvers:function(){var t=iM.f(this);return{promise:t.promise,resolve:t.resolve,reject:t.reject}}});var nM=eM,oM=uI,rM=qx;ka({target:"Promise",stat:!0,forced:!0},{try:function(t){var e=oM.f(this),i=rM(t);return(i.error?e.reject:e.resolve)(i.value),e.promise}});var sM=nM,aM=lb;!function(t){var e=BE.default,i=Oa,n=rv,o=AE,r=SE,s=zE,a=Yy,l=EE,h=sM,c=aM,d=gm;function u(){t.exports=u=function(){return p},t.exports.__esModule=!0,t.exports.default=t.exports;var f,p={},v=Object.prototype,g=v.hasOwnProperty,y=i||function(t,e,i){t[e]=i.value},m="function"==typeof n?n:{},b=m.iterator||"@@iterator",w=m.asyncIterator||"@@asyncIterator",A=m.toStringTag||"@@toStringTag";function k(t,e,n){return i(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{k({},"")}catch(f){k=function(t,e,i){return t[e]=i}}function E(t,e,i,n){var r=e&&e.prototype instanceof D?e:D,s=o(r.prototype),a=new H(n||[]);return y(s,"_invoke",{value:j(t,i,a)}),s}function C(t,e,i){try{return{type:"normal",arg:t.call(e,i)}}catch(t){return{type:"throw",arg:t}}}p.wrap=E;var x="suspendedStart",I="suspendedYield",S="executing",M="completed",O={};function D(){}function R(){}function B(){}var z={};k(z,b,(function(){return this}));var P=r&&r(r(V([])));P&&P!==v&&g.call(P,b)&&(z=P);var F=B.prototype=D.prototype=o(z);function T(t){var e;s(e=["next","throw","return"]).call(e,(function(e){k(t,e,(function(t){return this._invoke(e,t)}))}))}function N(t,i){function n(o,r,s,a){var l=C(t[o],t,r);if("throw"!==l.type){var h=l.arg,c=h.value;return c&&"object"==e(c)&&g.call(c,"__await")?i.resolve(c.__await).then((function(t){n("next",t,s,a)}),(function(t){n("throw",t,s,a)})):i.resolve(c).then((function(t){h.value=t,s(h)}),(function(t){return n("throw",t,s,a)}))}a(l.arg)}var o;y(this,"_invoke",{value:function(t,e){function r(){return new i((function(i,o){n(t,e,i,o)}))}return o=o?o.then(r,r):r()}})}function j(t,e,i){var n=x;return function(o,r){if(n===S)throw new Error("Generator is already running");if(n===M){if("throw"===o)throw r;return{value:f,done:!0}}for(i.method=o,i.arg=r;;){var s=i.delegate;if(s){var a=L(s,i);if(a){if(a===O)continue;return a}}if("next"===i.method)i.sent=i._sent=i.arg;else if("throw"===i.method){if(n===x)throw n=M,i.arg;i.dispatchException(i.arg)}else"return"===i.method&&i.abrupt("return",i.arg);n=S;var l=C(t,e,i);if("normal"===l.type){if(n=i.done?M:I,l.arg===O)continue;return{value:l.arg,done:i.done}}"throw"===l.type&&(n=M,i.method="throw",i.arg=l.arg)}}}function L(t,e){var i=e.method,n=t.iterator[i];if(n===f)return e.delegate=null,"throw"===i&&t.iterator.return&&(e.method="return",e.arg=f,L(t,e),"throw"===e.method)||"return"!==i&&(e.method="throw",e.arg=new TypeError("The iterator does not provide a '"+i+"' method")),O;var o=C(n,t.iterator,e.arg);if("throw"===o.type)return e.method="throw",e.arg=o.arg,e.delegate=null,O;var r=o.arg;return r?r.done?(e[t.resultName]=r.value,e.next=t.nextLoc,"return"!==e.method&&(e.method="next",e.arg=f),e.delegate=null,O):r:(e.method="throw",e.arg=new TypeError("iterator result is not an object"),e.delegate=null,O)}function U(t){var e,i={tryLoc:t[0]};1 in t&&(i.catchLoc=t[1]),2 in t&&(i.finallyLoc=t[2],i.afterLoc=t[3]),a(e=this.tryEntries).call(e,i)}function Q(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function H(t){this.tryEntries=[{tryLoc:"root"}],s(t).call(t,U,this),this.reset(!0)}function V(t){if(t||""===t){var i=t[b];if(i)return i.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var n=-1,o=function e(){for(;++n=0;--n){var o=this.tryEntries[n],r=o.completion;if("root"===o.tryLoc)return i("end");if(o.tryLoc<=this.prev){var s=g.call(o,"catchLoc"),a=g.call(o,"finallyLoc");if(s&&a){if(this.prev=0;--i){var n=this.tryEntries[i];if(n.tryLoc<=this.prev&&g.call(n,"finallyLoc")&&this.prev=0;--e){var i=this.tryEntries[e];if(i.finallyLoc===t)return this.complete(i.completion,i.afterLoc),Q(i),O}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var i=this.tryEntries[e];if(i.tryLoc===t){var n=i.completion;if("throw"===n.type){var o=n.arg;Q(i)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,e,i){return this.delegate={iterator:V(t),resultName:e,nextLoc:i},"next"===this.method&&(this.arg=f),O}},p}t.exports=u,t.exports.__esModule=!0,t.exports.default=t.exports}(DE);var lM=(0,DE.exports)(),hM=lM;try{regeneratorRuntime=lM}catch(t){"object"==typeof globalThis?globalThis.regeneratorRuntime=lM:Function("r","regeneratorRuntime = r")(lM)}var cM=Yn(hM),dM={exports:{}},uM=_n((function(){if("function"==typeof ArrayBuffer){var t=new ArrayBuffer(8);Object.isExtensible(t)&&Object.defineProperty(t,"a",{value:8})}})),fM=_n,pM=Yo,vM=po,gM=uM,yM=Object.isExtensible,mM=fM((function(){yM(1)}))||gM?function(t){return!!pM(t)&&((!gM||"ArrayBuffer"!==vM(t))&&(!yM||yM(t)))}:yM,bM=!_n((function(){return Object.isExtensible(Object.preventExtensions({}))})),wM=ka,AM=ho,kM=rh,EM=Yo,CM=Kr,xM=Gs.f,IM=Qh,SM=Wh,MM=mM,OM=bM,DM=!1,RM=Xr("meta"),BM=0,zM=function(t){xM(t,RM,{value:{objectID:"O"+BM++,weakData:{}}})},PM=dM.exports={enable:function(){PM.enable=function(){},DM=!0;var t=IM.f,e=AM([].splice),i={};i[RM]=1,t(i).length&&(IM.f=function(i){for(var n=t(i),o=0,r=n.length;o1?arguments[1]:void 0);e=e?e.next:i.first;)for(n(e.value,e.key,this);e&&e.removed;)e=e.previous},has:function(t){return!!l(this,t)}}),iO(r,i?{get:function(t){var e=l(this,t);return e&&e.value},set:function(t,e){return a(this,0===t?0:t,e)}}:{add:function(t){return a(this,t=0===t?0:t,t)}}),cO&&eO(r,"size",{configurable:!0,get:function(){return s(this).size}}),o},setStrong:function(t,e,i){var n=e+" Iterator",o=fO(e),r=fO(n);aO(t,e,(function(t,e){uO(this,{type:n,target:t,state:o(t),kind:e,last:void 0})}),(function(){for(var t=r(this),e=t.kind,i=t.last;i&&i.removed;)i=i.previous;return t.target&&(t.last=i=i?i.next:t.state.first)?lO("keys"===e?i.key:"values"===e?i.value:[i.key,i.value],!1):(t.target=void 0,lO(void 0,!0))}),i?"entries":"values",!i,!0),hO(e)}};_M("Map",(function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}}),pO);var vO=Yn(Zo.Map),gO=td.some;ka({target:"Array",proto:!0,forced:!lg("some")},{some:function(t){return gO(this,t,arguments.length>1?arguments[1]:void 0)}});var yO=Kv("Array","some"),mO=er,bO=yO,wO=Array.prototype,AO=function(t){var e=t.some;return t===wO||mO(wO,t)&&e===wO.some?bO:e},kO=Yn(AO),EO=Kv("Array","keys"),CO=il,xO=Kr,IO=er,SO=EO,MO=Array.prototype,OO={DOMTokenList:!0,NodeList:!0},DO=function(t){var e=t.keys;return t===MO||IO(MO,t)&&e===MO.keys||xO(OO,CO(t))?SO:e},RO=Yn(DO),BO=Jh,zO=Math.floor,PO=function(t,e){var i=t.length,n=zO(i/2);return i<8?FO(t,e):TO(t,PO(BO(t,0,n),e),PO(BO(t,n),e),e)},FO=function(t,e){for(var i,n,o=t.length,r=1;r0;)t[n]=t[--n];n!==r++&&(t[n]=i)}return t},TO=function(t,e,i,n){for(var o=e.length,r=i.length,s=0,a=0;s3)){if(tD)return!0;if(iD)return iD<603;var t,e,i,n,o="";for(t=65;t<76;t++){switch(e=String.fromCharCode(t),t){case 66:case 69:case 70:case 72:i=3;break;case 68:case 71:i=4;break;default:i=2}for(n=0;n<47;n++)nD.push({k:e+n,v:i})}for(nD.sort((function(t,e){return e.v-t.v})),n=0;nZO(i)?1:-1}}(t)),i=qO(o),n=0;nthis.max&&this.flush(),null!=this._timeout&&(clearTimeout(this._timeout),this._timeout=null),this.queue.length>0&&"number"==typeof this.delay&&(this._timeout=Cw((function(){t.flush()}),this.delay))}},{key:"flush",value:function(){var t,e;_m(t=Rb(e=this._queue).call(e,0)).call(t,(function(t){t.fn.apply(t.context||t.fn,t.args||[])}))}}],[{key:"extend",value:function(e,i){var n=new t(i);if(void 0!==e.flush)throw new Error("Target object already has a property flush");e.flush=function(){n.flush()};var o=[{name:"flush",original:void 0}];if(i&&i.replace)for(var r=0;r=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function qD(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);icM.mark((function e(){var n,o,r,s,a;return cM.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:n=KD(i),e.prev=1,n.s();case 3:if((o=n.n()).done){e.next=10;break}if(r=Am(o.value,2),s=r[0],a=r[1],!t(a,s)){e.next=8;break}return e.next=8,[s,a];case 8:e.next=3;break;case 10:e.next=15;break;case 12:e.prev=12,e.t0=e.catch(1),n.e(e.t0);case 15:return e.prev=15,n.f(),e.finish(15);case 18:case"end":return e.stop()}}),e,null,[[1,12,15,18]])}))()})}},{key:"forEach",value:function(t){var e,i=KD(this._pairs);try{for(i.s();!(e=i.n()).done;){var n=Am(e.value,2),o=n[0];t(n[1],o)}}catch(t){i.e(t)}finally{i.f()}}},{key:"map",value:function(t){var i=this._pairs;return new e({[xD]:()=>cM.mark((function e(){var n,o,r,s,a;return cM.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:n=KD(i),e.prev=1,n.s();case 3:if((o=n.n()).done){e.next=9;break}return r=Am(o.value,2),s=r[0],a=r[1],e.next=7,[s,t(a,s)];case 7:e.next=3;break;case 9:e.next=14;break;case 11:e.prev=11,e.t0=e.catch(1),n.e(e.t0);case 14:return e.prev=14,n.f(),e.finish(14);case 17:case"end":return e.stop()}}),e,null,[[1,11,14,17]])}))()})}},{key:"max",value:function(t){var e=GD(this._pairs),i=e.next();if(i.done)return null;for(var n=i.value[1],o=t(i.value[1],i.value[0]);!(i=e.next()).done;){var r=Am(i.value,2),s=r[0],a=r[1],l=t(a,s);l>o&&(o=l,n=a)}return n}},{key:"min",value:function(t){var e=GD(this._pairs),i=e.next();if(i.done)return null;for(var n=i.value[1],o=t(i.value[1],i.value[0]);!(i=e.next()).done;){var r=Am(i.value,2),s=r[0],a=r[1],l=t(a,s);l=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function _D(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i1?i-1:0),o=1;oo?1:no)&&(n=s,o=a)}}catch(t){r.e(t)}finally{r.f()}return n||null}},{key:"min",value:function(t){var e,i,n=null,o=null,r=XD(CD(e=this._data).call(e));try{for(r.s();!(i=r.n()).done;){var s=i.value,a=s[t];"number"==typeof a&&(null==o||acM.mark((function i(){var n,o,r,s;return cM.wrap((function(i){for(;;)switch(i.prev=i.next){case 0:n=XD(t),i.prev=1,n.s();case 3:if((o=n.n()).done){i.next=11;break}if(r=o.value,null==(s=e.get(r))){i.next=9;break}return i.next=9,[r,s];case 9:i.next=3;break;case 11:i.next=16;break;case 13:i.prev=13,i.t0=i.catch(1),n.e(i.t0);case 16:return i.prev=16,n.f(),i.finish(16);case 19:case"end":return i.stop()}}),i,null,[[1,13,16,19]])}))()})}var i;return new YD({[xD]:$v(i=PD(this._data)).call(i,this._data)})}}]),i}(VD);function eR(t,e){return"object"==typeof e&&null!==e&&t===e.idProp&&"function"==typeof _m(e)&&"function"==typeof e.get&&"function"==typeof e.getDataSet&&"function"==typeof e.getIds&&"number"==typeof e.length&&"function"==typeof Dg(e)&&"function"==typeof e.off&&"function"==typeof e.on&&"function"==typeof e.stream&&function(t,e){return"object"==typeof e&&null!==e&&t===e.idProp&&"function"==typeof e.add&&"function"==typeof e.clear&&"function"==typeof e.distinct&&"function"==typeof _m(e)&&"function"==typeof e.get&&"function"==typeof e.getDataSet&&"function"==typeof e.getIds&&"number"==typeof e.length&&"function"==typeof Dg(e)&&"function"==typeof e.max&&"function"==typeof e.min&&"function"==typeof e.off&&"function"==typeof e.on&&"function"==typeof e.remove&&"function"==typeof e.setOptions&&"function"==typeof e.stream&&"function"==typeof e.update&&"function"==typeof e.updateOnly}(t,e.getDataSet())} -/** - * vis-network - * https://visjs.github.io/vis-network/ - * - * A dynamic, browser-based visualization library. - * - * @version 9.1.9 - * @date 2023-11-03T01:42:27.418Z - * - * @copyright (c) 2011-2017 Almende B.V, http://almende.com - * @copyright (c) 2017-2019 visjs contributors, https://github.com/visjs - * - * @license - * vis.js is dual licensed under both - * - * 1. The Apache 2.0 License - * http://www.apache.org/licenses/LICENSE-2.0 - * - * and - * - * 2. The MIT License - * http://opensource.org/licenses/MIT - * - * vis.js may be distributed under either license. - */var iR="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function nR(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var oR=function(t){return t&&t.Math===Math&&t},rR=oR("object"==typeof globalThis&&globalThis)||oR("object"==typeof window&&window)||oR("object"==typeof self&&self)||oR("object"==typeof iR&&iR)||function(){return this}()||iR||Function("return this")(),sR=function(t){try{return!!t()}catch(t){return!0}},aR=!sR((function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")})),lR=aR,hR=Function.prototype,cR=hR.apply,dR=hR.call,uR="object"==typeof Reflect&&Reflect.apply||(lR?dR.bind(cR):function(){return dR.apply(cR,arguments)}),fR=aR,pR=Function.prototype,vR=pR.call,gR=fR&&pR.bind.bind(vR,vR),yR=fR?gR:function(t){return function(){return vR.apply(t,arguments)}},mR=yR,bR=mR({}.toString),wR=mR("".slice),AR=function(t){return wR(bR(t),8,-1)},kR=AR,ER=yR,CR=function(t){if("Function"===kR(t))return ER(t)},xR="object"==typeof document&&document.all,IR={all:xR,IS_HTMLDDA:void 0===xR&&void 0!==xR},SR=IR.all,MR=IR.IS_HTMLDDA?function(t){return"function"==typeof t||t===SR}:function(t){return"function"==typeof t},OR={},DR=!sR((function(){return 7!==Object.defineProperty({},1,{get:function(){return 7}})[1]})),RR=aR,BR=Function.prototype.call,zR=RR?BR.bind(BR):function(){return BR.apply(BR,arguments)},PR={},FR={}.propertyIsEnumerable,TR=Object.getOwnPropertyDescriptor,NR=TR&&!FR.call({1:2},1);PR.f=NR?function(t){var e=TR(this,t);return!!e&&e.enumerable}:FR;var jR,LR,UR=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}},QR=sR,HR=AR,VR=Object,WR=yR("".split),GR=QR((function(){return!VR("z").propertyIsEnumerable(0)}))?function(t){return"String"===HR(t)?WR(t,""):VR(t)}:VR,KR=function(t){return null==t},qR=KR,YR=TypeError,ZR=function(t){if(qR(t))throw new YR("Can't call method on "+t);return t},JR=GR,XR=ZR,_R=function(t){return JR(XR(t))},$R=MR,tB=IR.all,eB=IR.IS_HTMLDDA?function(t){return"object"==typeof t?null!==t:$R(t)||t===tB}:function(t){return"object"==typeof t?null!==t:$R(t)},iB={},nB=iB,oB=rR,rB=MR,sB=function(t){return rB(t)?t:void 0},aB=function(t,e){return arguments.length<2?sB(nB[t])||sB(oB[t]):nB[t]&&nB[t][e]||oB[t]&&oB[t][e]},lB=yR({}.isPrototypeOf),hB="undefined"!=typeof navigator&&String(navigator.userAgent)||"",cB=rR,dB=hB,uB=cB.process,fB=cB.Deno,pB=uB&&uB.versions||fB&&fB.version,vB=pB&&pB.v8;vB&&(LR=(jR=vB.split("."))[0]>0&&jR[0]<4?1:+(jR[0]+jR[1])),!LR&&dB&&(!(jR=dB.match(/Edge\/(\d+)/))||jR[1]>=74)&&(jR=dB.match(/Chrome\/(\d+)/))&&(LR=+jR[1]);var gB=LR,yB=gB,mB=sR,bB=rR.String,wB=!!Object.getOwnPropertySymbols&&!mB((function(){var t=Symbol("symbol detection");return!bB(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&yB&&yB<41})),AB=wB&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,kB=aB,EB=MR,CB=lB,xB=Object,IB=AB?function(t){return"symbol"==typeof t}:function(t){var e=kB("Symbol");return EB(e)&&CB(e.prototype,xB(t))},SB=String,MB=function(t){try{return SB(t)}catch(t){return"Object"}},OB=MR,DB=MB,RB=TypeError,BB=function(t){if(OB(t))return t;throw new RB(DB(t)+" is not a function")},zB=BB,PB=KR,FB=function(t,e){var i=t[e];return PB(i)?void 0:zB(i)},TB=zR,NB=MR,jB=eB,LB=TypeError,UB={exports:{}},QB=rR,HB=Object.defineProperty,VB=function(t,e){try{HB(QB,t,{value:e,configurable:!0,writable:!0})}catch(i){QB[t]=e}return e},WB="__core-js_shared__",GB=rR[WB]||VB(WB,{}),KB=GB;(UB.exports=function(t,e){return KB[t]||(KB[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.33.0",mode:"pure",copyright:"© 2014-2023 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.33.0/LICENSE",source:"https://github.com/zloirock/core-js"});var qB=UB.exports,YB=ZR,ZB=Object,JB=function(t){return ZB(YB(t))},XB=JB,_B=yR({}.hasOwnProperty),$B=Object.hasOwn||function(t,e){return _B(XB(t),e)},tz=yR,ez=0,iz=Math.random(),nz=tz(1..toString),oz=function(t){return"Symbol("+(void 0===t?"":t)+")_"+nz(++ez+iz,36)},rz=qB,sz=$B,az=oz,lz=wB,hz=AB,cz=rR.Symbol,dz=rz("wks"),uz=hz?cz.for||cz:cz&&cz.withoutSetter||az,fz=function(t){return sz(dz,t)||(dz[t]=lz&&sz(cz,t)?cz[t]:uz("Symbol."+t)),dz[t]},pz=zR,vz=eB,gz=IB,yz=FB,mz=function(t,e){var i,n;if("string"===e&&NB(i=t.toString)&&!jB(n=TB(i,t)))return n;if(NB(i=t.valueOf)&&!jB(n=TB(i,t)))return n;if("string"!==e&&NB(i=t.toString)&&!jB(n=TB(i,t)))return n;throw new LB("Can't convert object to primitive value")},bz=TypeError,wz=fz("toPrimitive"),Az=function(t,e){if(!vz(t)||gz(t))return t;var i,n=yz(t,wz);if(n){if(void 0===e&&(e="default"),i=pz(n,t,e),!vz(i)||gz(i))return i;throw new bz("Can't convert object to primitive value")}return void 0===e&&(e="number"),mz(t,e)},kz=IB,Ez=function(t){var e=Az(t,"string");return kz(e)?e:e+""},Cz=eB,xz=rR.document,Iz=Cz(xz)&&Cz(xz.createElement),Sz=function(t){return Iz?xz.createElement(t):{}},Mz=Sz,Oz=!DR&&!sR((function(){return 7!==Object.defineProperty(Mz("div"),"a",{get:function(){return 7}}).a})),Dz=DR,Rz=zR,Bz=PR,zz=UR,Pz=_R,Fz=Ez,Tz=$B,Nz=Oz,jz=Object.getOwnPropertyDescriptor;OR.f=Dz?jz:function(t,e){if(t=Pz(t),e=Fz(e),Nz)try{return jz(t,e)}catch(t){}if(Tz(t,e))return zz(!Rz(Bz.f,t,e),t[e])};var Lz=sR,Uz=MR,Qz=/#|\.prototype\./,Hz=function(t,e){var i=Wz[Vz(t)];return i===Kz||i!==Gz&&(Uz(e)?Lz(e):!!e)},Vz=Hz.normalize=function(t){return String(t).replace(Qz,".").toLowerCase()},Wz=Hz.data={},Gz=Hz.NATIVE="N",Kz=Hz.POLYFILL="P",qz=Hz,Yz=BB,Zz=aR,Jz=CR(CR.bind),Xz=function(t,e){return Yz(t),void 0===e?t:Zz?Jz(t,e):function(){return t.apply(e,arguments)}},_z={},$z=DR&&sR((function(){return 42!==Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype})),tP=eB,eP=String,iP=TypeError,nP=function(t){if(tP(t))return t;throw new iP(eP(t)+" is not an object")},oP=DR,rP=Oz,sP=$z,aP=nP,lP=Ez,hP=TypeError,cP=Object.defineProperty,dP=Object.getOwnPropertyDescriptor,uP="enumerable",fP="configurable",pP="writable";_z.f=oP?sP?function(t,e,i){if(aP(t),e=lP(e),aP(i),"function"==typeof t&&"prototype"===e&&"value"in i&&pP in i&&!i[pP]){var n=dP(t,e);n&&n[pP]&&(t[e]=i.value,i={configurable:fP in i?i[fP]:n[fP],enumerable:uP in i?i[uP]:n[uP],writable:!1})}return cP(t,e,i)}:cP:function(t,e,i){if(aP(t),e=lP(e),aP(i),rP)try{return cP(t,e,i)}catch(t){}if("get"in i||"set"in i)throw new hP("Accessors not supported");return"value"in i&&(t[e]=i.value),t};var vP=_z,gP=UR,yP=DR?function(t,e,i){return vP.f(t,e,gP(1,i))}:function(t,e,i){return t[e]=i,t},mP=rR,bP=uR,wP=CR,AP=MR,kP=OR.f,EP=qz,CP=iB,xP=Xz,IP=yP,SP=$B,MP=function(t){var e=function(i,n,o){if(this instanceof e){switch(arguments.length){case 0:return new t;case 1:return new t(i);case 2:return new t(i,n)}return new t(i,n,o)}return bP(t,this,arguments)};return e.prototype=t.prototype,e},OP=function(t,e){var i,n,o,r,s,a,l,h,c,d=t.target,u=t.global,f=t.stat,p=t.proto,v=u?mP:f?mP[d]:(mP[d]||{}).prototype,g=u?CP:CP[d]||IP(CP,d,{})[d],y=g.prototype;for(r in e)n=!(i=EP(u?r:d+(f?".":"#")+r,t.forced))&&v&&SP(v,r),a=g[r],n&&(l=t.dontCallGetSet?(c=kP(v,r))&&c.value:v[r]),s=n&&l?l:e[r],n&&typeof a==typeof s||(h=t.bind&&n?xP(s,mP):t.wrap&&n?MP(s):p&&AP(s)?wP(s):s,(t.sham||s&&s.sham||a&&a.sham)&&IP(h,"sham",!0),IP(g,r,h),p&&(SP(CP,o=d+"Prototype")||IP(CP,o,{}),IP(CP[o],r,s),t.real&&y&&(i||!y[r])&&IP(y,r,s)))},DP=Math.ceil,RP=Math.floor,BP=Math.trunc||function(t){var e=+t;return(e>0?RP:DP)(e)},zP=BP,PP=function(t){var e=+t;return e!=e||0===e?0:zP(e)},FP=PP,TP=Math.max,NP=Math.min,jP=function(t,e){var i=FP(t);return i<0?TP(i+e,0):NP(i,e)},LP=PP,UP=Math.min,QP=function(t){return t>0?UP(LP(t),9007199254740991):0},HP=function(t){return QP(t.length)},VP=_R,WP=jP,GP=HP,KP=function(t){return function(e,i,n){var o,r=VP(e),s=GP(r),a=WP(n,s);if(t&&i!=i){for(;s>a;)if((o=r[a++])!=o)return!0}else for(;s>a;a++)if((t||a in r)&&r[a]===i)return t||a||0;return!t&&-1}},qP={includes:KP(!0),indexOf:KP(!1)},YP={},ZP=$B,JP=_R,XP=qP.indexOf,_P=YP,$P=yR([].push),tF=function(t,e){var i,n=JP(t),o=0,r=[];for(i in n)!ZP(_P,i)&&ZP(n,i)&&$P(r,i);for(;e.length>o;)ZP(n,i=e[o++])&&(~XP(r,i)||$P(r,i));return r},eF=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],iF=tF,nF=eF,oF=Object.keys||function(t){return iF(t,nF)},rF={};rF.f=Object.getOwnPropertySymbols;var sF=DR,aF=yR,lF=zR,hF=sR,cF=oF,dF=rF,uF=PR,fF=JB,pF=GR,vF=Object.assign,gF=Object.defineProperty,yF=aF([].concat),mF=!vF||hF((function(){if(sF&&1!==vF({b:1},vF(gF({},"a",{enumerable:!0,get:function(){gF(this,"b",{value:3,enumerable:!1})}}),{b:2})).b)return!0;var t={},e={},i=Symbol("assign detection"),n="abcdefghijklmnopqrst";return t[i]=7,n.split("").forEach((function(t){e[t]=t})),7!==vF({},t)[i]||cF(vF({},e)).join("")!==n}))?function(t,e){for(var i=fF(t),n=arguments.length,o=1,r=dF.f,s=uF.f;n>o;)for(var a,l=pF(arguments[o++]),h=r?yF(cF(l),r(l)):cF(l),c=h.length,d=0;c>d;)a=h[d++],sF&&!lF(s,l,a)||(i[a]=l[a]);return i}:vF,bF=mF;OP({target:"Object",stat:!0,arity:2,forced:Object.assign!==bF},{assign:bF});var wF=nR(iB.Object.assign),AF=yR([].slice),kF=yR,EF=BB,CF=eB,xF=$B,IF=AF,SF=aR,MF=Function,OF=kF([].concat),DF=kF([].join),RF={},BF=SF?MF.bind:function(t){var e=EF(this),i=e.prototype,n=IF(arguments,1),o=function(){var i=OF(n,IF(arguments));return this instanceof o?function(t,e,i){if(!xF(RF,e)){for(var n=[],o=0;o=.1;)(p=+r[d++%s])>c&&(p=c),f=Math.sqrt(p*p/(1+h*h)),e+=f=a<0?-f:f,i+=h*f,!0===u?t.lineTo(e,i):t.moveTo(e,i),c-=p,u=!u}var YF={circle:VF,dashedLine:qF,database:KF,diamond:function(t,e,i,n){t.beginPath(),t.lineTo(e,i+n),t.lineTo(e+n,i),t.lineTo(e,i-n),t.lineTo(e-n,i),t.closePath()},ellipse:GF,ellipse_vis:GF,hexagon:function(t,e,i,n){t.beginPath();var o=2*Math.PI/6;t.moveTo(e+n,i);for(var r=1;r<6;r++)t.lineTo(e+n*Math.cos(o*r),i+n*Math.sin(o*r));t.closePath()},roundRect:WF,square:function(t,e,i,n){t.beginPath(),t.rect(e-n,i-n,2*n,2*n),t.closePath()},star:function(t,e,i,n){t.beginPath(),i+=.1*(n*=.82);for(var o=0;o<10;o++){var r=o%2==0?1.3*n:.5*n;t.lineTo(e+r*Math.sin(2*o*Math.PI/10),i-r*Math.cos(2*o*Math.PI/10))}t.closePath()},triangle:function(t,e,i,n){t.beginPath(),i+=.275*(n*=1.15);var o=2*n,r=o/2,s=Math.sqrt(3)/6*o,a=Math.sqrt(o*o-r*r);t.moveTo(e,i-(a-s)),t.lineTo(e+r,i+s),t.lineTo(e-r,i+s),t.lineTo(e,i-(a-s)),t.closePath()},triangleDown:function(t,e,i,n){t.beginPath(),i-=.275*(n*=1.15);var o=2*n,r=o/2,s=Math.sqrt(3)/6*o,a=Math.sqrt(o*o-r*r);t.moveTo(e,i+(a-s)),t.lineTo(e+r,i-s),t.lineTo(e-r,i-s),t.lineTo(e,i+(a-s)),t.closePath()}};var ZF={exports:{}};!function(t){function e(t){if(t)return function(t){for(var i in e.prototype)t[i]=e.prototype[i];return t}(t)}t.exports=e,e.prototype.on=e.prototype.addEventListener=function(t,e){return this._callbacks=this._callbacks||{},(this._callbacks["$"+t]=this._callbacks["$"+t]||[]).push(e),this},e.prototype.once=function(t,e){function i(){this.off(t,i),e.apply(this,arguments)}return i.fn=e,this.on(t,i),this},e.prototype.off=e.prototype.removeListener=e.prototype.removeAllListeners=e.prototype.removeEventListener=function(t,e){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var i,n=this._callbacks["$"+t];if(!n)return this;if(1==arguments.length)return delete this._callbacks["$"+t],this;for(var o=0;o=a?t?"":void 0:(n=yT(r,s))<55296||n>56319||s+1===a||(o=yT(r,s+1))<56320||o>57343?t?gT(r,s):n:t?mT(r,s,s+2):o-56320+(n-55296<<10)+65536}},wT={codeAt:bT(!1),charAt:bT(!0)},AT=MR,kT=rR.WeakMap,ET=AT(kT)&&/native code/.test(String(kT)),CT=oz,xT=qB("keys"),IT=function(t){return xT[t]||(xT[t]=CT(t))},ST=ET,MT=rR,OT=eB,DT=yP,RT=$B,BT=GB,zT=IT,PT=YP,FT="Object already initialized",TT=MT.TypeError,NT=MT.WeakMap;if(ST||BT.state){var jT=BT.state||(BT.state=new NT);jT.get=jT.get,jT.has=jT.has,jT.set=jT.set,_F=function(t,e){if(jT.has(t))throw new TT(FT);return e.facade=t,jT.set(t,e),e},$F=function(t){return jT.get(t)||{}},tT=function(t){return jT.has(t)}}else{var LT=zT("state");PT[LT]=!0,_F=function(t,e){if(RT(t,LT))throw new TT(FT);return e.facade=t,DT(t,LT,e),e},$F=function(t){return RT(t,LT)?t[LT]:{}},tT=function(t){return RT(t,LT)}}var UT={set:_F,get:$F,has:tT,enforce:function(t){return tT(t)?$F(t):_F(t,{})},getterFor:function(t){return function(e){var i;if(!OT(e)||(i=$F(e)).type!==t)throw new TT("Incompatible receiver, "+t+" required");return i}}},QT=DR,HT=$B,VT=Function.prototype,WT=QT&&Object.getOwnPropertyDescriptor,GT=HT(VT,"name"),KT={EXISTS:GT,PROPER:GT&&"something"===function(){}.name,CONFIGURABLE:GT&&(!QT||QT&&WT(VT,"name").configurable)},qT={},YT=DR,ZT=$z,JT=_z,XT=nP,_T=_R,$T=oF;qT.f=YT&&!ZT?Object.defineProperties:function(t,e){XT(t);for(var i,n=_T(e),o=$T(e),r=o.length,s=0;r>s;)JT.f(t,i=o[s++],n[i]);return t};var tN,eN=aB("document","documentElement"),iN=nP,nN=qT,oN=eF,rN=YP,sN=eN,aN=Sz,lN="prototype",hN="script",cN=IT("IE_PROTO"),dN=function(){},uN=function(t){return"<"+hN+">"+t+""},fN=function(t){t.write(uN("")),t.close();var e=t.parentWindow.Object;return t=null,e},pN=function(){try{tN=new ActiveXObject("htmlfile")}catch(t){}var t,e,i;pN="undefined"!=typeof document?document.domain&&tN?fN(tN):(e=aN("iframe"),i="java"+hN+":",e.style.display="none",sN.appendChild(e),e.src=String(i),(t=e.contentWindow.document).open(),t.write(uN("document.F=Object")),t.close(),t.F):fN(tN);for(var n=oN.length;n--;)delete pN[lN][oN[n]];return pN()};rN[cN]=!0;var vN,gN,yN,mN=Object.create||function(t,e){var i;return null!==t?(dN[lN]=iN(t),i=new dN,dN[lN]=null,i[cN]=t):i=pN(),void 0===e?i:nN.f(i,e)},bN=!sR((function(){function t(){}return t.prototype.constructor=null,Object.getPrototypeOf(new t)!==t.prototype})),wN=$B,AN=MR,kN=JB,EN=bN,CN=IT("IE_PROTO"),xN=Object,IN=xN.prototype,SN=EN?xN.getPrototypeOf:function(t){var e=kN(t);if(wN(e,CN))return e[CN];var i=e.constructor;return AN(i)&&e instanceof i?i.prototype:e instanceof xN?IN:null},MN=yP,ON=function(t,e,i,n){return n&&n.enumerable?t[e]=i:MN(t,e,i),t},DN=sR,RN=MR,BN=eB,zN=mN,PN=SN,FN=ON,TN=fz("iterator"),NN=!1;[].keys&&("next"in(yN=[].keys())?(gN=PN(PN(yN)))!==Object.prototype&&(vN=gN):NN=!0);var jN=!BN(vN)||DN((function(){var t={};return vN[TN].call(t)!==t}));RN((vN=jN?{}:zN(vN))[TN])||FN(vN,TN,(function(){return this}));var LN={IteratorPrototype:vN,BUGGY_SAFARI_ITERATORS:NN},UN=lT,QN=eT?{}.toString:function(){return"[object "+UN(this)+"]"},HN=eT,VN=_z.f,WN=yP,GN=$B,KN=QN,qN=fz("toStringTag"),YN=function(t,e,i,n){if(t){var o=i?t:t.prototype;GN(o,qN)||VN(o,qN,{configurable:!0,value:e}),n&&!HN&&WN(o,"toString",KN)}},ZN={},JN=LN.IteratorPrototype,XN=mN,_N=UR,$N=YN,tj=ZN,ej=function(){return this},ij=yR,nj=BB,oj=MR,rj=String,sj=TypeError,aj=function(t,e,i){try{return ij(nj(Object.getOwnPropertyDescriptor(t,e)[i]))}catch(t){}},lj=nP,hj=function(t){if("object"==typeof t||oj(t))return t;throw new sj("Can't set "+rj(t)+" as a prototype")},cj=Object.setPrototypeOf||("__proto__"in{}?function(){var t,e=!1,i={};try{(t=aj(Object.prototype,"__proto__","set"))(i,[]),e=i instanceof Array}catch(t){}return function(i,n){return lj(i),hj(n),e?t(i,n):i.__proto__=n,i}}():void 0),dj=OP,uj=zR,fj=function(t,e,i,n){var o=e+" Iterator";return t.prototype=XN(JN,{next:_N(+!n,i)}),$N(t,o,!1,!0),tj[o]=ej,t},pj=SN,vj=YN,gj=ON,yj=ZN,mj=KT.PROPER,bj=LN.BUGGY_SAFARI_ITERATORS,wj=fz("iterator"),Aj="keys",kj="values",Ej="entries",Cj=function(){return this},xj=function(t,e,i,n,o,r,s){fj(i,e,n);var a,l,h,c=function(t){if(t===o&&v)return v;if(!bj&&t&&t in f)return f[t];switch(t){case Aj:case kj:case Ej:return function(){return new i(this,t)}}return function(){return new i(this)}},d=e+" Iterator",u=!1,f=t.prototype,p=f[wj]||f["@@iterator"]||o&&f[o],v=!bj&&p||c(o),g="Array"===e&&f.entries||p;if(g&&(a=pj(g.call(new t)))!==Object.prototype&&a.next&&(vj(a,d,!0,!0),yj[d]=Cj),mj&&o===kj&&p&&p.name!==kj&&(u=!0,v=function(){return uj(p,this)}),o)if(l={values:c(kj),keys:r?v:c(Aj),entries:c(Ej)},s)for(h in l)(bj||u||!(h in f))&&gj(f,h,l[h]);else dj({target:e,proto:!0,forced:bj||u},l);return s&&f[wj]!==v&&gj(f,wj,v,{name:o}),yj[e]=v,l},Ij=function(t,e){return{value:t,done:e}},Sj=wT.charAt,Mj=dT,Oj=UT,Dj=xj,Rj=Ij,Bj="String Iterator",zj=Oj.set,Pj=Oj.getterFor(Bj);Dj(String,"String",(function(t){zj(this,{type:Bj,string:Mj(t),index:0})}),(function(){var t,e=Pj(this),i=e.string,n=e.index;return n>=i.length?Rj(void 0,!0):(t=Sj(i,n),e.index+=t.length,Rj(t,!1))}));var Fj=zR,Tj=nP,Nj=FB,jj=function(t,e,i){var n,o;Tj(t);try{if(!(n=Nj(t,"return"))){if("throw"===e)throw i;return i}n=Fj(n,t)}catch(t){o=!0,n=t}if("throw"===e)throw i;if(o)throw n;return Tj(n),i},Lj=nP,Uj=jj,Qj=ZN,Hj=fz("iterator"),Vj=Array.prototype,Wj=function(t){return void 0!==t&&(Qj.Array===t||Vj[Hj]===t)},Gj=MR,Kj=GB,qj=yR(Function.toString);Gj(Kj.inspectSource)||(Kj.inspectSource=function(t){return qj(t)});var Yj=Kj.inspectSource,Zj=yR,Jj=sR,Xj=MR,_j=lT,$j=Yj,tL=function(){},eL=[],iL=aB("Reflect","construct"),nL=/^\s*(?:class|function)\b/,oL=Zj(nL.exec),rL=!nL.test(tL),sL=function(t){if(!Xj(t))return!1;try{return iL(tL,eL,t),!0}catch(t){return!1}},aL=function(t){if(!Xj(t))return!1;switch(_j(t)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}try{return rL||!!oL(nL,$j(t))}catch(t){return!0}};aL.sham=!0;var lL=!iL||Jj((function(){var t;return sL(sL.call)||!sL(Object)||!sL((function(){t=!0}))||t}))?aL:sL,hL=Ez,cL=_z,dL=UR,uL=function(t,e,i){var n=hL(e);n in t?cL.f(t,n,dL(0,i)):t[n]=i},fL=lT,pL=FB,vL=KR,gL=ZN,yL=fz("iterator"),mL=function(t){if(!vL(t))return pL(t,yL)||pL(t,"@@iterator")||gL[fL(t)]},bL=zR,wL=BB,AL=nP,kL=MB,EL=mL,CL=TypeError,xL=function(t,e){var i=arguments.length<2?EL(t):e;if(wL(i))return AL(bL(i,t));throw new CL(kL(t)+" is not iterable")},IL=Xz,SL=zR,ML=JB,OL=function(t,e,i,n){try{return n?e(Lj(i)[0],i[1]):e(i)}catch(e){Uj(t,"throw",e)}},DL=Wj,RL=lL,BL=HP,zL=uL,PL=xL,FL=mL,TL=Array,NL=fz("iterator"),jL=!1;try{var LL=0,UL={next:function(){return{done:!!LL++}},return:function(){jL=!0}};UL[NL]=function(){return this},Array.from(UL,(function(){throw 2}))}catch(t){}var QL=function(t){var e=ML(t),i=RL(this),n=arguments.length,o=n>1?arguments[1]:void 0,r=void 0!==o;r&&(o=IL(o,n>2?arguments[2]:void 0));var s,a,l,h,c,d,u=FL(e),f=0;if(!u||this===TL&&DL(u))for(s=BL(e),a=i?new this(s):TL(s);s>f;f++)d=r?o(e[f],f):e[f],zL(a,f,d);else for(c=(h=PL(e,u)).next,a=i?new this:[];!(l=SL(c,h)).done;f++)d=r?OL(h,o,[l.value,f],!0):l.value,zL(a,f,d);return a.length=f,a},HL=function(t,e){try{if(!e&&!jL)return!1}catch(t){return!1}var i=!1;try{var n={};n[NL]=function(){return{next:function(){return{done:i=!0}}}},t(n)}catch(t){}return i};OP({target:"Array",stat:!0,forced:!HL((function(t){Array.from(t)}))},{from:QL});var VL=iB.Array.from,WL=nR(VL),GL=_R,KL=ZN,qL=UT;_z.f;var YL=xj,ZL=Ij,JL="Array Iterator",XL=qL.set,_L=qL.getterFor(JL);YL(Array,"Array",(function(t,e){XL(this,{type:JL,target:GL(t),index:0,kind:e})}),(function(){var t=_L(this),e=t.target,i=t.kind,n=t.index++;if(!e||n>=e.length)return t.target=void 0,ZL(void 0,!0);switch(i){case"keys":return ZL(n,!1);case"values":return ZL(e[n],!1)}return ZL([n,e[n]],!1)}),"values"),KL.Arguments=KL.Array;var $L=mL,tU={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0},eU=rR,iU=lT,nU=yP,oU=ZN,rU=fz("toStringTag");for(var sU in tU){var aU=eU[sU],lU=aU&&aU.prototype;lU&&iU(lU)!==rU&&nU(lU,rU,sU),oU[sU]=oU.Array}var hU=$L,cU=nR(hU),dU=nR(hU);function uU(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var fU={exports:{}},pU=OP,vU=DR,gU=_z.f;pU({target:"Object",stat:!0,forced:Object.defineProperty!==gU,sham:!vU},{defineProperty:gU});var yU=iB.Object,mU=fU.exports=function(t,e,i){return yU.defineProperty(t,e,i)};yU.defineProperty.sham&&(mU.sham=!0);var bU=fU.exports,wU=nR(bU),AU=AR,kU=Array.isArray||function(t){return"Array"===AU(t)},EU=TypeError,CU=function(t){if(t>9007199254740991)throw EU("Maximum allowed index exceeded");return t},xU=kU,IU=lL,SU=eB,MU=fz("species"),OU=Array,DU=function(t){var e;return xU(t)&&(e=t.constructor,(IU(e)&&(e===OU||xU(e.prototype))||SU(e)&&null===(e=e[MU]))&&(e=void 0)),void 0===e?OU:e},RU=function(t,e){return new(DU(t))(0===e?0:e)},BU=sR,zU=gB,PU=fz("species"),FU=function(t){return zU>=51||!BU((function(){var e=[];return(e.constructor={})[PU]=function(){return{foo:1}},1!==e[t](Boolean).foo}))},TU=OP,NU=sR,jU=kU,LU=eB,UU=JB,QU=HP,HU=CU,VU=uL,WU=RU,GU=FU,KU=gB,qU=fz("isConcatSpreadable"),YU=KU>=51||!NU((function(){var t=[];return t[qU]=!1,t.concat()[0]!==t})),ZU=function(t){if(!LU(t))return!1;var e=t[qU];return void 0!==e?!!e:jU(t)};TU({target:"Array",proto:!0,arity:1,forced:!YU||!GU("concat")},{concat:function(t){var e,i,n,o,r,s=UU(this),a=WU(s,0),l=0;for(e=-1,n=arguments.length;em;m++)if((a||m in v)&&(f=g(u=v[m],m,p),t))if(e)w[m]=f;else if(f)switch(t){case 3:return!0;case 5:return u;case 6:return m;case 2:DQ(w,u)}else switch(t){case 4:return!1;case 7:DQ(w,u)}return r?-1:n||o?o:w}},BQ={forEach:RQ(0),map:RQ(1),filter:RQ(2),some:RQ(3),every:RQ(4),find:RQ(5),findIndex:RQ(6),filterReject:RQ(7)},zQ=OP,PQ=rR,FQ=zR,TQ=yR,NQ=DR,jQ=wB,LQ=sR,UQ=$B,QQ=lB,HQ=nP,VQ=_R,WQ=Ez,GQ=dT,KQ=UR,qQ=mN,YQ=oF,ZQ=JU,JQ=$U,XQ=rF,_Q=OR,$Q=_z,tH=qT,eH=PR,iH=ON,nH=uQ,oH=qB,rH=YP,sH=oz,aH=fz,lH=fQ,hH=bQ,cH=CQ,dH=YN,uH=UT,fH=BQ.forEach,pH=IT("hidden"),vH="Symbol",gH="prototype",yH=uH.set,mH=uH.getterFor(vH),bH=Object[gH],wH=PQ.Symbol,AH=wH&&wH[gH],kH=PQ.RangeError,EH=PQ.TypeError,CH=PQ.QObject,xH=_Q.f,IH=$Q.f,SH=JQ.f,MH=eH.f,OH=TQ([].push),DH=oH("symbols"),RH=oH("op-symbols"),BH=oH("wks"),zH=!CH||!CH[gH]||!CH[gH].findChild,PH=function(t,e,i){var n=xH(bH,e);n&&delete bH[e],IH(t,e,i),n&&t!==bH&&IH(bH,e,n)},FH=NQ&&LQ((function(){return 7!==qQ(IH({},"a",{get:function(){return IH(this,"a",{value:7}).a}})).a}))?PH:IH,TH=function(t,e){var i=DH[t]=qQ(AH);return yH(i,{type:vH,tag:t,description:e}),NQ||(i.description=e),i},NH=function(t,e,i){t===bH&&NH(RH,e,i),HQ(t);var n=WQ(e);return HQ(i),UQ(DH,n)?(i.enumerable?(UQ(t,pH)&&t[pH][n]&&(t[pH][n]=!1),i=qQ(i,{enumerable:KQ(0,!1)})):(UQ(t,pH)||IH(t,pH,KQ(1,{})),t[pH][n]=!0),FH(t,n,i)):IH(t,n,i)},jH=function(t,e){HQ(t);var i=VQ(e),n=YQ(i).concat(HH(i));return fH(n,(function(e){NQ&&!FQ(LH,i,e)||NH(t,e,i[e])})),t},LH=function(t){var e=WQ(t),i=FQ(MH,this,e);return!(this===bH&&UQ(DH,e)&&!UQ(RH,e))&&(!(i||!UQ(this,e)||!UQ(DH,e)||UQ(this,pH)&&this[pH][e])||i)},UH=function(t,e){var i=VQ(t),n=WQ(e);if(i!==bH||!UQ(DH,n)||UQ(RH,n)){var o=xH(i,n);return!o||!UQ(DH,n)||UQ(i,pH)&&i[pH][n]||(o.enumerable=!0),o}},QH=function(t){var e=SH(VQ(t)),i=[];return fH(e,(function(t){UQ(DH,t)||UQ(rH,t)||OH(i,t)})),i},HH=function(t){var e=t===bH,i=SH(e?RH:VQ(t)),n=[];return fH(i,(function(t){!UQ(DH,t)||e&&!UQ(bH,t)||OH(n,DH[t])})),n};jQ||(wH=function(){if(QQ(AH,this))throw new EH("Symbol is not a constructor");var t=arguments.length&&void 0!==arguments[0]?GQ(arguments[0]):void 0,e=sH(t),i=function(t){this===bH&&FQ(i,RH,t),UQ(this,pH)&&UQ(this[pH],e)&&(this[pH][e]=!1);var n=KQ(1,t);try{FH(this,e,n)}catch(t){if(!(t instanceof kH))throw t;PH(this,e,n)}};return NQ&&zH&&FH(bH,e,{configurable:!0,set:i}),TH(e,t)},iH(AH=wH[gH],"toString",(function(){return mH(this).tag})),iH(wH,"withoutSetter",(function(t){return TH(sH(t),t)})),eH.f=LH,$Q.f=NH,tH.f=jH,_Q.f=UH,ZQ.f=JQ.f=QH,XQ.f=HH,lH.f=function(t){return TH(aH(t),t)},NQ&&nH(AH,"description",{configurable:!0,get:function(){return mH(this).description}})),zQ({global:!0,constructor:!0,wrap:!0,forced:!jQ,sham:!jQ},{Symbol:wH}),fH(YQ(BH),(function(t){hH(t)})),zQ({target:vH,stat:!0,forced:!jQ},{useSetter:function(){zH=!0},useSimple:function(){zH=!1}}),zQ({target:"Object",stat:!0,forced:!jQ,sham:!NQ},{create:function(t,e){return void 0===e?qQ(t):jH(qQ(t),e)},defineProperty:NH,defineProperties:jH,getOwnPropertyDescriptor:UH}),zQ({target:"Object",stat:!0,forced:!jQ},{getOwnPropertyNames:QH}),cH(),dH(wH,vH),rH[pH]=!0;var VH=wB&&!!Symbol.for&&!!Symbol.keyFor,WH=OP,GH=aB,KH=$B,qH=dT,YH=qB,ZH=VH,JH=YH("string-to-symbol-registry"),XH=YH("symbol-to-string-registry");WH({target:"Symbol",stat:!0,forced:!ZH},{for:function(t){var e=qH(t);if(KH(JH,e))return JH[e];var i=GH("Symbol")(e);return JH[e]=i,XH[i]=e,i}});var _H=OP,$H=$B,tV=IB,eV=MB,iV=VH,nV=qB("symbol-to-string-registry");_H({target:"Symbol",stat:!0,forced:!iV},{keyFor:function(t){if(!tV(t))throw new TypeError(eV(t)+" is not a symbol");if($H(nV,t))return nV[t]}});var oV=kU,rV=MR,sV=AR,aV=dT,lV=yR([].push),hV=OP,cV=aB,dV=uR,uV=zR,fV=yR,pV=sR,vV=MR,gV=IB,yV=AF,mV=function(t){if(rV(t))return t;if(oV(t)){for(var e=t.length,i=[],n=0;nt.length)&&(e=t.length);for(var i=0,n=new Array(e);i1?arguments[1]:void 0)}});var EG=FF("Array").map,CG=lB,xG=EG,IG=Array.prototype,SG=function(t){var e=t.map;return t===IG||CG(IG,t)&&e===IG.map?xG:e},MG=nR(SG),OG=JB,DG=oF;OP({target:"Object",stat:!0,forced:sR((function(){DG(1)}))},{keys:function(t){return DG(OG(t))}});var RG=nR(iB.Object.keys),BG=OP,zG=Date,PG=yR(zG.prototype.getTime);BG({target:"Date",stat:!0},{now:function(){return PG(new zG)}});var FG=nR(iB.Date.now),TG=sR,NG=function(t,e){var i=[][t];return!!i&&TG((function(){i.call(null,e||function(){return 1},1)}))},jG=BQ.forEach,LG=NG("forEach")?[].forEach:function(t){return jG(this,t,arguments.length>1?arguments[1]:void 0)};OP({target:"Array",proto:!0,forced:[].forEach!==LG},{forEach:LG});var UG=FF("Array").forEach,QG=lT,HG=$B,VG=lB,WG=UG,GG=Array.prototype,KG={DOMTokenList:!0,NodeList:!0},qG=function(t){var e=t.forEach;return t===GG||VG(GG,t)&&e===GG.forEach||HG(KG,QG(t))?WG:e},YG=nR(qG),ZG=OP,JG=kU,XG=yR([].reverse),_G=[1,2];ZG({target:"Array",proto:!0,forced:String(_G)===String(_G.reverse())},{reverse:function(){return JG(this)&&(this.length=this.length),XG(this)}});var $G=FF("Array").reverse,tK=lB,eK=$G,iK=Array.prototype,nK=function(t){var e=t.reverse;return t===iK||tK(iK,t)&&e===iK.reverse?eK:e},oK=nR(nK),rK=MB,sK=TypeError,aK=function(t,e){if(!delete t[e])throw new sK("Cannot delete property "+rK(e)+" of "+rK(t))},lK=OP,hK=JB,cK=jP,dK=PP,uK=HP,fK=CW,pK=CU,vK=RU,gK=uL,yK=aK,mK=FU("splice"),bK=Math.max,wK=Math.min;lK({target:"Array",proto:!0,forced:!mK},{splice:function(t,e){var i,n,o,r,s,a,l=hK(this),h=uK(l),c=cK(t,h),d=arguments.length;for(0===d?i=n=0:1===d?(i=0,n=h-c):(i=d-2,n=wK(bK(dK(e),0),h-c)),pK(h+i-n),o=vK(l,n),r=0;rh-n+i;r--)yK(l,r-1)}else if(i>n)for(r=h-n;r>c;r--)a=r+i-1,(s=r+n-1)in l?l[a]=l[s]:yK(l,a);for(r=0;r1?arguments[1]:void 0)}});var MK=FF("Array").includes,OK=eB,DK=AR,RK=fz("match"),BK=function(t){var e;return OK(t)&&(void 0!==(e=t[RK])?!!e:"RegExp"===DK(t))},zK=TypeError,PK=fz("match"),FK=OP,TK=function(t){if(BK(t))throw new zK("The method doesn't accept regular expressions");return t},NK=ZR,jK=dT,LK=function(t){var e=/./;try{"/./"[t](e)}catch(i){try{return e[PK]=!1,"/./"[t](e)}catch(t){}}return!1},UK=yR("".indexOf);FK({target:"String",proto:!0,forced:!LK("includes")},{includes:function(t){return!!~UK(jK(NK(this)),jK(TK(t)),arguments.length>1?arguments[1]:void 0)}});var QK=FF("String").includes,HK=lB,VK=MK,WK=QK,GK=Array.prototype,KK=String.prototype,qK=function(t){var e=t.includes;return t===GK||HK(GK,t)&&e===GK.includes?VK:"string"==typeof t||t===KK||HK(KK,t)&&e===KK.includes?WK:e},YK=nR(qK),ZK=JB,JK=SN,XK=bN;OP({target:"Object",stat:!0,forced:sR((function(){JK(1)})),sham:!XK},{getPrototypeOf:function(t){return JK(ZK(t))}});var _K=iB.Object.getPrototypeOf,$K=nR(_K),tq=BQ.filter;OP({target:"Array",proto:!0,forced:!FU("filter")},{filter:function(t){return tq(this,t,arguments.length>1?arguments[1]:void 0)}});var eq=FF("Array").filter,iq=lB,nq=eq,oq=Array.prototype,rq=function(t){var e=t.filter;return t===oq||iq(oq,t)&&e===oq.filter?nq:e},sq=nR(rq),aq="\t\n\v\f\r                 \u2028\u2029\ufeff",lq=ZR,hq=dT,cq=aq,dq=yR("".replace),uq=RegExp("^["+cq+"]+"),fq=RegExp("(^|[^"+cq+"])["+cq+"]+$"),pq=function(t){return function(e){var i=hq(lq(e));return 1&t&&(i=dq(i,uq,"")),2&t&&(i=dq(i,fq,"$1")),i}},vq={start:pq(1),end:pq(2),trim:pq(3)},gq=rR,yq=sR,mq=yR,bq=dT,wq=vq.trim,Aq=aq,kq=gq.parseInt,Eq=gq.Symbol,Cq=Eq&&Eq.iterator,xq=/^[+-]?0x/i,Iq=mq(xq.exec),Sq=8!==kq(Aq+"08")||22!==kq(Aq+"0x16")||Cq&&!yq((function(){kq(Object(Cq))}))?function(t,e){var i=wq(bq(t));return kq(i,e>>>0||(Iq(xq,i)?16:10))}:kq;OP({global:!0,forced:parseInt!==Sq},{parseInt:Sq});var Mq=nR(iB.parseInt),Oq=OP,Dq=qP.indexOf,Rq=NG,Bq=CR([].indexOf),zq=!!Bq&&1/Bq([1],1,-0)<0;Oq({target:"Array",proto:!0,forced:zq||!Rq("indexOf")},{indexOf:function(t){var e=arguments.length>1?arguments[1]:void 0;return zq?Bq(this,t,e)||0:Dq(this,t,e)}});var Pq=FF("Array").indexOf,Fq=lB,Tq=Pq,Nq=Array.prototype,jq=function(t){var e=t.indexOf;return t===Nq||Fq(Nq,t)&&e===Nq.indexOf?Tq:e},Lq=nR(jq);OP({target:"Object",stat:!0,sham:!DR},{create:mN});var Uq=iB.Object,Qq=function(t,e){return Uq.create(t,e)},Hq=Qq,Vq=nR(Hq),Wq=iB,Gq=uR;Wq.JSON||(Wq.JSON={stringify:JSON.stringify});var Kq=function(t,e,i){return Gq(Wq.JSON.stringify,null,arguments)},qq=nR(Kq),Yq="function"==typeof Bun&&Bun&&"string"==typeof Bun.version,Zq=TypeError,Jq=rR,Xq=uR,_q=MR,$q=Yq,tY=hB,eY=AF,iY=function(t,e){if(ti,s=_q(n)?n:nY(n),a=r?eY(arguments,i):[],l=r?function(){Xq(s,this,a)}:s;return e?t(l,o):t(l)}:t},sY=OP,aY=rR,lY=rY(aY.setInterval,!0);sY({global:!0,bind:!0,forced:aY.setInterval!==lY},{setInterval:lY});var hY=OP,cY=rR,dY=rY(cY.setTimeout,!0);hY({global:!0,bind:!0,forced:cY.setTimeout!==dY},{setTimeout:dY});var uY=nR(iB.setTimeout),fY=JB,pY=jP,vY=HP,gY=function(t){for(var e=fY(this),i=vY(e),n=arguments.length,o=pY(n>1?arguments[1]:void 0,i),r=n>2?arguments[2]:void 0,s=void 0===r?i:pY(r,i);s>o;)e[o++]=t;return e};OP({target:"Array",proto:!0},{fill:gY});var yY,mY=FF("Array").fill,bY=lB,wY=mY,AY=Array.prototype,kY=function(t){var e=t.fill;return t===AY||bY(AY,t)&&e===AY.fill?wY:e},EY=nR(kY); -/*! Hammer.JS - v2.0.17-rc - 2019-12-16 - * http://naver.github.io/egjs - * - * Forked By Naver egjs - * Copyright (c) hammerjs - * Licensed under the MIT license */ -function CY(){return CY=Object.assign||function(t){for(var e=1;e-1}var uZ=function(){function t(t,e){this.manager=t,this.set(e)}var e=t.prototype;return e.set=function(t){t===NY&&(t=this.compute()),TY&&this.manager.element.style&&VY[t]&&(this.manager.element.style[FY]=t),this.actions=t.toLowerCase().trim()},e.update=function(){this.set(this.manager.options.touchAction)},e.compute=function(){var t=[];return hZ(this.manager.recognizers,(function(e){cZ(e.options.enable,[e])&&(t=t.concat(e.getTouchAction()))})),function(t){if(dZ(t,UY))return UY;var e=dZ(t,QY),i=dZ(t,HY);return e&&i?UY:e||i?e?QY:HY:dZ(t,LY)?LY:jY}(t.join(" "))},e.preventDefaults=function(t){var e=t.srcEvent,i=t.offsetDirection;if(this.manager.session.prevented)e.preventDefault();else{var n=this.actions,o=dZ(n,UY)&&!VY[UY],r=dZ(n,HY)&&!VY[HY],s=dZ(n,QY)&&!VY[QY];if(o){var a=1===t.pointers.length,l=t.distance<2,h=t.deltaTime<250;if(a&&l&&h)return}if(!s||!r)return o||r&&i&oZ||s&&i&rZ?this.preventSrc(e):void 0}},e.preventSrc=function(t){this.manager.session.prevented=!0,t.preventDefault()},t}();function fZ(t,e){for(;t;){if(t===e)return!0;t=t.parentNode}return!1}function pZ(t){var e=t.length;if(1===e)return{x:RY(t[0].clientX),y:RY(t[0].clientY)};for(var i=0,n=0,o=0;o=BY(e)?t<0?tZ:eZ:e<0?iZ:nZ}function bZ(t,e,i){return{x:e/t||0,y:i/t||0}}function wZ(t,e){var i=t.session,n=e.pointers,o=n.length;i.firstInput||(i.firstInput=vZ(e)),o>1&&!i.firstMultiple?i.firstMultiple=vZ(e):1===o&&(i.firstMultiple=!1);var r=i.firstInput,s=i.firstMultiple,a=s?s.center:r.center,l=e.center=pZ(n);e.timeStamp=zY(),e.deltaTime=e.timeStamp-r.timeStamp,e.angle=yZ(a,l),e.distance=gZ(a,l),function(t,e){var i=e.center,n=t.offsetDelta||{},o=t.prevDelta||{},r=t.prevInput||{};e.eventType!==JY&&r.eventType!==XY||(o=t.prevDelta={x:r.deltaX||0,y:r.deltaY||0},n=t.offsetDelta={x:i.x,y:i.y}),e.deltaX=o.x+(i.x-n.x),e.deltaY=o.y+(i.y-n.y)}(i,e),e.offsetDirection=mZ(e.deltaX,e.deltaY);var h,c,d=bZ(e.deltaTime,e.deltaX,e.deltaY);e.overallVelocityX=d.x,e.overallVelocityY=d.y,e.overallVelocity=BY(d.x)>BY(d.y)?d.x:d.y,e.scale=s?(h=s.pointers,gZ((c=n)[0],c[1],lZ)/gZ(h[0],h[1],lZ)):1,e.rotation=s?function(t,e){return yZ(e[1],e[0],lZ)+yZ(t[1],t[0],lZ)}(s.pointers,n):0,e.maxPointers=i.prevInput?e.pointers.length>i.prevInput.maxPointers?e.pointers.length:i.prevInput.maxPointers:e.pointers.length,function(t,e){var i,n,o,r,s=t.lastInterval||e,a=e.timeStamp-s.timeStamp;if(e.eventType!==_Y&&(a>ZY||void 0===s.velocity)){var l=e.deltaX-s.deltaX,h=e.deltaY-s.deltaY,c=bZ(a,l,h);n=c.x,o=c.y,i=BY(c.x)>BY(c.y)?c.x:c.y,r=mZ(l,h),t.lastInterval=e}else i=s.velocity,n=s.velocityX,o=s.velocityY,r=s.direction;e.velocity=i,e.velocityX=n,e.velocityY=o,e.direction=r}(i,e);var u,f=t.element,p=e.srcEvent;fZ(u=p.composedPath?p.composedPath()[0]:p.path?p.path[0]:p.target,f)&&(f=u),e.target=f}function AZ(t,e,i){var n=i.pointers.length,o=i.changedPointers.length,r=e&JY&&n-o==0,s=e&(XY|_Y)&&n-o==0;i.isFirst=!!r,i.isFinal=!!s,r&&(t.session={}),i.eventType=e,wZ(t,i),t.emit("hammer.input",i),t.recognize(i),t.session.prevInput=i}function kZ(t){return t.trim().split(/\s+/g)}function EZ(t,e,i){hZ(kZ(e),(function(e){t.addEventListener(e,i,!1)}))}function CZ(t,e,i){hZ(kZ(e),(function(e){t.removeEventListener(e,i,!1)}))}function xZ(t){var e=t.ownerDocument||t;return e.defaultView||e.parentWindow||window}var IZ=function(){function t(t,e){var i=this;this.manager=t,this.callback=e,this.element=t.element,this.target=t.options.inputTarget,this.domHandler=function(e){cZ(t.options.enable,[t])&&i.handler(e)},this.init()}var e=t.prototype;return e.handler=function(){},e.init=function(){this.evEl&&EZ(this.element,this.evEl,this.domHandler),this.evTarget&&EZ(this.target,this.evTarget,this.domHandler),this.evWin&&EZ(xZ(this.element),this.evWin,this.domHandler)},e.destroy=function(){this.evEl&&CZ(this.element,this.evEl,this.domHandler),this.evTarget&&CZ(this.target,this.evTarget,this.domHandler),this.evWin&&CZ(xZ(this.element),this.evWin,this.domHandler)},t}();function SZ(t,e,i){if(t.indexOf&&!i)return t.indexOf(e);for(var n=0;ni[e]})):n.sort()),n}var FZ={touchstart:JY,touchmove:2,touchend:XY,touchcancel:_Y},TZ=function(t){function e(){var i;return e.prototype.evTarget="touchstart touchmove touchend touchcancel",(i=t.apply(this,arguments)||this).targetIds={},i}return xY(e,t),e.prototype.handler=function(t){var e=FZ[t.type],i=NZ.call(this,t,e);i&&this.callback(this.manager,e,{pointers:i[0],changedPointers:i[1],pointerType:qY,srcEvent:t})},e}(IZ);function NZ(t,e){var i,n,o=zZ(t.touches),r=this.targetIds;if(e&(2|JY)&&1===o.length)return r[o[0].identifier]=!0,[o,o];var s=zZ(t.changedTouches),a=[],l=this.target;if(n=o.filter((function(t){return fZ(t.target,l)})),e===JY)for(i=0;i-1&&n.splice(t,1)}),UZ)}}function HZ(t,e){t&JY?(this.primaryTouch=e.changedPointers[0].identifier,QZ.call(this,e)):t&(XY|_Y)&&QZ.call(this,e)}function VZ(t){for(var e=t.srcEvent.clientX,i=t.srcEvent.clientY,n=0;n-1&&this.requireFail.splice(e,1),this},e.hasRequireFailures=function(){return this.requireFail.length>0},e.canRecognizeWith=function(t){return!!this.simultaneous[t.id]},e.emit=function(t){var e=this,i=this.state;function n(i){e.manager.emit(i,t)}i<8&&n(e.options.event+ZZ(i)),n(e.options.event),t.additionalEvent&&n(t.additionalEvent),i>=8&&n(e.options.event+ZZ(i))},e.tryEmit=function(t){if(this.canEmit())return this.emit(t);this.state=KZ},e.canEmit=function(){for(var t=0;te.threshold&&o&e.direction},i.attrTest=function(t){return _Z.prototype.attrTest.call(this,t)&&(2&this.state||!(2&this.state)&&this.directionTest(t))},i.emit=function(e){this.pX=e.deltaX,this.pY=e.deltaY;var i=$Z(e.direction);i&&(e.additionalEvent=this.options.event+i),t.prototype.emit.call(this,e)},e}(_Z),eJ=function(t){function e(e){return void 0===e&&(e={}),t.call(this,CY({event:"swipe",threshold:10,velocity:.3,direction:oZ|rZ,pointers:1},e))||this}xY(e,t);var i=e.prototype;return i.getTouchAction=function(){return tJ.prototype.getTouchAction.call(this)},i.attrTest=function(e){var i,n=this.options.direction;return n&(oZ|rZ)?i=e.overallVelocity:n&oZ?i=e.overallVelocityX:n&rZ&&(i=e.overallVelocityY),t.prototype.attrTest.call(this,e)&&n&e.offsetDirection&&e.distance>this.options.threshold&&e.maxPointers===this.options.pointers&&BY(i)>this.options.velocity&&e.eventType&XY},i.emit=function(t){var e=$Z(t.offsetDirection);e&&this.manager.emit(this.options.event+e,t),this.manager.emit(this.options.event,t)},e}(_Z),iJ=function(t){function e(e){return void 0===e&&(e={}),t.call(this,CY({event:"pinch",threshold:0,pointers:2},e))||this}xY(e,t);var i=e.prototype;return i.getTouchAction=function(){return[UY]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.scale-1)>this.options.threshold||2&this.state)},i.emit=function(e){if(1!==e.scale){var i=e.scale<1?"in":"out";e.additionalEvent=this.options.event+i}t.prototype.emit.call(this,e)},e}(_Z),nJ=function(t){function e(e){return void 0===e&&(e={}),t.call(this,CY({event:"rotate",threshold:0,pointers:2},e))||this}xY(e,t);var i=e.prototype;return i.getTouchAction=function(){return[UY]},i.attrTest=function(e){return t.prototype.attrTest.call(this,e)&&(Math.abs(e.rotation)>this.options.threshold||2&this.state)},e}(_Z),oJ=function(t){function e(e){var i;return void 0===e&&(e={}),(i=t.call(this,CY({event:"press",pointers:1,time:251,threshold:9},e))||this)._timer=null,i._input=null,i}xY(e,t);var i=e.prototype;return i.getTouchAction=function(){return[jY]},i.process=function(t){var e=this,i=this.options,n=t.pointers.length===i.pointers,o=t.distancei.time;if(this._input=t,!o||!n||t.eventType&(XY|_Y)&&!r)this.reset();else if(t.eventType&JY)this.reset(),this._timer=setTimeout((function(){e.state=8,e.tryEmit()}),i.time);else if(t.eventType&XY)return 8;return KZ},i.reset=function(){clearTimeout(this._timer)},i.emit=function(t){8===this.state&&(t&&t.eventType&XY?this.manager.emit(this.options.event+"up",t):(this._input.timeStamp=zY(),this.manager.emit(this.options.event,this._input)))},e}(JZ),rJ={domEvents:!1,touchAction:NY,enable:!0,inputTarget:null,inputClass:null,cssProps:{userSelect:"none",touchSelect:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}},sJ=[[nJ,{enable:!1}],[iJ,{enable:!1},["rotate"]],[eJ,{direction:oZ}],[tJ,{direction:oZ},["swipe"]],[XZ],[XZ,{event:"doubletap",taps:2},["tap"]],[oJ]];function aJ(t,e){var i,n=t.element;n.style&&(hZ(t.options.cssProps,(function(o,r){i=PY(n.style,r),e?(t.oldCssProps[i]=n.style[i],n.style[i]=o):n.style[i]=t.oldCssProps[i]||""})),e||(t.oldCssProps={}))}var lJ=function(){function t(t,e){var i,n=this;this.options=MY({},rJ,e||{}),this.options.inputTarget=this.options.inputTarget||t,this.handlers={},this.session={},this.recognizers=[],this.oldCssProps={},this.element=t,this.input=new((i=this).options.inputClass||(GY?BZ:KY?TZ:WY?WZ:LZ))(i,AZ),this.touchAction=new uZ(this,this.options.touchAction),aJ(this,!0),hZ(this.options.recognizers,(function(t){var e=n.add(new t[0](t[1]));t[2]&&e.recognizeWith(t[2]),t[3]&&e.requireFailure(t[3])}),this)}var e=t.prototype;return e.set=function(t){return MY(this.options,t),t.touchAction&&this.touchAction.update(),t.inputTarget&&(this.input.destroy(),this.input.target=t.inputTarget,this.input.init()),this},e.stop=function(t){this.session.stopped=t?2:1},e.recognize=function(t){var e=this.session;if(!e.stopped){var i;this.touchAction.preventDefaults(t);var n=this.recognizers,o=e.curRecognizer;(!o||o&&8&o.state)&&(e.curRecognizer=null,o=null);for(var r=0;r\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",o=window.console&&(window.console.warn||window.console.log);return o&&o.call(window.console,n,i),t.apply(this,arguments)}}var fJ=uJ((function(t,e,i){for(var n=Object.keys(e),o=0;o=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function wJ(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i>>0,t=(o*=t)>>>0,t+=4294967296*(o-=t)}return 2.3283064365386963e-10*(t>>>0)}}(),e=t(" "),i=t(" "),n=t(" "),o=0;o2&&void 0!==arguments[2]&&arguments[2];for(var n in t)if(void 0!==e[n])if(null===e[n]||"object"!==fW(e[n]))RJ(t,e,n,i);else{var o=t[n],r=e[n];DJ(o)&&DJ(r)&&BJ(o,r,i)}}function zJ(t,e,i){var n=arguments.length>3&&void 0!==arguments[3]&&arguments[3];if(AG(i))throw new TypeError("Arrays are not supported by deepExtend");for(var o=0;o3&&void 0!==arguments[3]&&arguments[3];if(AG(i))throw new TypeError("Arrays are not supported by deepExtend");for(var o in i)if(Object.prototype.hasOwnProperty.call(i,o)&&!YK(t).call(t,o))if(i[o]&&i[o].constructor===Object)void 0===e[o]&&(e[o]={}),e[o].constructor===Object?FJ(e[o],i[o]):RJ(e,i,o,n);else if(AG(i[o])){e[o]=[];for(var r=0;r2&&void 0!==arguments[2]&&arguments[2],n=arguments.length>3&&void 0!==arguments[3]&&arguments[3];for(var o in e)if(Object.prototype.hasOwnProperty.call(e,o)||!0===i)if("object"===fW(e[o])&&null!==e[o]&&$K(e[o])===Object.prototype)void 0===t[o]?t[o]=FJ({},e[o],i):"object"===fW(t[o])&&null!==t[o]&&$K(t[o])===Object.prototype?FJ(t[o],e[o],i):RJ(t,e,o,n);else if(AG(e[o])){var r;t[o]=pG(r=e[o]).call(r)}else RJ(t,e,o,n);return t}function TJ(t,e){var i;return fG(i=[]).call(i,sG(t),[e])}function NJ(t){return t.getBoundingClientRect().top}function jJ(t,e){if(AG(t))for(var i=t.length,n=0;n3&&void 0!==arguments[3]?arguments[3]:{},o=function(t){return null!=t},r=function(t){return null!==t&&"object"===fW(t)};if(!r(t))throw new Error("Parameter mergeTarget must be an object");if(!r(e))throw new Error("Parameter options must be an object");if(!o(i))throw new Error("Parameter option must have a value");if(!r(n))throw new Error("Parameter globalOptions must be an object");var s=e[i],a=r(n)&&!function(t){for(var e in t)if(Object.prototype.hasOwnProperty.call(t,e))return!1;return!0}(n),l=a?n[i]:void 0,h=l?l.enabled:void 0;if(void 0!==s){if("boolean"==typeof s)return r(t[i])||(t[i]={}),void(t[i].enabled=s);if(null===s&&!r(t[i])){if(!o(l))return;t[i]=Vq(l)}if(r(s)){var c=!0;void 0!==s.enabled?c=s.enabled:void 0!==h&&(c=l.enabled),function(t,e,i){r(t[i])||(t[i]={});var n=e[i],o=t[i];for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(o[s]=n[s])}(t,e,i),t[i].enabled=c}}}var JJ={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return t*(2-t)},easeInOutQuad:function(t){return t<.5?2*t*t:(4-2*t)*t-1},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return--t*t*t+1},easeInOutCubic:function(t){return t<.5?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return 1- --t*t*t*t},easeInOutQuart:function(t){return t<.5?8*t*t*t*t:1-8*--t*t*t*t},easeInQuint:function(t){return t*t*t*t*t},easeOutQuint:function(t){return 1+--t*t*t*t*t},easeInOutQuint:function(t){return t<.5?16*t*t*t*t*t:1+16*--t*t*t*t*t}};function XJ(t,e){var i;AG(e)||(e=[e]);var n,o=bJ(t);try{for(o.s();!(n=o.n()).done;){var r=n.value;if(r){i=r[e[0]];for(var s=1;s0&&void 0!==arguments[0]?arguments[0]:1;uU(this,t),this.pixelRatio=e,this.generated=!1,this.centerCoordinates={x:144.5,y:144.5},this.r=289*.49,this.color={r:255,g:255,b:255,a:1},this.hueCircle=void 0,this.initialColor={r:255,g:255,b:255,a:1},this.previousColor=void 0,this.applied=!1,this.updateCallback=function(){},this.closeCallback=function(){},this._create()}return yW(t,[{key:"insertTo",value:function(t){void 0!==this.hammer&&(this.hammer.destroy(),this.hammer=void 0),this.container=t,this.container.appendChild(this.frame),this._bindHammer(),this._setSize()}},{key:"setUpdateCallback",value:function(t){if("function"!=typeof t)throw new Error("Function attempted to set as colorPicker update callback is not a function.");this.updateCallback=t}},{key:"setCloseCallback",value:function(t){if("function"!=typeof t)throw new Error("Function attempted to set as colorPicker closing callback is not a function.");this.closeCallback=t}},{key:"_isColorString",value:function(t){if("string"==typeof t)return _J[t]}},{key:"setColor",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if("none"!==t){var i,n=this._isColorString(t);if(void 0!==n&&(t=n),!0===OJ(t)){if(!0===qJ(t)){var o=t.substr(4).substr(0,t.length-5).split(",");i={r:o[0],g:o[1],b:o[2],a:1}}else if(!0===function(t){return SJ.test(t)}(t)){var r=t.substr(5).substr(0,t.length-6).split(",");i={r:r[0],g:r[1],b:r[2],a:r[3]}}else if(!0===KJ(t)){var s=LJ(t);i={r:s.r,g:s.g,b:s.b,a:1}}}else if(t instanceof Object&&void 0!==t.r&&void 0!==t.g&&void 0!==t.b){var a=void 0!==t.a?t.a:"1.0";i={r:t.r,g:t.g,b:t.b,a:a}}if(void 0===i)throw new Error("Unknown color passed to the colorPicker. Supported are strings: rgb, hex, rgba. Object: rgb ({r:r,g:g,b:b,[a:a]}). Supplied: "+qq(t));this._setColor(i,e)}}},{key:"show",value:function(){void 0!==this.closeCallback&&(this.closeCallback(),this.closeCallback=void 0),this.applied=!1,this.frame.style.display="block",this._generateHueCircle()}},{key:"_hide",value:function(){var t=this;!0===(!(arguments.length>0&&void 0!==arguments[0])||arguments[0])&&(this.previousColor=wF({},this.color)),!0===this.applied&&this.updateCallback(this.initialColor),this.frame.style.display="none",uY((function(){void 0!==t.closeCallback&&(t.closeCallback(),t.closeCallback=void 0)}),0)}},{key:"_save",value:function(){this.updateCallback(this.color),this.applied=!1,this._hide()}},{key:"_apply",value:function(){this.applied=!0,this.updateCallback(this.color),this._updatePicker(this.color)}},{key:"_loadLast",value:function(){void 0!==this.previousColor?this.setColor(this.previousColor,!1):alert("There is no last color to load...")}},{key:"_setColor",value:function(t){!0===(!(arguments.length>1&&void 0!==arguments[1])||arguments[1])&&(this.initialColor=wF({},t)),this.color=t;var e=VJ(t.r,t.g,t.b),i=2*Math.PI,n=this.r*e.s,o=this.centerCoordinates.x+n*Math.sin(i*e.h),r=this.centerCoordinates.y+n*Math.cos(i*e.h);this.colorPickerSelector.style.left=o-.5*this.colorPickerSelector.clientWidth+"px",this.colorPickerSelector.style.top=r-.5*this.colorPickerSelector.clientHeight+"px",this._updatePicker(t)}},{key:"_setOpacity",value:function(t){this.color.a=t/100,this._updatePicker(this.color)}},{key:"_setBrightness",value:function(t){var e=VJ(this.color.r,this.color.g,this.color.b);e.v=t/100;var i=WJ(e.h,e.s,e.v);i.a=this.color.a,this.color=i,this._updatePicker()}},{key:"_updatePicker",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.color,e=VJ(t.r,t.g,t.b),i=this.colorPickerCanvas.getContext("2d");void 0===this.pixelRation&&(this.pixelRatio=(window.devicePixelRatio||1)/(i.webkitBackingStorePixelRatio||i.mozBackingStorePixelRatio||i.msBackingStorePixelRatio||i.oBackingStorePixelRatio||i.backingStorePixelRatio||1)),i.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var n=this.colorPickerCanvas.clientWidth,o=this.colorPickerCanvas.clientHeight;i.clearRect(0,0,n,o),i.putImageData(this.hueCircle,0,0),i.fillStyle="rgba(0,0,0,"+(1-e.v)+")",i.circle(this.centerCoordinates.x,this.centerCoordinates.y,this.r),EY(i).call(i),this.brightnessRange.value=100*e.v,this.opacityRange.value=100*t.a,this.initialColorDiv.style.backgroundColor="rgba("+this.initialColor.r+","+this.initialColor.g+","+this.initialColor.b+","+this.initialColor.a+")",this.newColorDiv.style.backgroundColor="rgba("+this.color.r+","+this.color.g+","+this.color.b+","+this.color.a+")"}},{key:"_setSize",value:function(){this.colorPickerCanvas.style.width="100%",this.colorPickerCanvas.style.height="100%",this.colorPickerCanvas.width=289*this.pixelRatio,this.colorPickerCanvas.height=289*this.pixelRatio}},{key:"_create",value:function(){var t,e,i,n;if(this.frame=document.createElement("div"),this.frame.className="vis-color-picker",this.colorPickerDiv=document.createElement("div"),this.colorPickerSelector=document.createElement("div"),this.colorPickerSelector.className="vis-selector",this.colorPickerDiv.appendChild(this.colorPickerSelector),this.colorPickerCanvas=document.createElement("canvas"),this.colorPickerDiv.appendChild(this.colorPickerCanvas),this.colorPickerCanvas.getContext){var o=this.colorPickerCanvas.getContext("2d");this.pixelRatio=(window.devicePixelRatio||1)/(o.webkitBackingStorePixelRatio||o.mozBackingStorePixelRatio||o.msBackingStorePixelRatio||o.oBackingStorePixelRatio||o.backingStorePixelRatio||1),this.colorPickerCanvas.getContext("2d").setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0)}else{var r=document.createElement("DIV");r.style.color="red",r.style.fontWeight="bold",r.style.padding="10px",r.innerText="Error: your browser does not support HTML canvas",this.colorPickerCanvas.appendChild(r)}this.colorPickerDiv.className="vis-color",this.opacityDiv=document.createElement("div"),this.opacityDiv.className="vis-opacity",this.brightnessDiv=document.createElement("div"),this.brightnessDiv.className="vis-brightness",this.arrowDiv=document.createElement("div"),this.arrowDiv.className="vis-arrow",this.opacityRange=document.createElement("input");try{this.opacityRange.type="range",this.opacityRange.min="0",this.opacityRange.max="100"}catch(t){}this.opacityRange.value="100",this.opacityRange.className="vis-range",this.brightnessRange=document.createElement("input");try{this.brightnessRange.type="range",this.brightnessRange.min="0",this.brightnessRange.max="100"}catch(t){}this.brightnessRange.value="100",this.brightnessRange.className="vis-range",this.opacityDiv.appendChild(this.opacityRange),this.brightnessDiv.appendChild(this.brightnessRange);var s=this;this.opacityRange.onchange=function(){s._setOpacity(this.value)},this.opacityRange.oninput=function(){s._setOpacity(this.value)},this.brightnessRange.onchange=function(){s._setBrightness(this.value)},this.brightnessRange.oninput=function(){s._setBrightness(this.value)},this.brightnessLabel=document.createElement("div"),this.brightnessLabel.className="vis-label vis-brightness",this.brightnessLabel.innerText="brightness:",this.opacityLabel=document.createElement("div"),this.opacityLabel.className="vis-label vis-opacity",this.opacityLabel.innerText="opacity:",this.newColorDiv=document.createElement("div"),this.newColorDiv.className="vis-new-color",this.newColorDiv.innerText="new",this.initialColorDiv=document.createElement("div"),this.initialColorDiv.className="vis-initial-color",this.initialColorDiv.innerText="initial",this.cancelButton=document.createElement("div"),this.cancelButton.className="vis-button vis-cancel",this.cancelButton.innerText="cancel",this.cancelButton.onclick=HF(t=this._hide).call(t,this,!1),this.applyButton=document.createElement("div"),this.applyButton.className="vis-button vis-apply",this.applyButton.innerText="apply",this.applyButton.onclick=HF(e=this._apply).call(e,this),this.saveButton=document.createElement("div"),this.saveButton.className="vis-button vis-save",this.saveButton.innerText="save",this.saveButton.onclick=HF(i=this._save).call(i,this),this.loadButton=document.createElement("div"),this.loadButton.className="vis-button vis-load",this.loadButton.innerText="load last",this.loadButton.onclick=HF(n=this._loadLast).call(n,this),this.frame.appendChild(this.colorPickerDiv),this.frame.appendChild(this.arrowDiv),this.frame.appendChild(this.brightnessLabel),this.frame.appendChild(this.brightnessDiv),this.frame.appendChild(this.opacityLabel),this.frame.appendChild(this.opacityDiv),this.frame.appendChild(this.newColorDiv),this.frame.appendChild(this.initialColorDiv),this.frame.appendChild(this.cancelButton),this.frame.appendChild(this.applyButton),this.frame.appendChild(this.saveButton),this.frame.appendChild(this.loadButton)}},{key:"_bindHammer",value:function(){var t=this;this.drag={},this.pinch={},this.hammer=new kJ(this.colorPickerCanvas),this.hammer.get("pinch").set({enable:!0}),this.hammer.on("hammer.input",(function(e){e.isFirst&&t._moveSelector(e)})),this.hammer.on("tap",(function(e){t._moveSelector(e)})),this.hammer.on("panstart",(function(e){t._moveSelector(e)})),this.hammer.on("panmove",(function(e){t._moveSelector(e)})),this.hammer.on("panend",(function(e){t._moveSelector(e)}))}},{key:"_generateHueCircle",value:function(){if(!1===this.generated){var t=this.colorPickerCanvas.getContext("2d");void 0===this.pixelRation&&(this.pixelRatio=(window.devicePixelRatio||1)/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1)),t.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var e,i,n,o,r=this.colorPickerCanvas.clientWidth,s=this.colorPickerCanvas.clientHeight;t.clearRect(0,0,r,s),this.centerCoordinates={x:.5*r,y:.5*s},this.r=.49*r;var a,l=2*Math.PI/360,h=1/360,c=1/this.r;for(n=0;n<360;n++)for(o=0;o3&&void 0!==arguments[3]?arguments[3]:1,r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:function(){return!1};uU(this,t),this.parent=e,this.changedOptions=[],this.container=i,this.allowCreation=!1,this.hideOption=r,this.options={},this.initialized=!1,this.popupCounter=0,this.defaultOptions={enabled:!1,filter:!0,container:void 0,showButton:!0},wF(this.options,this.defaultOptions),this.configureOptions=n,this.moduleOptions={},this.domElements=[],this.popupDiv={},this.popupLimit=5,this.popupHistory={},this.colorPicker=new $J(o),this.wrapper=void 0}return yW(t,[{key:"setOptions",value:function(t){if(void 0!==t){this.popupHistory={},this._removePopup();var e=!0;if("string"==typeof t)this.options.filter=t;else if(AG(t))this.options.filter=t.join();else if("object"===fW(t)){if(null==t)throw new TypeError("options cannot be null");void 0!==t.container&&(this.options.container=t.container),void 0!==sq(t)&&(this.options.filter=sq(t)),void 0!==t.showButton&&(this.options.showButton=t.showButton),void 0!==t.enabled&&(e=t.enabled)}else"boolean"==typeof t?(this.options.filter=!0,e=t):"function"==typeof t&&(this.options.filter=t,e=!0);!1===sq(this.options)&&(e=!1),this.options.enabled=e}this._clean()}},{key:"setModuleOptions",value:function(t){this.moduleOptions=t,!0===this.options.enabled&&(this._clean(),void 0!==this.options.container&&(this.container=this.options.container),this._create())}},{key:"_create",value:function(){this._clean(),this.changedOptions=[];var t=sq(this.options),e=0,i=!1;for(var n in this.configureOptions)Object.prototype.hasOwnProperty.call(this.configureOptions,n)&&(this.allowCreation=!1,i=!1,"function"==typeof t?i=(i=t(n,[]))||this._handleObject(this.configureOptions[n],[n],!0):!0!==t&&-1===Lq(t).call(t,n)||(i=!0),!1!==i&&(this.allowCreation=!0,e>0&&this._makeItem([]),this._makeHeader(n),this._handleObject(this.configureOptions[n],[n])),e++);this._makeButton(),this._push()}},{key:"_push",value:function(){this.wrapper=document.createElement("div"),this.wrapper.className="vis-configuration-wrapper",this.container.appendChild(this.wrapper);for(var t=0;t1?i-1:0),o=1;o2&&void 0!==arguments[2]&&arguments[2],n=document.createElement("div");if(n.className="vis-configuration vis-config-label vis-config-s"+e.length,!0===i){for(;n.firstChild;)n.removeChild(n.firstChild);n.appendChild(tX("i","b",t))}else n.innerText=t+":";return n}},{key:"_makeDropdown",value:function(t,e,i){var n=document.createElement("select");n.className="vis-configuration vis-config-select";var o=0;void 0!==e&&-1!==Lq(t).call(t,e)&&(o=Lq(t).call(t,e));for(var r=0;rr&&1!==r&&(a.max=Math.ceil(e*c),h=a.max,l="range increased"),a.value=e}else a.value=n;var d=document.createElement("input");d.className="vis-configuration vis-config-rangeinput",d.value=a.value;var u=this;a.onchange=function(){d.value=this.value,u._update(Number(this.value),i)},a.oninput=function(){d.value=this.value};var f=this._makeLabel(i[i.length-1],i),p=this._makeItem(i,f,a,d);""!==l&&this.popupHistory[p]!==h&&(this.popupHistory[p]=h,this._setupPopup(l,p))}},{key:"_makeButton",value:function(){var t=this;if(!0===this.options.showButton){var e=document.createElement("div");e.className="vis-configuration vis-config-button",e.innerText="generate options",e.onclick=function(){t._printOptions()},e.onmouseover=function(){e.className="vis-configuration vis-config-button hover"},e.onmouseout=function(){e.className="vis-configuration vis-config-button"},this.optionsContainer=document.createElement("div"),this.optionsContainer.className="vis-configuration vis-config-option-container",this.domElements.push(this.optionsContainer),this.domElements.push(e)}}},{key:"_setupPopup",value:function(t,e){var i=this;if(!0===this.initialized&&!0===this.allowCreation&&this.popupCounter1&&void 0!==arguments[1]?arguments[1]:[],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=!1,o=sq(this.options),r=!1;for(var s in t)if(Object.prototype.hasOwnProperty.call(t,s)){n=!0;var a=t[s],l=TJ(e,s);if("function"==typeof o&&!1===(n=o(s,e))&&!AG(a)&&"string"!=typeof a&&"boolean"!=typeof a&&a instanceof Object&&(this.allowCreation=!1,n=this._handleObject(a,l,!0),this.allowCreation=!1===i),!1!==n){r=!0;var h=this._getValue(l);if(AG(a))this._handleArray(a,h,l);else if("string"==typeof a)this._makeTextInput(a,h,l);else if("boolean"==typeof a)this._makeCheckbox(a,h,l);else if(a instanceof Object){if(!this.hideOption(e,s,this.moduleOptions))if(void 0!==a.enabled){var c=TJ(l,"enabled"),d=this._getValue(c);if(!0===d){var u=this._makeLabel(s,l,!0);this._makeItem(l,u),r=this._handleObject(a,l)||r}else this._makeCheckbox(a,d,l)}else{var f=this._makeLabel(s,l,!0);this._makeItem(l,f),r=this._handleObject(a,l)||r}}else console.error("dont know how to handle",a,s,l)}}return r}},{key:"_handleArray",value:function(t,e,i){"string"==typeof t[0]&&"color"===t[0]?(this._makeColorField(t,e,i),t[1]!==e&&this.changedOptions.push({path:i,value:e})):"string"==typeof t[0]?(this._makeDropdown(t,e,i),t[0]!==e&&this.changedOptions.push({path:i,value:e})):"number"==typeof t[0]&&(this._makeRange(t,e,i),t[0]!==e&&this.changedOptions.push({path:i,value:Number(e)}))}},{key:"_update",value:function(t,e){var i=this._constructOptions(t,e);this.parent.body&&this.parent.body.emitter&&this.parent.body.emitter.emit&&this.parent.body.emitter.emit("configChange",i),this.initialized=!0,this.parent.setOptions(i)}},{key:"_constructOptions",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},n=i;t="false"!==(t="true"===t||t)&&t;for(var o=0;oo-this.padding&&(a=!0),r=a?this.x-i:this.x,s=l?this.y-e:this.y}else(s=this.y-e)+e+this.padding>n&&(s=n-e-this.padding),so&&(r=o-i-this.padding),rs.distance?" in "+t.printLocation(r.path,e,"")+"Perhaps it was misplaced? Matching option found at: "+t.printLocation(s.path,s.closestMatch,""):r.distance<=8?'. Did you mean "'+r.closestMatch+'"?'+t.printLocation(r.path,e):". Did you mean one of these: "+t.print(RG(i))+t.printLocation(n,e),console.error('%cUnknown option detected: "'+e+'"'+o,rX),oX=!0}},{key:"findInOptions",value:function(e,i,n){var o,r=arguments.length>3&&void 0!==arguments[3]&&arguments[3],s=1e9,a="",l=[],h=e.toLowerCase(),c=void 0;for(var d in i){var u=void 0;if(void 0!==i[d].__type__&&!0===r){var f=t.findInOptions(e,i[d],TJ(n,d));s>f.distance&&(a=f.closestMatch,l=f.path,s=f.distance,c=f.indexMatch)}else{var p;-1!==Lq(p=d.toLowerCase()).call(p,h)&&(c=d),s>(u=t.levenshteinDistance(e,d))&&(a=d,l=pG(o=n).call(o),s=u)}}return{closestMatch:a,path:l,distance:s,indexMatch:c}}},{key:"printLocation",value:function(t,e){for(var i="\n\n"+(arguments.length>2&&void 0!==arguments[2]?arguments[2]:"Problem value found at: \n")+"options = {\n",n=0;n":!0,"--":!0},mX="",bX=0,wX="",AX="",kX=gX.NULL;function EX(){bX++,wX=mX.charAt(bX)}function CX(){return mX.charAt(bX+1)}function xX(t){var e=t.charCodeAt(0);return e<47?35===e||46===e:e<59?e>47:e<91?e>64:e<96?95===e:e<123&&e>96}function IX(t,e){if(t||(t={}),e)for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}function SX(t,e,i){for(var n=e.split("."),o=t;n.length;){var r=n.shift();n.length?(o[r]||(o[r]={}),o=o[r]):o[r]=i}}function MX(t,e){for(var i,n,o=null,r=[t],s=t;s.parent;)r.push(s.parent),s=s.parent;if(s.nodes)for(i=0,n=s.nodes.length;i=0;i--){var a,l=r[i];l.nodes||(l.nodes=[]),-1===Lq(a=l.nodes).call(a,o)&&l.nodes.push(o)}e.attr&&(o.attr=IX(o.attr,e.attr))}function OX(t,e){if(t.edges||(t.edges=[]),t.edges.push(e),t.edge){var i=IX({},t.edge);e.attr=IX(i,e.attr)}}function DX(t,e,i,n,o){var r={from:e,to:i,type:n};return t.edge&&(r.attr=IX({},t.edge)),r.attr=IX(r.attr||{},o),null!=o&&o.hasOwnProperty("arrows")&&null!=o.arrows&&(r.arrows={to:{enabled:!0,type:o.arrows.type}},o.arrows=null),r}function RX(){for(kX=gX.NULL,AX="";" "===wX||"\t"===wX||"\n"===wX||"\r"===wX;)EX();do{var t=!1;if("#"===wX){for(var e=bX-1;" "===mX.charAt(e)||"\t"===mX.charAt(e);)e--;if("\n"===mX.charAt(e)||""===mX.charAt(e)){for(;""!=wX&&"\n"!=wX;)EX();t=!0}}if("/"===wX&&"/"===CX()){for(;""!=wX&&"\n"!=wX;)EX();t=!0}if("/"===wX&&"*"===CX()){for(;""!=wX;){if("*"===wX&&"/"===CX()){EX(),EX();break}EX()}t=!0}for(;" "===wX||"\t"===wX||"\n"===wX||"\r"===wX;)EX()}while(t);if(""!==wX){var i=wX+CX();if(yX[i])return kX=gX.DELIMITER,AX=i,EX(),void EX();if(yX[wX])return kX=gX.DELIMITER,AX=wX,void EX();if(xX(wX)||"-"===wX){for(AX+=wX,EX();xX(wX);)AX+=wX,EX();return"false"===AX?AX=!1:"true"===AX?AX=!0:isNaN(Number(AX))||(AX=Number(AX)),void(kX=gX.IDENTIFIER)}if('"'===wX){for(EX();""!=wX&&('"'!=wX||'"'===wX&&'"'===CX());)'"'===wX?(AX+=wX,EX()):"\\"===wX&&"n"===CX()?(AX+="\n",EX()):AX+=wX,EX();if('"'!=wX)throw NX('End of string " expected');return EX(),void(kX=gX.IDENTIFIER)}for(kX=gX.UNKNOWN;""!=wX;)AX+=wX,EX();throw new SyntaxError('Syntax error in part "'+jX(AX,30)+'"')}kX=gX.DELIMITER}function BX(t){for(;""!==AX&&"}"!=AX;)zX(t),";"===AX&&RX()}function zX(t){var e=PX(t);if(e)FX(t,e);else{var i=function(t){if("node"===AX)return RX(),t.node=TX(),"node";if("edge"===AX)return RX(),t.edge=TX(),"edge";if("graph"===AX)return RX(),t.graph=TX(),"graph";return null}(t);if(!i){if(kX!=gX.IDENTIFIER)throw NX("Identifier expected");var n=AX;if(RX(),"="===AX){if(RX(),kX!=gX.IDENTIFIER)throw NX("Identifier expected");t[n]=AX,RX()}else!function(t,e){var i={id:e},n=TX();n&&(i.attr=n);MX(t,i),FX(t,e)}(t,n)}}}function PX(t){var e=null;if("subgraph"===AX&&((e={}).type="subgraph",RX(),kX===gX.IDENTIFIER&&(e.id=AX,RX())),"{"===AX){if(RX(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,BX(e),"}"!=AX)throw NX("Angle bracket } expected");RX(),delete e.node,delete e.edge,delete e.graph,delete e.parent,t.subgraphs||(t.subgraphs=[]),t.subgraphs.push(e)}return e}function FX(t,e){for(;"->"===AX||"--"===AX;){var i,n=AX;RX();var o=PX(t);if(o)i=o;else{if(kX!=gX.IDENTIFIER)throw NX("Identifier or subgraph expected");MX(t,{id:i=AX}),RX()}OX(t,DX(t,e,i,n,TX())),e=i}}function TX(){for(var t,e,i=null,n={dashed:!0,solid:!1,dotted:[1,5]},o={dot:"circle",box:"box",crow:"crow",curve:"curve",icurve:"inv_curve",normal:"triangle",inv:"inv_triangle",diamond:"diamond",tee:"bar",vee:"vee"},r=new Array,s=new Array;"["===AX;){for(RX(),i={};""!==AX&&"]"!=AX;){if(kX!=gX.IDENTIFIER)throw NX("Attribute name expected");var a=AX;if(RX(),"="!=AX)throw NX("Equal sign = expected");if(RX(),kX!=gX.IDENTIFIER)throw NX("Attribute value expected");var l=AX;"style"===a&&(l=n[l]),"arrowhead"===a&&(a="arrows",l={to:{enabled:!0,type:o[l]}}),"arrowtail"===a&&(a="arrows",l={from:{enabled:!0,type:o[l]}}),r.push({attr:i,name:a,value:l}),s.push(a),RX(),","==AX&&RX()}if("]"!=AX)throw NX("Bracket ] expected");RX()}if(YK(s).call(s,"dir")){var h={arrows:{}};for(t=0;t"===t.type&&(e.arrows="to"),e};YG(o=i.edges).call(o,(function(t){var e,i,o,s,a,l,h;(e=t.from instanceof Object?t.from.nodes:{id:t.from},i=t.to instanceof Object?t.to.nodes:{id:t.to},t.from instanceof Object&&t.from.edges)&&YG(o=t.from.edges).call(o,(function(t){var e=r(t);n.edges.push(e)}));(a=i,l=function(e,i){var o=DX(n,e.id,i.id,t.type,t.attr),s=r(o);n.edges.push(s)},AG(s=e)?YG(s).call(s,(function(t){AG(a)?YG(a).call(a,(function(e){l(t,e)})):l(t,a)})):AG(a)?YG(a).call(a,(function(t){l(s,t)})):l(s,a),t.to instanceof Object&&t.to.edges)&&YG(h=t.to.edges).call(h,(function(t){var e=r(t);n.edges.push(e)}))}))}return i.attr&&(n.options=i.attr),n}var HX=Object.freeze({__proto__:null,cn:{addDescription:"单击空白处放置新节点。",addEdge:"添加连接线",addNode:"添加节点",back:"返回",close:"關閉",createEdgeError:"无法将连接线连接到群集。",del:"删除选定",deleteClusterError:"无法删除群集。",edgeDescription:"单击某个节点并将该连接线拖动到另一个节点以连接它们。",edit:"编辑",editClusterError:"无法编辑群集。",editEdge:"编辑连接线",editEdgeDescription:"单击控制节点并将它们拖到节点上连接。",editNode:"编辑节点"},cs:{addDescription:"Kluknutím do prázdného prostoru můžete přidat nový vrchol.",addEdge:"Přidat hranu",addNode:"Přidat vrchol",back:"Zpět",close:"Zavřít",createEdgeError:"Nelze připojit hranu ke shluku.",del:"Smazat výběr",deleteClusterError:"Nelze mazat shluky.",edgeDescription:"Přetažením z jednoho vrcholu do druhého můžete spojit tyto vrcholy novou hranou.",edit:"Upravit",editClusterError:"Nelze upravovat shluky.",editEdge:"Upravit hranu",editEdgeDescription:"Přetažením kontrolního vrcholu hrany ji můžete připojit k jinému vrcholu.",editNode:"Upravit vrchol"},de:{addDescription:"Klicke auf eine freie Stelle, um einen neuen Knoten zu plazieren.",addEdge:"Kante hinzufügen",addNode:"Knoten hinzufügen",back:"Zurück",close:"Schließen",createEdgeError:"Es ist nicht möglich, Kanten mit Clustern zu verbinden.",del:"Lösche Auswahl",deleteClusterError:"Cluster können nicht gelöscht werden.",edgeDescription:"Klicke auf einen Knoten und ziehe die Kante zu einem anderen Knoten, um diese zu verbinden.",edit:"Editieren",editClusterError:"Cluster können nicht editiert werden.",editEdge:"Kante editieren",editEdgeDescription:"Klicke auf die Verbindungspunkte und ziehe diese auf einen Knoten, um sie zu verbinden.",editNode:"Knoten editieren"},en:{addDescription:"Click in an empty space to place a new node.",addEdge:"Add Edge",addNode:"Add Node",back:"Back",close:"Close",createEdgeError:"Cannot link edges to a cluster.",del:"Delete selected",deleteClusterError:"Clusters cannot be deleted.",edgeDescription:"Click on a node and drag the edge to another node to connect them.",edit:"Edit",editClusterError:"Clusters cannot be edited.",editEdge:"Edit Edge",editEdgeDescription:"Click on the control points and drag them to a node to connect to it.",editNode:"Edit Node"},es:{addDescription:"Haga clic en un lugar vacío para colocar un nuevo nodo.",addEdge:"Añadir arista",addNode:"Añadir nodo",back:"Atrás",close:"Cerrar",createEdgeError:"No se puede conectar una arista a un grupo.",del:"Eliminar selección",deleteClusterError:"No es posible eliminar grupos.",edgeDescription:"Haga clic en un nodo y arrastre la arista hacia otro nodo para conectarlos.",edit:"Editar",editClusterError:"No es posible editar grupos.",editEdge:"Editar arista",editEdgeDescription:"Haga clic en un punto de control y arrastrelo a un nodo para conectarlo.",editNode:"Editar nodo"},fr:{addDescription:"Cliquez dans un endroit vide pour placer un nœud.",addEdge:"Ajouter un lien",addNode:"Ajouter un nœud",back:"Retour",close:"Fermer",createEdgeError:"Impossible de créer un lien vers un cluster.",del:"Effacer la sélection",deleteClusterError:"Les clusters ne peuvent pas être effacés.",edgeDescription:"Cliquez sur un nœud et glissez le lien vers un autre nœud pour les connecter.",edit:"Éditer",editClusterError:"Les clusters ne peuvent pas être édités.",editEdge:"Éditer le lien",editEdgeDescription:"Cliquez sur les points de contrôle et glissez-les pour connecter un nœud.",editNode:"Éditer le nœud"},it:{addDescription:"Clicca per aggiungere un nuovo nodo",addEdge:"Aggiungi un vertice",addNode:"Aggiungi un nodo",back:"Indietro",close:"Chiudere",createEdgeError:"Non si possono collegare vertici ad un cluster",del:"Cancella la selezione",deleteClusterError:"I cluster non possono essere cancellati",edgeDescription:"Clicca su un nodo e trascinalo ad un altro nodo per connetterli.",edit:"Modifica",editClusterError:"I clusters non possono essere modificati.",editEdge:"Modifica il vertice",editEdgeDescription:"Clicca sui Punti di controllo e trascinali ad un nodo per connetterli.",editNode:"Modifica il nodo"},nl:{addDescription:"Klik op een leeg gebied om een nieuwe node te maken.",addEdge:"Link toevoegen",addNode:"Node toevoegen",back:"Terug",close:"Sluiten",createEdgeError:"Kan geen link maken naar een cluster.",del:"Selectie verwijderen",deleteClusterError:"Clusters kunnen niet worden verwijderd.",edgeDescription:"Klik op een node en sleep de link naar een andere node om ze te verbinden.",edit:"Wijzigen",editClusterError:"Clusters kunnen niet worden aangepast.",editEdge:"Link wijzigen",editEdgeDescription:"Klik op de verbindingspunten en sleep ze naar een node om daarmee te verbinden.",editNode:"Node wijzigen"},pt:{addDescription:"Clique em um espaço em branco para adicionar um novo nó",addEdge:"Adicionar aresta",addNode:"Adicionar nó",back:"Voltar",close:"Fechar",createEdgeError:"Não foi possível linkar arestas a um cluster.",del:"Remover selecionado",deleteClusterError:"Clusters não puderam ser removidos.",edgeDescription:"Clique em um nó e arraste a aresta até outro nó para conectá-los",edit:"Editar",editClusterError:"Clusters não puderam ser editados.",editEdge:"Editar aresta",editEdgeDescription:"Clique nos pontos de controle e os arraste para um nó para conectá-los",editNode:"Editar nó"},ru:{addDescription:"Кликните в свободное место, чтобы добавить новый узел.",addEdge:"Добавить ребро",addNode:"Добавить узел",back:"Назад",close:"Закрывать",createEdgeError:"Невозможно соединить ребра в кластер.",del:"Удалить выбранное",deleteClusterError:"Кластеры не могут быть удалены",edgeDescription:"Кликните на узел и протяните ребро к другому узлу, чтобы соединить их.",edit:"Редактировать",editClusterError:"Кластеры недоступны для редактирования.",editEdge:"Редактировать ребро",editEdgeDescription:"Кликните на контрольные точки и перетащите их в узел, чтобы подключиться к нему.",editNode:"Редактировать узел"},uk:{addDescription:"Kлікніть на вільне місце, щоб додати новий вузол.",addEdge:"Додати край",addNode:"Додати вузол",back:"Назад",close:"Закрити",createEdgeError:"Не можливо об'єднати краї в групу.",del:"Видалити обране",deleteClusterError:"Групи не можуть бути видалені.",edgeDescription:"Клікніть на вузол і перетягніть край до іншого вузла, щоб їх з'єднати.",edit:"Редагувати",editClusterError:"Групи недоступні для редагування.",editEdge:"Редагувати край",editEdgeDescription:"Клікніть на контрольні точки і перетягніть їх у вузол, щоб підключитися до нього.",editNode:"Редагувати вузол"}});var VX=function(){function t(){uU(this,t),this.NUM_ITERATIONS=4,this.image=new Image,this.canvas=document.createElement("canvas")}return yW(t,[{key:"init",value:function(){if(!this.initialized()){this.src=this.image.src;var t=this.image.width,e=this.image.height;this.width=t,this.height=e;var i=Math.floor(e/2),n=Math.floor(e/4),o=Math.floor(e/8),r=Math.floor(e/16),s=Math.floor(t/2),a=Math.floor(t/4),l=Math.floor(t/8),h=Math.floor(t/16);this.canvas.width=3*a,this.canvas.height=i,this.coordinates=[[0,0,s,i],[s,0,a,n],[s,n,l,o],[5*l,n,h,r]],this._fillMipMap()}}},{key:"initialized",value:function(){return void 0!==this.coordinates}},{key:"_fillMipMap",value:function(){var t=this.canvas.getContext("2d"),e=this.coordinates[0];t.drawImage(this.image,e[0],e[1],e[2],e[3]);for(var i=1;i2){e*=.5;for(var s=0;e>2&&s=this.NUM_ITERATIONS&&(s=this.NUM_ITERATIONS-1);var a=this.coordinates[s];t.drawImage(this.canvas,a[0],a[1],a[2],a[3],i,n,o,r)}else t.drawImage(this.image,i,n,o,r)}}]),t}(),WX=function(){function t(e){uU(this,t),this.images={},this.imageBroken={},this.callback=e}return yW(t,[{key:"_tryloadBrokenUrl",value:function(t,e,i){void 0!==t&&void 0!==i&&(void 0!==e?(i.image.onerror=function(){console.error("Could not load brokenImage:",e)},i.image.src=e):console.warn("No broken url image defined"))}},{key:"_redrawWithImage",value:function(t){this.callback&&this.callback(t)}},{key:"load",value:function(t,e){var i=this,n=this.images[t];if(n)return n;var o=new VX;return this.images[t]=o,o.image.onload=function(){i._fixImageCoordinates(o.image),o.init(),i._redrawWithImage(o)},o.image.onerror=function(){console.error("Could not load image:",t),i._tryloadBrokenUrl(t,e,o)},o.image.src=t,o}},{key:"_fixImageCoordinates",value:function(t){0===t.width&&(document.body.appendChild(t),t.width=t.offsetWidth,t.height=t.offsetHeight,document.body.removeChild(t))}}]),t}(),GX={exports:{}},KX=sR((function(){if("function"==typeof ArrayBuffer){var t=new ArrayBuffer(8);Object.isExtensible(t)&&Object.defineProperty(t,"a",{value:8})}})),qX=sR,YX=eB,ZX=AR,JX=KX,XX=Object.isExtensible,_X=qX((function(){XX(1)}))||JX?function(t){return!!YX(t)&&((!JX||"ArrayBuffer"!==ZX(t))&&(!XX||XX(t)))}:XX,$X=!sR((function(){return Object.isExtensible(Object.preventExtensions({}))})),t_=OP,e_=yR,i_=YP,n_=eB,o_=$B,r_=_z.f,s_=JU,a_=$U,l_=_X,h_=$X,c_=!1,d_=oz("meta"),u_=0,f_=function(t){r_(t,d_,{value:{objectID:"O"+u_++,weakData:{}}})},p_=GX.exports={enable:function(){p_.enable=function(){},c_=!0;var t=s_.f,e=e_([].splice),i={};i[d_]=1,t(i).length&&(s_.f=function(i){for(var n=t(i),o=0,r=n.length;or;r++)if((a=y(t[r]))&&k_(M_,a))return a;return new S_(!1)}n=E_(t,o)}for(l=u?t.next:n.next;!(h=y_(l,n)).done;){try{a=y(h.value)}catch(t){x_(n,"throw",t)}if("object"==typeof a&&a&&k_(M_,a))return a}return new S_(!1)},D_=lB,R_=TypeError,B_=function(t,e){if(D_(e,t))return t;throw new R_("Incorrect invocation")},z_=OP,P_=rR,F_=v_,T_=sR,N_=yP,j_=O_,L_=B_,U_=MR,Q_=eB,H_=KR,V_=YN,W_=_z.f,G_=BQ.forEach,K_=DR,q_=UT.set,Y_=UT.getterFor,Z_=function(t,e,i){var n,o=-1!==t.indexOf("Map"),r=-1!==t.indexOf("Weak"),s=o?"set":"add",a=P_[t],l=a&&a.prototype,h={};if(K_&&U_(a)&&(r||l.forEach&&!T_((function(){(new a).entries().next()})))){var c=(n=e((function(e,i){q_(L_(e,c),{type:t,collection:new a}),H_(i)||j_(i,e[s],{that:e,AS_ENTRIES:o})}))).prototype,d=Y_(t);G_(["add","clear","delete","forEach","get","has","set","keys","values","entries"],(function(t){var e="add"===t||"set"===t;!(t in l)||r&&"clear"===t||N_(c,t,(function(i,n){var o=d(this).collection;if(!e&&r&&!Q_(i))return"get"===t&&void 0;var s=o[t](0===i?0:i,n);return e?this:s}))})),r||W_(c,"size",{configurable:!0,get:function(){return d(this).collection.size}})}else n=i.getConstructor(e,t,o,s),F_.enable();return V_(n,t,!1,!0),h[t]=n,z_({global:!0,forced:!0},h),r||i.setStrong(n,t,o),n},J_=ON,X_=function(t,e,i){for(var n in e)i&&i.unsafe&&t[n]?t[n]=e[n]:J_(t,n,e[n],i);return t},__=aB,$_=uQ,t$=DR,e$=fz("species"),i$=mN,n$=uQ,o$=X_,r$=Xz,s$=B_,a$=KR,l$=O_,h$=xj,c$=Ij,d$=function(t){var e=__(t);t$&&e&&!e[e$]&&$_(e,e$,{configurable:!0,get:function(){return this}})},u$=DR,f$=v_.fastKey,p$=UT.set,v$=UT.getterFor,g$={getConstructor:function(t,e,i,n){var o=t((function(t,o){s$(t,r),p$(t,{type:e,index:i$(null),first:void 0,last:void 0,size:0}),u$||(t.size=0),a$(o)||l$(o,t[n],{that:t,AS_ENTRIES:i})})),r=o.prototype,s=v$(e),a=function(t,e,i){var n,o,r=s(t),a=l(t,e);return a?a.value=i:(r.last=a={index:o=f$(e,!0),key:e,value:i,previous:n=r.last,next:void 0,removed:!1},r.first||(r.first=a),n&&(n.next=a),u$?r.size++:t.size++,"F"!==o&&(r.index[o]=a)),t},l=function(t,e){var i,n=s(t),o=f$(e);if("F"!==o)return n.index[o];for(i=n.first;i;i=i.next)if(i.key===e)return i};return o$(r,{clear:function(){for(var t=s(this),e=t.index,i=t.first;i;)i.removed=!0,i.previous&&(i.previous=i.previous.next=void 0),delete e[i.index],i=i.next;t.first=t.last=void 0,u$?t.size=0:this.size=0},delete:function(t){var e=this,i=s(e),n=l(e,t);if(n){var o=n.next,r=n.previous;delete i.index[n.index],n.removed=!0,r&&(r.next=o),o&&(o.previous=r),i.first===n&&(i.first=o),i.last===n&&(i.last=r),u$?i.size--:e.size--}return!!n},forEach:function(t){for(var e,i=s(this),n=r$(t,arguments.length>1?arguments[1]:void 0);e=e?e.next:i.first;)for(n(e.value,e.key,this);e&&e.removed;)e=e.previous},has:function(t){return!!l(this,t)}}),o$(r,i?{get:function(t){var e=l(this,t);return e&&e.value},set:function(t,e){return a(this,0===t?0:t,e)}}:{add:function(t){return a(this,t=0===t?0:t,t)}}),u$&&n$(r,"size",{configurable:!0,get:function(){return s(this).size}}),o},setStrong:function(t,e,i){var n=e+" Iterator",o=v$(e),r=v$(n);h$(t,e,(function(t,e){p$(this,{type:n,target:t,state:o(t),kind:e,last:void 0})}),(function(){for(var t=r(this),e=t.kind,i=t.last;i&&i.removed;)i=i.previous;return t.target&&(t.last=i=i?i.next:t.state.first)?c$("keys"===e?i.key:"values"===e?i.value:[i.key,i.value],!1):(t.target=void 0,c$(void 0,!0))}),i?"entries":"values",!i,!0),d$(e)}};Z_("Map",(function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}}),g$);var y$=nR(iB.Map),m$=function(){function t(){uU(this,t),this.clear(),this._defaultIndex=0,this._groupIndex=0,this._defaultGroups=[{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"},hover:{border:"#2B7CE9",background:"#D2E5FF"}},{border:"#FFA500",background:"#FFFF00",highlight:{border:"#FFA500",background:"#FFFFA3"},hover:{border:"#FFA500",background:"#FFFFA3"}},{border:"#FA0A10",background:"#FB7E81",highlight:{border:"#FA0A10",background:"#FFAFB1"},hover:{border:"#FA0A10",background:"#FFAFB1"}},{border:"#41A906",background:"#7BE141",highlight:{border:"#41A906",background:"#A1EC76"},hover:{border:"#41A906",background:"#A1EC76"}},{border:"#E129F0",background:"#EB7DF4",highlight:{border:"#E129F0",background:"#F0B3F5"},hover:{border:"#E129F0",background:"#F0B3F5"}},{border:"#7C29F0",background:"#AD85E4",highlight:{border:"#7C29F0",background:"#D3BDF0"},hover:{border:"#7C29F0",background:"#D3BDF0"}},{border:"#C37F00",background:"#FFA807",highlight:{border:"#C37F00",background:"#FFCA66"},hover:{border:"#C37F00",background:"#FFCA66"}},{border:"#4220FB",background:"#6E6EFD",highlight:{border:"#4220FB",background:"#9B9BFD"},hover:{border:"#4220FB",background:"#9B9BFD"}},{border:"#FD5A77",background:"#FFC0CB",highlight:{border:"#FD5A77",background:"#FFD1D9"},hover:{border:"#FD5A77",background:"#FFD1D9"}},{border:"#4AD63A",background:"#C2FABC",highlight:{border:"#4AD63A",background:"#E6FFE3"},hover:{border:"#4AD63A",background:"#E6FFE3"}},{border:"#990000",background:"#EE0000",highlight:{border:"#BB0000",background:"#FF3333"},hover:{border:"#BB0000",background:"#FF3333"}},{border:"#FF6000",background:"#FF6000",highlight:{border:"#FF6000",background:"#FF6000"},hover:{border:"#FF6000",background:"#FF6000"}},{border:"#97C2FC",background:"#2B7CE9",highlight:{border:"#D2E5FF",background:"#2B7CE9"},hover:{border:"#D2E5FF",background:"#2B7CE9"}},{border:"#399605",background:"#255C03",highlight:{border:"#399605",background:"#255C03"},hover:{border:"#399605",background:"#255C03"}},{border:"#B70054",background:"#FF007E",highlight:{border:"#B70054",background:"#FF007E"},hover:{border:"#B70054",background:"#FF007E"}},{border:"#AD85E4",background:"#7C29F0",highlight:{border:"#D3BDF0",background:"#7C29F0"},hover:{border:"#D3BDF0",background:"#7C29F0"}},{border:"#4557FA",background:"#000EA1",highlight:{border:"#6E6EFD",background:"#000EA1"},hover:{border:"#6E6EFD",background:"#000EA1"}},{border:"#FFC0CB",background:"#FD5A77",highlight:{border:"#FFD1D9",background:"#FD5A77"},hover:{border:"#FFD1D9",background:"#FD5A77"}},{border:"#C2FABC",background:"#74D66A",highlight:{border:"#E6FFE3",background:"#74D66A"},hover:{border:"#E6FFE3",background:"#74D66A"}},{border:"#EE0000",background:"#990000",highlight:{border:"#FF3333",background:"#BB0000"},hover:{border:"#FF3333",background:"#BB0000"}}],this.options={},this.defaultOptions={useDefaultGroups:!0},wF(this.options,this.defaultOptions)}return yW(t,[{key:"setOptions",value:function(t){var e=["useDefaultGroups"];if(void 0!==t)for(var i in t)if(Object.prototype.hasOwnProperty.call(t,i)&&-1===Lq(e).call(e,i)){var n=t[i];this.add(i,n)}}},{key:"clear",value:function(){this._groups=new y$,this._groupNames=[]}},{key:"get",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=this._groups.get(t);if(void 0===i&&e)if(!1===this.options.useDefaultGroups&&this._groupNames.length>0){var n=this._groupIndex%this._groupNames.length;++this._groupIndex,(i={}).color=this._groups.get(this._groupNames[n]),this._groups.set(t,i)}else{var o=this._defaultIndex%this._defaultGroups.length;this._defaultIndex++,(i={}).color=this._defaultGroups[o],this._groups.set(t,i)}return i}},{key:"add",value:function(t,e){return this._groups.has(t)||this._groupNames.push(t),this._groups.set(t,e),e}}]),t}();OP({target:"Number",stat:!0},{isNaN:function(t){return t!=t}});var b$=nR(iB.Number.isNaN),w$=rR.isFinite,A$=Number.isFinite||function(t){return"number"==typeof t&&w$(t)};OP({target:"Number",stat:!0},{isFinite:A$});var k$=nR(iB.Number.isFinite),E$=BQ.some;OP({target:"Array",proto:!0,forced:!NG("some")},{some:function(t){return E$(this,t,arguments.length>1?arguments[1]:void 0)}});var C$=FF("Array").some,x$=lB,I$=C$,S$=Array.prototype,M$=function(t){var e=t.some;return t===S$||x$(S$,t)&&e===S$.some?I$:e},O$=nR(M$),D$=nR(iB.Object.getOwnPropertySymbols),R$={exports:{}},B$=OP,z$=sR,P$=_R,F$=OR.f,T$=DR;B$({target:"Object",stat:!0,forced:!T$||z$((function(){F$(1)})),sham:!T$},{getOwnPropertyDescriptor:function(t,e){return F$(P$(t),e)}});var N$=iB.Object,j$=R$.exports=function(t,e){return N$.getOwnPropertyDescriptor(t,e)};N$.getOwnPropertyDescriptor.sham&&(j$.sham=!0);var L$=R$.exports,U$=nR(L$),Q$=wG,H$=_R,V$=OR,W$=uL;OP({target:"Object",stat:!0,sham:!DR},{getOwnPropertyDescriptors:function(t){for(var e,i,n=H$(t),o=V$.f,r=Q$(n),s={},a=0;r.length>a;)void 0!==(i=o(n,e=r[a++]))&&W$(s,e,i);return s}});var G$=nR(iB.Object.getOwnPropertyDescriptors),K$={exports:{}},q$=OP,Y$=DR,Z$=qT.f;q$({target:"Object",stat:!0,forced:Object.defineProperties!==Z$,sham:!Y$},{defineProperties:Z$});var J$=iB.Object,X$=K$.exports=function(t,e){return J$.defineProperties(t,e)};J$.defineProperties.sham&&(X$.sham=!0);var _$=nR(K$.exports),$$=nR(bU);function t0(t,e,i){return(e=vW(e))in t?wU(t,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[e]=i,t}var e0=rR,i0=sR,n0=dT,o0=vq.trim,r0=aq,s0=yR("".charAt),a0=e0.parseFloat,l0=e0.Symbol,h0=l0&&l0.iterator,c0=1/a0(r0+"-0")!=-1/0||h0&&!i0((function(){a0(Object(h0))}))?function(t){var e=o0(n0(t)),i=a0(e);return 0===i&&"-"===s0(e,0)?-0:i}:a0;OP({global:!0,forced:parseFloat!==c0},{parseFloat:c0});var d0=nR(iB.parseFloat),u0=OP,f0=sR,p0=$U.f;u0({target:"Object",stat:!0,forced:f0((function(){return!Object.getOwnPropertyNames(1)}))},{getOwnPropertyNames:p0});var v0=iB.Object,g0=function(t){return v0.getOwnPropertyNames(t)},y0=nR(g0);function m0(t,e){var i=["node","edge","label"],n=!0,o=XJ(e,"chosen");if("boolean"==typeof o)n=o;else if("object"===fW(o)){if(-1===Lq(i).call(i,t))throw new Error("choosify: subOption '"+t+"' should be one of '"+i.join("', '")+"'");var r=XJ(e,["chosen",t]);"boolean"!=typeof r&&"function"!=typeof r||(n=r)}return n}function b0(t,e,i){if(t.width<=0||t.height<=0)return!1;if(void 0!==i){var n={x:e.x-i.x,y:e.y-i.y};if(0!==i.angle){var o=-i.angle;e={x:Math.cos(o)*n.x-Math.sin(o)*n.y,y:Math.sin(o)*n.x+Math.cos(o)*n.y}}else e=n}var r=t.x+t.width,s=t.y+t.width;return t.lefte.x&&t.tope.y}function w0(t){return"string"==typeof t&&""!==t}function A0(t,e,i,n){var o=n.x,r=n.y;if("function"==typeof n.distanceToBorder){var s=n.distanceToBorder(t,e),a=Math.sin(e)*s,l=Math.cos(e)*s;l===s?(o+=s,r=n.y):a===s?(o=n.x,r-=s):(o+=l,r-=a)}else n.shape.width>n.shape.height?(o=n.x+.5*n.shape.width,r=n.y-i):(o=n.x+i,r=n.y-.5*n.shape.height);return{x:o,y:r}}var k0=FF("Array").values,E0=lT,C0=$B,x0=lB,I0=k0,S0=Array.prototype,M0={DOMTokenList:!0,NodeList:!0},O0=function(t){var e=t.values;return t===S0||x0(S0,t)&&e===S0.values||C0(M0,E0(t))?I0:e},D0=nR(O0),R0=function(){function t(e){uU(this,t),this.measureText=e,this.current=0,this.width=0,this.height=0,this.lines=[]}return yW(t,[{key:"_add",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"normal";void 0===this.lines[t]&&(this.lines[t]={width:0,height:0,blocks:[]});var n=e;void 0!==e&&""!==e||(n=" ");var o=this.measureText(n,i),r=wF({},D0(o));r.text=e,r.width=o.width,r.mod=i,void 0!==e&&""!==e||(r.width=0),this.lines[t].blocks.push(r),this.lines[t].width+=r.width}},{key:"curWidth",value:function(){var t=this.lines[this.current];return void 0===t?0:t.width}},{key:"append",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"normal";this._add(this.current,t,e)}},{key:"newLine",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"normal";this._add(this.current,t,e),this.current++}},{key:"determineLineHeights",value:function(){for(var t=0;tt&&(t=n.width),e+=n.height}this.width=t,this.height=e}},{key:"removeEmptyBlocks",value:function(){for(var t=[],e=0;e"://,""://,""://,"":/<\/b>/,"":/<\/i>/,"":/<\/code>/,"*":/\*/,_:/_/,"`":/`/,afterBold:/[^*]/,afterItal:/[^_]/,afterMono:/[^`]/},z0=function(){function t(e){uU(this,t),this.text=e,this.bold=!1,this.ital=!1,this.mono=!1,this.spacing=!1,this.position=0,this.buffer="",this.modStack=[],this.blocks=[]}return yW(t,[{key:"mod",value:function(){return 0===this.modStack.length?"normal":this.modStack[0]}},{key:"modName",value:function(){return 0===this.modStack.length?"normal":"mono"===this.modStack[0]?"mono":this.bold&&this.ital?"boldital":this.bold?"bold":this.ital?"ital":void 0}},{key:"emitBlock",value:function(){this.spacing&&(this.add(" "),this.spacing=!1),this.buffer.length>0&&(this.blocks.push({text:this.buffer,mod:this.modName()}),this.buffer="")}},{key:"add",value:function(t){" "===t&&(this.spacing=!0),this.spacing&&(this.buffer+=" ",this.spacing=!1)," "!=t&&(this.buffer+=t)}},{key:"parseWS",value:function(t){return!!/[ \t]/.test(t)&&(this.mono?this.add(t):this.spacing=!0,!0)}},{key:"setTag",value:function(t){this.emitBlock(),this[t]=!0,this.modStack.unshift(t)}},{key:"unsetTag",value:function(t){this.emitBlock(),this[t]=!1,this.modStack.shift()}},{key:"parseStartTag",value:function(t,e){return!(this.mono||this[t]||!this.match(e))&&(this.setTag(t),!0)}},{key:"match",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=rG(this.prepareRegExp(t),2),n=i[0],o=i[1],r=n.test(this.text.substr(this.position,o));return r&&e&&(this.position+=o-1),r}},{key:"parseEndTag",value:function(t,e,i){var n=this.mod()===t;return!(!(n="mono"===t?n&&this.mono:n&&!this.mono)||!this.match(e))&&(void 0!==i?(this.position===this.text.length-1||this.match(i,!1))&&this.unsetTag(t):this.unsetTag(t),!0)}},{key:"replace",value:function(t,e){return!!this.match(t)&&(this.add(e),this.position+=length-1,!0)}},{key:"prepareRegExp",value:function(t){var e,i;if(t instanceof RegExp)i=t,e=1;else{var n=B0[t];i=void 0!==n?n:new RegExp(t),e=t.length}return[i,e]}}]),t}(),P0=function(){function t(e,i,n,o){var r=this;uU(this,t),this.ctx=e,this.parent=i,this.selected=n,this.hover=o;this.lines=new R0((function(t,i){if(void 0===t)return 0;var s=r.parent.getFormattingValues(e,n,o,i),a=0;""!==t&&(a=r.ctx.measureText(t).width);return{width:a,values:s}}))}return yW(t,[{key:"process",value:function(t){if(!w0(t))return this.lines.finalize();var e=this.parent.fontOptions;t=(t=t.replace(/\r\n/g,"\n")).replace(/\r/g,"\n");var i=String(t).split("\n"),n=i.length;if(e.multi)for(var o=0;o0)for(var s=0;s0)for(var u=0;u")||e.parseStartTag("ital","")||e.parseStartTag("mono","")||e.parseEndTag("bold","")||e.parseEndTag("ital","")||e.parseEndTag("mono",""))||i(n)||e.add(n),e.position++}return e.emitBlock(),e.blocks}},{key:"splitMarkdownBlocks",value:function(t){for(var e=this,i=new z0(t),n=!0,o=function(t){return!!/\\/.test(t)&&(i.positionthis.parent.fontOptions.maxWdt}},{key:"getLongestFit",value:function(t){for(var e="",i=0;i1&&void 0!==arguments[1]?arguments[1]:"normal",i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];this.parent.getFormattingValues(this.ctx,this.selected,this.hover,e);for(var n=(t=(t=t.replace(/^( +)/g,"$1\r")).replace(/([^\r][^ ]*)( +)/g,"$1\r$2\r")).split("\r");n.length>0;){var o=this.getLongestFit(n);if(0===o){var r=n[0],s=this.getLongestFitWord(r);this.lines.newLine(pG(r).call(r,0,s),e),n[0]=pG(r).call(r,s)}else{var a=o;" "===n[o-1]?o--:" "===n[a]&&a++;var l=pG(n).call(n,0,o).join("");o==n.length&&i?this.lines.append(l,e):this.lines.newLine(l,e),n=pG(n).call(n,a)}}}}]),t}(),F0=["bold","ital","boldital","mono"],T0=function(){function t(e,i){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];uU(this,t),this.body=e,this.pointToSelf=!1,this.baseSize=void 0,this.fontOptions={},this.setOptions(i),this.size={top:0,left:0,width:0,height:0,yLine:0},this.isEdgeLabel=n}return yW(t,[{key:"setOptions",value:function(t){if(this.elementOptions=t,this.initFontOptions(t.font),w0(t.label)?this.labelDirty=!0:t.label=void 0,void 0!==t.font&&null!==t.font)if("string"==typeof t.font)this.baseSize=this.fontOptions.size;else if("object"===fW(t.font)){var e=t.font.size;void 0!==e&&(this.baseSize=e)}}},{key:"initFontOptions",value:function(e){var i=this;jJ(F0,(function(t){i.fontOptions[t]={}})),t.parseFontString(this.fontOptions,e)?this.fontOptions.vadjust=0:jJ(e,(function(t,e){null!=t&&"object"!==fW(t)&&(i.fontOptions[e]=t)}))}},{key:"constrain",value:function(t){var e={constrainWidth:!1,maxWdt:-1,minWdt:-1,constrainHeight:!1,minHgt:-1,valign:"middle"},i=XJ(t,"widthConstraint");if("number"==typeof i)e.maxWdt=Number(i),e.minWdt=Number(i);else if("object"===fW(i)){var n=XJ(t,["widthConstraint","maximum"]);"number"==typeof n&&(e.maxWdt=Number(n));var o=XJ(t,["widthConstraint","minimum"]);"number"==typeof o&&(e.minWdt=Number(o))}var r=XJ(t,"heightConstraint");if("number"==typeof r)e.minHgt=Number(r);else if("object"===fW(r)){var s=XJ(t,["heightConstraint","minimum"]);"number"==typeof s&&(e.minHgt=Number(s));var a=XJ(t,["heightConstraint","valign"]);"string"==typeof a&&("top"!==a&&"bottom"!==a||(e.valign=a))}return e}},{key:"update",value:function(t,e){this.setOptions(t,!0),this.propagateFonts(e),FJ(this.fontOptions,this.constrain(e)),this.fontOptions.chooser=m0("label",e)}},{key:"adjustSizes",value:function(t){var e=t?t.right+t.left:0;this.fontOptions.constrainWidth&&(this.fontOptions.maxWdt-=e,this.fontOptions.minWdt-=e);var i=t?t.top+t.bottom:0;this.fontOptions.constrainHeight&&(this.fontOptions.minHgt-=i)}},{key:"addFontOptionsToPile",value:function(t,e){for(var i=0;i5&&void 0!==arguments[5]?arguments[5]:"middle";if(void 0!==this.elementOptions.label){var s=this.fontOptions.size*this.body.view.scale;this.elementOptions.label&&s=this.elementOptions.scaling.label.maxVisible&&(s=Number(this.elementOptions.scaling.label.maxVisible)/this.body.view.scale),this.calculateLabelSize(t,n,o,e,i,r),this._drawBackground(t),this._drawText(t,e,this.size.yLine,r,s))}}},{key:"_drawBackground",value:function(t){if(void 0!==this.fontOptions.background&&"none"!==this.fontOptions.background){t.fillStyle=this.fontOptions.background;var e=this.getSize();t.fillRect(e.left,e.top,e.width,e.height)}}},{key:"_drawText",value:function(t,e,i){var n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"middle",o=arguments.length>4?arguments[4]:void 0,r=rG(this._setAlignment(t,e,i,n),2);e=r[0],i=r[1],t.textAlign="left",e-=this.size.width/2,this.fontOptions.valign&&this.size.height>this.size.labelHeight&&("top"===this.fontOptions.valign&&(i-=(this.size.height-this.size.labelHeight)/2),"bottom"===this.fontOptions.valign&&(i+=(this.size.height-this.size.labelHeight)/2));for(var s=0;s0&&(t.lineWidth=c.strokeWidth,t.strokeStyle=f,t.lineJoin="round"),t.fillStyle=u,c.strokeWidth>0&&t.strokeText(c.text,e+l,i+c.vadjust),t.fillText(c.text,e+l,i+c.vadjust),l+=c.width}i+=a.height}}}},{key:"_setAlignment",value:function(t,e,i,n){if(this.isEdgeLabel&&"horizontal"!==this.fontOptions.align&&!1===this.pointToSelf){e=0,i=0;"top"===this.fontOptions.align?(t.textBaseline="alphabetic",i-=4):"bottom"===this.fontOptions.align?(t.textBaseline="hanging",i+=4):t.textBaseline="middle"}else t.textBaseline=n;return[e,i]}},{key:"_getColor",value:function(t,e,i){var n=t||"#000000",o=i||"#ffffff";if(e<=this.elementOptions.scaling.label.drawThreshold){var r=Math.max(0,Math.min(1,1-(this.elementOptions.scaling.label.drawThreshold-e)));n=UJ(n,r),o=UJ(o,r)}return[n,o]}},{key:"getTextSize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return this._processLabel(t,e,i),{width:this.size.width,height:this.size.height,lineCount:this.lineCount}}},{key:"getSize",value:function(){var t=this.size.left,e=this.size.top-1;if(this.isEdgeLabel){var i=.5*-this.size.width;switch(this.fontOptions.align){case"middle":t=i,e=.5*-this.size.height;break;case"top":t=i,e=-(this.size.height+2);break;case"bottom":t=i,e=2}}return{left:t,top:e,width:this.size.width,height:this.size.height}}},{key:"calculateLabelSize",value:function(t,e,i){var n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,o=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,r=arguments.length>5&&void 0!==arguments[5]?arguments[5]:"middle";this._processLabel(t,e,i),this.size.left=n-.5*this.size.width,this.size.top=o-.5*this.size.height,this.size.yLine=o+.5*(1-this.lineCount)*this.fontOptions.size,"hanging"===r&&(this.size.top+=.5*this.fontOptions.size,this.size.top+=4,this.size.yLine+=4)}},{key:"getFormattingValues",value:function(t,e,i,n){var o=function(t,e,i){return"normal"===e?"mod"===i?"":t[i]:void 0!==t[e][i]?t[e][i]:t[i]},r={color:o(this.fontOptions,n,"color"),size:o(this.fontOptions,n,"size"),face:o(this.fontOptions,n,"face"),mod:o(this.fontOptions,n,"mod"),vadjust:o(this.fontOptions,n,"vadjust"),strokeWidth:this.fontOptions.strokeWidth,strokeColor:this.fontOptions.strokeColor};(e||i)&&("normal"===n&&!0===this.fontOptions.chooser&&this.elementOptions.labelHighlightBold?r.mod="bold":"function"==typeof this.fontOptions.chooser&&this.fontOptions.chooser(r,this.elementOptions.id,e,i));var s="";return void 0!==r.mod&&""!==r.mod&&(s+=r.mod+" "),s+=r.size+"px "+r.face,t.font=s.replace(/"/g,""),r.font=t.font,r.height=r.size,r}},{key:"differentState",value:function(t,e){return t!==this.selectedState||e!==this.hoverState}},{key:"_processLabelText",value:function(t,e,i,n){return new P0(t,this,e,i).process(n)}},{key:"_processLabel",value:function(t,e,i){if(!1!==this.labelDirty||this.differentState(e,i)){var n=this._processLabelText(t,e,i,this.elementOptions.label);this.fontOptions.minWdt>0&&n.width0&&n.height0&&(this.enableBorderDashes(t,e),t.stroke(),this.disableBorderDashes(t,e)),t.restore()}},{key:"performFill",value:function(t,e){t.save(),t.fillStyle=e.color,this.enableShadow(t,e),EY(t).call(t),this.disableShadow(t,e),t.restore(),this.performStroke(t,e)}},{key:"_addBoundingBoxMargin",value:function(t){this.boundingBox.left-=t,this.boundingBox.top-=t,this.boundingBox.bottom+=t,this.boundingBox.right+=t}},{key:"_updateBoundingBox",value:function(t,e,i,n,o){void 0!==i&&this.resize(i,n,o),this.left=t-this.width/2,this.top=e-this.height/2,this.boundingBox.left=this.left,this.boundingBox.top=this.top,this.boundingBox.bottom=this.top+this.height,this.boundingBox.right=this.left+this.width}},{key:"updateBoundingBox",value:function(t,e,i,n,o){this._updateBoundingBox(t,e,i,n,o)}},{key:"getDimensionsFromLabel",value:function(t,e,i){this.textSize=this.labelModule.getTextSize(t,e,i);var n=this.textSize.width,o=this.textSize.height;return 0===n&&(n=14,o=14),{width:n,height:o}}}]),t}();function c1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var d1=function(t){r1(i,t);var e=c1(i);function i(t,n,o){var r;return uU(this,i),(r=e.call(this,t,n,o))._setMargins(o),r}return yW(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(this.needsRefresh(e,i)){var n=this.getDimensionsFromLabel(t,e,i);this.width=n.width+this.margin.right+this.margin.left,this.height=n.height+this.margin.top+this.margin.bottom,this.radius=this.width/2}}},{key:"draw",value:function(t,e,i,n,o,r){this.resize(t,n,o),this.left=e-this.width/2,this.top=i-this.height/2,this.initContextForDraw(t,r),WF(t,this.left,this.top,this.width,this.height,r.borderRadius),this.performFill(t,r),this.updateBoundingBox(e,i,t,n,o),this.labelModule.draw(t,this.left+this.textSize.width/2+this.margin.left,this.top+this.textSize.height/2+this.margin.top,n,o)}},{key:"updateBoundingBox",value:function(t,e,i,n,o){this._updateBoundingBox(t,e,i,n,o);var r=this.options.shapeProperties.borderRadius;this._addBoundingBoxMargin(r)}},{key:"distanceToBorder",value:function(t,e){t&&this.resize(t);var i=this.options.borderWidth;return Math.min(Math.abs(this.width/2/Math.cos(e)),Math.abs(this.height/2/Math.sin(e)))+i}}]),i}(h1);function u1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var f1=function(t){r1(i,t);var e=u1(i);function i(t,n,o){var r;return uU(this,i),(r=e.call(this,t,n,o)).labelOffset=0,r.selected=!1,r}return yW(i,[{key:"setOptions",value:function(t,e,i){this.options=t,void 0===e&&void 0===i||this.setImages(e,i)}},{key:"setImages",value:function(t,e){e&&this.selected?(this.imageObj=e,this.imageObjAlt=t):(this.imageObj=t,this.imageObjAlt=e)}},{key:"switchImages",value:function(t){var e=t&&!this.selected||!t&&this.selected;if(this.selected=t,void 0!==this.imageObjAlt&&e){var i=this.imageObj;this.imageObj=this.imageObjAlt,this.imageObjAlt=i}}},{key:"_getImagePadding",value:function(){var t={top:0,right:0,bottom:0,left:0};if(this.options.imagePadding){var e=this.options.imagePadding;"object"==fW(e)?(t.top=e.top,t.right=e.right,t.bottom=e.bottom,t.left=e.left):(t.top=e,t.right=e,t.bottom=e,t.left=e)}return t}},{key:"_resizeImage",value:function(){var t,e;if(!1===this.options.shapeProperties.useImageSize){var i=1,n=1;this.imageObj.width&&this.imageObj.height&&(this.imageObj.width>this.imageObj.height?i=this.imageObj.width/this.imageObj.height:n=this.imageObj.height/this.imageObj.width),t=2*this.options.size*i,e=2*this.options.size*n}else{var o=this._getImagePadding();t=this.imageObj.width+o.left+o.right,e=this.imageObj.height+o.top+o.bottom}this.width=t,this.height=e,this.radius=.5*this.width}},{key:"_drawRawCircle",value:function(t,e,i,n){this.initContextForDraw(t,n),VF(t,e,i,n.size),this.performFill(t,n)}},{key:"_drawImageAtPosition",value:function(t,e){if(0!=this.imageObj.width){t.globalAlpha=void 0!==e.opacity?e.opacity:1,this.enableShadow(t,e);var i=1;!0===this.options.shapeProperties.interpolation&&(i=this.imageObj.width/this.width/this.body.view.scale);var n=this._getImagePadding(),o=this.left+n.left,r=this.top+n.top,s=this.width-n.left-n.right,a=this.height-n.top-n.bottom;this.imageObj.drawImageAtPosition(t,i,o,r,s,a),this.disableShadow(t,e)}}},{key:"_drawImageLabel",value:function(t,e,i,n,o){var r=0;if(void 0!==this.height){r=.5*this.height;var s=this.labelModule.getTextSize(t,n,o);s.lineCount>=1&&(r+=s.height/2)}var a=i+r;this.options.label&&(this.labelOffset=r),this.labelModule.draw(t,e,a,n,o,"hanging")}}]),i}(h1);function p1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var v1=function(t){r1(i,t);var e=p1(i);function i(t,n,o){var r;return uU(this,i),(r=e.call(this,t,n,o))._setMargins(o),r}return yW(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(this.needsRefresh(e,i)){var n=this.getDimensionsFromLabel(t,e,i),o=Math.max(n.width+this.margin.right+this.margin.left,n.height+this.margin.top+this.margin.bottom);this.options.size=o/2,this.width=o,this.height=o,this.radius=this.width/2}}},{key:"draw",value:function(t,e,i,n,o,r){this.resize(t,n,o),this.left=e-this.width/2,this.top=i-this.height/2,this._drawRawCircle(t,e,i,r),this.updateBoundingBox(e,i),this.labelModule.draw(t,this.left+this.textSize.width/2+this.margin.left,i,n,o)}},{key:"updateBoundingBox",value:function(t,e){this.boundingBox.top=e-this.options.size,this.boundingBox.left=t-this.options.size,this.boundingBox.right=t+this.options.size,this.boundingBox.bottom=e+this.options.size}},{key:"distanceToBorder",value:function(t){return t&&this.resize(t),.5*this.width}}]),i}(f1);function g1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var y1=function(t){r1(i,t);var e=g1(i);function i(t,n,o,r,s){var a;return uU(this,i),(a=e.call(this,t,n,o)).setImages(r,s),a}return yW(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(void 0===this.imageObj.src||void 0===this.imageObj.width||void 0===this.imageObj.height){var n=2*this.options.size;return this.width=n,this.height=n,void(this.radius=.5*this.width)}this.needsRefresh(e,i)&&this._resizeImage()}},{key:"draw",value:function(t,e,i,n,o,r){this.switchImages(n),this.resize();var s=e,a=i;"top-left"===this.options.shapeProperties.coordinateOrigin?(this.left=e,this.top=i,s+=this.width/2,a+=this.height/2):(this.left=e-this.width/2,this.top=i-this.height/2),this._drawRawCircle(t,s,a,r),t.save(),t.clip(),this._drawImageAtPosition(t,r),t.restore(),this._drawImageLabel(t,s,a,n,o),this.updateBoundingBox(e,i)}},{key:"updateBoundingBox",value:function(t,e){"top-left"===this.options.shapeProperties.coordinateOrigin?(this.boundingBox.top=e,this.boundingBox.left=t,this.boundingBox.right=t+2*this.options.size,this.boundingBox.bottom=e+2*this.options.size):(this.boundingBox.top=e-this.options.size,this.boundingBox.left=t-this.options.size,this.boundingBox.right=t+this.options.size,this.boundingBox.bottom=e+this.options.size),this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelOffset)}},{key:"distanceToBorder",value:function(t){return t&&this.resize(t),.5*this.width}}]),i}(f1);function m1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var b1=function(t){r1(i,t);var e=m1(i);function i(t,n,o){return uU(this,i),e.call(this,t,n,o)}return yW(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover,n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{size:this.options.size};if(this.needsRefresh(e,i)){var o,r;this.labelModule.getTextSize(t,e,i);var s=2*n.size;this.width=null!==(o=this.customSizeWidth)&&void 0!==o?o:s,this.height=null!==(r=this.customSizeHeight)&&void 0!==r?r:s,this.radius=.5*this.width}}},{key:"_drawShape",value:function(t,e,i,n,o,r,s,a){var l,h=this;return this.resize(t,r,s,a),this.left=n-this.width/2,this.top=o-this.height/2,this.initContextForDraw(t,a),(l=e,Object.prototype.hasOwnProperty.call(YF,l)?YF[l]:function(t){for(var e=arguments.length,i=new Array(e>1?e-1:0),n=1;n0&&(this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelModule.size.height))}}]),i}(h1);function w1(t,e){var i=RG(t);if(D$){var n=D$(t);e&&(n=sq(n).call(n,(function(e){return U$(t,e).enumerable}))),i.push.apply(i,n)}return i}function A1(t){for(var e=1;e1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(this.needsRefresh(e,i)){var n=this.getDimensionsFromLabel(t,e,i);this.height=2*n.height,this.width=n.width+n.height,this.radius=.5*this.width}}},{key:"draw",value:function(t,e,i,n,o,r){this.resize(t,n,o),this.left=e-.5*this.width,this.top=i-.5*this.height,this.initContextForDraw(t,r),GF(t,this.left,this.top,this.width,this.height),this.performFill(t,r),this.updateBoundingBox(e,i,t,n,o),this.labelModule.draw(t,e,i,n,o)}},{key:"distanceToBorder",value:function(t,e){t&&this.resize(t);var i=.5*this.width,n=.5*this.height,o=Math.sin(e)*i,r=Math.cos(e)*n;return i*n/Math.sqrt(o*o+r*r)}}]),i}(h1);function B1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var z1=function(t){r1(i,t);var e=B1(i);function i(t,n,o){var r;return uU(this,i),(r=e.call(this,t,n,o))._setMargins(o),r}return yW(i,[{key:"resize",value:function(t,e,i){this.needsRefresh(e,i)&&(this.iconSize={width:Number(this.options.icon.size),height:Number(this.options.icon.size)},this.width=this.iconSize.width+this.margin.right+this.margin.left,this.height=this.iconSize.height+this.margin.top+this.margin.bottom,this.radius=.5*this.width)}},{key:"draw",value:function(t,e,i,n,o,r){var s=this;return this.resize(t,n,o),this.options.icon.size=this.options.icon.size||50,this.left=e-this.width/2,this.top=i-this.height/2,this._icon(t,e,i,n,o,r),{drawExternalLabel:function(){if(void 0!==s.options.label){s.labelModule.draw(t,s.left+s.iconSize.width/2+s.margin.left,i+s.height/2+5,n)}s.updateBoundingBox(e,i)}}}},{key:"updateBoundingBox",value:function(t,e){if(this.boundingBox.top=e-.5*this.options.icon.size,this.boundingBox.left=t-.5*this.options.icon.size,this.boundingBox.right=t+.5*this.options.icon.size,this.boundingBox.bottom=e+.5*this.options.icon.size,void 0!==this.options.label&&this.labelModule.size.width>0){this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelModule.size.height+5)}}},{key:"_icon",value:function(t,e,i,n,o,r){var s=Number(this.options.icon.size);void 0!==this.options.icon.code?(t.font=[null!=this.options.icon.weight?this.options.icon.weight:n?"bold":"",(null!=this.options.icon.weight&&n?5:0)+s+"px",this.options.icon.face].join(" "),t.fillStyle=this.options.icon.color||"black",t.textAlign="center",t.textBaseline="middle",this.enableShadow(t,r),t.fillText(this.options.icon.code,e,i),this.disableShadow(t,r)):console.error("When using the icon shape, you need to define the code in the icon options object. This can be done per node or globally.")}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(h1);function P1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var F1=function(t){r1(i,t);var e=P1(i);function i(t,n,o,r,s){var a;return uU(this,i),(a=e.call(this,t,n,o)).setImages(r,s),a}return yW(i,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(void 0===this.imageObj.src||void 0===this.imageObj.width||void 0===this.imageObj.height){var n=2*this.options.size;return this.width=n,void(this.height=n)}this.needsRefresh(e,i)&&this._resizeImage()}},{key:"draw",value:function(t,e,i,n,o,r){t.save(),this.switchImages(n),this.resize();var s=e,a=i;if("top-left"===this.options.shapeProperties.coordinateOrigin?(this.left=e,this.top=i,s+=this.width/2,a+=this.height/2):(this.left=e-this.width/2,this.top=i-this.height/2),!0===this.options.shapeProperties.useBorderWithImage){var l=this.options.borderWidth,h=this.options.borderWidthSelected||2*this.options.borderWidth,c=(n?h:l)/this.body.view.scale;t.lineWidth=Math.min(this.width,c),t.beginPath();var d=n?this.options.color.highlight.border:o?this.options.color.hover.border:this.options.color.border,u=n?this.options.color.highlight.background:o?this.options.color.hover.background:this.options.color.background;void 0!==r.opacity&&(d=UJ(d,r.opacity),u=UJ(u,r.opacity)),t.strokeStyle=d,t.fillStyle=u,t.rect(this.left-.5*t.lineWidth,this.top-.5*t.lineWidth,this.width+t.lineWidth,this.height+t.lineWidth),EY(t).call(t),this.performStroke(t,r),t.closePath()}this._drawImageAtPosition(t,r),this._drawImageLabel(t,s,a,n,o),this.updateBoundingBox(e,i),t.restore()}},{key:"updateBoundingBox",value:function(t,e){this.resize(),"top-left"===this.options.shapeProperties.coordinateOrigin?(this.left=t,this.top=e):(this.left=t-this.width/2,this.top=e-this.height/2),this.boundingBox.left=this.left,this.boundingBox.top=this.top,this.boundingBox.bottom=this.top+this.height,this.boundingBox.right=this.left+this.width,void 0!==this.options.label&&this.labelModule.size.width>0&&(this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelOffset))}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(f1);function T1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var N1=function(t){r1(i,t);var e=T1(i);function i(t,n,o){return uU(this,i),e.call(this,t,n,o)}return yW(i,[{key:"draw",value:function(t,e,i,n,o,r){return this._drawShape(t,"square",2,e,i,n,o,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(b1);function j1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var L1=function(t){r1(i,t);var e=j1(i);function i(t,n,o){return uU(this,i),e.call(this,t,n,o)}return yW(i,[{key:"draw",value:function(t,e,i,n,o,r){return this._drawShape(t,"hexagon",4,e,i,n,o,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(b1);function U1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var Q1=function(t){r1(i,t);var e=U1(i);function i(t,n,o){return uU(this,i),e.call(this,t,n,o)}return yW(i,[{key:"draw",value:function(t,e,i,n,o,r){return this._drawShape(t,"star",4,e,i,n,o,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(b1);function H1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var V1=function(t){r1(i,t);var e=H1(i);function i(t,n,o){var r;return uU(this,i),(r=e.call(this,t,n,o))._setMargins(o),r}return yW(i,[{key:"resize",value:function(t,e,i){this.needsRefresh(e,i)&&(this.textSize=this.labelModule.getTextSize(t,e,i),this.width=this.textSize.width+this.margin.right+this.margin.left,this.height=this.textSize.height+this.margin.top+this.margin.bottom,this.radius=.5*this.width)}},{key:"draw",value:function(t,e,i,n,o,r){this.resize(t,n,o),this.left=e-this.width/2,this.top=i-this.height/2,this.enableShadow(t,r),this.labelModule.draw(t,this.left+this.textSize.width/2+this.margin.left,this.top+this.textSize.height/2+this.margin.top,n,o),this.disableShadow(t,r),this.updateBoundingBox(e,i,t,n,o)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(h1);function W1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var G1=function(t){r1(i,t);var e=W1(i);function i(t,n,o){return uU(this,i),e.call(this,t,n,o)}return yW(i,[{key:"draw",value:function(t,e,i,n,o,r){return this._drawShape(t,"triangle",3,e,i,n,o,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(b1);function K1(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var q1=function(t){r1(i,t);var e=K1(i);function i(t,n,o){return uU(this,i),e.call(this,t,n,o)}return yW(i,[{key:"draw",value:function(t,e,i,n,o,r){return this._drawShape(t,"triangleDown",3,e,i,n,o,r)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),i}(b1);function Y1(t,e){var i=RG(t);if(D$){var n=D$(t);e&&(n=sq(n).call(n,(function(e){return U$(t,e).enumerable}))),i.push.apply(i,n)}return i}function Z1(t){for(var e=1;et.left&&this.shape.topt.top}},{key:"isBoundingBoxOverlappingWith",value:function(t){return this.shape.boundingBox.leftt.left&&this.shape.boundingBox.topt.top}}],[{key:"checkOpacity",value:function(t){return 0<=t&&t<=1}},{key:"checkCoordinateOrigin",value:function(t){return void 0===t||"center"===t||"top-left"===t}},{key:"updateGroupOptions",value:function(e,i,n){var o;if(void 0!==n){var r=e.group;if(void 0!==i&&void 0!==i.group&&r!==i.group)throw new Error("updateGroupOptions: group values in options don't match.");if("number"==typeof r||"string"==typeof r&&""!=r){var s=n.get(r);void 0!==s.opacity&&void 0===i.opacity&&(t.checkOpacity(s.opacity)||(console.error("Invalid option for node opacity. Value must be between 0 and 1, found: "+s.opacity),s.opacity=void 0));var a=sq(o=y0(i)).call(o,(function(t){return null!=i[t]}));a.push("font"),PJ(a,e,s),e.color=HJ(e.color)}}}},{key:"parseOptions",value:function(e,i){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},r=arguments.length>4?arguments[4]:void 0;if(PJ(["color","fixed","shadow"],e,i,n),t.checkMass(i),void 0!==e.opacity&&(t.checkOpacity(e.opacity)||(console.error("Invalid option for node opacity. Value must be between 0 and 1, found: "+e.opacity),e.opacity=void 0)),void 0!==i.opacity&&(t.checkOpacity(i.opacity)||(console.error("Invalid option for node opacity. Value must be between 0 and 1, found: "+i.opacity),i.opacity=void 0)),i.shapeProperties&&!t.checkCoordinateOrigin(i.shapeProperties.coordinateOrigin)&&console.error("Invalid option for node coordinateOrigin, found: "+i.shapeProperties.coordinateOrigin),ZJ(e,i,"shadow",o),void 0!==i.color&&null!==i.color){var s=HJ(i.color);BJ(e.color,s)}else!0===n&&null===i.color&&(e.color=YJ(o.color));void 0!==i.fixed&&null!==i.fixed&&("boolean"==typeof i.fixed?(e.fixed.x=i.fixed,e.fixed.y=i.fixed):(void 0!==i.fixed.x&&"boolean"==typeof i.fixed.x&&(e.fixed.x=i.fixed.x),void 0!==i.fixed.y&&"boolean"==typeof i.fixed.y&&(e.fixed.y=i.fixed.y))),!0===n&&null===i.font&&(e.font=YJ(o.font)),t.updateGroupOptions(e,i,r),void 0!==i.scaling&&ZJ(e.scaling,i.scaling,"label",o.scaling)}},{key:"checkMass",value:function(t,e){if(void 0!==t.mass&&t.mass<=0){var i="";void 0!==e&&(i=" in node id: "+e),console.error("%cNegative or zero mass disallowed"+i+", setting mass to 1.",dX),t.mass=1}}}]),t}();function X1(t,e){var i=void 0!==aG&&dU(t)||t["@@iterator"];if(!i){if(AG(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return _1(t,e);var n=pG(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return WL(t);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _1(t,e)}(t))||e){i&&(t=i);var n=0,o=function(){};return{s:o,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function _1(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i1?console.error("Invalid option for node opacity. Value must be between 0 and 1, found: "+t.opacity):this.options.opacity=t.opacity),void 0!==t.shape)for(var e in this.body.nodes)Object.prototype.hasOwnProperty.call(this.body.nodes,e)&&this.body.nodes[e].updateShape();if(void 0!==t.font||void 0!==t.widthConstraint||void 0!==t.heightConstraint)for(var i=0,n=RG(this.body.nodes);i1&&void 0!==arguments[1]&&arguments[1],i=this.body.data.nodes;if(eR("id",t))this.body.data.nodes=t;else if(AG(t))this.body.data.nodes=new tR,this.body.data.nodes.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.body.data.nodes=new tR}if(i&&jJ(this.nodesListeners,(function(t,e){i.off(e,t)})),this.body.nodes={},this.body.data.nodes){var n=this;jJ(this.nodesListeners,(function(t,e){n.body.data.nodes.on(e,t)}));var o=this.body.data.nodes.getIds();this.add(o,!0)}!1===e&&this.body.emitter.emit("_dataChanged")}},{key:"add",value:function(t){for(var e,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=[],o=0;o1&&void 0!==arguments[1]?arguments[1]:J1)(t,this.body,this.images,this.groups,this.options,this.defaultOptions)}},{key:"refresh",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];jJ(this.body.nodes,(function(i,n){var o=t.body.data.nodes.get(n);void 0!==o&&(!0===e&&i.setOptions({x:null,y:null}),i.setOptions({fixed:!1}),i.setOptions(o))}))}},{key:"getPositions",value:function(t){var e={};if(void 0!==t){if(!0===AG(t)){for(var i=0;i0?(n=i/a)*n:i;return a===1/0?1/0:a*f2(o)}});var p2=nR(iB.Math.hypot);function v2(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var g2=function(){function t(){uU(this,t)}return yW(t,null,[{key:"transform",value:function(t,e){AG(t)||(t=[t]);for(var i=e.point.x,n=e.point.y,o=e.angle,r=e.length,s=0;s4&&void 0!==arguments[4]?arguments[4]:this.getViaNode();t.strokeStyle=this.getColor(t,e),t.lineWidth=e.width,!1!==e.dashes?this._drawDashedLine(t,e,o):this._drawLine(t,e,o)}},{key:"_drawLine",value:function(t,e,i,n,o){if(this.from!=this.to)this._line(t,e,i,n,o);else{var r=rG(this._getCircleData(t),3),s=r[0],a=r[1],l=r[2];this._circle(t,e,s,a,l)}}},{key:"_drawDashedLine",value:function(t,e,i,n,o){t.lineCap="round";var r=AG(e.dashes)?e.dashes:[5,5];if(void 0!==t.setLineDash){if(t.save(),t.setLineDash(r),t.lineDashOffset=0,this.from!=this.to)this._line(t,e,i);else{var s=rG(this._getCircleData(t),3),a=s[0],l=s[1],h=s[2];this._circle(t,e,a,l,h)}t.setLineDash([0]),t.lineDashOffset=0,t.restore()}else{if(this.from!=this.to)qF(t,this.from.x,this.from.y,this.to.x,this.to.y,r);else{var c=rG(this._getCircleData(t),3),d=c[0],u=c[1],f=c[2];this._circle(t,e,d,u,f)}this.enableShadow(t,e),t.stroke(),this.disableShadow(t,e)}}},{key:"findBorderPosition",value:function(t,e,i){return this.from!=this.to?this._findBorderPosition(t,e,i):this._findBorderPositionCircle(t,e,i)}},{key:"findBorderPositions",value:function(t){if(this.from!=this.to)return{from:this._findBorderPosition(this.from,t),to:this._findBorderPosition(this.to,t)};var e,i=rG(pG(e=this._getCircleData(t)).call(e,0,2),2),n=i[0],o=i[1];return{from:this._findBorderPositionCircle(this.from,t,{x:n,y:o,low:.25,high:.6,direction:-1}),to:this._findBorderPositionCircle(this.from,t,{x:n,y:o,low:.6,high:.8,direction:1})}}},{key:"_getCircleData",value:function(t){var e=this.options.selfReference.size;void 0!==t&&void 0===this.from.shape.width&&this.from.shape.resize(t);var i=A0(t,this.options.selfReference.angle,e,this.from);return[i.x,i.y,e]}},{key:"_pointOnCircle",value:function(t,e,i,n){var o=2*n*Math.PI;return{x:t+i*Math.cos(o),y:e-i*Math.sin(o)}}},{key:"_findBorderPositionCircle",value:function(t,e,i){var n,o=i.x,r=i.y,s=i.low,a=i.high,l=i.direction,h=this.options.selfReference.size,c=.5*(s+a),d=0;!0===this.options.arrowStrikethrough&&(-1===l?d=this.options.endPointOffset.from:1===l&&(d=this.options.endPointOffset.to));var u=0;do{c=.5*(s+a),n=this._pointOnCircle(o,r,h,c);var f=Math.atan2(t.y-n.y,t.x-n.x),p=t.distanceToBorder(e,f)+d-Math.sqrt(Math.pow(n.x-t.x,2)+Math.pow(n.y-t.y,2));if(Math.abs(p)<.05)break;p>0?l>0?s=c:a=c:l>0?a=c:s=c,++u}while(s<=a&&u<10);return R2(R2({},n),{},{t:c})}},{key:"getLineWidth",value:function(t,e){return!0===t?Math.max(this.selectionWidth,.3/this._body.view.scale):!0===e?Math.max(this.hoverWidth,.3/this._body.view.scale):Math.max(this.options.width,.3/this._body.view.scale)}},{key:"getColor",value:function(t,e){if(!1!==e.inheritsColor){if("both"===e.inheritsColor&&this.from.id!==this.to.id){var i=t.createLinearGradient(this.from.x,this.from.y,this.to.x,this.to.y),n=this.from.options.color.highlight.border,o=this.to.options.color.highlight.border;return!1===this.from.selected&&!1===this.to.selected?(n=UJ(this.from.options.color.border,e.opacity),o=UJ(this.to.options.color.border,e.opacity)):!0===this.from.selected&&!1===this.to.selected?o=this.to.options.color.border:!1===this.from.selected&&!0===this.to.selected&&(n=this.from.options.color.border),i.addColorStop(0,n),i.addColorStop(1,o),i}return"to"===e.inheritsColor?UJ(this.to.options.color.border,e.opacity):UJ(this.from.options.color.border,e.opacity)}return UJ(e.color,e.opacity)}},{key:"_circle",value:function(t,e,i,n,o){this.enableShadow(t,e);var r=0,s=2*Math.PI;if(!this.options.selfReference.renderBehindTheNode){var a=this.options.selfReference.angle,l=this.options.selfReference.angle+Math.PI,h=this._findBorderPositionCircle(this.from,t,{x:i,y:n,low:a,high:l,direction:-1}),c=this._findBorderPositionCircle(this.from,t,{x:i,y:n,low:a,high:l,direction:1});r=Math.atan2(h.y-n,h.x-i),s=Math.atan2(c.y-n,c.x-i)}t.beginPath(),t.arc(i,n,o,r,s,!1),t.stroke(),this.disableShadow(t,e)}},{key:"getDistanceToEdge",value:function(t,e,i,n,o,r){if(this.from!=this.to)return this._getDistanceToEdge(t,e,i,n,o,r);var s=rG(this._getCircleData(void 0),3),a=s[0],l=s[1],h=s[2],c=a-o,d=l-r;return Math.abs(Math.sqrt(c*c+d*d)-h)}},{key:"_getDistanceToLine",value:function(t,e,i,n,o,r){var s=i-t,a=n-e,l=((o-t)*s+(r-e)*a)/(s*s+a*a);l>1?l=1:l<0&&(l=0);var h=t+l*s-o,c=e+l*a-r;return Math.sqrt(h*h+c*c)}},{key:"getArrowData",value:function(t,e,i,n,o,r){var s,a,l,h,c,d,u,f=r.width;"from"===e?(l=this.from,h=this.to,c=r.fromArrowScale<0,d=Math.abs(r.fromArrowScale),u=r.fromArrowType):"to"===e?(l=this.to,h=this.from,c=r.toArrowScale<0,d=Math.abs(r.toArrowScale),u=r.toArrowType):(l=this.to,h=this.from,c=r.middleArrowScale<0,d=Math.abs(r.middleArrowScale),u=r.middleArrowType);var p=15*d+3*f;if(l!=h){var v=p/p2(l.x-h.x,l.y-h.y);if("middle"!==e)if(!0===this.options.smooth.enabled){var g=this._findBorderPosition(l,t,{via:i}),y=this.getPoint(g.t+v*("from"===e?1:-1),i);s=Math.atan2(g.y-y.y,g.x-y.x),a=g}else s=Math.atan2(l.y-h.y,l.x-h.x),a=this._findBorderPosition(l,t);else{var m=(c?-v:v)/2,b=this.getPoint(.5+m,i),w=this.getPoint(.5-m,i);s=Math.atan2(b.y-w.y,b.x-w.x),a=this.getPoint(.5,i)}}else{var A=rG(this._getCircleData(t),3),k=A[0],E=A[1],C=A[2];if("from"===e){var x=this.options.selfReference.angle,I=this.options.selfReference.angle+Math.PI,S=this._findBorderPositionCircle(this.from,t,{x:k,y:E,low:x,high:I,direction:-1});s=-2*S.t*Math.PI+1.5*Math.PI+.1*Math.PI,a=S}else if("to"===e){var M=this.options.selfReference.angle,O=this.options.selfReference.angle+Math.PI,D=this._findBorderPositionCircle(this.from,t,{x:k,y:E,low:M,high:O,direction:1});s=-2*D.t*Math.PI+1.5*Math.PI-1.1*Math.PI,a=D}else{var R=this.options.selfReference.angle/(2*Math.PI);a=this._pointOnCircle(k,E,C,R),s=-2*R*Math.PI+1.5*Math.PI+.1*Math.PI}}return{point:a,core:{x:a.x-.9*p*Math.cos(s),y:a.y-.9*p*Math.sin(s)},angle:s,length:p,type:u}}},{key:"drawArrowHead",value:function(t,e,i,n,o){t.strokeStyle=this.getColor(t,e),t.fillStyle=t.strokeStyle,t.lineWidth=e.width,O2.draw(t,o)&&(this.enableShadow(t,e),EY(t).call(t),this.disableShadow(t,e))}},{key:"enableShadow",value:function(t,e){!0===e.shadow&&(t.shadowColor=e.shadowColor,t.shadowBlur=e.shadowSize,t.shadowOffsetX=e.shadowX,t.shadowOffsetY=e.shadowY)}},{key:"disableShadow",value:function(t,e){!0===e.shadow&&(t.shadowColor="rgba(0,0,0,0)",t.shadowBlur=0,t.shadowOffsetX=0,t.shadowOffsetY=0)}},{key:"drawBackground",value:function(t,e){if(!1!==e.background){var i={strokeStyle:t.strokeStyle,lineWidth:t.lineWidth,dashes:t.dashes};t.strokeStyle=e.backgroundColor,t.lineWidth=e.backgroundSize,this.setStrokeDashed(t,e.backgroundDashes),t.stroke(),t.strokeStyle=i.strokeStyle,t.lineWidth=i.lineWidth,t.dashes=i.dashes,this.setStrokeDashed(t,e.dashes)}}},{key:"setStrokeDashed",value:function(t,e){if(!1!==e)if(void 0!==t.setLineDash){var i=AG(e)?e:[5,5];t.setLineDash(i)}else console.warn("setLineDash is not supported in this browser. The dashed stroke cannot be used.");else void 0!==t.setLineDash?t.setLineDash([]):console.warn("setLineDash is not supported in this browser. The dashed stroke cannot be used.")}}]),t}();function z2(t,e){var i=RG(t);if(D$){var n=D$(t);e&&(n=sq(n).call(n,(function(e){return U$(t,e).enumerable}))),i.push.apply(i,n)}return i}function P2(t){for(var e=1;e2&&void 0!==arguments[2]?arguments[2]:this._getViaCoordinates(),r=!1,s=1,a=0,l=this.to,h=this.options.endPointOffset?this.options.endPointOffset.to:0;t.id===this.from.id&&(l=this.from,r=!0,h=this.options.endPointOffset?this.options.endPointOffset.from:0),!1===this.options.arrowStrikethrough&&(h=0);var c=0;do{n=.5*(a+s),i=this.getPoint(n,o);var d=Math.atan2(l.y-i.y,l.x-i.x),u=l.distanceToBorder(e,d)+h-Math.sqrt(Math.pow(i.x-l.x,2)+Math.pow(i.y-l.y,2));if(Math.abs(u)<.2)break;u<0?!1===r?a=n:s=n:!1===r?s=n:a=n,++c}while(a<=s&&c<10);return P2(P2({},i),{},{t:n})}},{key:"_getDistanceToBezierEdge",value:function(t,e,i,n,o,r,s){var a,l,h,c,d,u=1e9,f=t,p=e;for(l=1;l<10;l++)h=.1*l,c=Math.pow(1-h,2)*t+2*h*(1-h)*s.x+Math.pow(h,2)*i,d=Math.pow(1-h,2)*e+2*h*(1-h)*s.y+Math.pow(h,2)*n,l>0&&(u=(a=this._getDistanceToLine(f,p,c,d,o,r))1&&void 0!==arguments[1]?arguments[1]:this.via;if(this.from===this.to){var i=rG(this._getCircleData(),3),n=i[0],o=i[1],r=i[2],s=2*Math.PI*(1-t);return{x:n+r*Math.sin(s),y:o+r-r*(1-Math.cos(s))}}return{x:Math.pow(1-t,2)*this.fromPoint.x+2*t*(1-t)*e.x+Math.pow(t,2)*this.toPoint.x,y:Math.pow(1-t,2)*this.fromPoint.y+2*t*(1-t)*e.y+Math.pow(t,2)*this.toPoint.y}}},{key:"_findBorderPosition",value:function(t,e){return this._findBorderPositionBezier(t,e,this.via)}},{key:"_getDistanceToEdge",value:function(t,e,i,n,o,r){return this._getDistanceToBezierEdge(t,e,i,n,o,r,this.via)}}]),i}(T2);function L2(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var U2=function(t){r1(i,t);var e=L2(i);function i(t,n,o){return uU(this,i),e.call(this,t,n,o)}return yW(i,[{key:"_line",value:function(t,e,i){this._bezierCurve(t,e,i)}},{key:"getViaNode",value:function(){return this._getViaCoordinates()}},{key:"_getViaCoordinates",value:function(){var t,e,i=this.options.smooth.roundness,n=this.options.smooth.type,o=Math.abs(this.from.x-this.to.x),r=Math.abs(this.from.y-this.to.y);if("discrete"===n||"diagonalCross"===n){var s,a;s=a=o<=r?i*r:i*o,this.from.x>this.to.x&&(s=-s),this.from.y>=this.to.y&&(a=-a);var l=this.from.x+s,h=this.from.y+a;return"discrete"===n&&(o<=r?l=othis.to.x&&(t=-t),this.from.y>=this.to.y&&(e=-e);var w=this.from.x+t,A=this.from.y+e;return o<=r?w=this.from.x<=this.to.x?this.to.xw?this.to.x:w:A=this.from.y>=this.to.y?this.to.y>A?this.to.y:A:this.to.y2&&void 0!==arguments[2]?arguments[2]:{};return this._findBorderPositionBezier(t,e,i.via)}},{key:"_getDistanceToEdge",value:function(t,e,i,n,o,r){var s=arguments.length>6&&void 0!==arguments[6]?arguments[6]:this._getViaCoordinates();return this._getDistanceToBezierEdge(t,e,i,n,o,r,s)}},{key:"getPoint",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this._getViaCoordinates(),i=t;return{x:Math.pow(1-i,2)*this.fromPoint.x+2*i*(1-i)*e.x+Math.pow(i,2)*this.toPoint.x,y:Math.pow(1-i,2)*this.fromPoint.y+2*i*(1-i)*e.y+Math.pow(i,2)*this.toPoint.y}}}]),i}(T2);function Q2(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var H2=function(t){r1(i,t);var e=Q2(i);function i(t,n,o){return uU(this,i),e.call(this,t,n,o)}return yW(i,[{key:"_getDistanceToBezierEdge2",value:function(t,e,i,n,o,r,s,a){for(var l=1e9,h=t,c=e,d=[0,0,0,0],u=1;u<10;u++){var f=.1*u;d[0]=Math.pow(1-f,3),d[1]=3*f*Math.pow(1-f,2),d[2]=3*Math.pow(f,2)*(1-f),d[3]=Math.pow(f,3);var p=d[0]*t+d[1]*s.x+d[2]*a.x+d[3]*i,v=d[0]*e+d[1]*s.y+d[2]*a.y+d[3]*n;if(u>0){var g=this._getDistanceToLine(h,c,p,v,o,r);l=gMath.abs(r)||!0===this.options.smooth.forceDirection||"horizontal"===this.options.smooth.forceDirection)&&"vertical"!==this.options.smooth.forceDirection?(e=this.from.y,n=this.to.y,t=this.from.x-s*o,i=this.to.x+s*o):(e=this.from.y-s*r,n=this.to.y+s*r,t=this.from.x,i=this.to.x),[{x:t,y:e},{x:i,y:n}]}},{key:"getViaNode",value:function(){return this._getViaCoordinates()}},{key:"_findBorderPosition",value:function(t,e){return this._findBorderPositionBezier(t,e)}},{key:"_getDistanceToEdge",value:function(t,e,i,n,o,r){var s=rG(arguments.length>6&&void 0!==arguments[6]?arguments[6]:this._getViaCoordinates(),2),a=s[0],l=s[1];return this._getDistanceToBezierEdge2(t,e,i,n,o,r,a,l)}},{key:"getPoint",value:function(t){var e=rG(arguments.length>1&&void 0!==arguments[1]?arguments[1]:this._getViaCoordinates(),2),i=e[0],n=e[1],o=t,r=[Math.pow(1-o,3),3*o*Math.pow(1-o,2),3*Math.pow(o,2)*(1-o),Math.pow(o,3)];return{x:r[0]*this.fromPoint.x+r[1]*i.x+r[2]*n.x+r[3]*this.toPoint.x,y:r[0]*this.fromPoint.y+r[1]*i.y+r[2]*n.y+r[3]*this.toPoint.y}}}]),i}(H2);function G2(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var K2=function(t){r1(i,t);var e=G2(i);function i(t,n,o){return uU(this,i),e.call(this,t,n,o)}return yW(i,[{key:"_line",value:function(t,e){t.beginPath(),t.moveTo(this.fromPoint.x,this.fromPoint.y),t.lineTo(this.toPoint.x,this.toPoint.y),this.enableShadow(t,e),t.stroke(),this.disableShadow(t,e)}},{key:"getViaNode",value:function(){}},{key:"getPoint",value:function(t){return{x:(1-t)*this.fromPoint.x+t*this.toPoint.x,y:(1-t)*this.fromPoint.y+t*this.toPoint.y}}},{key:"_findBorderPosition",value:function(t,e){var i=this.to,n=this.from;t.id===this.from.id&&(i=this.from,n=this.to);var o=Math.atan2(i.y-n.y,i.x-n.x),r=i.x-n.x,s=i.y-n.y,a=Math.sqrt(r*r+s*s),l=(a-t.distanceToBorder(e,o))/a;return{x:(1-l)*n.x+l*i.x,y:(1-l)*n.y+l*i.y,t:0}}},{key:"_getDistanceToEdge",value:function(t,e,i,n,o,r){return this._getDistanceToLine(t,e,i,n,o,r)}}]),i}(B2),q2=function(){function t(e,i,n,o,r){if(uU(this,t),void 0===i)throw new Error("No body provided");this.options=YJ(o),this.globalOptions=o,this.defaultOptions=r,this.body=i,this.imagelist=n,this.id=void 0,this.fromId=void 0,this.toId=void 0,this.selected=!1,this.hover=!1,this.labelDirty=!0,this.baseWidth=this.options.width,this.baseFontSize=this.options.font.size,this.from=void 0,this.to=void 0,this.edgeType=void 0,this.connected=!1,this.labelModule=new T0(this.body,this.options,!0),this.setOptions(e)}return yW(t,[{key:"setOptions",value:function(e){if(e){var i=void 0!==e.physics&&this.options.physics!==e.physics||void 0!==e.hidden&&(this.options.hidden||!1)!==(e.hidden||!1)||void 0!==e.from&&this.options.from!==e.from||void 0!==e.to&&this.options.to!==e.to;t.parseOptions(this.options,e,!0,this.globalOptions),void 0!==e.id&&(this.id=e.id),void 0!==e.from&&(this.fromId=e.from),void 0!==e.to&&(this.toId=e.to),void 0!==e.title&&(this.title=e.title),void 0!==e.value&&(e.value=d0(e.value));var n=[e,this.options,this.defaultOptions];return this.chooser=m0("edge",n),this.updateLabelModule(e),i=this.updateEdgeType()||i,this._setInteractionWidths(),this.connect(),i}}},{key:"getFormattingValues",value:function(){var t=!0===this.options.arrows.to||!0===this.options.arrows.to.enabled,e=!0===this.options.arrows.from||!0===this.options.arrows.from.enabled,i=!0===this.options.arrows.middle||!0===this.options.arrows.middle.enabled,n=this.options.color.inherit,o={toArrow:t,toArrowScale:this.options.arrows.to.scaleFactor,toArrowType:this.options.arrows.to.type,toArrowSrc:this.options.arrows.to.src,toArrowImageWidth:this.options.arrows.to.imageWidth,toArrowImageHeight:this.options.arrows.to.imageHeight,middleArrow:i,middleArrowScale:this.options.arrows.middle.scaleFactor,middleArrowType:this.options.arrows.middle.type,middleArrowSrc:this.options.arrows.middle.src,middleArrowImageWidth:this.options.arrows.middle.imageWidth,middleArrowImageHeight:this.options.arrows.middle.imageHeight,fromArrow:e,fromArrowScale:this.options.arrows.from.scaleFactor,fromArrowType:this.options.arrows.from.type,fromArrowSrc:this.options.arrows.from.src,fromArrowImageWidth:this.options.arrows.from.imageWidth,fromArrowImageHeight:this.options.arrows.from.imageHeight,arrowStrikethrough:this.options.arrowStrikethrough,color:n?void 0:this.options.color.color,inheritsColor:n,opacity:this.options.color.opacity,hidden:this.options.hidden,length:this.options.length,shadow:this.options.shadow.enabled,shadowColor:this.options.shadow.color,shadowSize:this.options.shadow.size,shadowX:this.options.shadow.x,shadowY:this.options.shadow.y,dashes:this.options.dashes,width:this.options.width,background:this.options.background.enabled,backgroundColor:this.options.background.color,backgroundSize:this.options.background.size,backgroundDashes:this.options.background.dashes};if(this.selected||this.hover)if(!0===this.chooser){if(this.selected){var r=this.options.selectionWidth;"function"==typeof r?o.width=r(o.width):"number"==typeof r&&(o.width+=r),o.width=Math.max(o.width,.3/this.body.view.scale),o.color=this.options.color.highlight,o.shadow=this.options.shadow.enabled}else if(this.hover){var s=this.options.hoverWidth;"function"==typeof s?o.width=s(o.width):"number"==typeof s&&(o.width+=s),o.width=Math.max(o.width,.3/this.body.view.scale),o.color=this.options.color.hover,o.shadow=this.options.shadow.enabled}}else"function"==typeof this.chooser&&(this.chooser(o,this.options.id,this.selected,this.hover),void 0!==o.color&&(o.inheritsColor=!1),!1===o.shadow&&(o.shadowColor===this.options.shadow.color&&o.shadowSize===this.options.shadow.size&&o.shadowX===this.options.shadow.x&&o.shadowY===this.options.shadow.y||(o.shadow=!0)));else o.shadow=this.options.shadow.enabled,o.width=Math.max(o.width,.3/this.body.view.scale);return o}},{key:"updateLabelModule",value:function(t){var e=[t,this.options,this.globalOptions,this.defaultOptions];this.labelModule.update(this.options,e),void 0!==this.labelModule.baseSize&&(this.baseFontSize=this.labelModule.baseSize)}},{key:"updateEdgeType",value:function(){var t=this.options.smooth,e=!1,i=!0;return void 0!==this.edgeType&&((this.edgeType instanceof j2&&!0===t.enabled&&"dynamic"===t.type||this.edgeType instanceof W2&&!0===t.enabled&&"cubicBezier"===t.type||this.edgeType instanceof U2&&!0===t.enabled&&"dynamic"!==t.type&&"cubicBezier"!==t.type||this.edgeType instanceof K2&&!1===t.type.enabled)&&(i=!1),!0===i&&(e=this.cleanup())),!0===i?!0===t.enabled?"dynamic"===t.type?(e=!0,this.edgeType=new j2(this.options,this.body,this.labelModule)):"cubicBezier"===t.type?this.edgeType=new W2(this.options,this.body,this.labelModule):this.edgeType=new U2(this.options,this.body,this.labelModule):this.edgeType=new K2(this.options,this.body,this.labelModule):this.edgeType.setOptions(this.options),e}},{key:"connect",value:function(){this.disconnect(),this.from=this.body.nodes[this.fromId]||void 0,this.to=this.body.nodes[this.toId]||void 0,this.connected=void 0!==this.from&&void 0!==this.to,!0===this.connected?(this.from.attachEdge(this),this.to.attachEdge(this)):(this.from&&this.from.detachEdge(this),this.to&&this.to.detachEdge(this)),this.edgeType.connect()}},{key:"disconnect",value:function(){this.from&&(this.from.detachEdge(this),this.from=void 0),this.to&&(this.to.detachEdge(this),this.to=void 0),this.connected=!1}},{key:"getTitle",value:function(){return this.title}},{key:"isSelected",value:function(){return this.selected}},{key:"getValue",value:function(){return this.options.value}},{key:"setValueRange",value:function(t,e,i){if(void 0!==this.options.value){var n=this.options.scaling.customScalingFunction(t,e,i,this.options.value),o=this.options.scaling.max-this.options.scaling.min;if(!0===this.options.scaling.label.enabled){var r=this.options.scaling.label.max-this.options.scaling.label.min;this.options.font.size=this.options.scaling.label.min+n*r}this.options.width=this.options.scaling.min+n*o}else this.options.width=this.baseWidth,this.options.font.size=this.baseFontSize;this._setInteractionWidths(),this.updateLabelModule()}},{key:"_setInteractionWidths",value:function(){"function"==typeof this.options.hoverWidth?this.edgeType.hoverWidth=this.options.hoverWidth(this.options.width):this.edgeType.hoverWidth=this.options.hoverWidth+this.options.width,"function"==typeof this.options.selectionWidth?this.edgeType.selectionWidth=this.options.selectionWidth(this.options.width):this.edgeType.selectionWidth=this.options.selectionWidth+this.options.width}},{key:"draw",value:function(t){var e=this.getFormattingValues();if(!e.hidden){var i=this.edgeType.getViaNode();this.edgeType.drawLine(t,e,this.selected,this.hover,i),this.drawLabel(t,i)}}},{key:"drawArrows",value:function(t){var e=this.getFormattingValues();if(!e.hidden){var i=this.edgeType.getViaNode(),n={};this.edgeType.fromPoint=this.edgeType.from,this.edgeType.toPoint=this.edgeType.to,e.fromArrow&&(n.from=this.edgeType.getArrowData(t,"from",i,this.selected,this.hover,e),!1===e.arrowStrikethrough&&(this.edgeType.fromPoint=n.from.core),e.fromArrowSrc&&(n.from.image=this.imagelist.load(e.fromArrowSrc)),e.fromArrowImageWidth&&(n.from.imageWidth=e.fromArrowImageWidth),e.fromArrowImageHeight&&(n.from.imageHeight=e.fromArrowImageHeight)),e.toArrow&&(n.to=this.edgeType.getArrowData(t,"to",i,this.selected,this.hover,e),!1===e.arrowStrikethrough&&(this.edgeType.toPoint=n.to.core),e.toArrowSrc&&(n.to.image=this.imagelist.load(e.toArrowSrc)),e.toArrowImageWidth&&(n.to.imageWidth=e.toArrowImageWidth),e.toArrowImageHeight&&(n.to.imageHeight=e.toArrowImageHeight)),e.middleArrow&&(n.middle=this.edgeType.getArrowData(t,"middle",i,this.selected,this.hover,e),e.middleArrowSrc&&(n.middle.image=this.imagelist.load(e.middleArrowSrc)),e.middleArrowImageWidth&&(n.middle.imageWidth=e.middleArrowImageWidth),e.middleArrowImageHeight&&(n.middle.imageHeight=e.middleArrowImageHeight)),e.fromArrow&&this.edgeType.drawArrowHead(t,e,this.selected,this.hover,n.from),e.middleArrow&&this.edgeType.drawArrowHead(t,e,this.selected,this.hover,n.middle),e.toArrow&&this.edgeType.drawArrowHead(t,e,this.selected,this.hover,n.to)}}},{key:"drawLabel",value:function(t,e){if(void 0!==this.options.label){var i,n=this.from,o=this.to;if(this.labelModule.differentState(this.selected,this.hover)&&this.labelModule.getTextSize(t,this.selected,this.hover),n.id!=o.id){this.labelModule.pointToSelf=!1,i=this.edgeType.getPoint(.5,e),t.save();var r=this._getRotation(t);0!=r.angle&&(t.translate(r.x,r.y),t.rotate(r.angle)),this.labelModule.draw(t,i.x,i.y,this.selected,this.hover),t.restore()}else{this.labelModule.pointToSelf=!0;var s=A0(t,this.options.selfReference.angle,this.options.selfReference.size,n);i=this._pointOnCircle(s.x,s.y,this.options.selfReference.size,this.options.selfReference.angle),this.labelModule.draw(t,i.x,i.y,this.selected,this.hover)}}}},{key:"getItemsOnPoint",value:function(t){var e=[];if(this.labelModule.visible()){var i=this._getRotation();b0(this.labelModule.getSize(),t,i)&&e.push({edgeId:this.id,labelId:0})}var n={left:t.x,top:t.y};return this.isOverlappingWith(n)&&e.push({edgeId:this.id}),e}},{key:"isOverlappingWith",value:function(t){if(this.connected){var e=this.from.x,i=this.from.y,n=this.to.x,o=this.to.y,r=t.left,s=t.top;return this.edgeType.getDistanceToEdge(e,i,n,o,r,s)<10}return!1}},{key:"_getRotation",value:function(t){var e=this.edgeType.getViaNode(),i=this.edgeType.getPoint(.5,e);void 0!==t&&this.labelModule.calculateLabelSize(t,this.selected,this.hover,i.x,i.y);var n={x:i.x,y:this.labelModule.size.yLine,angle:0};if(!this.labelModule.visible())return n;if("horizontal"===this.options.font.align)return n;var o=this.from.y-this.to.y,r=this.from.x-this.to.x,s=Math.atan2(o,r);return(s<-1&&r<0||s>0&&r<0)&&(s+=Math.PI),n.angle=s,n}},{key:"_pointOnCircle",value:function(t,e,i,n){return{x:t+i*Math.cos(n),y:e-i*Math.sin(n)}}},{key:"select",value:function(){this.selected=!0}},{key:"unselect",value:function(){this.selected=!1}},{key:"cleanup",value:function(){return this.edgeType.cleanup()}},{key:"remove",value:function(){this.cleanup(),this.disconnect(),delete this.body.edges[this.id]}},{key:"endPointsValid",value:function(){return void 0!==this.body.nodes[this.fromId]&&void 0!==this.body.nodes[this.toId]}}],[{key:"parseOptions",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},o=arguments.length>4&&void 0!==arguments[4]&&arguments[4];if(zJ(["endPointOffset","arrowStrikethrough","id","from","hidden","hoverWidth","labelHighlightBold","length","line","opacity","physics","scaling","selectionWidth","selfReferenceSize","selfReference","to","title","value","width","font","chosen","widthConstraint"],t,e,i),void 0!==e.endPointOffset&&void 0!==e.endPointOffset.from&&(k$(e.endPointOffset.from)?t.endPointOffset.from=e.endPointOffset.from:(t.endPointOffset.from=void 0!==n.endPointOffset.from?n.endPointOffset.from:0,console.error("endPointOffset.from is not a valid number"))),void 0!==e.endPointOffset&&void 0!==e.endPointOffset.to&&(k$(e.endPointOffset.to)?t.endPointOffset.to=e.endPointOffset.to:(t.endPointOffset.to=void 0!==n.endPointOffset.to?n.endPointOffset.to:0,console.error("endPointOffset.to is not a valid number"))),w0(e.label)?t.label=e.label:w0(t.label)||(t.label=void 0),ZJ(t,e,"smooth",n),ZJ(t,e,"shadow",n),ZJ(t,e,"background",n),void 0!==e.dashes&&null!==e.dashes?t.dashes=e.dashes:!0===i&&null===e.dashes&&(t.dashes=Vq(n.dashes)),void 0!==e.scaling&&null!==e.scaling?(void 0!==e.scaling.min&&(t.scaling.min=e.scaling.min),void 0!==e.scaling.max&&(t.scaling.max=e.scaling.max),ZJ(t.scaling,e.scaling,"label",n.scaling)):!0===i&&null===e.scaling&&(t.scaling=Vq(n.scaling)),void 0!==e.arrows&&null!==e.arrows)if("string"==typeof e.arrows){var r=e.arrows.toLowerCase();t.arrows.to.enabled=-1!=Lq(r).call(r,"to"),t.arrows.middle.enabled=-1!=Lq(r).call(r,"middle"),t.arrows.from.enabled=-1!=Lq(r).call(r,"from")}else{if("object"!==fW(e.arrows))throw new Error("The arrow newOptions can only be an object or a string. Refer to the documentation. You used:"+qq(e.arrows));ZJ(t.arrows,e.arrows,"to",n.arrows),ZJ(t.arrows,e.arrows,"middle",n.arrows),ZJ(t.arrows,e.arrows,"from",n.arrows)}else!0===i&&null===e.arrows&&(t.arrows=Vq(n.arrows));if(void 0!==e.color&&null!==e.color){var s=OJ(e.color)?{color:e.color,highlight:e.color,hover:e.color,inherit:!1,opacity:1}:e.color,a=t.color;if(o)FJ(a,n.color,!1,i);else for(var l in a)Object.prototype.hasOwnProperty.call(a,l)&&delete a[l];if(OJ(a))a.color=a,a.highlight=a,a.hover=a,a.inherit=!1,void 0===s.opacity&&(a.opacity=1);else{var h=!1;void 0!==s.color&&(a.color=s.color,h=!0),void 0!==s.highlight&&(a.highlight=s.highlight,h=!0),void 0!==s.hover&&(a.hover=s.hover,h=!0),void 0!==s.inherit&&(a.inherit=s.inherit),void 0!==s.opacity&&(a.opacity=Math.min(1,Math.max(0,s.opacity))),!0===h?a.inherit=!1:void 0===a.inherit&&(a.inherit="from")}}else!0===i&&null===e.color&&(t.color=YJ(n.color));!0===i&&null===e.font&&(t.font=YJ(n.font)),Object.prototype.hasOwnProperty.call(e,"selfReferenceSize")&&(console.warn("The selfReferenceSize property has been deprecated. Please use selfReference property instead. The selfReference can be set like thise selfReference:{size:30, angle:Math.PI / 4}"),t.selfReference.size=e.selfReferenceSize)}}]),t}(),Y2=function(){function t(e,i,n){var o,r=this;uU(this,t),this.body=e,this.images=i,this.groups=n,this.body.functions.createEdge=HF(o=this.create).call(o,this),this.edgesListeners={add:function(t,e){r.add(e.items)},update:function(t,e){r.update(e.items)},remove:function(t,e){r.remove(e.items)}},this.options={},this.defaultOptions={arrows:{to:{enabled:!1,scaleFactor:1,type:"arrow"},middle:{enabled:!1,scaleFactor:1,type:"arrow"},from:{enabled:!1,scaleFactor:1,type:"arrow"}},endPointOffset:{from:0,to:0},arrowStrikethrough:!0,color:{color:"#848484",highlight:"#848484",hover:"#848484",inherit:"from",opacity:1},dashes:!1,font:{color:"#343434",size:14,face:"arial",background:"none",strokeWidth:2,strokeColor:"#ffffff",align:"horizontal",multi:!1,vadjust:0,bold:{mod:"bold"},boldital:{mod:"bold italic"},ital:{mod:"italic"},mono:{mod:"",size:15,face:"courier new",vadjust:2}},hidden:!1,hoverWidth:1.5,label:void 0,labelHighlightBold:!0,length:void 0,physics:!0,scaling:{min:1,max:15,label:{enabled:!0,min:14,max:30,maxVisible:30,drawThreshold:5},customScalingFunction:function(t,e,i,n){if(e===t)return.5;var o=1/(e-t);return Math.max(0,(n-t)*o)}},selectionWidth:1.5,selfReference:{size:20,angle:Math.PI/4,renderBehindTheNode:!0},shadow:{enabled:!1,color:"rgba(0,0,0,0.5)",size:10,x:5,y:5},background:{enabled:!1,color:"rgba(111,111,111,1)",size:10,dashes:!1},smooth:{enabled:!0,type:"dynamic",forceDirection:"none",roundness:.5},title:void 0,width:1,value:void 0},FJ(this.options,this.defaultOptions),this.bindEventListeners()}return yW(t,[{key:"bindEventListeners",value:function(){var t,e,i=this;this.body.emitter.on("_forceDisableDynamicCurves",(function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];"dynamic"===t&&(t="continuous");var n=!1;for(var o in i.body.edges)if(Object.prototype.hasOwnProperty.call(i.body.edges,o)){var r=i.body.edges[o],s=i.body.data.edges.get(o);if(null!=s){var a=s.smooth;void 0!==a&&!0===a.enabled&&"dynamic"===a.type&&(void 0===t?r.setOptions({smooth:!1}):r.setOptions({smooth:{type:t}}),n=!0)}}!0===e&&!0===n&&i.body.emitter.emit("_dataChanged")})),this.body.emitter.on("_dataUpdated",(function(){i.reconnectEdges()})),this.body.emitter.on("refreshEdges",HF(t=this.refresh).call(t,this)),this.body.emitter.on("refresh",HF(e=this.refresh).call(e,this)),this.body.emitter.on("destroy",(function(){jJ(i.edgesListeners,(function(t,e){i.body.data.edges&&i.body.data.edges.off(e,t)})),delete i.body.functions.createEdge,delete i.edgesListeners.add,delete i.edgesListeners.update,delete i.edgesListeners.remove,delete i.edgesListeners}))}},{key:"setOptions",value:function(t){if(void 0!==t){q2.parseOptions(this.options,t,!0,this.defaultOptions,!0);var e=!1;if(void 0!==t.smooth)for(var i in this.body.edges)Object.prototype.hasOwnProperty.call(this.body.edges,i)&&(e=this.body.edges[i].updateEdgeType()||e);if(void 0!==t.font)for(var n in this.body.edges)Object.prototype.hasOwnProperty.call(this.body.edges,n)&&this.body.edges[n].updateLabelModule();void 0===t.hidden&&void 0===t.physics&&!0!==e||this.body.emitter.emit("_dataChanged")}}},{key:"setData",value:function(t){var e=this,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=this.body.data.edges;if(eR("id",t))this.body.data.edges=t;else if(AG(t))this.body.data.edges=new tR,this.body.data.edges.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.body.data.edges=new tR}if(n&&jJ(this.edgesListeners,(function(t,e){n.off(e,t)})),this.body.edges={},this.body.data.edges){jJ(this.edgesListeners,(function(t,i){e.body.data.edges.on(i,t)}));var o=this.body.data.edges.getIds();this.add(o,!0)}this.body.emitter.emit("_adjustEdgesForHierarchicalLayout"),!1===i&&this.body.emitter.emit("_dataChanged")}},{key:"add",value:function(t){for(var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=this.body.edges,n=this.body.data.edges,o=0;o1&&void 0!==arguments[1])||arguments[1];if(0!==t.length){var i=this.body.edges;jJ(t,(function(t){var e=i[t];void 0!==e&&e.remove()})),e&&this.body.emitter.emit("_dataChanged")}}},{key:"refresh",value:function(){var t=this;jJ(this.body.edges,(function(e,i){var n=t.body.data.edges.get(i);void 0!==n&&e.setOptions(n)}))}},{key:"create",value:function(t){return new q2(t,this.body,this.images,this.options,this.defaultOptions)}},{key:"reconnectEdges",value:function(){var t,e=this.body.nodes,i=this.body.edges;for(t in e)Object.prototype.hasOwnProperty.call(e,t)&&(e[t].edges=[]);for(t in i)if(Object.prototype.hasOwnProperty.call(i,t)){var n=i[t];n.from=null,n.to=null,n.connect()}}},{key:"getConnectedNodes",value:function(t){var e=[];if(void 0!==this.body.edges[t]){var i=this.body.edges[t];void 0!==i.fromId&&e.push(i.fromId),void 0!==i.toId&&e.push(i.toId)}return e}},{key:"_updateState",value:function(){this._addMissingEdges(),this._removeInvalidEdges()}},{key:"_removeInvalidEdges",value:function(){var t=this,e=[];jJ(this.body.edges,(function(i,n){var o=t.body.nodes[i.toId],r=t.body.nodes[i.fromId];void 0!==o&&!0===o.isCluster||void 0!==r&&!0===r.isCluster||void 0!==o&&void 0!==r||e.push(n)})),this.remove(e,!1)}},{key:"_addMissingEdges",value:function(){var t=this.body.data.edges;if(null!=t){var e=this.body.edges,i=[];YG(t).call(t,(function(t,n){void 0===e[n]&&i.push(n)})),this.add(i,!0)}}}]),t}(),Z2=function(){function t(e,i,n){uU(this,t),this.body=e,this.physicsBody=i,this.barnesHutTree,this.setOptions(n),this._rng=AJ("BARNES HUT SOLVER")}return yW(t,[{key:"setOptions",value:function(t){this.options=t,this.thetaInversed=1/this.options.theta,this.overlapAvoidanceFactor=1-Math.max(0,Math.min(1,this.options.avoidOverlap))}},{key:"solve",value:function(){if(0!==this.options.gravitationalConstant&&this.physicsBody.physicsNodeIndices.length>0){var t,e=this.body.nodes,i=this.physicsBody.physicsNodeIndices,n=i.length,o=this._formBarnesHutTree(e,i);this.barnesHutTree=o;for(var r=0;r0&&this._getForceContributions(o.root,t)}}},{key:"_getForceContributions",value:function(t,e){this._getForceContribution(t.children.NW,e),this._getForceContribution(t.children.NE,e),this._getForceContribution(t.children.SW,e),this._getForceContribution(t.children.SE,e)}},{key:"_getForceContribution",value:function(t,e){if(t.childrenCount>0){var i=t.centerOfMass.x-e.x,n=t.centerOfMass.y-e.y,o=Math.sqrt(i*i+n*n);o*t.calcSize>this.thetaInversed?this._calculateForces(o,i,n,e,t):4===t.childrenCount?this._getForceContributions(t,e):t.children.data.id!=e.id&&this._calculateForces(o,i,n,e,t)}}},{key:"_calculateForces",value:function(t,e,i,n,o){0===t&&(e=t=.1),this.overlapAvoidanceFactor<1&&n.shape.radius&&(t=Math.max(.1+this.overlapAvoidanceFactor*n.shape.radius,t-n.shape.radius));var r=this.options.gravitationalConstant*o.mass*n.options.mass/Math.pow(t,3),s=e*r,a=i*r;this.physicsBody.forces[n.id].x+=s,this.physicsBody.forces[n.id].y+=a}},{key:"_formBarnesHutTree",value:function(t,e){for(var i,n=e.length,o=t[e[0]].x,r=t[e[0]].y,s=t[e[0]].x,a=t[e[0]].y,l=1;l0&&(cs&&(s=c),da&&(a=d))}var u=Math.abs(s-o)-Math.abs(a-r);u>0?(r-=.5*u,a+=.5*u):(o+=.5*u,s-=.5*u);var f=Math.max(1e-5,Math.abs(s-o)),p=.5*f,v=.5*(o+s),g=.5*(r+a),y={root:{centerOfMass:{x:0,y:0},mass:0,range:{minX:v-p,maxX:v+p,minY:g-p,maxY:g+p},size:f,calcSize:1/f,children:{data:null},maxWidth:0,level:0,childrenCount:4}};this._splitBranch(y.root);for(var m=0;m0&&this._placeInTree(y.root,i);return y}},{key:"_updateBranchMass",value:function(t,e){var i=t.centerOfMass,n=t.mass+e.options.mass,o=1/n;i.x=i.x*t.mass+e.x*e.options.mass,i.x*=o,i.y=i.y*t.mass+e.y*e.options.mass,i.y*=o,t.mass=n;var r=Math.max(Math.max(e.height,e.radius),e.width);t.maxWidth=t.maxWidthe.x?o.maxY>e.y?"NW":"SW":o.maxY>e.y?"NE":"SE",this._placeInRegion(t,e,n)}},{key:"_placeInRegion",value:function(t,e,i){var n=t.children[i];switch(n.childrenCount){case 0:n.children.data=e,n.childrenCount=1,this._updateBranchMass(n,e);break;case 1:n.children.data.x===e.x&&n.children.data.y===e.y?(e.x+=this._rng(),e.y+=this._rng()):(this._splitBranch(n),this._placeInTree(n,e));break;case 4:this._placeInTree(n,e)}}},{key:"_splitBranch",value:function(t){var e=null;1===t.childrenCount&&(e=t.children.data,t.mass=0,t.centerOfMass.x=0,t.centerOfMass.y=0),t.childrenCount=4,t.children.data=null,this._insertRegion(t,"NW"),this._insertRegion(t,"NE"),this._insertRegion(t,"SW"),this._insertRegion(t,"SE"),null!=e&&this._placeInTree(t,e)}},{key:"_insertRegion",value:function(t,e){var i,n,o,r,s=.5*t.size;switch(e){case"NW":i=t.range.minX,n=t.range.minX+s,o=t.range.minY,r=t.range.minY+s;break;case"NE":i=t.range.minX+s,n=t.range.maxX,o=t.range.minY,r=t.range.minY+s;break;case"SW":i=t.range.minX,n=t.range.minX+s,o=t.range.minY+s,r=t.range.maxY;break;case"SE":i=t.range.minX+s,n=t.range.maxX,o=t.range.minY+s,r=t.range.maxY}t.children[e]={centerOfMass:{x:0,y:0},mass:0,range:{minX:i,maxX:n,minY:o,maxY:r},size:.5*t.size,calcSize:2*t.calcSize,children:{data:null},maxWidth:0,level:t.level+1,childrenCount:0}}},{key:"_debug",value:function(t,e){void 0!==this.barnesHutTree&&(t.lineWidth=1,this._drawBranch(this.barnesHutTree.root,t,e))}},{key:"_drawBranch",value:function(t,e,i){void 0===i&&(i="#FF0000"),4===t.childrenCount&&(this._drawBranch(t.children.NW,e),this._drawBranch(t.children.NE,e),this._drawBranch(t.children.SE,e),this._drawBranch(t.children.SW,e)),e.strokeStyle=i,e.beginPath(),e.moveTo(t.range.minX,t.range.minY),e.lineTo(t.range.maxX,t.range.minY),e.stroke(),e.beginPath(),e.moveTo(t.range.maxX,t.range.minY),e.lineTo(t.range.maxX,t.range.maxY),e.stroke(),e.beginPath(),e.moveTo(t.range.maxX,t.range.maxY),e.lineTo(t.range.minX,t.range.maxY),e.stroke(),e.beginPath(),e.moveTo(t.range.minX,t.range.maxY),e.lineTo(t.range.minX,t.range.minY),e.stroke()}}]),t}(),J2=function(){function t(e,i,n){uU(this,t),this._rng=AJ("REPULSION SOLVER"),this.body=e,this.physicsBody=i,this.setOptions(n)}return yW(t,[{key:"setOptions",value:function(t){this.options=t}},{key:"solve",value:function(){for(var t,e,i,n,o,r,s,a,l=this.body.nodes,h=this.physicsBody.physicsNodeIndices,c=this.physicsBody.forces,d=this.options.nodeDistance,u=-2/3/d,f=4/3,p=0;p0){var r=o.edges.length+1,s=this.options.centralGravity*r*o.options.mass;n[o.id].x=e*s,n[o.id].y=i*s}}}]),i}(t3),r3=function(){function t(e){uU(this,t),this.body=e,this.physicsBody={physicsNodeIndices:[],physicsEdgeIndices:[],forces:{},velocities:{}},this.physicsEnabled=!0,this.simulationInterval=1e3/60,this.requiresTimeout=!0,this.previousStates={},this.referenceState={},this.freezeCache={},this.renderTimer=void 0,this.adaptiveTimestep=!1,this.adaptiveTimestepEnabled=!1,this.adaptiveCounter=0,this.adaptiveInterval=3,this.stabilized=!1,this.startedStabilization=!1,this.stabilizationIterations=0,this.ready=!1,this.options={},this.defaultOptions={enabled:!0,barnesHut:{theta:.5,gravitationalConstant:-2e3,centralGravity:.3,springLength:95,springConstant:.04,damping:.09,avoidOverlap:0},forceAtlas2Based:{theta:.5,gravitationalConstant:-50,centralGravity:.01,springConstant:.08,springLength:100,damping:.4,avoidOverlap:0},repulsion:{centralGravity:.2,springLength:200,springConstant:.05,nodeDistance:100,damping:.09,avoidOverlap:0},hierarchicalRepulsion:{centralGravity:0,springLength:100,springConstant:.01,nodeDistance:120,damping:.09},maxVelocity:50,minVelocity:.75,solver:"barnesHut",stabilization:{enabled:!0,iterations:1e3,updateInterval:50,onlyDynamicEdges:!1,fit:!0},timestep:.5,adaptiveTimestep:!0,wind:{x:0,y:0}},wF(this.options,this.defaultOptions),this.timestep=.5,this.layoutFailed=!1,this.bindEventListeners()}return yW(t,[{key:"bindEventListeners",value:function(){var t=this;this.body.emitter.on("initPhysics",(function(){t.initPhysics()})),this.body.emitter.on("_layoutFailed",(function(){t.layoutFailed=!0})),this.body.emitter.on("resetPhysics",(function(){t.stopSimulation(),t.ready=!1})),this.body.emitter.on("disablePhysics",(function(){t.physicsEnabled=!1,t.stopSimulation()})),this.body.emitter.on("restorePhysics",(function(){t.setOptions(t.options),!0===t.ready&&t.startSimulation()})),this.body.emitter.on("startSimulation",(function(){!0===t.ready&&t.startSimulation()})),this.body.emitter.on("stopSimulation",(function(){t.stopSimulation()})),this.body.emitter.on("destroy",(function(){t.stopSimulation(!1),t.body.emitter.off()})),this.body.emitter.on("_dataChanged",(function(){t.updatePhysicsData()}))}},{key:"setOptions",value:function(t){if(void 0!==t)if(!1===t)this.options.enabled=!1,this.physicsEnabled=!1,this.stopSimulation();else if(!0===t)this.options.enabled=!0,this.physicsEnabled=!0,this.startSimulation();else{this.physicsEnabled=!0,PJ(["stabilization"],this.options,t),ZJ(this.options,t,"stabilization"),void 0===t.enabled&&(this.options.enabled=!0),!1===this.options.enabled&&(this.physicsEnabled=!1,this.stopSimulation());var e=this.options.wind;e&&(("number"!=typeof e.x||b$(e.x))&&(e.x=0),("number"!=typeof e.y||b$(e.y))&&(e.y=0)),this.timestep=this.options.timestep}this.init()}},{key:"init",value:function(){var t;"forceAtlas2Based"===this.options.solver?(t=this.options.forceAtlas2Based,this.nodesSolver=new i3(this.body,this.physicsBody,t),this.edgesSolver=new _2(this.body,this.physicsBody,t),this.gravitySolver=new o3(this.body,this.physicsBody,t)):"repulsion"===this.options.solver?(t=this.options.repulsion,this.nodesSolver=new J2(this.body,this.physicsBody,t),this.edgesSolver=new _2(this.body,this.physicsBody,t),this.gravitySolver=new t3(this.body,this.physicsBody,t)):"hierarchicalRepulsion"===this.options.solver?(t=this.options.hierarchicalRepulsion,this.nodesSolver=new X2(this.body,this.physicsBody,t),this.edgesSolver=new $2(this.body,this.physicsBody,t),this.gravitySolver=new t3(this.body,this.physicsBody,t)):(t=this.options.barnesHut,this.nodesSolver=new Z2(this.body,this.physicsBody,t),this.edgesSolver=new _2(this.body,this.physicsBody,t),this.gravitySolver=new t3(this.body,this.physicsBody,t)),this.modelOptions=t}},{key:"initPhysics",value:function(){!0===this.physicsEnabled&&!0===this.options.enabled?!0===this.options.stabilization.enabled?this.stabilize():(this.stabilized=!1,this.ready=!0,this.body.emitter.emit("fit",{},this.layoutFailed),this.startSimulation()):(this.ready=!0,this.body.emitter.emit("fit"))}},{key:"startSimulation",value:function(){var t;!0===this.physicsEnabled&&!0===this.options.enabled?(this.stabilized=!1,this.adaptiveTimestep=!1,this.body.emitter.emit("_resizeNodes"),void 0===this.viewFunction&&(this.viewFunction=HF(t=this.simulationStep).call(t,this),this.body.emitter.on("initRedraw",this.viewFunction),this.body.emitter.emit("_startRendering"))):this.body.emitter.emit("_redraw")}},{key:"stopSimulation",value:function(){var t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];this.stabilized=!0,!0===t&&this._emitStabilized(),void 0!==this.viewFunction&&(this.body.emitter.off("initRedraw",this.viewFunction),this.viewFunction=void 0,!0===t&&this.body.emitter.emit("_stopRendering"))}},{key:"simulationStep",value:function(){var t=FG();this.physicsTick(),(FG()-t<.4*this.simulationInterval||!0===this.runDoubleSpeed)&&!1===this.stabilized&&(this.physicsTick(),this.runDoubleSpeed=!0),!0===this.stabilized&&this.stopSimulation()}},{key:"_emitStabilized",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.stabilizationIterations;(this.stabilizationIterations>1||!0===this.startedStabilization)&&uY((function(){t.body.emitter.emit("stabilized",{iterations:e}),t.startedStabilization=!1,t.stabilizationIterations=0}),0)}},{key:"physicsStep",value:function(){this.gravitySolver.solve(),this.nodesSolver.solve(),this.edgesSolver.solve(),this.moveNodes()}},{key:"adjustTimeStep",value:function(){!0===this._evaluateStepQuality()?this.timestep=1.2*this.timestep:this.timestep/1.2.3))return!1;return!0}},{key:"moveNodes",value:function(){for(var t=this.physicsBody.physicsNodeIndices,e=0,i=0,n=0;nn&&(t=t>0?n:-n),t}},{key:"_performStep",value:function(t){var e=this.body.nodes[t],i=this.physicsBody.forces[t];this.options.wind&&(i.x+=this.options.wind.x,i.y+=this.options.wind.y);var n=this.physicsBody.velocities[t];return this.previousStates[t]={x:e.x,y:e.y,vx:n.x,vy:n.y},!1===e.options.fixed.x?(n.x=this.calculateComponentVelocity(n.x,i.x,e.options.mass),e.x+=n.x*this.timestep):(i.x=0,n.x=0),!1===e.options.fixed.y?(n.y=this.calculateComponentVelocity(n.y,i.y,e.options.mass),e.y+=n.y*this.timestep):(i.y=0,n.y=0),Math.sqrt(Math.pow(n.x,2)+Math.pow(n.y,2))}},{key:"_freezeNodes",value:function(){var t=this.body.nodes;for(var e in t)if(Object.prototype.hasOwnProperty.call(t,e)&&t[e].x&&t[e].y){var i=t[e].options.fixed;this.freezeCache[e]={x:i.x,y:i.y},i.x=!0,i.y=!0}}},{key:"_restoreFrozenNodes",value:function(){var t=this.body.nodes;for(var e in t)Object.prototype.hasOwnProperty.call(t,e)&&void 0!==this.freezeCache[e]&&(t[e].options.fixed.x=this.freezeCache[e].x,t[e].options.fixed.y=this.freezeCache[e].y);this.freezeCache={}}},{key:"stabilize",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.options.stabilization.iterations;"number"!=typeof e&&(e=this.options.stabilization.iterations,console.error("The stabilize method needs a numeric amount of iterations. Switching to default: ",e)),0!==this.physicsBody.physicsNodeIndices.length?(this.adaptiveTimestep=this.options.adaptiveTimestep,this.body.emitter.emit("_resizeNodes"),this.stopSimulation(),this.stabilized=!1,this.body.emitter.emit("_blockRedraw"),this.targetIterations=e,!0===this.options.stabilization.onlyDynamicEdges&&this._freezeNodes(),this.stabilizationIterations=0,uY((function(){return t._stabilizationBatch()}),0)):this.ready=!0}},{key:"_startStabilizing",value:function(){return!0!==this.startedStabilization&&(this.body.emitter.emit("startStabilizing"),this.startedStabilization=!0,!0)}},{key:"_stabilizationBatch",value:function(){var t=this,e=function(){return!1===t.stabilized&&t.stabilizationIterations1&&void 0!==arguments[1]?arguments[1]:[],n=1e9,o=-1e9,r=1e9,s=-1e9;if(i.length>0)for(var a=0;a(e=t[i[a]]).shape.boundingBox.left&&(r=e.shape.boundingBox.left),se.shape.boundingBox.top&&(n=e.shape.boundingBox.top),o1&&void 0!==arguments[1]?arguments[1]:[],n=1e9,o=-1e9,r=1e9,s=-1e9;if(i.length>0)for(var a=0;a(e=t[i[a]]).x&&(r=e.x),se.y&&(n=e.y),o=t&&i.push(o.id)}for(var r=0;r0&&void 0!==arguments[0]?arguments[0]:{},i=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(void 0===e.joinCondition)throw new Error("Cannot call clusterByNodeData without a joinCondition function in the options.");e=this._checkOptions(e);var n={},o={};jJ(this.body.nodes,(function(i,r){i.options&&!0===e.joinCondition(i.options)&&(n[r]=i,jJ(i.edges,(function(e){void 0===t.clusteredEdges[e.id]&&(o[e.id]=e)})))})),this._cluster(n,o,e,i)}},{key:"clusterByEdgeCount",value:function(t,e){var i=this,n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];e=this._checkOptions(e);for(var o,r,s,a=[],l={},h=function(){var n={},h={},d=i.body.nodeIndices[c],u=i.body.nodes[d];if(void 0===l[d]){s=0,r=[];for(var f=0;f0&&RG(h).length>0&&!0===v){var m=function(){for(var t=0;t1&&void 0!==arguments[1])||arguments[1];this.clusterByEdgeCount(1,t,e)}},{key:"clusterBridges",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];this.clusterByEdgeCount(2,t,e)}},{key:"clusterByConnection",value:function(t,e){var i,n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];if(void 0===t)throw new Error("No nodeId supplied to clusterByConnection!");if(void 0===this.body.nodes[t])throw new Error("The nodeId given to clusterByConnection does not exist!");var o=this.body.nodes[t];void 0===(e=this._checkOptions(e,o)).clusterNodeProperties.x&&(e.clusterNodeProperties.x=o.x),void 0===e.clusterNodeProperties.y&&(e.clusterNodeProperties.y=o.y),void 0===e.clusterNodeProperties.fixed&&(e.clusterNodeProperties.fixed={},e.clusterNodeProperties.fixed.x=o.options.fixed.x,e.clusterNodeProperties.fixed.y=o.options.fixed.y);var r={},s={},a=o.id,l=u3.cloneOptions(o);r[a]=o;for(var h=0;h-1&&(s[y.id]=y)}this._cluster(r,s,e,n)}},{key:"_createClusterEdges",value:function(t,e,i,n){for(var o,r,s,a,l,h,c=RG(t),d=[],u=0;u0&&void 0!==arguments[0]?arguments[0]:{};return void 0===t.clusterEdgeProperties&&(t.clusterEdgeProperties={}),void 0===t.clusterNodeProperties&&(t.clusterNodeProperties={}),t}},{key:"_cluster",value:function(t,e,i){var n=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],o=[];for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&void 0!==this.clusteredNodes[r]&&o.push(r);for(var s=0;so?e.x:o,r=e.ys?e.y:s;return{x:.5*(n+o),y:.5*(r+s)}}},{key:"openCluster",value:function(t,e){var i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];if(void 0===t)throw new Error("No clusterNodeId supplied to openCluster.");var n=this.body.nodes[t];if(void 0===n)throw new Error("The clusterNodeId supplied to openCluster does not exist.");if(!0!==n.isCluster||void 0===n.containedNodes||void 0===n.containedEdges)throw new Error("The node:"+t+" is not a valid cluster.");var o=this.findNode(t),r=Lq(o).call(o,t)-1;if(r>=0){var s=o[r];return this.body.nodes[s]._openChildCluster(t),delete this.body.nodes[t],void(!0===i&&this.body.emitter.emit("_dataChanged"))}var a=n.containedNodes,l=n.containedEdges;if(void 0!==e&&void 0!==e.releaseFunction&&"function"==typeof e.releaseFunction){var h={},c={x:n.x,y:n.y};for(var d in a)if(Object.prototype.hasOwnProperty.call(a,d)){var u=this.body.nodes[d];h[d]={x:u.x,y:u.y}}var f=e.releaseFunction(c,h);for(var p in a)if(Object.prototype.hasOwnProperty.call(a,p)){var v=this.body.nodes[p];void 0!==f[p]&&(v.x=void 0===f[p].x?n.x:f[p].x,v.y=void 0===f[p].y?n.y:f[p].y)}}else jJ(a,(function(t){!1===t.options.fixed.x&&(t.x=n.x),!1===t.options.fixed.y&&(t.y=n.y)}));for(var g in a)if(Object.prototype.hasOwnProperty.call(a,g)){var y=this.body.nodes[g];y.vx=n.vx,y.vy=n.vy,y.setOptions({physics:!0}),delete this.clusteredNodes[g]}for(var m=[],b=0;b0&&o<100;){var r=e.pop();if(void 0!==r){var s=this.body.edges[r];if(void 0!==s){o++;var a=s.clusteringEdgeReplacingIds;if(void 0===a)n.push(r);else for(var l=0;ln&&(n=r.edges.length),t+=r.edges.length,e+=Math.pow(r.edges.length,2),i+=1}t/=i;var s=(e/=i)-Math.pow(t,2),a=Math.sqrt(s),l=Math.floor(t+2*a);return l>n&&(l=n),l}},{key:"_createClusteredEdge",value:function(t,e,i,n,o){var r=u3.cloneOptions(i,"edge");FJ(r,n),r.from=t,r.to=e,r.id="clusterEdge:"+d3(),void 0!==o&&FJ(r,o);var s=this.body.functions.createEdge(r);return s.clusteringEdgeReplacingIds=[i.id],s.connect(),this.body.edges[s.id]=s,s}},{key:"_clusterEdges",value:function(t,e,i,n){if(e instanceof q2){var o=e,r={};r[o.id]=o,e=r}if(t instanceof J1){var s=t,a={};a[s.id]=s,t=a}if(null==i)throw new Error("_clusterEdges: parameter clusterNode required");for(var l in void 0===n&&(n=i.clusterEdgeProperties),this._createClusterEdges(t,e,i,n),e)if(Object.prototype.hasOwnProperty.call(e,l)&&void 0!==this.body.edges[l]){var h=this.body.edges[l];this._backupEdgeOptions(h),h.setOptions({physics:!1})}for(var c in t)Object.prototype.hasOwnProperty.call(t,c)&&(this.clusteredNodes[c]={clusterId:i.id,node:this.body.nodes[c]},this.body.nodes[c].setOptions({physics:!1}))}},{key:"_getClusterNodeForNode",value:function(t){if(void 0!==t){var e=this.clusteredNodes[t];if(void 0!==e){var i=e.clusterId;if(void 0!==i)return this.body.nodes[i]}}}},{key:"_filter",value:function(t,e){var i=[];return jJ(t,(function(t){e(t)&&i.push(t)})),i}},{key:"_updateState",value:function(){var t,e=this,i=[],n={},o=function(t){jJ(e.body.nodes,(function(e){!0===e.isCluster&&t(e)}))};for(t in this.clusteredNodes){if(Object.prototype.hasOwnProperty.call(this.clusteredNodes,t))void 0===this.body.nodes[t]&&i.push(t)}o((function(t){for(var e=0;e0}t.endPointsValid()&&o||(n[i]=i)})),o((function(t){jJ(n,(function(i){delete t.containedEdges[i],jJ(t.edges,(function(o,r){o.id!==i?o.clusteringEdgeReplacingIds=e._filter(o.clusteringEdgeReplacingIds,(function(t){return!n[t]})):t.edges[r]=null})),t.edges=e._filter(t.edges,(function(t){return null!==t}))}))})),jJ(n,(function(t){delete e.clusteredEdges[t]})),jJ(n,(function(t){delete e.body.edges[t]})),jJ(RG(this.body.edges),(function(t){var i=e.body.edges[t],n=e._isClusteredNode(i.fromId)||e._isClusteredNode(i.toId);if(n!==e._isClusteredEdge(i.id))if(n){var o=e._getClusterNodeForNode(i.fromId);void 0!==o&&e._clusterEdges(e.body.nodes[i.fromId],i,o);var r=e._getClusterNodeForNode(i.toId);void 0!==r&&e._clusterEdges(e.body.nodes[i.toId],i,r)}else delete e._clusterEdges[t],e._restoreEdge(i)}));for(var s=!1,a=!0,l=function(){var t=[];o((function(e){var i=RG(e.containedNodes).length,n=!0===e.options.allowSingleNodeCluster;(n&&i<1||!n&&i<2)&&t.push(e.id)}));for(var i=0;i0,s=s||a};a;)l();s&&this._updateState()}},{key:"_isClusteredNode",value:function(t){return void 0!==this.clusteredNodes[t]}},{key:"_isClusteredEdge",value:function(t){return void 0!==this.clusteredEdges[t]}}]),t}();var g3=function(){function t(e,i){var n;uU(this,t),void 0!==window&&(n=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame),window.requestAnimationFrame=void 0===n?function(t){t()}:n,this.body=e,this.canvas=i,this.redrawRequested=!1,this.renderTimer=void 0,this.requiresTimeout=!0,this.renderingActive=!1,this.renderRequests=0,this.allowRedraw=!0,this.dragging=!1,this.zooming=!1,this.options={},this.defaultOptions={hideEdgesOnDrag:!1,hideEdgesOnZoom:!1,hideNodesOnDrag:!1},wF(this.options,this.defaultOptions),this._determineBrowserMethod(),this.bindEventListeners()}return yW(t,[{key:"bindEventListeners",value:function(){var t,e=this;this.body.emitter.on("dragStart",(function(){e.dragging=!0})),this.body.emitter.on("dragEnd",(function(){e.dragging=!1})),this.body.emitter.on("zoom",(function(){e.zooming=!0,window.clearTimeout(e.zoomTimeoutId),e.zoomTimeoutId=uY((function(){var t;e.zooming=!1,HF(t=e._requestRedraw).call(t,e)()}),250)})),this.body.emitter.on("_resizeNodes",(function(){e._resizeNodes()})),this.body.emitter.on("_redraw",(function(){!1===e.renderingActive&&e._redraw()})),this.body.emitter.on("_blockRedraw",(function(){e.allowRedraw=!1})),this.body.emitter.on("_allowRedraw",(function(){e.allowRedraw=!0,e.redrawRequested=!1})),this.body.emitter.on("_requestRedraw",HF(t=this._requestRedraw).call(t,this)),this.body.emitter.on("_startRendering",(function(){e.renderRequests+=1,e.renderingActive=!0,e._startRendering()})),this.body.emitter.on("_stopRendering",(function(){e.renderRequests-=1,e.renderingActive=e.renderRequests>0,e.renderTimer=void 0})),this.body.emitter.on("destroy",(function(){e.renderRequests=0,e.allowRedraw=!1,e.renderingActive=!1,!0===e.requiresTimeout?clearTimeout(e.renderTimer):window.cancelAnimationFrame(e.renderTimer),e.body.emitter.off()}))}},{key:"setOptions",value:function(t){if(void 0!==t){zJ(["hideEdgesOnDrag","hideEdgesOnZoom","hideNodesOnDrag"],this.options,t)}}},{key:"_requestNextFrame",value:function(t,e){if("undefined"!=typeof window){var i,n=window;return!0===this.requiresTimeout?i=uY(t,e):n.requestAnimationFrame&&(i=n.requestAnimationFrame(t)),i}}},{key:"_startRendering",value:function(){var t;!0===this.renderingActive&&(void 0===this.renderTimer&&(this.renderTimer=this._requestNextFrame(HF(t=this._renderStep).call(t,this),this.simulationInterval)))}},{key:"_renderStep",value:function(){!0===this.renderingActive&&(this.renderTimer=void 0,!0===this.requiresTimeout&&this._startRendering(),this._redraw(),!1===this.requiresTimeout&&this._startRendering())}},{key:"redraw",value:function(){this.body.emitter.emit("setSize"),this._redraw()}},{key:"_requestRedraw",value:function(){var t=this;!0!==this.redrawRequested&&!1===this.renderingActive&&!0===this.allowRedraw&&(this.redrawRequested=!0,this._requestNextFrame((function(){t._redraw(!1)}),0))}},{key:"_redraw",value:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(!0===this.allowRedraw){this.body.emitter.emit("initRedraw"),this.redrawRequested=!1;var e={drawExternalLabels:null};0!==this.canvas.frame.canvas.width&&0!==this.canvas.frame.canvas.height||this.canvas.setSize(),this.canvas.setTransform();var i=this.canvas.getContext(),n=this.canvas.frame.canvas.clientWidth,o=this.canvas.frame.canvas.clientHeight;if(i.clearRect(0,0,n,o),0===this.canvas.frame.clientWidth)return;if(i.save(),i.translate(this.body.view.translation.x,this.body.view.translation.y),i.scale(this.body.view.scale,this.body.view.scale),i.beginPath(),this.body.emitter.emit("beforeDrawing",i),i.closePath(),!1===t&&(!1===this.dragging||!0===this.dragging&&!1===this.options.hideEdgesOnDrag)&&(!1===this.zooming||!0===this.zooming&&!1===this.options.hideEdgesOnZoom)&&this._drawEdges(i),!1===this.dragging||!0===this.dragging&&!1===this.options.hideNodesOnDrag){var r=this._drawNodes(i,t).drawExternalLabels;e.drawExternalLabels=r}!1===t&&(!1===this.dragging||!0===this.dragging&&!1===this.options.hideEdgesOnDrag)&&(!1===this.zooming||!0===this.zooming&&!1===this.options.hideEdgesOnZoom)&&this._drawArrows(i),null!=e.drawExternalLabels&&e.drawExternalLabels(),!1===t&&this._drawSelectionBox(i),i.beginPath(),this.body.emitter.emit("afterDrawing",i),i.closePath(),i.restore(),!0===t&&i.clearRect(0,0,n,o)}}},{key:"_resizeNodes",value:function(){this.canvas.setTransform();var t=this.canvas.getContext();t.save(),t.translate(this.body.view.translation.x,this.body.view.translation.y),t.scale(this.body.view.scale,this.body.view.scale);var e,i=this.body.nodes;for(var n in i)Object.prototype.hasOwnProperty.call(i,n)&&((e=i[n]).resize(t),e.updateBoundingBox(t,e.selected));t.restore()}},{key:"_drawNodes",value:function(t){for(var e,i,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],o=this.body.nodes,r=this.body.nodeIndices,s=[],a=[],l=this.canvas.DOMtoCanvas({x:-20,y:-20}),h=this.canvas.DOMtoCanvas({x:this.canvas.frame.canvas.clientWidth+20,y:this.canvas.frame.canvas.clientHeight+20}),c={top:l.y,left:l.x,bottom:h.y,right:h.x},d=[],u=0;u0&&void 0!==arguments[0]?arguments[0]:this.pixelRatio;!0===this.initialized&&(this.cameraState.previousWidth=this.frame.canvas.width/t,this.cameraState.previousHeight=this.frame.canvas.height/t,this.cameraState.scale=this.body.view.scale,this.cameraState.position=this.DOMtoCanvas({x:.5*this.frame.canvas.width/t,y:.5*this.frame.canvas.height/t}))}},{key:"_setCameraState",value:function(){if(void 0!==this.cameraState.scale&&0!==this.frame.canvas.clientWidth&&0!==this.frame.canvas.clientHeight&&0!==this.pixelRatio&&this.cameraState.previousWidth>0&&this.cameraState.previousHeight>0){var t=this.frame.canvas.width/this.pixelRatio/this.cameraState.previousWidth,e=this.frame.canvas.height/this.pixelRatio/this.cameraState.previousHeight,i=this.cameraState.scale;1!=t&&1!=e?i=.5*this.cameraState.scale*(t+e):1!=t?i=this.cameraState.scale*t:1!=e&&(i=this.cameraState.scale*e),this.body.view.scale=i;var n=this.DOMtoCanvas({x:.5*this.frame.canvas.clientWidth,y:.5*this.frame.canvas.clientHeight}),o={x:n.x-this.cameraState.position.x,y:n.y-this.cameraState.position.y};this.body.view.translation.x+=o.x*this.body.view.scale,this.body.view.translation.y+=o.y*this.body.view.scale}}},{key:"_prepareValue",value:function(t){if("number"==typeof t)return t+"px";if("string"==typeof t){if(-1!==Lq(t).call(t,"%")||-1!==Lq(t).call(t,"px"))return t;if(-1===Lq(t).call(t,"%"))return t+"px"}throw new Error("Could not use the value supplied for width or height:"+t)}},{key:"_create",value:function(){for(;this.body.container.hasChildNodes();)this.body.container.removeChild(this.body.container.firstChild);if(this.frame=document.createElement("div"),this.frame.className="vis-network",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.tabIndex=0,this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),this.frame.canvas.getContext)this._setPixelRatio(),this.setTransform();else{var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerText="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t)}this.body.container.appendChild(this.frame),this.body.view.scale=1,this.body.view.translation={x:.5*this.frame.canvas.clientWidth,y:.5*this.frame.canvas.clientHeight},this._bindHammer()}},{key:"_bindHammer",value:function(){var t=this;void 0!==this.hammer&&this.hammer.destroy(),this.drag={},this.pinch={},this.hammer=new hX(this.frame.canvas),this.hammer.get("pinch").set({enable:!0}),this.hammer.get("pan").set({threshold:5,direction:hX.DIRECTION_ALL}),m3(this.hammer,(function(e){t.body.eventListeners.onTouch(e)})),this.hammer.on("tap",(function(e){t.body.eventListeners.onTap(e)})),this.hammer.on("doubletap",(function(e){t.body.eventListeners.onDoubleTap(e)})),this.hammer.on("press",(function(e){t.body.eventListeners.onHold(e)})),this.hammer.on("panstart",(function(e){t.body.eventListeners.onDragStart(e)})),this.hammer.on("panmove",(function(e){t.body.eventListeners.onDrag(e)})),this.hammer.on("panend",(function(e){t.body.eventListeners.onDragEnd(e)})),this.hammer.on("pinch",(function(e){t.body.eventListeners.onPinch(e)})),this.frame.canvas.addEventListener("wheel",(function(e){t.body.eventListeners.onMouseWheel(e)})),this.frame.canvas.addEventListener("mousemove",(function(e){t.body.eventListeners.onMouseMove(e)})),this.frame.canvas.addEventListener("contextmenu",(function(e){t.body.eventListeners.onContext(e)})),this.hammerFrame=new hX(this.frame),b3(this.hammerFrame,(function(e){t.body.eventListeners.onRelease(e)}))}},{key:"setSize",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.options.width,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.options.height;t=this._prepareValue(t),e=this._prepareValue(e);var i=!1,n=this.frame.canvas.width,o=this.frame.canvas.height,r=this.pixelRatio;if(this._setPixelRatio(),t!=this.options.width||e!=this.options.height||this.frame.style.width!=t||this.frame.style.height!=e)this._getCameraState(r),this.frame.style.width=t,this.frame.style.height=e,this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=Math.round(this.frame.canvas.clientWidth*this.pixelRatio),this.frame.canvas.height=Math.round(this.frame.canvas.clientHeight*this.pixelRatio),this.options.width=t,this.options.height=e,this.canvasViewCenter={x:.5*this.frame.clientWidth,y:.5*this.frame.clientHeight},i=!0;else{var s=Math.round(this.frame.canvas.clientWidth*this.pixelRatio),a=Math.round(this.frame.canvas.clientHeight*this.pixelRatio);this.frame.canvas.width===s&&this.frame.canvas.height===a||this._getCameraState(r),this.frame.canvas.width!==s&&(this.frame.canvas.width=s,i=!0),this.frame.canvas.height!==a&&(this.frame.canvas.height=a,i=!0)}return!0===i&&(this.body.emitter.emit("resize",{width:Math.round(this.frame.canvas.width/this.pixelRatio),height:Math.round(this.frame.canvas.height/this.pixelRatio),oldWidth:Math.round(n/this.pixelRatio),oldHeight:Math.round(o/this.pixelRatio)}),this._setCameraState()),this.initialized=!0,i}},{key:"getContext",value:function(){return this.frame.canvas.getContext("2d")}},{key:"_determinePixelRatio",value:function(){var t=this.getContext();if(void 0===t)throw new Error("Could not get canvax context");var e=1;return"undefined"!=typeof window&&(e=window.devicePixelRatio||1),e/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1)}},{key:"_setPixelRatio",value:function(){this.pixelRatio=this._determinePixelRatio()}},{key:"setTransform",value:function(){var t=this.getContext();if(void 0===t)throw new Error("Could not get canvax context");t.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0)}},{key:"_XconvertDOMtoCanvas",value:function(t){return(t-this.body.view.translation.x)/this.body.view.scale}},{key:"_XconvertCanvasToDOM",value:function(t){return t*this.body.view.scale+this.body.view.translation.x}},{key:"_YconvertDOMtoCanvas",value:function(t){return(t-this.body.view.translation.y)/this.body.view.scale}},{key:"_YconvertCanvasToDOM",value:function(t){return t*this.body.view.scale+this.body.view.translation.y}},{key:"canvasToDOM",value:function(t){return{x:this._XconvertCanvasToDOM(t.x),y:this._YconvertCanvasToDOM(t.y)}}},{key:"DOMtoCanvas",value:function(t){return{x:this._XconvertDOMtoCanvas(t.x),y:this._YconvertDOMtoCanvas(t.y)}}}]),t}();var A3=function(){function t(e,i){var n,o,r=this;uU(this,t),this.body=e,this.canvas=i,this.animationSpeed=1/this.renderRefreshRate,this.animationEasingFunction="easeInOutQuint",this.easingTime=0,this.sourceScale=0,this.targetScale=0,this.sourceTranslation=0,this.targetTranslation=0,this.lockedOnNodeId=void 0,this.lockedOnNodeOffset=void 0,this.touchTime=0,this.viewFunction=void 0,this.body.emitter.on("fit",HF(n=this.fit).call(n,this)),this.body.emitter.on("animationFinished",(function(){r.body.emitter.emit("_stopRendering")})),this.body.emitter.on("unlockNode",HF(o=this.releaseNode).call(o,this))}return yW(t,[{key:"setOptions",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.options=t}},{key:"fit",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];t=function(t,e){var i=wF({nodes:e,minZoomLevel:Number.MIN_VALUE,maxZoomLevel:1},null!=t?t:{});if(!AG(i.nodes))throw new TypeError("Nodes has to be an array of ids.");if(0===i.nodes.length&&(i.nodes=e),!("number"==typeof i.minZoomLevel&&i.minZoomLevel>0))throw new TypeError("Min zoom level has to be a number higher than zero.");if(!("number"==typeof i.maxZoomLevel&&i.minZoomLevel<=i.maxZoomLevel))throw new TypeError("Max zoom level has to be a number higher than min zoom level.");return i}(t,this.body.nodeIndices);var i,n,o=this.canvas.frame.canvas.clientWidth,r=this.canvas.frame.canvas.clientHeight;if(0===o||0===r)n=1,i=u3.getRange(this.body.nodes,t.nodes);else if(!0===e){var s=0;for(var a in this.body.nodes){if(Object.prototype.hasOwnProperty.call(this.body.nodes,a))!0===this.body.nodes[a].predefinedPosition&&(s+=1)}if(s>.5*this.body.nodeIndices.length)return void this.fit(t,!1);i=u3.getRange(this.body.nodes,t.nodes),n=12.662/(this.body.nodeIndices.length+7.4147)+.0964822,n*=Math.min(o/600,r/600)}else{this.body.emitter.emit("_resizeNodes"),i=u3.getRange(this.body.nodes,t.nodes);var l=o/(1.1*Math.abs(i.maxX-i.minX)),h=r/(1.1*Math.abs(i.maxY-i.minY));n=l<=h?l:h}n>t.maxZoomLevel?n=t.maxZoomLevel:n1&&void 0!==arguments[1]?arguments[1]:{};if(void 0!==this.body.nodes[t]){var i={x:this.body.nodes[t].x,y:this.body.nodes[t].y};e.position=i,e.lockedOnNode=t,this.moveTo(e)}else console.error("Node: "+t+" cannot be found.")}},{key:"moveTo",value:function(t){if(void 0!==t){if(null!=t.offset){if(null!=t.offset.x){if(t.offset.x=+t.offset.x,!k$(t.offset.x))throw new TypeError('The option "offset.x" has to be a finite number.')}else t.offset.x=0;if(null!=t.offset.y){if(t.offset.y=+t.offset.y,!k$(t.offset.y))throw new TypeError('The option "offset.y" has to be a finite number.')}else t.offset.x=0}else t.offset={x:0,y:0};if(null!=t.position){if(null!=t.position.x){if(t.position.x=+t.position.x,!k$(t.position.x))throw new TypeError('The option "position.x" has to be a finite number.')}else t.position.x=0;if(null!=t.position.y){if(t.position.y=+t.position.y,!k$(t.position.y))throw new TypeError('The option "position.y" has to be a finite number.')}else t.position.x=0}else t.position=this.getViewPosition();if(null!=t.scale){if(t.scale=+t.scale,!(t.scale>0))throw new TypeError('The option "scale" has to be a number greater than zero.')}else t.scale=this.body.view.scale;void 0===t.animation&&(t.animation={duration:0}),!1===t.animation&&(t.animation={duration:0}),!0===t.animation&&(t.animation={}),void 0===t.animation.duration&&(t.animation.duration=1e3),void 0===t.animation.easingFunction&&(t.animation.easingFunction="easeInOutQuad"),this.animateView(t)}else t={}}},{key:"animateView",value:function(t){if(void 0!==t){this.animationEasingFunction=t.animation.easingFunction,this.releaseNode(),!0===t.locked&&(this.lockedOnNodeId=t.lockedOnNode,this.lockedOnNodeOffset=t.offset),0!=this.easingTime&&this._transitionRedraw(!0),this.sourceScale=this.body.view.scale,this.sourceTranslation=this.body.view.translation,this.targetScale=t.scale,this.body.view.scale=this.targetScale;var e,i,n=this.canvas.DOMtoCanvas({x:.5*this.canvas.frame.canvas.clientWidth,y:.5*this.canvas.frame.canvas.clientHeight}),o=n.x-t.position.x,r=n.y-t.position.y;if(this.targetTranslation={x:this.sourceTranslation.x+o*this.targetScale+t.offset.x,y:this.sourceTranslation.y+r*this.targetScale+t.offset.y},0===t.animation.duration)if(null!=this.lockedOnNodeId)this.viewFunction=HF(e=this._lockedRedraw).call(e,this),this.body.emitter.on("initRedraw",this.viewFunction);else this.body.view.scale=this.targetScale,this.body.view.translation=this.targetTranslation,this.body.emitter.emit("_requestRedraw");else this.animationSpeed=1/(60*t.animation.duration*.001)||1/60,this.animationEasingFunction=t.animation.easingFunction,this.viewFunction=HF(i=this._transitionRedraw).call(i,this),this.body.emitter.on("initRedraw",this.viewFunction),this.body.emitter.emit("_startRendering")}}},{key:"_lockedRedraw",value:function(){var t=this.body.nodes[this.lockedOnNodeId].x,e=this.body.nodes[this.lockedOnNodeId].y,i=this.canvas.DOMtoCanvas({x:.5*this.canvas.frame.canvas.clientWidth,y:.5*this.canvas.frame.canvas.clientHeight}),n=i.x-t,o=i.y-e,r=this.body.view.translation,s={x:r.x+n*this.body.view.scale+this.lockedOnNodeOffset.x,y:r.y+o*this.body.view.scale+this.lockedOnNodeOffset.y};this.body.view.translation=s}},{key:"releaseNode",value:function(){void 0!==this.lockedOnNodeId&&void 0!==this.viewFunction&&(this.body.emitter.off("initRedraw",this.viewFunction),this.lockedOnNodeId=void 0,this.lockedOnNodeOffset=void 0)}},{key:"_transitionRedraw",value:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];this.easingTime+=this.animationSpeed,this.easingTime=!0===t?1:this.easingTime;var e=JJ[this.animationEasingFunction](this.easingTime);if(this.body.view.scale=this.sourceScale+(this.targetScale-this.sourceScale)*e,this.body.view.translation={x:this.sourceTranslation.x+(this.targetTranslation.x-this.sourceTranslation.x)*e,y:this.sourceTranslation.y+(this.targetTranslation.y-this.sourceTranslation.y)*e},this.easingTime>=1){var i;if(this.body.emitter.off("initRedraw",this.viewFunction),this.easingTime=0,null!=this.lockedOnNodeId)this.viewFunction=HF(i=this._lockedRedraw).call(i,this),this.body.emitter.on("initRedraw",this.viewFunction);this.body.emitter.emit("animationFinished")}}},{key:"getScale",value:function(){return this.body.view.scale}},{key:"getViewPosition",value:function(){return this.canvas.DOMtoCanvas({x:.5*this.canvas.frame.canvas.clientWidth,y:.5*this.canvas.frame.canvas.clientHeight})}}]),t}();function k3(t){var e,i=t&&t.preventDefault||!1,n=t&&t.container||window,o={},r={keydown:{},keyup:{}},s={};for(e=97;e<=122;e++)s[String.fromCharCode(e)]={code:e-97+65,shift:!1};for(e=65;e<=90;e++)s[String.fromCharCode(e)]={code:e,shift:!0};for(e=0;e<=9;e++)s[""+e]={code:48+e,shift:!1};for(e=1;e<=12;e++)s["F"+e]={code:111+e,shift:!1};for(e=0;e<=9;e++)s["num"+e]={code:96+e,shift:!1};s["num*"]={code:106,shift:!1},s["num+"]={code:107,shift:!1},s["num-"]={code:109,shift:!1},s["num/"]={code:111,shift:!1},s["num."]={code:110,shift:!1},s.left={code:37,shift:!1},s.up={code:38,shift:!1},s.right={code:39,shift:!1},s.down={code:40,shift:!1},s.space={code:32,shift:!1},s.enter={code:13,shift:!1},s.shift={code:16,shift:void 0},s.esc={code:27,shift:!1},s.backspace={code:8,shift:!1},s.tab={code:9,shift:!1},s.ctrl={code:17,shift:!1},s.alt={code:18,shift:!1},s.delete={code:46,shift:!1},s.pageup={code:33,shift:!1},s.pagedown={code:34,shift:!1},s["="]={code:187,shift:!1},s["-"]={code:189,shift:!1},s["]"]={code:221,shift:!1},s["["]={code:219,shift:!1};var a=function(t){h(t,"keydown")},l=function(t){h(t,"keyup")},h=function(t,e){if(void 0!==r[e][t.keyCode]){for(var n=r[e][t.keyCode],o=0;o700&&(this.body.emitter.emit("fit",{duration:700}),this.touchTime=(new Date).valueOf())}},{key:"_stopMovement",value:function(){for(var t in this.boundFunctions)Object.prototype.hasOwnProperty.call(this.boundFunctions,t)&&(this.body.emitter.off("initRedraw",this.boundFunctions[t]),this.body.emitter.emit("_stopRendering"));this.boundFunctions={}}},{key:"_moveUp",value:function(){this.body.view.translation.y+=this.options.keyboard.speed.y}},{key:"_moveDown",value:function(){this.body.view.translation.y-=this.options.keyboard.speed.y}},{key:"_moveLeft",value:function(){this.body.view.translation.x+=this.options.keyboard.speed.x}},{key:"_moveRight",value:function(){this.body.view.translation.x-=this.options.keyboard.speed.x}},{key:"_zoomIn",value:function(){var t=this.body.view.scale,e=this.body.view.scale*(1+this.options.keyboard.speed.zoom),i=this.body.view.translation,n=e/t,o=(1-n)*this.canvas.canvasViewCenter.x+i.x*n,r=(1-n)*this.canvas.canvasViewCenter.y+i.y*n;this.body.view.scale=e,this.body.view.translation={x:o,y:r},this.body.emitter.emit("zoom",{direction:"+",scale:this.body.view.scale,pointer:null})}},{key:"_zoomOut",value:function(){var t=this.body.view.scale,e=this.body.view.scale/(1+this.options.keyboard.speed.zoom),i=this.body.view.translation,n=e/t,o=(1-n)*this.canvas.canvasViewCenter.x+i.x*n,r=(1-n)*this.canvas.canvasViewCenter.y+i.y*n;this.body.view.scale=e,this.body.view.translation={x:o,y:r},this.body.emitter.emit("zoom",{direction:"-",scale:this.body.view.scale,pointer:null})}},{key:"configureKeyboardBindings",value:function(){var t,e,i,n,o,r,s,a,l,h,c,d,u,f,p,v,g,y,m,b,w,A,k,E,C=this;(void 0!==this.keycharm&&this.keycharm.destroy(),!0===this.options.keyboard.enabled)&&(!0===this.options.keyboard.bindToWindow?this.keycharm=k3({container:window,preventDefault:!0}):this.keycharm=k3({container:this.canvas.frame,preventDefault:!0}),this.keycharm.reset(),!0===this.activated&&(HF(t=this.keycharm).call(t,"up",(function(){C.bindToRedraw("_moveUp")}),"keydown"),HF(e=this.keycharm).call(e,"down",(function(){C.bindToRedraw("_moveDown")}),"keydown"),HF(i=this.keycharm).call(i,"left",(function(){C.bindToRedraw("_moveLeft")}),"keydown"),HF(n=this.keycharm).call(n,"right",(function(){C.bindToRedraw("_moveRight")}),"keydown"),HF(o=this.keycharm).call(o,"=",(function(){C.bindToRedraw("_zoomIn")}),"keydown"),HF(r=this.keycharm).call(r,"num+",(function(){C.bindToRedraw("_zoomIn")}),"keydown"),HF(s=this.keycharm).call(s,"num-",(function(){C.bindToRedraw("_zoomOut")}),"keydown"),HF(a=this.keycharm).call(a,"-",(function(){C.bindToRedraw("_zoomOut")}),"keydown"),HF(l=this.keycharm).call(l,"[",(function(){C.bindToRedraw("_zoomOut")}),"keydown"),HF(h=this.keycharm).call(h,"]",(function(){C.bindToRedraw("_zoomIn")}),"keydown"),HF(c=this.keycharm).call(c,"pageup",(function(){C.bindToRedraw("_zoomIn")}),"keydown"),HF(d=this.keycharm).call(d,"pagedown",(function(){C.bindToRedraw("_zoomOut")}),"keydown"),HF(u=this.keycharm).call(u,"up",(function(){C.unbindFromRedraw("_moveUp")}),"keyup"),HF(f=this.keycharm).call(f,"down",(function(){C.unbindFromRedraw("_moveDown")}),"keyup"),HF(p=this.keycharm).call(p,"left",(function(){C.unbindFromRedraw("_moveLeft")}),"keyup"),HF(v=this.keycharm).call(v,"right",(function(){C.unbindFromRedraw("_moveRight")}),"keyup"),HF(g=this.keycharm).call(g,"=",(function(){C.unbindFromRedraw("_zoomIn")}),"keyup"),HF(y=this.keycharm).call(y,"num+",(function(){C.unbindFromRedraw("_zoomIn")}),"keyup"),HF(m=this.keycharm).call(m,"num-",(function(){C.unbindFromRedraw("_zoomOut")}),"keyup"),HF(b=this.keycharm).call(b,"-",(function(){C.unbindFromRedraw("_zoomOut")}),"keyup"),HF(w=this.keycharm).call(w,"[",(function(){C.unbindFromRedraw("_zoomOut")}),"keyup"),HF(A=this.keycharm).call(A,"]",(function(){C.unbindFromRedraw("_zoomIn")}),"keyup"),HF(k=this.keycharm).call(k,"pageup",(function(){C.unbindFromRedraw("_zoomIn")}),"keyup"),HF(E=this.keycharm).call(E,"pagedown",(function(){C.unbindFromRedraw("_zoomOut")}),"keyup")))}}]),t}();function C3(t,e){var i=void 0!==aG&&dU(t)||t["@@iterator"];if(!i){if(AG(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return x3(t,e);var n=pG(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return WL(t);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return x3(t,e)}(t))||e){i&&(t=i);var n=0,o=function(){};return{s:o,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function x3(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i50&&(this.drag.pointer=this.getPointer(t.center),this.drag.pinched=!1,this.pinch.scale=this.body.view.scale,this.touchTime=(new Date).valueOf())}},{key:"onTap",value:function(t){var e=this.getPointer(t.center),i=this.selectionHandler.options.multiselect&&(t.changedPointers[0].ctrlKey||t.changedPointers[0].metaKey);this.checkSelectionChanges(e,i),this.selectionHandler.commitAndEmit(e,t),this.selectionHandler.generateClickEvent("click",t,e)}},{key:"onDoubleTap",value:function(t){var e=this.getPointer(t.center);this.selectionHandler.generateClickEvent("doubleClick",t,e)}},{key:"onHold",value:function(t){var e=this.getPointer(t.center),i=this.selectionHandler.options.multiselect;this.checkSelectionChanges(e,i),this.selectionHandler.commitAndEmit(e,t),this.selectionHandler.generateClickEvent("click",t,e),this.selectionHandler.generateClickEvent("hold",t,e)}},{key:"onRelease",value:function(t){if((new Date).valueOf()-this.touchTime>10){var e=this.getPointer(t.center);this.selectionHandler.generateClickEvent("release",t,e),this.touchTime=(new Date).valueOf()}}},{key:"onContext",value:function(t){var e=this.getPointer({x:t.clientX,y:t.clientY});this.selectionHandler.generateClickEvent("oncontext",t,e)}},{key:"checkSelectionChanges",value:function(t){!0===(arguments.length>1&&void 0!==arguments[1]&&arguments[1])?this.selectionHandler.selectAdditionalOnPoint(t):this.selectionHandler.selectOnPoint(t)}},{key:"_determineDifference",value:function(t,e){var i=function(t,e){for(var i=[],n=0;n=o.minX&&i.x<=o.maxX&&i.y>=o.minY&&i.y<=o.maxY}));YG(r).call(r,(function(t){return e.selectionHandler.selectObject(e.body.nodes[t])}));var s=this.getPointer(t.center);this.selectionHandler.commitAndEmit(s,t),this.selectionHandler.generateClickEvent("dragEnd",t,this.getPointer(t.center),void 0,!0),this.body.emitter.emit("_requestRedraw")}else{var a=this.drag.selection;a&&a.length?(YG(a).call(a,(function(t){t.node.options.fixed.x=t.xFixed,t.node.options.fixed.y=t.yFixed})),this.selectionHandler.generateClickEvent("dragEnd",t,this.getPointer(t.center)),this.body.emitter.emit("startSimulation")):(this.selectionHandler.generateClickEvent("dragEnd",t,this.getPointer(t.center),void 0,!0),this.body.emitter.emit("_requestRedraw"))}}},{key:"onPinch",value:function(t){var e=this.getPointer(t.center);this.drag.pinched=!0,void 0===this.pinch.scale&&(this.pinch.scale=1);var i=this.pinch.scale*t.scale;this.zoom(i,e)}},{key:"zoom",value:function(t,e){if(!0===this.options.zoomView){var i=this.body.view.scale;t<1e-5&&(t=1e-5),t>10&&(t=10);var n=void 0;void 0!==this.drag&&!0===this.drag.dragging&&(n=this.canvas.DOMtoCanvas(this.drag.pointer));var o=this.body.view.translation,r=t/i,s=(1-r)*e.x+o.x*r,a=(1-r)*e.y+o.y*r;if(this.body.view.scale=t,this.body.view.translation={x:s,y:a},null!=n){var l=this.canvas.canvasToDOM(n);this.drag.pointer.x=l.x,this.drag.pointer.y=l.y}this.body.emitter.emit("_requestRedraw"),i0&&(this.popupObj=h[c[c.length-1]],r=!0)}if(void 0===this.popupObj&&!1===r){for(var u,f=this.body.edgeIndices,p=this.body.edges,v=[],g=0;g0&&(this.popupObj=p[v[v.length-1]],s="edge")}void 0!==this.popupObj?this.popupObj.id!==o&&(void 0===this.popup&&(this.popup=new cX(this.canvas.frame)),this.popup.popupTargetType=s,this.popup.popupTargetId=this.popupObj.id,this.popup.setPosition(t.x+3,t.y-5),this.popup.setText(this.popupObj.getTitle()),this.popup.show(),this.body.emitter.emit("showPopup",this.popupObj.id)):void 0!==this.popup&&(this.popup.hide(),this.body.emitter.emit("hidePopup"))}},{key:"_checkHidePopup",value:function(t){var e=this.selectionHandler._pointerToPositionObject(t),i=!1;if("node"===this.popup.popupTargetType){if(void 0!==this.body.nodes[this.popup.popupTargetId]&&!0===(i=this.body.nodes[this.popup.popupTargetId].isOverlappingWith(e))){var n=this.selectionHandler.getNodeAt(t);i=void 0!==n&&n.id===this.popup.popupTargetId}}else void 0===this.selectionHandler.getNodeAt(t)&&void 0!==this.body.edges[this.popup.popupTargetId]&&(i=this.body.edges[this.popup.popupTargetId].isOverlappingWith(e));!1===i&&(this.popupObj=void 0,this.popup.hide(),this.body.emitter.emit("hidePopup"))}}]),t}();Z_("Set",(function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}}),g$);var S3=nR(iB.Set),M3=yR,O3=X_,D3=v_.getWeakData,R3=B_,B3=nP,z3=KR,P3=eB,F3=O_,T3=$B,N3=UT.set,j3=UT.getterFor,L3=BQ.find,U3=BQ.findIndex,Q3=M3([].splice),H3=0,V3=function(t){return t.frozen||(t.frozen=new W3)},W3=function(){this.entries=[]},G3=function(t,e){return L3(t.entries,(function(t){return t[0]===e}))};W3.prototype={get:function(t){var e=G3(this,t);if(e)return e[1]},has:function(t){return!!G3(this,t)},set:function(t,e){var i=G3(this,t);i?i[1]=e:this.entries.push([t,e])},delete:function(t){var e=U3(this.entries,(function(e){return e[0]===t}));return~e&&Q3(this.entries,e,1),!!~e}};var K3,q3={getConstructor:function(t,e,i,n){var o=t((function(t,o){R3(t,r),N3(t,{type:e,id:H3++,frozen:void 0}),z3(o)||F3(o,t[n],{that:t,AS_ENTRIES:i})})),r=o.prototype,s=j3(e),a=function(t,e,i){var n=s(t),o=D3(B3(e),!0);return!0===o?V3(n).set(e,i):o[n.id]=i,t};return O3(r,{delete:function(t){var e=s(this);if(!P3(t))return!1;var i=D3(t);return!0===i?V3(e).delete(t):i&&T3(i,e.id)&&delete i[e.id]},has:function(t){var e=s(this);if(!P3(t))return!1;var i=D3(t);return!0===i?V3(e).has(t):i&&T3(i,e.id)}}),O3(r,i?{get:function(t){var e=s(this);if(P3(t)){var i=D3(t);return!0===i?V3(e).get(t):i?i[e.id]:void 0}},set:function(t,e){return a(this,t,e)}}:{add:function(t){return a(this,t,!0)}}),o}},Y3=$X,Z3=rR,J3=yR,X3=X_,_3=v_,$3=Z_,t5=q3,e5=eB,i5=UT.enforce,n5=sR,o5=ET,r5=Object,s5=Array.isArray,a5=r5.isExtensible,l5=r5.isFrozen,h5=r5.isSealed,c5=r5.freeze,d5=r5.seal,u5={},f5={},p5=!Z3.ActiveXObject&&"ActiveXObject"in Z3,v5=function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}},g5=$3("WeakMap",v5,t5),y5=g5.prototype,m5=J3(y5.set);if(o5)if(p5){K3=t5.getConstructor(v5,"WeakMap",!0),_3.enable();var b5=J3(y5.delete),w5=J3(y5.has),A5=J3(y5.get);X3(y5,{delete:function(t){if(e5(t)&&!a5(t)){var e=i5(this);return e.frozen||(e.frozen=new K3),b5(this,t)||e.frozen.delete(t)}return b5(this,t)},has:function(t){if(e5(t)&&!a5(t)){var e=i5(this);return e.frozen||(e.frozen=new K3),w5(this,t)||e.frozen.has(t)}return w5(this,t)},get:function(t){if(e5(t)&&!a5(t)){var e=i5(this);return e.frozen||(e.frozen=new K3),w5(this,t)?A5(this,t):e.frozen.get(t)}return A5(this,t)},set:function(t,e){if(e5(t)&&!a5(t)){var i=i5(this);i.frozen||(i.frozen=new K3),w5(this,t)?m5(this,t,e):i.frozen.set(t,e)}else m5(this,t,e);return this}})}else Y3&&n5((function(){var t=c5([]);return m5(new g5,t,1),!l5(t)}))&&X3(y5,{set:function(t,e){var i;return s5(t)&&(l5(t)?i=u5:h5(t)&&(i=f5)),m5(this,t,e),i===u5&&c5(t),i===f5&&d5(t),this}});var k5,E5,C5,x5,I5,S5=nR(iB.WeakMap);function M5(t,e,i,n){if("a"===i&&!n)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!n:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===i?n:"a"===i?n.call(t):n?n.value:e.get(t)}function O5(t,e,i,n,o){if("function"==typeof e?t!==e||!o:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return e.set(t,i),i}function D5(t,e){var i=void 0!==aG&&dU(t)||t["@@iterator"];if(!i){if(AG(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return R5(t,e);var n=pG(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return WL(t);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return R5(t,e)}(t))||e){i&&(t=i);var n=0,o=function(){};return{s:o,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function R5(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i0&&void 0!==arguments[0]?arguments[0]:function(){};uU(this,t),C5.set(this,new z5),x5.set(this,new z5),I5.set(this,void 0),O5(this,I5,e)}return yW(t,[{key:"sizeNodes",get:function(){return M5(this,C5,"f").size}},{key:"sizeEdges",get:function(){return M5(this,x5,"f").size}},{key:"getNodes",value:function(){return M5(this,C5,"f").getSelection()}},{key:"getEdges",value:function(){return M5(this,x5,"f").getSelection()}},{key:"addNodes",value:function(){var t;(t=M5(this,C5,"f")).add.apply(t,arguments)}},{key:"addEdges",value:function(){var t;(t=M5(this,x5,"f")).add.apply(t,arguments)}},{key:"deleteNodes",value:function(t){M5(this,C5,"f").delete(t)}},{key:"deleteEdges",value:function(t){M5(this,x5,"f").delete(t)}},{key:"clear",value:function(){M5(this,C5,"f").clear(),M5(this,x5,"f").clear()}},{key:"commit",value:function(){for(var t,e,i={nodes:M5(this,C5,"f").commit(),edges:M5(this,x5,"f").commit()},n=arguments.length,o=new Array(n),r=0;r=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function T5(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i4&&void 0!==arguments[4]&&arguments[4],r=this._initBaseEvent(e,i);if(!0===o)r.nodes=[],r.edges=[];else{var s=this.getSelection();r.nodes=s.nodes,r.edges=s.edges}void 0!==n&&(r.previousSelection=n),"click"==t&&(r.items=this.getClickedItems(i)),void 0!==e.controlEdge&&(r.controlEdge=e.controlEdge),this.body.emitter.emit(t,r)}},{key:"selectObject",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.options.selectConnectedEdges;if(void 0!==t){if(t instanceof J1){var i;if(!0===e)(i=this._selectionAccumulator).addEdges.apply(i,sG(t.edges));this._selectionAccumulator.addNodes(t)}else this._selectionAccumulator.addEdges(t);return!0}return!1}},{key:"deselectObject",value:function(t){!0===t.isSelected()&&(t.selected=!1,this._removeFromSelection(t))}},{key:"_getAllNodesOverlappingWith",value:function(t){for(var e=[],i=this.body.nodes,n=0;n1&&void 0!==arguments[1])||arguments[1],i=this._pointerToPositionObject(t),n=this._getAllNodesOverlappingWith(i);return n.length>0?!0===e?this.body.nodes[n[n.length-1]]:n[n.length-1]:void 0}},{key:"_getEdgesOverlappingWith",value:function(t,e){for(var i=this.body.edges,n=0;n1&&void 0!==arguments[1])||arguments[1],i=this.canvas.DOMtoCanvas(t),n=10,o=null,r=this.body.edges,s=0;s0&&(this.generateClickEvent("deselectEdge",e,t,o),i=!0),n.nodes.deleted.length>0&&(this.generateClickEvent("deselectNode",e,t,o),i=!0),n.nodes.added.length>0&&(this.generateClickEvent("selectNode",e,t),i=!0),n.edges.added.length>0&&(this.generateClickEvent("selectEdge",e,t),i=!0),!0===i&&this.generateClickEvent("select",e,t)}},{key:"getSelection",value:function(){return{nodes:this.getSelectedNodeIds(),edges:this.getSelectedEdgeIds()}}},{key:"getSelectedNodes",value:function(){return this._selectionAccumulator.getNodes()}},{key:"getSelectedEdges",value:function(){return this._selectionAccumulator.getEdges()}},{key:"getSelectedNodeIds",value:function(){var t;return MG(t=this._selectionAccumulator.getNodes()).call(t,(function(t){return t.id}))}},{key:"getSelectedEdgeIds",value:function(){var t;return MG(t=this._selectionAccumulator.getEdges()).call(t,(function(t){return t.id}))}},{key:"setSelection",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!t||!t.nodes&&!t.edges)throw new TypeError("Selection must be an object with nodes and/or edges properties");if((e.unselectAll||void 0===e.unselectAll)&&this.unselectAll(),t.nodes){var i,n=F5(t.nodes);try{for(n.s();!(i=n.n()).done;){var o=i.value,r=this.body.nodes[o];if(!r)throw new RangeError('Node with id "'+o+'" not found');this.selectObject(r,e.highlightEdges)}}catch(t){n.e(t)}finally{n.f()}}if(t.edges){var s,a=F5(t.edges);try{for(a.s();!(s=a.n()).done;){var l=s.value,h=this.body.edges[l];if(!h)throw new RangeError('Edge with id "'+l+'" not found');this.selectObject(h)}}catch(t){a.e(t)}finally{a.f()}}this.body.emitter.emit("_requestRedraw"),this._selectionAccumulator.commit()}},{key:"selectNodes",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(!t||void 0===t.length)throw"Selection must be an array with ids";this.setSelection({nodes:t},{highlightEdges:e})}},{key:"selectEdges",value:function(t){if(!t||void 0===t.length)throw"Selection must be an array with ids";this.setSelection({edges:t})}},{key:"updateSelection",value:function(){for(var t in this._selectionAccumulator.getNodes())Object.prototype.hasOwnProperty.call(this.body.nodes,t.id)||this._selectionAccumulator.deleteNodes(t);for(var e in this._selectionAccumulator.getEdges())Object.prototype.hasOwnProperty.call(this.body.edges,e.id)||this._selectionAccumulator.deleteEdges(e)}},{key:"getClickedItems",value:function(t){for(var e=this.canvas.DOMtoCanvas(t),i=[],n=this.body.nodeIndices,o=this.body.nodes,r=n.length-1;r>=0;r--){var s=o[n[r]].getItemsOnPoint(e);i.push.apply(i,s)}for(var a=this.body.edgeIndices,l=this.body.edges,h=a.length-1;h>=0;h--){var c=l[a[h]].getItemsOnPoint(e);i.push.apply(i,c)}return i}}]),t}(),j5=rQ,L5=Math.floor,U5=function(t,e){var i=t.length,n=L5(i/2);return i<8?Q5(t,e):H5(t,U5(j5(t,0,n),e),U5(j5(t,n),e),e)},Q5=function(t,e){for(var i,n,o=t.length,r=1;r0;)t[n]=t[--n];n!==r++&&(t[n]=i)}return t},H5=function(t,e,i,n){for(var o=e.length,r=i.length,s=0,a=0;s3)){if(s7)return!0;if(l7)return l7<603;var t,e,i,n,o="";for(t=65;t<76;t++){switch(e=String.fromCharCode(t),t){case 66:case 69:case 70:case 72:i=3;break;case 68:case 71:i=4;break;default:i=2}for(n=0;n<47;n++)h7.push({k:e+n,v:i})}for(h7.sort((function(t,e){return e.v-t.v})),n=0;ne7(i)?1:-1}}(t)),i=$5(o),n=0;n=0:a>l;l+=h)l in s&&(o=i(o,s[l],l,r));return o}},M7={left:S7(!1),right:S7(!0)},O7="process"===AR(rR.process),D7=M7.left;OP({target:"Array",proto:!0,forced:!O7&&gB>79&&gB<83||!NG("reduce")},{reduce:function(t){var e=arguments.length;return D7(this,t,e,e>1?arguments[1]:void 0)}});var R7=FF("Array").reduce,B7=lB,z7=R7,P7=Array.prototype,F7=function(t){var e=t.reduce;return t===P7||B7(P7,t)&&e===P7.reduce?z7:e},T7=nR(F7);function N7(t){var e=function(){if("undefined"==typeof Reflect||!t1)return!1;if(t1.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(t1(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var i,n=l1(t);if(e){var o=l1(this).constructor;i=t1(n,arguments,o)}else i=n.apply(this,arguments);return s1(this,i)}}var j7=function(){function t(){uU(this,t)}return yW(t,[{key:"abstract",value:function(){throw new Error("Can't instantiate abstract class!")}},{key:"fake_use",value:function(){}},{key:"curveType",value:function(){return this.abstract()}},{key:"getPosition",value:function(t){return this.fake_use(t),this.abstract()}},{key:"setPosition",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0;this.fake_use(t,e,i),this.abstract()}},{key:"getTreeSize",value:function(t){return this.fake_use(t),this.abstract()}},{key:"sort",value:function(t){this.fake_use(t),this.abstract()}},{key:"fix",value:function(t,e){this.fake_use(t,e),this.abstract()}},{key:"shift",value:function(t,e){this.fake_use(t,e),this.abstract()}}]),t}(),L7=function(t){r1(i,t);var e=N7(i);function i(t){var n;return uU(this,i),(n=e.call(this)).layout=t,n}return yW(i,[{key:"curveType",value:function(){return"horizontal"}},{key:"getPosition",value:function(t){return t.x}},{key:"setPosition",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0;void 0!==i&&this.layout.hierarchical.addToOrdering(t,i),t.x=e}},{key:"getTreeSize",value:function(t){var e=this.layout.hierarchical.getTreeSize(this.layout.body.nodes,t);return{min:e.min_x,max:e.max_x}}},{key:"sort",value:function(t){A7(t).call(t,(function(t,e){return t.x-e.x}))}},{key:"fix",value:function(t,e){t.y=this.layout.options.hierarchical.levelSeparation*e,t.options.fixed.y=!0}},{key:"shift",value:function(t,e){this.layout.body.nodes[t].x+=e}}]),i}(j7),U7=function(t){r1(i,t);var e=N7(i);function i(t){var n;return uU(this,i),(n=e.call(this)).layout=t,n}return yW(i,[{key:"curveType",value:function(){return"vertical"}},{key:"getPosition",value:function(t){return t.y}},{key:"setPosition",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0;void 0!==i&&this.layout.hierarchical.addToOrdering(t,i),t.y=e}},{key:"getTreeSize",value:function(t){var e=this.layout.hierarchical.getTreeSize(this.layout.body.nodes,t);return{min:e.min_y,max:e.max_y}}},{key:"sort",value:function(t){A7(t).call(t,(function(t,e){return t.y-e.y}))}},{key:"fix",value:function(t,e){t.x=this.layout.options.hierarchical.levelSeparation*e,t.options.fixed.x=!0}},{key:"shift",value:function(t,e){this.layout.body.nodes[t].y+=e}}]),i}(j7),Q7=BQ.every;OP({target:"Array",proto:!0,forced:!NG("every")},{every:function(t){return Q7(this,t,arguments.length>1?arguments[1]:void 0)}});var H7=FF("Array").every,V7=lB,W7=H7,G7=Array.prototype,K7=function(t){var e=t.every;return t===G7||V7(G7,t)&&e===G7.every?W7:e},q7=nR(K7);function Y7(t,e){var i=void 0!==aG&&dU(t)||t["@@iterator"];if(!i){if(AG(t)||(i=function(t,e){var i;if(!t)return;if("string"==typeof t)return Z7(t,e);var n=pG(i=Object.prototype.toString.call(t)).call(i,8,-1);"Object"===n&&t.constructor&&(n=t.constructor.name);if("Map"===n||"Set"===n)return WL(t);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return Z7(t,e)}(t))||e){i&&(t=i);var n=0,o=function(){};return{s:o,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function Z7(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i=e[n])&&(e[n]=e[i]+1)})),e}function X7(t,e,i,n){var o,r,s=Vq(null),a=T7(o=sG(D0(n).call(n))).call(o,(function(t,e){return t+1+e.edges.length}),0),l=i+"Id",h="to"===i?1:-1,c=Y7(n);try{var d,u=function(){var o=rG(r.value,2),c=o[0],d=o[1];if(!n.has(c)||!t(d))return 0;s[c]=0;for(var u,f,p=[d],v=0,g=function(){var t,o;if(!n.has(c))return 0;var r=s[u.id]+h;if(YG(t=sq(o=u.edges).call(o,(function(t){return t.connected&&t.to!==t.from&&t[i]!==u&&n.has(t.toId)&&n.has(t.fromId)}))).call(t,(function(t){var n=t[l],o=s[n];(null==o||e(r,o))&&(s[n]=r,p.push(t[i]))})),v>a)return{v:{v:J7(n,s)}};++v};u=p.pop();)if(0!==(f=g())&&f)return f.v};for(c.s();!(r=c.n()).done;)if(0!==(d=u())&&d)return d.v}catch(t){c.e(t)}finally{c.f()}return s}var _7=function(){function t(){uU(this,t),this.childrenReference={},this.parentReference={},this.trees={},this.distributionOrdering={},this.levels={},this.distributionIndex={},this.isTree=!1,this.treeIndex=-1}return yW(t,[{key:"addRelation",value:function(t,e){void 0===this.childrenReference[t]&&(this.childrenReference[t]=[]),this.childrenReference[t].push(e),void 0===this.parentReference[e]&&(this.parentReference[e]=[]),this.parentReference[e].push(t)}},{key:"checkIfTree",value:function(){for(var t in this.parentReference)if(this.parentReference[t].length>1)return void(this.isTree=!1);this.isTree=!0}},{key:"numTrees",value:function(){return this.treeIndex+1}},{key:"setTreeIndex",value:function(t,e){void 0!==e&&void 0===this.trees[t.id]&&(this.trees[t.id]=e,this.treeIndex=Math.max(e,this.treeIndex))}},{key:"ensureLevel",value:function(t){void 0===this.levels[t]&&(this.levels[t]=0)}},{key:"getMaxLevel",value:function(t){var e=this,i={};return function t(n){if(void 0!==i[n])return i[n];var o=e.levels[n];if(e.childrenReference[n]){var r=e.childrenReference[n];if(r.length>0)for(var s=0;s0&&(i.levelSeparation*=-1):i.levelSeparation<0&&(i.levelSeparation*=-1),this.setDirectionStrategy(),this.body.emitter.emit("_resetHierarchicalLayout"),this.adaptAllOptionsForHierarchicalLayout(e);if(!0===n)return this.body.emitter.emit("refresh"),FJ(e,this.optionsBackup)}return e}},{key:"_resetRNG",value:function(t){this.initialRandomSeed=t,this._rng=AJ(this.initialRandomSeed)}},{key:"adaptAllOptionsForHierarchicalLayout",value:function(t){if(!0===this.options.hierarchical.enabled){var e=this.optionsBackup.physics;void 0===t.physics||!0===t.physics?(t.physics={enabled:void 0===e.enabled||e.enabled,solver:"hierarchicalRepulsion"},e.enabled=void 0===e.enabled||e.enabled,e.solver=e.solver||"barnesHut"):"object"===fW(t.physics)?(e.enabled=void 0===t.physics.enabled||t.physics.enabled,e.solver=t.physics.solver||"barnesHut",t.physics.solver="hierarchicalRepulsion"):!1!==t.physics&&(e.solver="barnesHut",t.physics={solver:"hierarchicalRepulsion"});var i=this.direction.curveType();if(void 0===t.edges)this.optionsBackup.edges={smooth:{enabled:!0,type:"dynamic"}},t.edges={smooth:!1};else if(void 0===t.edges.smooth)this.optionsBackup.edges={smooth:{enabled:!0,type:"dynamic"}},t.edges.smooth=!1;else if("boolean"==typeof t.edges.smooth)this.optionsBackup.edges={smooth:t.edges.smooth},t.edges.smooth={enabled:t.edges.smooth,type:i};else{var n=t.edges.smooth;void 0!==n.type&&"dynamic"!==n.type&&(i=n.type),this.optionsBackup.edges={smooth:{enabled:void 0===n.enabled||n.enabled,type:void 0===n.type?"dynamic":n.type,roundness:void 0===n.roundness?.5:n.roundness,forceDirection:void 0!==n.forceDirection&&n.forceDirection}},t.edges.smooth={enabled:void 0===n.enabled||n.enabled,type:i,roundness:void 0===n.roundness?.5:n.roundness,forceDirection:void 0!==n.forceDirection&&n.forceDirection}}this.body.emitter.emit("_forceDisableDynamicCurves",i)}return t}},{key:"positionInitially",value:function(t){if(!0!==this.options.hierarchical.enabled){this._resetRNG(this.initialRandomSeed);for(var e=t.length+50,i=0;io){for(var s=t.length;t.length>o&&n<=10;){n+=1;var a=t.length;if(n%3==0?this.body.modules.clustering.clusterBridges(r):this.body.modules.clustering.clusterOutliers(r),a==t.length&&n%3!=0)return this._declusterAll(),this.body.emitter.emit("_layoutFailed"),void console.info("This network could not be positioned by this version of the improved layout algorithm. Please disable improvedLayout for better performance.")}this.body.modules.kamadaKawai.setOptions({springLength:Math.max(150,2*s)})}n>10&&console.info("The clustering didn't succeed within the amount of interations allowed, progressing with partial result."),this.body.modules.kamadaKawai.solve(t,this.body.edgeIndices,!0),this._shiftToCenter();for(var l=0;l0){var t,e,i=!1,n=!1;for(e in this.lastNodeOnLevel={},this.hierarchical=new _7,this.body.nodes)Object.prototype.hasOwnProperty.call(this.body.nodes,e)&&(void 0!==(t=this.body.nodes[e]).options.level?(i=!0,this.hierarchical.levels[e]=t.options.level):n=!0);if(!0===n&&!0===i)throw new Error("To use the hierarchical layout, nodes require either no predefined levels or levels have to be defined for all nodes.");if(!0===n){var o=this.options.hierarchical.sortMethod;"hubsize"===o?this._determineLevelsByHubsize():"directed"===o?this._determineLevelsDirected():"custom"===o&&this._determineLevelsCustomCallback()}for(var r in this.body.nodes)Object.prototype.hasOwnProperty.call(this.body.nodes,r)&&this.hierarchical.ensureLevel(r);var s=this._getDistribution();this._generateMap(),this._placeNodesByHierarchy(s),this._condenseHierarchy(),this._shiftToCenter()}}},{key:"_condenseHierarchy",value:function(){var t=this,e=!1,i={},n=function(e,i){var n=t.hierarchical.trees;for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&n[o]===e&&t.direction.shift(o,i)},o=function(){for(var e=[],i=0;i0)for(var r=0;r1&&void 0!==arguments[1]?arguments[1]:1e9,n=1e9,o=1e9,r=1e9,s=-1e9;for(var a in e)if(Object.prototype.hasOwnProperty.call(e,a)){var l=t.body.nodes[a],h=t.hierarchical.levels[l.id],c=t.direction.getPosition(l),d=rG(t._getSpaceAroundNode(l,e),2),u=d[0],f=d[1];n=Math.min(u,n),o=Math.min(f,o),h<=i&&(r=Math.min(c,r),s=Math.max(c,s))}return[r,s,n,o]},a=function(e,i,n){for(var o=t.hierarchical,r=0;r1)for(var l=0;l2&&void 0!==arguments[2]&&arguments[2],a=t.direction.getPosition(i),l=t.direction.getPosition(n),h=Math.abs(l-a),c=t.options.hierarchical.nodeSpacing;if(h>c){var d={},u={};r(i,d),r(n,u);var f=function(e,i){var n=t.hierarchical.getMaxLevel(e.id),o=t.hierarchical.getMaxLevel(i.id);return Math.min(n,o)}(i,n),p=s(d,f),v=s(u,f),g=p[1],y=v[0],m=v[2];if(Math.abs(g-y)>c){var b=g-y+c;b<-m+c&&(b=-m+c),b<0&&(t._shiftBlock(n.id,b),e=!0,!0===o&&t._centerParent(n))}}},h=function(n,o){for(var a=o.id,l=o.edges,h=t.hierarchical.levels[o.id],c=t.options.hierarchical.levelSeparation*t.options.hierarchical.levelSeparation,d={},u=[],f=0;f0?f=Math.min(u,d-t.options.hierarchical.nodeSpacing):u<0&&(f=-Math.min(-u,c-t.options.hierarchical.nodeSpacing)),0!=f&&(t._shiftBlock(o.id,f),e=!0)}(b),function(i){var n=t.direction.getPosition(o),r=rG(t._getSpaceAroundNode(o),2),s=r[0],a=r[1],l=i-n,h=n;l>0?h=Math.min(n+(a-t.options.hierarchical.nodeSpacing),i):l<0&&(h=Math.max(n-(s-t.options.hierarchical.nodeSpacing),i)),h!==n&&(t.direction.setPosition(o,h),e=!0)}(b=m(n,l))};!0===this.options.hierarchical.blockShifting&&(function(i){var n=t.hierarchical.getLevels();n=oK(n).call(n);for(var o=0;o0&&Math.abs(d)0&&(l=this.direction.getPosition(n[r-1])+a),this.direction.setPosition(s,l,e),this._validatePositionAndContinue(s,e,l),o++}}}}},{key:"_placeBranchNodes",value:function(t,e){var i,n=this.hierarchical.childrenReference[t];if(void 0!==n){for(var o=[],r=0;re&&void 0===this.positionedNodes[a.id]))return;var h=this.options.hierarchical.nodeSpacing,c=void 0;c=0===s?this.direction.getPosition(this.body.nodes[t]):this.direction.getPosition(o[s-1])+h,this.direction.setPosition(a,c,l),this._validatePositionAndContinue(a,l,c)}var d=this._getCenterPosition(o);this.direction.setPosition(this.body.nodes[t],d,e)}}},{key:"_validatePositionAndContinue",value:function(t,e,i){if(this.hierarchical.isTree){if(void 0!==this.lastNodeOnLevel[e]){var n=this.direction.getPosition(this.body.nodes[this.lastNodeOnLevel[e]]);if(i-nt}),"from",t)}(i),this.hierarchical.setMinLevelToZero(this.body.nodes)}},{key:"_generateMap",value:function(){var t=this;this._crawlNetwork((function(e,i){t.hierarchical.levels[i.id]>t.hierarchical.levels[e.id]&&t.hierarchical.addRelation(e.id,i.id)})),this.hierarchical.checkIfTree()}},{key:"_crawlNetwork",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:function(){},i=arguments.length>1?arguments[1]:void 0,n={},o=function i(o,r){if(void 0===n[o.id]){var s;t.hierarchical.setTreeIndex(o,r),n[o.id]=!0;for(var a=t._getActiveEdges(o),l=0;l=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,a=!1;return{s:function(){i=i.call(t)},n:function(){var t=i.next();return s=t.done,t},e:function(t){a=!0,r=t},f:function(){try{s||null==i.return||i.return()}finally{if(a)throw r}}}}function e4(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,n=new Array(e);i0&&!1!==this.options.deleteNode||0===i&&!1!==this.options.deleteEdge)&&(!0===s&&this._createSeperator(4),this._createDeleteButton(r)),this._bindElementEvents(this.closeDiv,HF(t=this.toggleEditMode).call(t,this)),this._temporaryBindEvent("select",HF(e=this.showManipulatorToolbar).call(e,this))}this.body.emitter.emit("_redraw")}},{key:"addNodeMode",value:function(){var t;if(!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="addNode",!0===this.guiEnabled){var e,i=this.options.locales[this.options.locale];this.manipulationDOM={},this._createBackButton(i),this._createSeperator(),this._createDescription(i.addDescription||this.options.locales.en.addDescription),this._bindElementEvents(this.closeDiv,HF(e=this.toggleEditMode).call(e,this))}this._temporaryBindEvent("click",HF(t=this._performAddNode).call(t,this))}},{key:"editNode",value:function(){var t=this;!0!==this.editMode&&this.enableEditMode(),this._clean();var e=this.selectionHandler.getSelectedNodes()[0];if(void 0!==e){if(this.inMode="editNode","function"!=typeof this.options.editNode)throw new Error("No function has been configured to handle the editing of nodes.");if(!0!==e.isCluster){var i=FJ({},e.options,!1);if(i.x=e.x,i.y=e.y,2!==this.options.editNode.length)throw new Error("The function for edit does not support two arguments (data, callback)");this.options.editNode(i,(function(e){null!=e&&"editNode"===t.inMode&&t.body.data.nodes.getDataSet().update(e),t.showManipulatorToolbar()}))}else alert(this.options.locales[this.options.locale].editClusterError||this.options.locales.en.editClusterError)}else this.showManipulatorToolbar()}},{key:"addEdgeMode",value:function(){var t,e,i,n,o;if(!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="addEdge",!0===this.guiEnabled){var r,s=this.options.locales[this.options.locale];this.manipulationDOM={},this._createBackButton(s),this._createSeperator(),this._createDescription(s.edgeDescription||this.options.locales.en.edgeDescription),this._bindElementEvents(this.closeDiv,HF(r=this.toggleEditMode).call(r,this))}this._temporaryBindUI("onTouch",HF(t=this._handleConnect).call(t,this)),this._temporaryBindUI("onDragEnd",HF(e=this._finishConnect).call(e,this)),this._temporaryBindUI("onDrag",HF(i=this._dragControlNode).call(i,this)),this._temporaryBindUI("onRelease",HF(n=this._finishConnect).call(n,this)),this._temporaryBindUI("onDragStart",HF(o=this._dragStartEdge).call(o,this)),this._temporaryBindUI("onHold",(function(){}))}},{key:"editEdgeMode",value:function(){if(!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="editEdge","object"!==fW(this.options.editEdge)||"function"!=typeof this.options.editEdge.editWithoutDrag||(this.edgeBeingEditedId=this.selectionHandler.getSelectedEdgeIds()[0],void 0===this.edgeBeingEditedId)){if(!0===this.guiEnabled){var t,e=this.options.locales[this.options.locale];this.manipulationDOM={},this._createBackButton(e),this._createSeperator(),this._createDescription(e.editEdgeDescription||this.options.locales.en.editEdgeDescription),this._bindElementEvents(this.closeDiv,HF(t=this.toggleEditMode).call(t,this))}if(this.edgeBeingEditedId=this.selectionHandler.getSelectedEdgeIds()[0],void 0!==this.edgeBeingEditedId){var i,n,o,r,s=this.body.edges[this.edgeBeingEditedId],a=this._getNewTargetNode(s.from.x,s.from.y),l=this._getNewTargetNode(s.to.x,s.to.y);this.temporaryIds.nodes.push(a.id),this.temporaryIds.nodes.push(l.id),this.body.nodes[a.id]=a,this.body.nodeIndices.push(a.id),this.body.nodes[l.id]=l,this.body.nodeIndices.push(l.id),this._temporaryBindUI("onTouch",HF(i=this._controlNodeTouch).call(i,this)),this._temporaryBindUI("onTap",(function(){})),this._temporaryBindUI("onHold",(function(){})),this._temporaryBindUI("onDragStart",HF(n=this._controlNodeDragStart).call(n,this)),this._temporaryBindUI("onDrag",HF(o=this._controlNodeDrag).call(o,this)),this._temporaryBindUI("onDragEnd",HF(r=this._controlNodeDragEnd).call(r,this)),this._temporaryBindUI("onMouseMove",(function(){})),this._temporaryBindEvent("beforeDrawing",(function(t){var e=s.edgeType.findBorderPositions(t);!1===a.selected&&(a.x=e.from.x,a.y=e.from.y),!1===l.selected&&(l.x=e.to.x,l.y=e.to.y)})),this.body.emitter.emit("_redraw")}else this.showManipulatorToolbar()}else{var h=this.body.edges[this.edgeBeingEditedId];this._performEditEdge(h.from.id,h.to.id)}}},{key:"deleteSelected",value:function(){var t=this;!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="delete";var e=this.selectionHandler.getSelectedNodeIds(),i=this.selectionHandler.getSelectedEdgeIds(),n=void 0;if(e.length>0){for(var o=0;o0&&"function"==typeof this.options.deleteEdge&&(n=this.options.deleteEdge);if("function"==typeof n){var r={nodes:e,edges:i};if(2!==n.length)throw new Error("The function for delete does not support two arguments (data, callback)");n(r,(function(e){null!=e&&"delete"===t.inMode?(t.body.data.edges.getDataSet().remove(e.edges),t.body.data.nodes.getDataSet().remove(e.nodes),t.body.emitter.emit("startSimulation"),t.showManipulatorToolbar()):(t.body.emitter.emit("startSimulation"),t.showManipulatorToolbar())}))}else this.body.data.edges.getDataSet().remove(i),this.body.data.nodes.getDataSet().remove(e),this.body.emitter.emit("startSimulation"),this.showManipulatorToolbar()}},{key:"_setup",value:function(){!0===this.options.enabled?(this.guiEnabled=!0,this._createWrappers(),!1===this.editMode?this._createEditButton():this.showManipulatorToolbar()):(this._removeManipulationDOM(),this.guiEnabled=!1)}},{key:"_createWrappers",value:function(){var t,e;(void 0===this.manipulationDiv&&(this.manipulationDiv=document.createElement("div"),this.manipulationDiv.className="vis-manipulation",!0===this.editMode?this.manipulationDiv.style.display="block":this.manipulationDiv.style.display="none",this.canvas.frame.appendChild(this.manipulationDiv)),void 0===this.editModeDiv&&(this.editModeDiv=document.createElement("div"),this.editModeDiv.className="vis-edit-mode",!0===this.editMode?this.editModeDiv.style.display="none":this.editModeDiv.style.display="block",this.canvas.frame.appendChild(this.editModeDiv)),void 0===this.closeDiv)&&(this.closeDiv=document.createElement("button"),this.closeDiv.className="vis-close",this.closeDiv.setAttribute("aria-label",null!==(t=null===(e=this.options.locales[this.options.locale])||void 0===e?void 0:e.close)&&void 0!==t?t:this.options.locales.en.close),this.closeDiv.style.display=this.manipulationDiv.style.display,this.canvas.frame.appendChild(this.closeDiv))}},{key:"_getNewTargetNode",value:function(t,e){var i=FJ({},this.options.controlNodeStyle);i.id="targetNode"+d3(),i.hidden=!1,i.physics=!1,i.x=t,i.y=e;var n=this.body.functions.createNode(i);return n.shape.boundingBox={left:t,right:t,top:e,bottom:e},n}},{key:"_createEditButton",value:function(){var t;this._clean(),this.manipulationDOM={},MJ(this.editModeDiv);var e=this.options.locales[this.options.locale],i=this._createButton("editMode","vis-edit vis-edit-mode",e.edit||this.options.locales.en.edit);this.editModeDiv.appendChild(i),this._bindElementEvents(i,HF(t=this.toggleEditMode).call(t,this))}},{key:"_clean",value:function(){this.inMode=!1,!0===this.guiEnabled&&(MJ(this.editModeDiv),MJ(this.manipulationDiv),this._cleanupDOMEventListeners()),this._cleanupTemporaryNodesAndEdges(),this._unbindTemporaryUIs(),this._unbindTemporaryEvents(),this.body.emitter.emit("restorePhysics")}},{key:"_cleanupDOMEventListeners",value:function(){var t,e,i=t4(IK(t=this._domEventListenerCleanupQueue).call(t,0));try{for(i.s();!(e=i.n()).done;){(0,e.value)()}}catch(t){i.e(t)}finally{i.f()}}},{key:"_removeManipulationDOM",value:function(){this._clean(),MJ(this.manipulationDiv),MJ(this.editModeDiv),MJ(this.closeDiv),this.manipulationDiv&&this.canvas.frame.removeChild(this.manipulationDiv),this.editModeDiv&&this.canvas.frame.removeChild(this.editModeDiv),this.closeDiv&&this.canvas.frame.removeChild(this.closeDiv),this.manipulationDiv=void 0,this.editModeDiv=void 0,this.closeDiv=void 0}},{key:"_createSeperator",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1;this.manipulationDOM["seperatorLineDiv"+t]=document.createElement("div"),this.manipulationDOM["seperatorLineDiv"+t].className="vis-separator-line",this.manipulationDiv.appendChild(this.manipulationDOM["seperatorLineDiv"+t])}},{key:"_createAddNodeButton",value:function(t){var e,i=this._createButton("addNode","vis-add",t.addNode||this.options.locales.en.addNode);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,HF(e=this.addNodeMode).call(e,this))}},{key:"_createAddEdgeButton",value:function(t){var e,i=this._createButton("addEdge","vis-connect",t.addEdge||this.options.locales.en.addEdge);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,HF(e=this.addEdgeMode).call(e,this))}},{key:"_createEditNodeButton",value:function(t){var e,i=this._createButton("editNode","vis-edit",t.editNode||this.options.locales.en.editNode);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,HF(e=this.editNode).call(e,this))}},{key:"_createEditEdgeButton",value:function(t){var e,i=this._createButton("editEdge","vis-edit",t.editEdge||this.options.locales.en.editEdge);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,HF(e=this.editEdgeMode).call(e,this))}},{key:"_createDeleteButton",value:function(t){var e,i;i=this.options.rtl?"vis-delete-rtl":"vis-delete";var n=this._createButton("delete",i,t.del||this.options.locales.en.del);this.manipulationDiv.appendChild(n),this._bindElementEvents(n,HF(e=this.deleteSelected).call(e,this))}},{key:"_createBackButton",value:function(t){var e,i=this._createButton("back","vis-back",t.back||this.options.locales.en.back);this.manipulationDiv.appendChild(i),this._bindElementEvents(i,HF(e=this.showManipulatorToolbar).call(e,this))}},{key:"_createButton",value:function(t,e,i){var n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"vis-label";return this.manipulationDOM[t+"Div"]=document.createElement("button"),this.manipulationDOM[t+"Div"].className="vis-button "+e,this.manipulationDOM[t+"Label"]=document.createElement("div"),this.manipulationDOM[t+"Label"].className=n,this.manipulationDOM[t+"Label"].innerText=i,this.manipulationDOM[t+"Div"].appendChild(this.manipulationDOM[t+"Label"]),this.manipulationDOM[t+"Div"]}},{key:"_createDescription",value:function(t){this.manipulationDOM.descriptionLabel=document.createElement("div"),this.manipulationDOM.descriptionLabel.className="vis-none",this.manipulationDOM.descriptionLabel.innerText=t,this.manipulationDiv.appendChild(this.manipulationDOM.descriptionLabel)}},{key:"_temporaryBindEvent",value:function(t,e){this.temporaryEventFunctions.push({event:t,boundFunction:e}),this.body.emitter.on(t,e)}},{key:"_temporaryBindUI",value:function(t,e){if(void 0===this.body.eventListeners[t])throw new Error("This UI function does not exist. Typo? You tried: "+t+" possible are: "+qq(RG(this.body.eventListeners)));this.temporaryUIFunctions[t]=this.body.eventListeners[t],this.body.eventListeners[t]=e}},{key:"_unbindTemporaryUIs",value:function(){for(var t in this.temporaryUIFunctions)Object.prototype.hasOwnProperty.call(this.temporaryUIFunctions,t)&&(this.body.eventListeners[t]=this.temporaryUIFunctions[t],delete this.temporaryUIFunctions[t]);this.temporaryUIFunctions={}}},{key:"_unbindTemporaryEvents",value:function(){for(var t=0;t=0;s--)if(o[s]!==this.selectedControlNode.id){r=this.body.nodes[o[s]];break}if(void 0!==r&&void 0!==this.selectedControlNode)if(!0===r.isCluster)alert(this.options.locales[this.options.locale].createEdgeError||this.options.locales.en.createEdgeError);else{var a=this.body.nodes[this.temporaryIds.nodes[0]];this.selectedControlNode.id===a.id?this._performEditEdge(r.id,n.to.id):this._performEditEdge(n.from.id,r.id)}else n.updateEdgeType(),this.body.emitter.emit("restorePhysics");this.body.emitter.emit("_redraw")}}},{key:"_handleConnect",value:function(t){if((new Date).valueOf()-this.touchTime>100){this.lastTouch=this.body.functions.getPointer(t.center),this.lastTouch.translation=wF({},this.body.view.translation),this.interactionHandler.drag.pointer=this.lastTouch,this.interactionHandler.drag.translation=this.lastTouch.translation;var e=this.lastTouch,i=this.selectionHandler.getNodeAt(e);if(void 0!==i)if(!0===i.isCluster)alert(this.options.locales[this.options.locale].createEdgeError||this.options.locales.en.createEdgeError);else{var n=this._getNewTargetNode(i.x,i.y);this.body.nodes[n.id]=n,this.body.nodeIndices.push(n.id);var o=this.body.functions.createEdge({id:"connectionEdge"+d3(),from:i.id,to:n.id,physics:!1,smooth:{enabled:!0,type:"continuous",roundness:.5}});this.body.edges[o.id]=o,this.body.edgeIndices.push(o.id),this.temporaryIds.nodes.push(n.id),this.temporaryIds.edges.push(o.id)}this.touchTime=(new Date).valueOf()}}},{key:"_dragControlNode",value:function(t){var e=this.body.functions.getPointer(t.center),i=this.selectionHandler._pointerToPositionObject(e),n=void 0;void 0!==this.temporaryIds.edges[0]&&(n=this.body.edges[this.temporaryIds.edges[0]].fromId);for(var o=this.selectionHandler._getAllNodesOverlappingWith(i),r=void 0,s=o.length-1;s>=0;s--){var a;if(-1===Lq(a=this.temporaryIds.nodes).call(a,o[s])){r=this.body.nodes[o[s]];break}}if(t.controlEdge={from:n,to:r?r.id:void 0},this.selectionHandler.generateClickEvent("controlNodeDragging",t,e),void 0!==this.temporaryIds.nodes[0]){var l=this.body.nodes[this.temporaryIds.nodes[0]];l.x=this.canvas._XconvertDOMtoCanvas(e.x),l.y=this.canvas._YconvertDOMtoCanvas(e.y),this.body.emitter.emit("_redraw")}else this.interactionHandler.onDrag(t)}},{key:"_finishConnect",value:function(t){var e=this.body.functions.getPointer(t.center),i=this.selectionHandler._pointerToPositionObject(e),n=void 0;void 0!==this.temporaryIds.edges[0]&&(n=this.body.edges[this.temporaryIds.edges[0]].fromId);for(var o=this.selectionHandler._getAllNodesOverlappingWith(i),r=void 0,s=o.length-1;s>=0;s--){var a;if(-1===Lq(a=this.temporaryIds.nodes).call(a,o[s])){r=this.body.nodes[o[s]];break}}this._cleanupTemporaryNodesAndEdges(),void 0!==r&&(!0===r.isCluster?alert(this.options.locales[this.options.locale].createEdgeError||this.options.locales.en.createEdgeError):void 0!==this.body.nodes[n]&&void 0!==this.body.nodes[r.id]&&this._performAddEdge(n,r.id)),t.controlEdge={from:n,to:r?r.id:void 0},this.selectionHandler.generateClickEvent("controlNodeDragEnd",t,e),this.body.emitter.emit("_redraw")}},{key:"_dragStartEdge",value:function(t){var e=this.lastTouch;this.selectionHandler.generateClickEvent("dragStart",t,e,void 0,!0)}},{key:"_performAddNode",value:function(t){var e=this,i={id:d3(),x:t.pointer.canvas.x,y:t.pointer.canvas.y,label:"new"};if("function"==typeof this.options.addNode){if(2!==this.options.addNode.length)throw this.showManipulatorToolbar(),new Error("The function for add does not support two arguments (data,callback)");this.options.addNode(i,(function(t){null!=t&&"addNode"===e.inMode&&e.body.data.nodes.getDataSet().add(t),e.showManipulatorToolbar()}))}else this.body.data.nodes.getDataSet().add(i),this.showManipulatorToolbar()}},{key:"_performAddEdge",value:function(t,e){var i=this,n={from:t,to:e};if("function"==typeof this.options.addEdge){if(2!==this.options.addEdge.length)throw new Error("The function for connect does not support two arguments (data,callback)");this.options.addEdge(n,(function(t){null!=t&&"addEdge"===i.inMode&&(i.body.data.edges.getDataSet().add(t),i.selectionHandler.unselectAll(),i.showManipulatorToolbar())}))}else this.body.data.edges.getDataSet().add(n),this.selectionHandler.unselectAll(),this.showManipulatorToolbar()}},{key:"_performEditEdge",value:function(t,e){var i=this,n={id:this.edgeBeingEditedId,from:t,to:e,label:this.body.data.edges.get(this.edgeBeingEditedId).label},o=this.options.editEdge;if("object"===fW(o)&&(o=o.editWithoutDrag),"function"==typeof o){if(2!==o.length)throw new Error("The function for edit does not support two arguments (data, callback)");o(n,(function(t){null==t||"editEdge"!==i.inMode?(i.body.edges[n.id].updateEdgeType(),i.body.emitter.emit("_redraw"),i.showManipulatorToolbar()):(i.body.data.edges.getDataSet().update(t),i.selectionHandler.unselectAll(),i.showManipulatorToolbar())}))}else this.body.data.edges.getDataSet().update(n),this.selectionHandler.unselectAll(),this.showManipulatorToolbar()}}]),t}(),n4="string",o4="boolean",r4="number",s4="array",a4="object",l4=["arrow","bar","box","circle","crow","curve","diamond","image","inv_curve","inv_triangle","triangle","vee"],h4={borderWidth:{number:r4},borderWidthSelected:{number:r4,undefined:"undefined"},brokenImage:{string:n4,undefined:"undefined"},chosen:{label:{boolean:o4,function:"function"},node:{boolean:o4,function:"function"},__type__:{object:a4,boolean:o4}},color:{border:{string:n4},background:{string:n4},highlight:{border:{string:n4},background:{string:n4},__type__:{object:a4,string:n4}},hover:{border:{string:n4},background:{string:n4},__type__:{object:a4,string:n4}},__type__:{object:a4,string:n4}},opacity:{number:r4,undefined:"undefined"},fixed:{x:{boolean:o4},y:{boolean:o4},__type__:{object:a4,boolean:o4}},font:{align:{string:n4},color:{string:n4},size:{number:r4},face:{string:n4},background:{string:n4},strokeWidth:{number:r4},strokeColor:{string:n4},vadjust:{number:r4},multi:{boolean:o4,string:n4},bold:{color:{string:n4},size:{number:r4},face:{string:n4},mod:{string:n4},vadjust:{number:r4},__type__:{object:a4,string:n4}},boldital:{color:{string:n4},size:{number:r4},face:{string:n4},mod:{string:n4},vadjust:{number:r4},__type__:{object:a4,string:n4}},ital:{color:{string:n4},size:{number:r4},face:{string:n4},mod:{string:n4},vadjust:{number:r4},__type__:{object:a4,string:n4}},mono:{color:{string:n4},size:{number:r4},face:{string:n4},mod:{string:n4},vadjust:{number:r4},__type__:{object:a4,string:n4}},__type__:{object:a4,string:n4}},group:{string:n4,number:r4,undefined:"undefined"},heightConstraint:{minimum:{number:r4},valign:{string:n4},__type__:{object:a4,boolean:o4,number:r4}},hidden:{boolean:o4},icon:{face:{string:n4},code:{string:n4},size:{number:r4},color:{string:n4},weight:{string:n4,number:r4},__type__:{object:a4}},id:{string:n4,number:r4},image:{selected:{string:n4,undefined:"undefined"},unselected:{string:n4,undefined:"undefined"},__type__:{object:a4,string:n4}},imagePadding:{top:{number:r4},right:{number:r4},bottom:{number:r4},left:{number:r4},__type__:{object:a4,number:r4}},label:{string:n4,undefined:"undefined"},labelHighlightBold:{boolean:o4},level:{number:r4,undefined:"undefined"},margin:{top:{number:r4},right:{number:r4},bottom:{number:r4},left:{number:r4},__type__:{object:a4,number:r4}},mass:{number:r4},physics:{boolean:o4},scaling:{min:{number:r4},max:{number:r4},label:{enabled:{boolean:o4},min:{number:r4},max:{number:r4},maxVisible:{number:r4},drawThreshold:{number:r4},__type__:{object:a4,boolean:o4}},customScalingFunction:{function:"function"},__type__:{object:a4}},shadow:{enabled:{boolean:o4},color:{string:n4},size:{number:r4},x:{number:r4},y:{number:r4},__type__:{object:a4,boolean:o4}},shape:{string:["custom","ellipse","circle","database","box","text","image","circularImage","diamond","dot","star","triangle","triangleDown","square","icon","hexagon"]},ctxRenderer:{function:"function"},shapeProperties:{borderDashes:{boolean:o4,array:s4},borderRadius:{number:r4},interpolation:{boolean:o4},useImageSize:{boolean:o4},useBorderWithImage:{boolean:o4},coordinateOrigin:{string:["center","top-left"]},__type__:{object:a4}},size:{number:r4},title:{string:n4,dom:"dom",undefined:"undefined"},value:{number:r4,undefined:"undefined"},widthConstraint:{minimum:{number:r4},maximum:{number:r4},__type__:{object:a4,boolean:o4,number:r4}},x:{number:r4},y:{number:r4},__type__:{object:a4}},c4={configure:{enabled:{boolean:o4},filter:{boolean:o4,string:n4,array:s4,function:"function"},container:{dom:"dom"},showButton:{boolean:o4},__type__:{object:a4,boolean:o4,string:n4,array:s4,function:"function"}},edges:{arrows:{to:{enabled:{boolean:o4},scaleFactor:{number:r4},type:{string:l4},imageHeight:{number:r4},imageWidth:{number:r4},src:{string:n4},__type__:{object:a4,boolean:o4}},middle:{enabled:{boolean:o4},scaleFactor:{number:r4},type:{string:l4},imageWidth:{number:r4},imageHeight:{number:r4},src:{string:n4},__type__:{object:a4,boolean:o4}},from:{enabled:{boolean:o4},scaleFactor:{number:r4},type:{string:l4},imageWidth:{number:r4},imageHeight:{number:r4},src:{string:n4},__type__:{object:a4,boolean:o4}},__type__:{string:["from","to","middle"],object:a4}},endPointOffset:{from:{number:r4},to:{number:r4},__type__:{object:a4,number:r4}},arrowStrikethrough:{boolean:o4},background:{enabled:{boolean:o4},color:{string:n4},size:{number:r4},dashes:{boolean:o4,array:s4},__type__:{object:a4,boolean:o4}},chosen:{label:{boolean:o4,function:"function"},edge:{boolean:o4,function:"function"},__type__:{object:a4,boolean:o4}},color:{color:{string:n4},highlight:{string:n4},hover:{string:n4},inherit:{string:["from","to","both"],boolean:o4},opacity:{number:r4},__type__:{object:a4,string:n4}},dashes:{boolean:o4,array:s4},font:{color:{string:n4},size:{number:r4},face:{string:n4},background:{string:n4},strokeWidth:{number:r4},strokeColor:{string:n4},align:{string:["horizontal","top","middle","bottom"]},vadjust:{number:r4},multi:{boolean:o4,string:n4},bold:{color:{string:n4},size:{number:r4},face:{string:n4},mod:{string:n4},vadjust:{number:r4},__type__:{object:a4,string:n4}},boldital:{color:{string:n4},size:{number:r4},face:{string:n4},mod:{string:n4},vadjust:{number:r4},__type__:{object:a4,string:n4}},ital:{color:{string:n4},size:{number:r4},face:{string:n4},mod:{string:n4},vadjust:{number:r4},__type__:{object:a4,string:n4}},mono:{color:{string:n4},size:{number:r4},face:{string:n4},mod:{string:n4},vadjust:{number:r4},__type__:{object:a4,string:n4}},__type__:{object:a4,string:n4}},hidden:{boolean:o4},hoverWidth:{function:"function",number:r4},label:{string:n4,undefined:"undefined"},labelHighlightBold:{boolean:o4},length:{number:r4,undefined:"undefined"},physics:{boolean:o4},scaling:{min:{number:r4},max:{number:r4},label:{enabled:{boolean:o4},min:{number:r4},max:{number:r4},maxVisible:{number:r4},drawThreshold:{number:r4},__type__:{object:a4,boolean:o4}},customScalingFunction:{function:"function"},__type__:{object:a4}},selectionWidth:{function:"function",number:r4},selfReferenceSize:{number:r4},selfReference:{size:{number:r4},angle:{number:r4},renderBehindTheNode:{boolean:o4},__type__:{object:a4}},shadow:{enabled:{boolean:o4},color:{string:n4},size:{number:r4},x:{number:r4},y:{number:r4},__type__:{object:a4,boolean:o4}},smooth:{enabled:{boolean:o4},type:{string:["dynamic","continuous","discrete","diagonalCross","straightCross","horizontal","vertical","curvedCW","curvedCCW","cubicBezier"]},roundness:{number:r4},forceDirection:{string:["horizontal","vertical","none"],boolean:o4},__type__:{object:a4,boolean:o4}},title:{string:n4,undefined:"undefined"},width:{number:r4},widthConstraint:{maximum:{number:r4},__type__:{object:a4,boolean:o4,number:r4}},value:{number:r4,undefined:"undefined"},__type__:{object:a4}},groups:{useDefaultGroups:{boolean:o4},__any__:h4,__type__:{object:a4}},interaction:{dragNodes:{boolean:o4},dragView:{boolean:o4},hideEdgesOnDrag:{boolean:o4},hideEdgesOnZoom:{boolean:o4},hideNodesOnDrag:{boolean:o4},hover:{boolean:o4},keyboard:{enabled:{boolean:o4},speed:{x:{number:r4},y:{number:r4},zoom:{number:r4},__type__:{object:a4}},bindToWindow:{boolean:o4},autoFocus:{boolean:o4},__type__:{object:a4,boolean:o4}},multiselect:{boolean:o4},navigationButtons:{boolean:o4},selectable:{boolean:o4},selectConnectedEdges:{boolean:o4},hoverConnectedEdges:{boolean:o4},tooltipDelay:{number:r4},zoomView:{boolean:o4},zoomSpeed:{number:r4},__type__:{object:a4}},layout:{randomSeed:{undefined:"undefined",number:r4,string:n4},improvedLayout:{boolean:o4},clusterThreshold:{number:r4},hierarchical:{enabled:{boolean:o4},levelSeparation:{number:r4},nodeSpacing:{number:r4},treeSpacing:{number:r4},blockShifting:{boolean:o4},edgeMinimization:{boolean:o4},parentCentralization:{boolean:o4},direction:{string:["UD","DU","LR","RL"]},sortMethod:{string:["hubsize","directed"]},shakeTowards:{string:["leaves","roots"]},__type__:{object:a4,boolean:o4}},__type__:{object:a4}},manipulation:{enabled:{boolean:o4},initiallyActive:{boolean:o4},addNode:{boolean:o4,function:"function"},addEdge:{boolean:o4,function:"function"},editNode:{function:"function"},editEdge:{editWithoutDrag:{function:"function"},__type__:{object:a4,boolean:o4,function:"function"}},deleteNode:{boolean:o4,function:"function"},deleteEdge:{boolean:o4,function:"function"},controlNodeStyle:h4,__type__:{object:a4,boolean:o4}},nodes:h4,physics:{enabled:{boolean:o4},barnesHut:{theta:{number:r4},gravitationalConstant:{number:r4},centralGravity:{number:r4},springLength:{number:r4},springConstant:{number:r4},damping:{number:r4},avoidOverlap:{number:r4},__type__:{object:a4}},forceAtlas2Based:{theta:{number:r4},gravitationalConstant:{number:r4},centralGravity:{number:r4},springLength:{number:r4},springConstant:{number:r4},damping:{number:r4},avoidOverlap:{number:r4},__type__:{object:a4}},repulsion:{centralGravity:{number:r4},springLength:{number:r4},springConstant:{number:r4},nodeDistance:{number:r4},damping:{number:r4},__type__:{object:a4}},hierarchicalRepulsion:{centralGravity:{number:r4},springLength:{number:r4},springConstant:{number:r4},nodeDistance:{number:r4},damping:{number:r4},avoidOverlap:{number:r4},__type__:{object:a4}},maxVelocity:{number:r4},minVelocity:{number:r4},solver:{string:["barnesHut","repulsion","hierarchicalRepulsion","forceAtlas2Based"]},stabilization:{enabled:{boolean:o4},iterations:{number:r4},updateInterval:{number:r4},onlyDynamicEdges:{boolean:o4},fit:{boolean:o4},__type__:{object:a4,boolean:o4}},timestep:{number:r4},adaptiveTimestep:{boolean:o4},wind:{x:{number:r4},y:{number:r4},__type__:{object:a4}},__type__:{object:a4,boolean:o4}},autoResize:{boolean:o4},clickToUse:{boolean:o4},locale:{string:n4},locales:{__any__:{any:"any"},__type__:{object:a4}},height:{string:n4},width:{string:n4},__type__:{object:a4}},d4={nodes:{borderWidth:[1,0,10,1],borderWidthSelected:[2,0,10,1],color:{border:["color","#2B7CE9"],background:["color","#97C2FC"],highlight:{border:["color","#2B7CE9"],background:["color","#D2E5FF"]},hover:{border:["color","#2B7CE9"],background:["color","#D2E5FF"]}},opacity:[0,0,1,.1],fixed:{x:!1,y:!1},font:{color:["color","#343434"],size:[14,0,100,1],face:["arial","verdana","tahoma"],background:["color","none"],strokeWidth:[0,0,50,1],strokeColor:["color","#ffffff"]},hidden:!1,labelHighlightBold:!0,physics:!0,scaling:{min:[10,0,200,1],max:[30,0,200,1],label:{enabled:!1,min:[14,0,200,1],max:[30,0,200,1],maxVisible:[30,0,200,1],drawThreshold:[5,0,20,1]}},shadow:{enabled:!1,color:"rgba(0,0,0,0.5)",size:[10,0,20,1],x:[5,-30,30,1],y:[5,-30,30,1]},shape:["ellipse","box","circle","database","diamond","dot","square","star","text","triangle","triangleDown","hexagon"],shapeProperties:{borderDashes:!1,borderRadius:[6,0,20,1],interpolation:!0,useImageSize:!1},size:[25,0,200,1]},edges:{arrows:{to:{enabled:!1,scaleFactor:[1,0,3,.05],type:"arrow"},middle:{enabled:!1,scaleFactor:[1,0,3,.05],type:"arrow"},from:{enabled:!1,scaleFactor:[1,0,3,.05],type:"arrow"}},endPointOffset:{from:[0,-10,10,1],to:[0,-10,10,1]},arrowStrikethrough:!0,color:{color:["color","#848484"],highlight:["color","#848484"],hover:["color","#848484"],inherit:["from","to","both",!0,!1],opacity:[1,0,1,.05]},dashes:!1,font:{color:["color","#343434"],size:[14,0,100,1],face:["arial","verdana","tahoma"],background:["color","none"],strokeWidth:[2,0,50,1],strokeColor:["color","#ffffff"],align:["horizontal","top","middle","bottom"]},hidden:!1,hoverWidth:[1.5,0,5,.1],labelHighlightBold:!0,physics:!0,scaling:{min:[1,0,100,1],max:[15,0,100,1],label:{enabled:!0,min:[14,0,200,1],max:[30,0,200,1],maxVisible:[30,0,200,1],drawThreshold:[5,0,20,1]}},selectionWidth:[1.5,0,5,.1],selfReferenceSize:[20,0,200,1],selfReference:{size:[20,0,200,1],angle:[Math.PI/2,-6*Math.PI,6*Math.PI,Math.PI/8],renderBehindTheNode:!0},shadow:{enabled:!1,color:"rgba(0,0,0,0.5)",size:[10,0,20,1],x:[5,-30,30,1],y:[5,-30,30,1]},smooth:{enabled:!0,type:["dynamic","continuous","discrete","diagonalCross","straightCross","horizontal","vertical","curvedCW","curvedCCW","cubicBezier"],forceDirection:["horizontal","vertical","none"],roundness:[.5,0,1,.05]},width:[1,0,30,1]},layout:{hierarchical:{enabled:!1,levelSeparation:[150,20,500,5],nodeSpacing:[100,20,500,5],treeSpacing:[200,20,500,5],blockShifting:!0,edgeMinimization:!0,parentCentralization:!0,direction:["UD","DU","LR","RL"],sortMethod:["hubsize","directed"],shakeTowards:["leaves","roots"]}},interaction:{dragNodes:!0,dragView:!0,hideEdgesOnDrag:!1,hideEdgesOnZoom:!1,hideNodesOnDrag:!1,hover:!1,keyboard:{enabled:!1,speed:{x:[10,0,40,1],y:[10,0,40,1],zoom:[.02,0,.1,.005]},bindToWindow:!0,autoFocus:!0},multiselect:!1,navigationButtons:!1,selectable:!0,selectConnectedEdges:!0,hoverConnectedEdges:!0,tooltipDelay:[300,0,1e3,25],zoomView:!0,zoomSpeed:[1,.1,2,.1]},manipulation:{enabled:!1,initiallyActive:!1},physics:{enabled:!0,barnesHut:{theta:[.5,.1,1,.05],gravitationalConstant:[-2e3,-3e4,0,50],centralGravity:[.3,0,10,.05],springLength:[95,0,500,5],springConstant:[.04,0,1.2,.005],damping:[.09,0,1,.01],avoidOverlap:[0,0,1,.01]},forceAtlas2Based:{theta:[.5,.1,1,.05],gravitationalConstant:[-50,-500,0,1],centralGravity:[.01,0,1,.005],springLength:[95,0,500,5],springConstant:[.08,0,1.2,.005],damping:[.4,0,1,.01],avoidOverlap:[0,0,1,.01]},repulsion:{centralGravity:[.2,0,10,.05],springLength:[200,0,500,5],springConstant:[.05,0,1.2,.005],nodeDistance:[100,0,500,5],damping:[.09,0,1,.01]},hierarchicalRepulsion:{centralGravity:[.2,0,10,.05],springLength:[100,0,500,5],springConstant:[.01,0,1.2,.005],nodeDistance:[120,0,500,5],damping:[.09,0,1,.01],avoidOverlap:[0,0,1,.01]},maxVelocity:[50,0,150,1],minVelocity:[.1,.01,.5,.01],solver:["barnesHut","forceAtlas2Based","repulsion","hierarchicalRepulsion"],timestep:[.5,.01,1,.01],wind:{x:[0,-10,10,.1],y:[0,-10,10,.1]}}},u4=function(t,e,i){var n;return!(!YK(t).call(t,"physics")||!YK(n=d4.physics.solver).call(n,e)||i.physics.solver===e||"wind"===e)},f4=function(){function t(){uU(this,t)}return yW(t,[{key:"getDistances",value:function(t,e,i){for(var n={},o=t.edges,r=0;r2&&void 0!==arguments[2]&&arguments[2],n=this.distanceSolver.getDistances(this.body,t,e);this._createL_matrix(n),this._createK_matrix(n),this._createE_matrix();for(var o=0,r=Math.max(1e3,Math.min(10*this.body.nodeIndices.length,6e3)),s=1e9,a=0,l=0,h=0,c=0,d=0;s>.01&&o1&&d<5;){d+=1,this._moveNode(a,l,h);var f=rG(this._getEnergy(a),3);c=f[0],l=f[1],h=f[2]}}}},{key:"_getHighestEnergyNode",value:function(t){for(var e=this.body.nodeIndices,i=this.body.nodes,n=0,o=e[0],r=0,s=0,a=0;a{var e;let i=t;for(;i;){if(["hui-card-preview","hui-dialog-edit-card"].includes(i.localName))return!0;const t=i.getRootNode();i=null!==(e=i.parentElement)&&void 0!==e?e:t instanceof ShadowRoot?t.host:null}return!1};var y4={Controller:"data:image/png;base64,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",RoomStat:"data:image/png;base64,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",SmartPlug:"data:image/png;base64,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",TemperatureHumiditySensor:"data:image/png;base64,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",iTRV:"data:image/png;base64,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",UnderFloorHeating:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAACgCAYAAACLz2ctAAAY8klEQVR42u2da6gkx3XH/+dUd8/jzn3sal93V1pp9bASaSM7D4wxDtZaAn9IiB2MDQkxKIEkkBCcL/FHy/vRMcQQCARCTBziD14ZY+MQCIYgG+PEkaU4WFo7jqxHWEleaXfvex7dVXXyoXt6ume6Z3qu7oaEnB8I7c5Mz3RXnTrvqgUURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEURVEU5X8ltOwFIkJEJPLGGys4c+b83o0bAiICIgBx9UVRlP4/BphtxGH4c/D+NIdhaOMYAKfvMwgeIvAPhWF43iZWQCAIAAgk+z8AeADifelBpHSjk89KxS15ETBR9l0CzodC4EHIfix9xXsQc/2YeJ89Amd3ln02u07G95fdLxmunYbiN/ip11Dz9/JD0+zfRebPaaOZT+8qewZC+q1n2u32ee/9lWuvvfZ7Dz/8cAIARCS3RQBFhAHItZdffvfI2i8EYXivYQKBCERTX5q+lCQJnPP5L0k6GN47J14EAQew3paGIwzCVqvdhngPGV8jAhHJB0syARIAfiyIAkjVcFa8zsTw3k0kl6g0adl9ggAwM5x3s5MrADGDiOCcm/oKgmGGy+9NYIwBMcM5h2yiSjORj9v0DJXur0p0qDhJ6Wdz2ZOZLyOiwljK9C9W/IrkPyUQUPbXOI7RHwzkZx58kEaj0d8eP3HiifSxyN8uAQyIyL7wgx/8+T0XLvxRf3/fRVFkjDF45nvfw+aZM7jnnnuQJEn+5aM4TgecKJ80gMBMuHbtGlbX1rC2tgbnXD5Yznk47z1lA5oOQDpgAoBEwMzY29/HKI5x4vhxWGsrH6coeJJdNxwMsLO7i9OnTsHPaAcpTBRjOBpie3sHp0+fgnjJR00EYCYMBgPs7+/j1MlT2XMCRAybxLh+/U2cO3cOAiAwBtvb2xgMhzi7uZmPSeUEUPYDBJAAIJ5o88L9EnF+ryJ+cl3pKYpDLwX1MK35BBACUWHECl9Sti7ZXHhP1lp0Oh2548Qd3B8M793c3HxZRLipEAaHsdvW+32bJD4IAnHWifeeTp86jU63i+FgCOssgiBIV5oHINkAUrrqrbWwVtDudBAYg9FwlF0T5uPfDpm9F1gPkBCEJB06AYQ8mBmBiTDyFswGxL5yJacTlk0KEQJjkCQeo2GCIAyRJMmUcqHsOgIbBsEgHiYwHMDBFiZQEJgA8ciifzBEsBnCS3oPxAzmAEnsQWAQA2wMrPUY9EcwxuSfLUpDeh+UCyGBACY4icHZVI21JoHgEMOLA1MApjAVRJqY6cmCJAh5kFBJ7VDJYlOuHHLhpGntnI0npX6RgMHMYpjZJtYbY5aWp0MJIIl0IOBut+uts+S94N777oXzDt55CAG7+3uIwgjWD2F9jIBb6LZ66Ha7SKyFiMfa+jpEPLwXxHGMt27cQDuKIBTipZseJ1cJJ3uEJNM8VFjdiU3AUYJeFGCUDGAQls0sjf1GKem2xCaIVgSnumsYJQdgRPBe8kGWbApEBNY6UJjgzF0biF0fjCgzWelExEmM3nqIlY07MIwP0nsgAbyHcIw7L9wBhyEM2kiSEdbvaGPteAvDuA/DUYUtotILDgm24hdhZYRT0UUQgoJfKzhw1zHwW+jyKfTMmSk3gzHyOxj6bfTMGRiK0nuTCsstdTZgkfHM3KJ8ekRuqwASkQOAdrv9vuFwgFY74jCKUmdegCAwmT/kcf36ddjQ4iX797gZ/xib7V/EI62PQODRbrdyP2S8qtutFl599b9A3mJPVvH91zzuPWFwZo0gFMAw5drMIMSe+yl+ePAlWBni/vav4FT0CJwMsoEheO/hxSMITR68EBgJBnj54Gvouxs4x+/FPa1LSDDItZF4gXMOQdiCwxA/7n8VffcWzkXvwd3txxC7Prz3aIUdDNwN/Kj/JST+APd0Hsdm+G4M7R6YQrwcfx3b9iXcET6E+/jXMMQN/MfwKcR+D/e0H8Mp+iVY6YPIlCY1m1YwGcR+F7H0EfFKydyOtVUqhG9i1ZwtGNaJGCXYBxMjkT4C6kCQlMx5LkZl93ei+KTshwqQ+90ikvu/qWUDWrc7Cn7yySeDy5cv23/97nf/8sLdd/8+E9vRaBRYZ0urRSR1dKMwgkDgvQcTgzkVjOFwiMRaeOdKQYUAaEUR2IR4Y49wrEM43jPY2t5Bv98HM2N6kRUj4zxe8x7dbhdhEGJndyebvIrrCJMIkQjiPaIwwuraKm7dulXyI4kY3jl0u120223c2roFAqfvZdc757C2tgrDBlvb2/n9Hjt2DKPRCP2DPohT//f4sWNgNrO+X66DARGPod8GU4AWr2cBQObJEWPod+BkiJBWEHEv9QNRWGwygJUhWrw+WWBlMa6RhmLkPNarY7NLJT8wiWPptNu0vrEhZMw7NjY2XrxtPuCnP/1pXL58GRvr6z/qra1BrEVvtQcRySNREUm1iHdw3sHaNOIzTCBiGGPQ6/VyDZXGF6ka9+LhnAMT8LOrBC+AgGECA2bOJ1Qmklf2mwqEYYgwDCfXFVISkvlI01GgJ4IJDFqtFowxBZM2GfQgDNP32eQCUzTbYRgiMAGYGYY51ZZRBGdtJnzp661WO7UCpemdfZIWnc2e2ZWECADWcDJNjcBB4AGYksoKZR1Ex+BhCxJH86LMPCgj1ETeMnEeJYvswzCEF4G53RpQRAwRuf7O3l901np/cLCz69iQmQxMKkjifSllMvG1qexIU2ryxip98t9Ei/aHA3Q7bbTCCFIT4eaGS4rfTROnWSa/QTQRwlyAsgAgH/RssryXSbqFygJCRKVFl/7eJM2BTIONv4+Y0mfNJjiKIljvsL9/AGaqCTen00e0OINXFDRJg5I8eBvfXyGyEJlocO99KTWUuklVcljKugkRkXNO2Jh3nD59+sXbGQV7EQl2bt16zAz6sM7mP1PvfgqkxtGdfqP0GhGSJMHe3h6uvvACdra389VmrYX3HkEYQryHsxYmDFP/01okSYIHHngAQRjih1evpprQGEAE1loYk2rUJElAzAiDIMtXOhw7fgz33Xc/nnvuOSATLBMEsEkCay1OnT6Nu+++G889+2yeCgkCgyR7f/PsWZw9exb/9txzYDawNsFDDz8M7z2uXr2KKAzhnMc73/UIzpzZhPceIjRfmKSUXqyNDpoFD/WayBeEcdo1oNl4IFcy+TWt5b3AxgL4/PPPR08//bT/hYsX7xOi+weDIUSERKpFjuYIpZQduMrXCWm6Jh6NsLOzgySO4YxBEIYYjUbw3sMEAeIkQRLH6HBqMuPRKM1DEmFvdxej0QjOObQ7HXjnMBwOcxM7HA4RBAGMMfnnkthiNIox6A9Sc2kMmMepIpd//3A4TM27MWDD+fX9fh/WWgyHQ4RhiNFwhMFgkP95nBs92D8o+VJF01YSJU8VaaVCtJ6ltyb/I9Sk4yuy27Nj7wsJfprK+01Hv7nLRQQSAcUxPfnkk8ELL7zA9WWxMtxUAC9evBhfunTJMofvXN/YMN57myp4KYTj2Y1JWbakEGSMTWKldJZeF1jnMBqNYBOb5dY4/w3OIjDJzMY4wEn/zGi1WhgOh6Asn0bE8D7VaMScrnZKX58MZhrJp6ZVMLaqkucwx1Fg+h5R2SQz8URrmtQjIqaC1qVMbAhxkmQRZFF6xsNZYY6pmEGhsnku/E+KgcIhi2/jbINMXSFZoTL/nfFcpfVZnDx5Mr58+bK9ePFifOQa8Dvf/vYnB4OBDEb9D4VxBKR2foH5nTj5MueDde+NNYm1SVrGIoJ3Lk2TBEFWNXFZRJuaX+/TBK8xBoPBIFvVHoQ0MBoLoXcuE9ii/+nBbOCczUprlJpuCMT7NHDKUjXe+ZI28Nn7Niuzjf1H71Ozz5nQe0k/F8dxungKXlk5L0czlT8qpfDSMklWMMlS47JUdbdKMabB1NiHlpLA19SWyXvxKysdfvaZZz/7uc997pkLFy7gwx/+8GePVABF5DOtVgvtTgeD/gFAxNNaDsWgIFPNeYZ/vKgbFsbHvl2SaYpU46VRZRAEYGPSiJk5z/uNNVrUDhFkvqIxQUk7msDkAmdM+uexsAFAGIWZhjUTofcCEwRpSS0IUm0cBGBiUPbdaRHA5WY7DNOqjsl8zzAMEQZh9n76HEmSVIsKSe2iLomFFP+2nNCNS5q5v1f0NcWnZblc8HzRNS9VRLJrOY5jePEf3dvf/6hzHgA+e6RR8Bf+5gt7YRi0f/1DHyLvnJGpIv9EHU9W0vS3l0z02MQVfJ6JcFIeIVtnYZ2d+Dsym28s/nmcLA2zMpsXn323L5eZss8lSYLt3V10Ox0QEVqtFtqtFkbxqJS2oSwqDoIAQWAwGsWT5xlH3ZlQB2GYajhJswGBCcBBgCSO8+8LwzA305LXu6e8kfw1yc01TwUIVf0vJWGVibksmMx8nIrRu2TJUedcmjIiLjeRSFnUx+6NIF1gW7e27D9+4xtYXe39yxNPPPHLR6oBw8D82eaZM5+KosglcVJYCcVWqeq6+jwzna6k2evHqy+iqJw6qfstKesC8R5RFJUqLnWaYBiP0Ov10Gq1IN6ju9JFK27lAlDqBsmEJQyj3E8ruhDjNFK3250ssOya9rgtrWD280ulOnCYXqSlxd4g5JVi80DRx57pXio8Z+brEnPpvbysTuWuJ0BgmBGEAfUHA3PXXXd++ch9QA54a31tLUtHJLm2qeq7o5mUAE3cWKGK/Nb0cpYZH7xKiGSmnFm+yI0rLVMdIqXridBbWU0DHJ82OQyHI9gkwUx2pJQUc6W2LKlqn5uJOV1pAVHevUIl1w8iC6PVct5Fyl00DfzsOVkzeO/yyHamA6fm+rGAG8Ng4fDoBZAD9t5nUVbNoE/l8yaxlMwOYWW/2qRGVnqd6nvU5t7D1AeqSlAiHq1WlDVF+LxXL09IV7VJNfK4Js9Rl5+TqXJX2rRa8oQX+HDFIRPAS61WbOYhSjm0r+ijlBorNn6WMAjEExr3A/ISHTDtcu2SGjmQ9Z+qM9uFtETFU+cLoMLHrAqI6jJgMt3RXNBKpUZRqR99WuhET55DGjjjRcvaRFiEilpzvqRRk++T6SeThs9ZXKNMRNQ+cgHcPH36+0LoA0QiVVmicraoupRUfLt6qU50AS0Ky5utdKp7X5pNDRU1s1Q+bUV3xCQXKk2zDMVM3oIMQVUXdM2zSGNhzFSFzN64LJa6cUmOgyD46cpK56tHLoDve/TRf7DWvthqtZiYPTHl7ThMphC9cpbspSxxm7XszCRVpXYYpCZR3diMiFRKiMz7bPV2kilZrW4YmJ3d5imRahmlxSlkqfopqRVYmbd3phSclK+hJmOf5g2Fmen48WNvPP7441ePXAC/9pWv/BZBHoqT2BPATJPCu/Npa1UubIWu3rFfJaVoSpaajul9GI3y+9Jw9uteKtlqyf2/+sCzLPTSUOhoSrvOWSoVJlNm3ZXFIzin2WHyAWpqvvMsiHCSJP7mzZuPfOtb3/r4kQch/cHgTmYO4MU55+D9JKfmfdbz533uzIznzYuH8x5EgsCYBmaowdDJ8kJFM0K8IMKsuDmZd+NUmM4F6RHK0znUyLmSqsgD831TaTiONOdTXNc3WPNjzCzWOrN9a/vckWtAJ2LTxLDDiz/5CZzNNtUQ8rLYJP3h8zs3bCZqvlZrZKuZDiec0qAaIFgivYFiS7A0r2MtUQmjSWlo4ToiTLXty2ErvTJdVF6gHQ9X2COi5MgFMIqifhAGEBEk1uZB6FjYxivfZ1spUbbENcJFsyt8kQY4VFAiZSGhBcIns+Z+oUYRaTxReeUDy3gbc5o45mUAZha/zA3Oli/oTbsWgiBge+QCeP369fe89trrMMZQp90ulYbyDHreCcJT/kHzCO3tbJ2u16BUjixknuCVZ18WJG0hiz3XGVkgWhxoULGUhkZaT6oGgsrJ/fzL5TDzMCeGyxoYWmGEg4ODzSMXwI319Y877yUIAr77/HkYw1n9lfP9C/UZieqcBC3aDL2gs02mI1apmZCFMzh25qW2WkANWpYW2zRplJ+hGbNbM2rUcOFOh7TFkuUSecIqyaPCPBERO+/d1s7ubxx5EHL+zrvQ662QtYljIpN1PBQ2NE92S/nCkRnjpqVUYOt6zxZ4t7JI8S9vKmY8QVnuG6jcSAU5koNPKhp2Z8prMmOmaa7TLHVFqHniVeiUGV9EMzvkZrRZeiaHWVlZOX/kAnjvA/f/qiSJjWP7d61W60Qcj4TAeexnAs77yNINOxPhGgtfKa8kMlf7jfvS5k9OvXBSzY656kGnmYY7WeicSd4aR3P747OSXMNolxqkm2p+AvXitZyvV97iSfm+ESnszZ5OEBARBUGw98HHPvA7uwcHP71dm5Job2vrRhS1jsdxnJ5SNL2sZo5zkDldt1iqQXWqajonaKk/lEcaRjcLdaa8zdRNbTfP/Ewj1fmuNHUuTLNETP1hS/nRH1I646OyKUREwjAk59zNs+fOnVhGpniZHXGvvPLKeu4rLUwxSe1OpMXTsnh91kW8MrOvtZnrPr+8NvsBaSB8S+8KIlroG0qT6gvJodL8k0YLmWrAqM83Tt/J1tbWxpUrV8zRNyMQuV6v59gEpX0UM3dDyCsG1Xm1+aMgMkeziRwuE10VlDRN3orMHsrTIDJcJoMohQOYlvYURcopqKY18kqJohnLIIVnbtIZY611H/vYx9yRCyAA3LhxI++Xi5O4orVE5moRWdCYWpeMnimNy7w8IdXvtjtMwYpm88zztKlkyWtqrH9lYQ60dtmJHLLWXNHdNyXIyyygtwPjUFHabKMiKpoXKxNmqN/GWT8RMrsrZ8aplrmVhXIiThY45TRrZ2Xx+XnFr5YGmZFDOenSwIoslVGR2nwTUX3f37J+/ZGejlXc4S/zTJgs6s5b1Fgqc5t9m6RQpKoCMC+tUzrgURpZRarai1F3PzTb/9dok9a02V1wPurCWFjmB07TbmW+DTZfbL5pr8zRCeAJAN5acHbGyfz2T8lrlyLLL9fi/oQqxSYLmoVm3q8wz7UtqyJVmZmayVq+wkPjHYMLnINS81cDaaV5i6/q9IWpNNJ0J2Zx89Hu7i4Gg3SzfqfdQafbSVv3fbrVNN0jc5sFECdOwHtBq91qOCjzBrlBz9LcUkl2fKgcLsMkC3aXNErFFfdNNG44nb9Hurj1UhpomGY9e9XNFySzbVcyJYheBGEQYH9vH6+8+mq6YSuK0n6AzOzeee5OrK72DmWDlzbBHuKddTJZVFIbPcp8w7vg+I75oaQUV7XMydiVqgnztN9s0bXRaAoaHIUxveBkCV9bZovDSwUaxUqG1O5rmc5lF2fPOoeNjQ08EIVZwzEwHI7ATAiCAGtrq7DWeVDKbfYBabXdadP+/n7CzKZ4DrFIGtQQVRy9PN0AWfYvvMwEMfmRbaa8s4Lypodxk4Mh9rX+XJMEsyx1cEVJ5uf6e6U+AJlOa01K2VJ/QFOd0BbHZbbMm15riN2U5PP8+86PBQMD+b8MICLo9XpYW1stmeXsvsVa63q9XrS1vS2j0ciO/yWFoz4ZgQEc3Lpx44+TJPnUysrK5q2trfyQSe8crHPwzksYBjw+iqJ+F9lk1xinKffstIFyslliCyPsZapKUtRwB+TYk9QUB5awCgXfTxpVLeqd/9qFMD7gnNIzqMdd5GPFUXT0q8UkfT/ZHyLi0AtToTFg8r54j0EgJojC1Jxmh7M3OUlLvM96PanamhROxDLMWF1dNaPh8Koh+tPNs2cHTz31FGOyb/VoS3FEJLuvv37SBsGf7OztXer3+3zQ78v+3t7x7Z2dC+12G2EQ/KcJgr2Vbjc7kFvqfCKJooiuv/nmC9vb2693u11iZkl9D8dMxn9//8XffMvv3pXs9tOTBAyPjykAsQECxvs33/XS+dXNbSuudMxtKeigt3l+WfkI1uwrGODsX/XwzXYiCpEYYygejQ5eu3btO0EUpUeNpKZg8s+NZJ0c+b86wtlvMGPFtPDP21f/8CcHr/VokECYgKwrKT2fmtBdW8W71x78p3XfecYDtLq60u12e+9tep9Te3JBU2cDEpGEYQgCdqMo+roH/urixYv7y2i/w5wRLdkhlW8B+GTxvS9+8YsfuXr1h19+8B0PbD966dLvnj9//ptHkah89K9/u//0689+4Ew/ciudVSNBOjsGjOvDbW87zG90+5+48vhn/h3/j3j/55+w37z2zPs2457vdFdy08oieH140/PuCh/8vHzi8x+8/Pz/1D1duXLFjM8RVxRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFURRFUZT/4/w3cJtL5IKBfQ4AAAAASUVORK5CYII=",HeatingActuator:"data:image/png;base64,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",DimmableLight:"data:image/png;base64,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",OnOffLight:"data:image/png;base64,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",LoadControl:"data:image/png;base64,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",Shutter:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAACgCAYAAACLz2ctAABMg0lEQVR42u29d5Bk93Xf+/n9buo8OW7OOWCBXSQCIAiCFAiSIsUkKtCUSFoqqZRs+VW5nl316tnPqWzr2fX0Sk9yULKtQEWSIsUEEjktFlhgc5qdnZ0cO9/0+70/7u2e7p6ZXYCSsBC2T9XU7oTbffvec0/8nu+BtrSlLW1pS1va0pa2tKUtbWlLW9rSlra0pS1taUtb2tKWtrSlLW1pS1va0pa2tKUtbWlLW9rSlra0pS1taUtb2tKWtrSlLW1pS1va0pa2vAkR79QTO3DoiKhUXdG+RX9zSSYc/fprr+j2lWhLW/6+WMBjd9+7cXpuvgdACIHWyw9w6/erfjARfbSb/d3tIP093XMvvvDcaFsBbyLbd+2TF8+dUvfed/9HqyF/2rYPf0PR0f21bEeIoProC88/+53aNX6nnKL5TrxuhmFcm5ucCHsHhm1DQNg2Yj/YdYyv3dzsdDjU1z3/TjzHd5QCVgsLAsD3g+752anQ93wGh9cpYdhSa61Fza++m4zUm4wRap99rb8XQojG30kCESgdTk1cNyqlkrF5/fAu4MQ77fPLd8qJrB8eNsbGx8O777nvkdGxsT8KgzC5OD+D6/u1cxRaa1b7egs3+4Z/X/td69/c7Jg3+7qrfS/WEFNqYUpd//5mf9/8Oy2kNPB931hamKeju5fZhfzvP/L+D/zoxXOn1PZd+2Q7BlxD+aZnZv+0VC7mADq6ekmnMzrUUryZhGOtQEhrgQ4DhGkAELgeQRhgJ5KoUBH4PolkAinivxUgEFTdKoY0sW1zWXE0IEQcYOn4CkqU1igVEgYKpRSOYyOERAiF1qKeONXOVakoQBNCoxvsgEChtMJ1AwBs28YwZP3Y6BQ0AnGT4E8j0NrzXGFIRwtDCaEJe7tyP/Gdb3/zD94psaDxTlK+fKn056VyOatUSFdPP9lsljAMEVIKRHQTV/u6oRUUkb5kM0k83wOtWb9ugHVDvQRBQFdHis0bBygWi4RBgJASjQKt2Lx+gGTColio4PoeUkoQiiAMEAiUAt8P8QMf2zRI2BaD/Z0MDfZQKBRwvQClFaDwfR8hDXzPRWmFlBJBGNuASF2E0KACHNtky6Yh+no7qVaqFMsVhBT4vgdCYhqSMFQ3/OyRUgshTFtHl0CHGIZRLlc/vn/f3vPHX3r+9e279sn5uRl92yrg9l375MjIZVVTvkrVywSeSy6yfCoIQqQUQmtJZJM0usl46zWVElH7C41tCh647wgXr4zSmXZ4+KH7mJ2dIwxD7rxjL57rsmvnFi6NjGEakmrV5cC+HezeuZkgCKi6HuuHukklHe46vJdCoYQUmnQqyfBgL/29nRSLJe65ax8bNgwT+B47tm6gWMjT29ONQcj6oV7K5Srrh/uxTJOjd+zFD0IWF5cwpBlb3Uh1wjDk0IHdDA70UlhapK+3B0MK1g10kUo63HP0ABcvXcUwjOi6rHYN0GghEErFJl1IQ6K0NI2q6/3Ivj173hFKaNxKyzcyclnde9/9H10sVP48VCpVKZfDXGeXzGazBKEWSCNSvijCWdPprHTBuqaeCDSGFKwf7ufUqXPYTppd29dz7dp1ShWPTDrB1775HHce3sP4xAyeF7lVCaSSDkEQsmP7RoaHB+jv7aJULtPf141bKXPXnfuxLQNDCrZvWc/E1ByD/d2kM2lK5Qq7d26lsyPD8PAAvb29dHVm2bl9I50dObLZJNeuTVAo+UhDImLvLqVBpeIRhj62ZdLf101/fzd9vd0MDfUjhcBxLC5cvoZpmsQxQfxv/JlrVlGI2M1H10ghhCF1qJBGuVx5R1hCeSvd7r333f/RhXz5j0KtnDAMda6zy0ilUvh+oBEyjsdEHEPFT/Rq1u4m8WEYhmSzKe4+epiuzgye5+MkktiWSTab5WOPP0ixUKBYqiIMiVKajlwG1/Xp7+/BMEw8z2dqeo4gCEkkbPbu3YlWIZZpYJomqXSacsVlZnaBEyfPk8lkCEJFuVxhemYeKTRdnVlc12NpaYn8Up5UKoXWQeR6qcWWIKQgmUwg49DX90OmZ2bQKiSVShGGmkQigVLLngAd/SMgumYiUkQtBCr60hqhQyUNiVLSkMY7ITERb6e7rZVaGpVPo50gCELHcQzHSagwDAUCgTAjxYuvas2avZlT1jULqAWIAJSiI5ejsyPL1PQcSUeSzmSZX1jCsmyymSTjk3MoFcVmSkukhA3DfSwuFcgXCvT3djO/VCKVsJFSYFsmhmmyc9tGTp25SL5QJFACx5IUyz4d2WRU5zINKhWXjlya2bkFcrksSml838OybBaWSnGS0ZwlO5ZAKYVpWiSTDqVSmY5chvmlErlMkmLZxfeD6AFsuCyNFrCmhI03WwmhJUpIgVJISeg3JSa1v327EpRbkgU/8v4P/Oj1qdnfCVVoqzAMnUTScGyLMFQaaQodaVycIYof4CQjixDdgBBDguv55BcXUCog8D3CMMS2k1iOTSLVQSLhRMlAPdvUuJ6LZVpEJQ0vcnlKEaLQcaYbWSgfwzAQwkAphWEIwlCjdZTVChlZYdO0UWGARiIEaA2mGVl44oy4Jkqp2EEpwjDEMCzC0McwLLQKEbIeNCK00ayAqzyo9c/V5KvRUiAalfBdawE/9/mf+vwnP/kJ59/923/nTczM/5Y0DKOmfLZlaaUUdcvHsvt4s1Zv5cWOLKAUitD3KJaKSCmw7ASWYaAAt1qhUi4ihKSzuw/DtGNLpNd07UKAJMQPAoIgKpXIWmlFa6QQ9X/fjDQes2ac1Pqa0sAwDaSQUZatzWVlvGGRRsdeAS21FiqubUuhhFupeL2dmZ/94pe+OPHd7z4x+Lu//d9/+++9Ah44dES8/tor+r577+uamJ4duf/+Y7nZ2TmeeuoZ+gaHdSadFaZl6bgkBkLGxks0WL+3poCNFkwIgVYBpWLkap1ECnSI67oorXEcBykEi4sLhEFAT18/Qhj12FPoBvevwzie9CkWCnhuJVZIucZ5KLSKPtKbPvfY6Qm5/LpaqxXvoUKFkJDt6CaVTBDWnGUcN0eWVKypgELU7SBCaor5pXBxfsbYvnM3G9cP8saps8WuTHrjs889u1C7h38vW3GTU5MAnDxzzu7q7Ew8+fSLemBwSAyu2xgChpNw8P0gunDCWL4oTa73rT0jrbUxz3MxTAvHcQiCyA1H9T4oLkGuq5vOrm7mZ2cpFvJ0dHQSag0Nbi0KByJlLhbz2jBMkc11RnW5tcoLpoVlO5FRF7UOS/P/GxWs7n611kEYCt/z0Fqt8RklYRiSn5+Brp4oMVEqjgWNG9obUctZ4gdMopFSGslUFtf19amzl4XW0jp9/oL9rukFm4ZESIll22JmZkqnUmnDth0dKR+iZvnqN4cfzPWuqoha4Vg2SmuKhSWElPQNDCClpFQuU1iax+rtJ53JUC6XoxspzPrD0OgZXc/HsRPCMi3mZiZBGBimuaqiqKBApqOLZDq3ogUXnVsY/1DGxXIjtm6eWJqfj5XYbLKodeXzXVLZDlLZDoqFPMlkMnbTb93/aY3OZLI6mUzKMADTtPCCAMexeNeBEWoX0fd9TDMhtLSiO6xFU+zyg1i+NeMnaSOFiQbCIKCjswswUYEmmchQrVRwXRfHcTBcFxWG2jANoRvev9Yuk8JE2hZutUi1WmXDlh2Aaor3NNHDNj87RbVaJZPJECqFxqpX6yLPbtQCvKbQIVQG1UqJdZu2YJlmkzWvvXZ+cY5ysUjfwAC+7xH4AaZl1q31zS6djjMgDSghhVZCCGGgRYDQAt5G0Id5Swo/tRZaQ2Cv9d9RQCqNFoCqEb13rXwRF3+jf6OLr5dTyvpJa63BiB4Q2QB21VrV63cACoEhli1npFhG9L1YTg60bjax9T6xUCgVopQmVCrOhkFKGblrBKrB1JnmW7+FUWwr6r1tIUCr5lrk7QHHakkY1np8dXzBROONavn/au5XCIEh4wxSGmSyOZYWp+ns6kEKSbFUxDAMHNsiCAKEkFG/d81QwkJrTTKZJJXJMjV+FUMaa8Zdua5ulJIgdJwA3BhAobXGsW1yXb3MTl1f87XD0KOjuw8VKgzDRJoW6q30FETDs8VtigfUWtdRJzdSpkaF0i1JRivCZFlZGw2ggdYaFQSksx0kk0nm5ubQSmE7Nql0BuJuiWnZy7FUvaxR/w8CgWEIDCEYXreBSrXSVMNrTDKklFEio+JuBGp1C9iokFqjwoDBwSFcz0Wp5det2dfGso/ruthOEuoW9mZlmIZkhBYlXPGD28ICxl2LmyBa1rJ6qymtqPvzZeU0TZNQCCrVKgknSd/AEEEQJwHKr/+/VlhudL81+EP9IdACaRgoFWJaDqufdgzBinMMKQQIefMQQ0RZatX3kNLANGSrw4jOQYWEYYDjOAhpouK6Z2MJ680ENE0Pc5z28TbP0Nw6BZTxDYnBnKtZs7WUsNYyW/MY0dzR0DrEsSRS2nieVy9yR68lQWksJw0iwvXREA0IatY3igyV0rh+WMfm3ajFruN4963l8xKBjJVtDeslTUxhQFMBO7Z9ovEJWs2srRXqSIQ24xjQf/crYC0QZg1rdjOXfCOkcqPyRTFTlCwYhonjmIRhgFIaHYZIKZCmvfz3YmUbsNGqiiZktWjqkCyfjv4B+gC6pexzI5+4fN0az6l+LWn+mWiwoI2fS2u9SlIkbp8YUDUoWZMbFo3xXUOjvdH90hDrtbTtRIsFFCLKHJXym95PNNXZatYj7n40dBRaFVrUrZquOS503CqLcMgN3YbWh0jrBjepm/VPtCplq7WqZa0K9PIDoxsfjMaj6g/VyuIf75DxmlvngrWIkMcNFm3ZsrXGhqLpRq+wHY2oD7EyvmmNG1ezMDX0TL041OiGWx+SmmXRECofIQxMQxCqECGMCCgQI2IbyzFxmSd25aBCPypmGzI+hhWoGCmXY0+BQgqNHygMjKiGGH82IZexf7pBt6XUBGGAVhrTdBoetNt9Kk5opJDLwXPdujTUBeuWkIZW1nKmW/9d/YlePbPUzf6xjrOL8A9Qr73W4i7RCIZYA/yqo8/Q2dFBpVKhVC6TTCRwPY9AgSEjV29bFjoaNcV1vXr86tgm2VyGMAyoVH0qVR/DMKMaYpyVW5aJ6/pYllWPRwPfZ2iwj6rrMze3hJ2IQLN+4KNDHaFxLAPLtDAMA9/z6OzI0d3VwaWRCWzbjOZRRKvhvTVp8K2LAWM31mghai5ICo0KFOVKFAybtoFpWtRgw0IIlFYEcZ/XkMZyPFN3fSyXJuKST82weV6A1grHslAijEsa0TyIbZkNLa1lF9w4EiCEIAgC+nqyHD2yj5GrY7heyLqhHiqVKqVyFT8ISCaTqDB6/b7eHubm5wAolX08z2X/3u1cG5sknUpScT3y+SI9XTlsO2qDFYplXM/j6tg0SocRSkEKyhWXwwd2cfzVU8zOFVg33Mv64T6ymRTJZILpmXlGRifJF0qkUykOH9jFyVMXYmu67D2aqw8aZCi00LfnXPByQ17geSE9HTa7d+1FKcXFSyPML7mI2FVpDUnbZMuO9YyNz1Ioe8sXVzT7Z61jdEn8ve+7bN4wiGGYXLl6HdMykWh27trMwmKBqbmluAW2XCZafu3lCq4Rv2ChUGDPri2MXpvAdX26Ojvo6uygUq2yfdsmRkevk0qncasu27ZsJJ1O8MKLrxEEIYYUuNUK+/Zsx/M8ypUqxWKZTCaF57p0dg4yOTVLwjYpVavxQJLB4uIir75+jjsO7ubi5Wv88OPvBWBmbp6B/h5SyQT3HjvEzNw84+MzvPr6OeYX8zhOIq4trlaLVCgi/OJtk4TQAqkXQuNVPTZuHOSXfvZTeH4Q/+ZB/t3//fvMLuQBqFZcdu/YwC/97Cf5j7/+R4ydOEdHLo1G4PmR1dShxnYcTBM8Lxq9NA2JYcKPfvIDnDk3wrkLI/hhhCL5yc9+iBdfPs0f//kThKbC96JRTcMwqFSqWJaN57o4toVhSTAkxbLL+OQ8Z89dIpnOUipV6i7W9yPLValUMQ2JaRoEQYhpGszNLxFqwflL16h6Id998iUSjkXV9UkmE/ieR9X1kVKSTiepelGXRmmF0ALLSbC4lOfEybM8/OBRLl4a5aUTZ/D9AN/38APFow8fY/eunXz9m89RLHux8umGBGpl+Uei3vYpjbdFAYNQ3bQQGgXckqrrsW/3FtYN9fLrv/UnPPHUS2wY7qdc9ejIpDhyaCeu67OUL7JUqNLb08n7H7qTi1euEwQhQwPrUErT39fFq6+fZ36hxKYN/ezfu43Ll69y9tIEzz7/GlevjmEaJnce3hmjoSOQhFKKuw/tprMjwwvHz1B1Pe48tINr12fYumkrY+MzTM/OY5gW1WqFkdFxpJRMzxexrSgU8AOFbRksXZvAjDsx9Z5xnFgIw+DchSuYponna6QEy5RMTc8ipIFhWAitmZ3PY1l2HABEA25aaRzbolAo8uQzJ3j/w0dZyhcZ6Ouiq7OfpXyJjRsGGB0dZalQJpVKoMKa8mlEY3JVz5wFWhlaCCneNVNx6UxWlIsFUulMxkkkfkUahqHRGIYpbMuph7yNCYg0BKViiV07N/OB9x3jjoO7uHhlnEKhwD/7336aHds2kM1l0Bq2bh6mp6eTQwd2cHDfdiqVKr/4M59ASIP33HOIwYEeFhfz/PLP/yQTk9M8/NBR3GqVR957lFQqw5ZNg3zqY++j6nrs2bGeEycvcOfh3Tz84BEW8yUe+8B9XB25xi/8zGfYs2sz77nnEBOTs1weuY4wBF0dHRw+sAPbtrhj/3ZSKYe+3k62bBxmoK+L/r4utm4aJpNOsHXTOtYN9ZHLptFacOfB3aRTSbZsXMeu7esZGuhloK+L4cE+Du7fwdJSgXLVj+PBuG0pohC3BueyLIvFpSW2bFrP+qEeMpkU9x47xN49Wzh1+hJPP/9q3EsWDZWcGBPIyrJSnFGLUPlhtVL8tVKhUBoYHBLTUxPvoqk4TZ0ZoFYeqXU10GCZNuOT0/wf/+o3+fXf+hMAfuFnP80nP/YI2XSSf/0ffpv/89/8F149eY5UKsGff+V7/Lff+TPWDfcxONhLuRrw2//jq3zzuy8y0NfNo+87BtqrW+G9e7ZSqYZYluThB+/kz77yPX7t1/+AiakF+vt7OHbXXhbzLgAduTTr1w/jej7XJ+b4x//7f+LEyQs4iRSeq+jpzpEvFCnk83h+QFdnJ5Wqx+BgL7Zt49g21apLT3cHQRAwOzdPX283AN1dObo6c0gpmFtYoqe7g0wmS1dXJ5l0knQqQRgnMK319khxTBQGlmWzuJjn4pXrADz34mv89u9/Fc8L8IPW4r5oKsG8E6h2bmEWXMPGNbhgQ1Iulbj36D527dzMd554nsHBXj78gbvxvICEY7Bn5xYsy2ZwoKdeUilUA555/iSvvX6Bzo4MpuWQSSdxbJN8vkIqlWDk6hinz14hmbD4zI88wviEYmGxwMaN69i2ZT1dnTmqVY9SKYLaP/vCSc5duApAKpXgjVPnWcpXyOUkIHGcBCPXJtm9YxPZXI6Z2cVo5sQ0eePUeZLJJJVKBcuKpugq1QhzePXaBPlihTPnrmCaERInX6hw/tI1pBCUyhU6chkKxQqGEYMMasjRuIAtdEO3g6isspQvcuzOfRRLFU6euoBtmwRBEM+56HqNsLUDI27QtHt3xoANrgCh67Ff9DQqDNNianaJD75/iF/95S+C9vjyXz7N1/76aZSCj33kIZbyJV45cZar16ZwXZdsJkVnZ44f+ejDvPTyGxTyJWbnlhi9Ps1ffO0JcrkkDz1wFwAnXj3LxNQi8wt5Xj5xmp/+yY/y45/5IRYW80xOzfLGmYt85kce5RMfe4RSqcozz7/K1WtTBKEi4dhEIPaojhYGIadOX8ELAgyjxh8T03vEOD50SBiCYRoYUhKq6DOevXi9DseXhiIMYjShMLk2Po8hiNHWetllohu0JbJuge/j+T6PPHSMr3/rWbo6c7z3/iMUS9X49ZfLUY3x3zIPQ4vyvc1lmL9TG9w3OCxmJsd1prNnoLu7e9S0LFtppS3LEQkn09R2bOw2+H6AVi4duYgbplAs49gWrueTy2aREipVnyDweezR9/AjH76PZ148y/jENB943zH+3//yZ3jVIocO7uWNM5eZnVti/XAfY+MzzC8UyObSSClZWpgjlcmSStgsFcpYtonrBphC0dnZSRgGeJ6PFgbVahXDsKKuhdD4vk9vdye7d2xkYbHAuYtXMWIsYVdHGieRpFCsMNDXieuFeJ7L9Mw869cNMTM7h2GYuK6LlAbJpEOl4uKHCseK5j2EMKh6XgRmrcduy/1iKTWeH5ByLD7y2EO88PLrXLw8ThAEHD2yi/17t/N7f/BVUulcHUWzXJhfCYOLUDYaJARuxVuYm9w4NT4+9fd6KOnNjI+L1v6wUpimgRBpSiUPLQTJOEtNJJMUK1WkMBBa09mR496je3jmxbP8P7/xe3zuxz7J2QtXyReKHNq/k1Bp5heW2L51HZZpsLhU4PCBbYyOTVMoldm3dweuFzI6NsM9d+5j9Np18sUK64YHGJ+Ypbu7gzAImJia49D+HVwbm6JQqCBMgQoDctkMvT1dJBMJpIRNG9dHQ+u2ydjYFKXiCHcfPcj161Nksylc1yOZSlAqufUa4qZNm5kYHyOXy1J1PRYX8/T2dlMulfj+s69Flk7WkoTI9UoJvueSy6Q4tH8HZ85dJJNO0t2VxrEkdx3Zz87t6/nIY+/lK19/imQq3dQXfpNorXd/J0S2lGFa+fmEEQ0rhWr56TVNCyk0YRBw5+E9mJbFy6+8QX9/P4cPbObb3zvOxOQsdxzYSSrp4DgOYRgShiEP3HuIOw7t4fiJ04yNT7N/z3aef/FVMimbw4d2c+rsFTZtGOLQgZ3MzD5Pd2eGUrnC/XcfAGAkDFBCIxEIw6JcLnPi5Dksy6C3u5OlpXxU9zNNpmeXKFd9zp67zFK+SFdnLoLXzy8xt5AnDHxyuSyTk5PMzC1QLFWRUlCquCxdHiUIFYYkhluJetQihYoSno4cdx7ew7MvvEoymeSTH3uE9GtnkTGL1vmLY8zOznPv0X0cf+080rQaJuJWxZ0DvhbaELcRGEE3lQLWgllpGqgrtCbQIJA88t47+fZ3X2Bmepp/8GMfJZVKcv7iVWrhV9R71YShwjQjzpd8ocD84hJWPMQjDYtKtcDs7DzJpIOUkrPnR7h0ZYyd2zZQrrgopRtmLxRam1imzczcAtVqRLuWcKbwwzCK1MKo92sYBs+9eAppCJASCXhuBWFYmIZA6UkMKeLzs/B8H8e2o4F3GaOqha6j/QBCFZBJJjh8YBcvHD+ty9VQBKrKf/u9P6dSCQDFC8dPYztJFhcWOXxgO4f2b+fEGxexTDvWPL1KElKrByredXVAO5HKJJPJpjqgaVr1ALhV8VagnFsUVEqB70Xo5g++/wHe9+CdhCrkd37/L7k6PovjJFhcmEMh8T2f6ZlFiqUqI9fG8Tyf+YUC18Zn4s6EydzcEvlCEcsymJyap1SuYkiDYrlCoVBkZGySbCZFqeziVqsIadaTp0P7t5PNpFlYzCOA7s4OEgmbIFCEKsC2omm6INQoDft2b6G3u4NSqYJp2WgVYjtJgiAgnUrihwrDlMuDSJHTbbgQYBoG18cnKbueqJFnCiEiwiXHiZIgHZJKp5iZXaJYKhFqFYNdddOogW6qA6qoDhiqt60OaN4qVrjGKjyrrGBYjflK6+XhHssy+dpff5/XT51HSIOro2MobZBIJNBaM79YZWL6fARkMCwqboCQNq+fHcEyLZKJRL12ZjsO1ycXYoJ0SbnqY5gmS8VKPFhucOLkBSzLwjCcCDZfddmzcyNhGFIul3nv/YfxgxDfD+jt7WZ+fhGApXyRcxevsm6wm+nZeXbt2MyFS6Mc2r8DKWWd/dQ0JDNzS/R0d1Kturz02hmENhtmUmrXxaTqhegwJAwjgqJlg+a1QAk9EBCWQizTivGCoinTFU146tsmBgzfVCE0igtbuVpq2bKBbUuujc2ghcZ2UjF1Rjy4Y5qkLLMO14qsgsaxHTSRW7Ysq/4+tm22YPGIptJiSSYTNE5S2qbJwmKBnds2IKRBKp0mDBUzM7NRJtyZpVCsIA2DZMKhI5dmKV9iZHSci5evsXP7BoYG+7Ftm0uXR9mwfhDLMslmkliWFc3nNhSQG6+BUoqe7iw7t+2tj23eSC5euc7cYgFDmssP/Y0KtLcLGqY1GWvtDSOiHmkNZi5jq1i76EIY2AkDrUI0IVrJKGKUEqXCFota+3kDyZAUKB3Uh8Q1AVJEhWZNgBBmnbAlUoJlbmjDMplfyPPK6xcJw4DTZ69Eiuw4vHLyQlREVgEIA6UEr58ZwbFt3jhzBa0FZ85f4+z566iYc+bcxWtYdoLXT12J0DvSbILR1zCThiGolD22bhrmH37+w5EFvIFYlsl//o0/YXJmATNh3nzmSBu3DyIaVMNwumhCK9cwG9VKFaUiC6S0olIpYNhJpJD4nhs18S0j5mkxsJ0ElXI56qFKCHyFZdlUyx6gcBJJDCOaEymXKiSSDqFSeHGJJCIugoTjUKlUo7lbGdXgwlBjyNo5RlRpnhfEiGSzjjWUhhWNG8iIbUsakDQT9UGjGteQ0hpkxNogDSPikY67HzXgbVNIovUPNLQmpWjijhWr2sB4KInbZSaEBmh903hgDUQqCIMqB/dtw3FsTp+9jGXZ3HXHXUxOTuEFmuHBXvzA5/r1SQYGNscMpfPs37ObS5dHKVdchvs7mZ4tsnXLMLlMkpHRSapVn2TCYt/uzZy/MEI6m2ZoYANnzl5m04YhLDPCCh7ev5X5hQKeH1Aul+nsyOH5QX2MM18oIQ2rqcldG2xvfaBqzAONsy6iCYUslofiV1G+xtDASTicv3SN/+s//P6aBEaNMjm9pB3bFK2DVGsh1W87QGrzRY6g+tVqlXuP7iWTTlIsVdi1YyPrhgcZuz7Jjh3bOHPuMjt3bOLipVHWrRtkz67tPPn0i9x5eA+GFDi7tlAqV7n76EH+5x/9FQ8/cAevvX6BatWnXM5z/z33A3Dszn0IEdFePHj/HYRKYxgWw4PdLC4V2L93G9Wqx8zsPHt2bWF+oYjnuVwbn2FhqYw0IFSqHh7oNab56re+da55eSDlTTiNGpxLslSoMDufv7nB0mBZtjAMc8WAUtNUXJNn4t2/qKYJldF0VeJtGUoxPDzAC8dP89fffbEOEnjqqRd4+rlXuHptmtFrk4xcHaNU9rl8ZZTt2zaRyWR4+pkX6O7uZHRsmvGJaXKZBGfPXSWZcNi9cwMH9+8mlUrw9LOvMDDQg9aK5148yfbtGxkdm2J0bJKlfIHLI9epVKqcPHWRXTs2Mzk1h2VKOjpyTExOY8b4P3mD8dEmpWwYQ60nYUIsj1k2fLUOatVGWWuvZxgGyWSCZOImX8lE054RoXUDm4OoUUvfssbIO2ZjzootFxLGx6e44+AuHnnoLrq7OgA4euwOHn7wKJ0daRKORTKdJQwDFvNFUqkkYRhw5MgdlMsVFpcKEUhAWizli5imQUcug+97eK7LXUf2MT+3iCEFRw7t4erVSdYN9TE82E06leKTH3uE6ZkF5uYXSKcTLOWLEbjC96lUvGUGQ7FyFFQp1cxspfXfQtgsVvRu62wJWtdjzIiVTjf9W7OyuomvUNfZyG7VVtFbCMm/EWedxk5YvHLyHHt2bsGxLV594wLJhMOenVs4f+EK+UKBsxdGmV+qIPHZv2c7Lx4/TeiV2bVrOydOXsGxHV4/dZ7FxSUG+rqYmV3k1LmraKWZXyyxfcswz7/8BrlMksHBfr71vRfYunkDUmrmF4pUXS+CTDk2f/2dF6hUXK5PzNYJKHXDgMWqXC/87WLvRCOTvhArMCWNylmfY5Et0351llTe/au61kbDpEQykSSsxyCigWRbI7RAi2jDkFf142JxAqVDvKofQZvMaFuQbRoEYUgYhJi2hYHE9XxMy4rKLKrGjlBbfWUhpCQIfALPx05YKAVhEJEVBb5XdwwxbzWObaNDBYZCx2UKQ9bcmlyzg9P681ZSpbUYvf424umqW8WxnTqBuhGPBkDLwH1DbEmotBBSeH753Y6GCRuoLfQazCUCoQ0yaYMg1FHxWkA24xACCSsiEipXqnRkU5SKZQKlwNAkkhaOFV30UskjnbYplXXcQov490zDxEpF7UDTEGBFCmfbEVu+0iquCUb5uqwthRGNREHNRfJWhVuzt91CmbEWFckKRobGnHkNZjAhBCpUHNq7lYsjU2zdNMDcfJ65xTxWTMLeFPPVlO92c8FrYnBjoKpEUHFdjuzZydzcIvv3buPa2CR+EDA00Esum+bU6fNkO9axbfM6Xjx+ilTKYdOGdbx4/HUeeegY5y6M4Lou+/ftZPTaBC+/eh7HcWJCJJqY6hvZp2pKp6LeaIMiNWwkegsbMtdi9tINP1uLdu5mzGCtShoBFhQH9u9hdGySXTs2c+7CCNNzi1hmVGZZDY51qxKRd14SImp4oRApAvL5Itu2RHi+9cMD9Pd2Y0hBOp2ms6uLns4Mz7/4Knt2bcUyTaSAjlyGXC5FMuGwZfNGXnzpNfp6ukgm7SY+mhutfRUtyUVtsk01sJZGu0GWf187ppaA1L4aE5IatceqWa5YnddGtzCIraV8y1ZN4bllPM/H8zzCwAd945jr9smCG1kHxIoqVDNbaDxDsWf3NkavT2PbJplMivOXxnjy6RfZvXNzNPtrRD3gcxev1pmvvvntZ+np7mRwoKu+/qq+ymoVy6VblGCtHcJSyiZquMbBqtbXWAtQoRqUshUPeTOKOr0KcKNOU1I3gRFu8uiRvWTSWbZt2UjCsephj76tuWFEC0tT6/NXp9WIyPN93+P8hVEmJmdRYYjnBximybE793H81bNIIbjrzkM8/fxrOHaE0fPcCvfcfYTJyWnOnL/CPccOc+HSKJWqh+3Yy3zIjQpzk6XVN1LOVvcoGtx6XTnXSEjWIuFcKw5sjTXrzKo6GrBXKGzHQkoYGZ3gxMkLJJNOPG8iV7pafWND8K5Z0/CWFVRIlFIkEhm+9cSLOLbF9OxSHRR6fXw6Tk4U5y9dQ2uFlBavnRoB4Ct//TRCKwIF45MzhMrAtiPlWyvYXxGhrgILa1VQDWjVvLtXr9LxWAti1mrN1uKoblVCFb9nZP3UMt2GAtuyGL02ydj4NIZhR/AyYxmIoGkkftK3dCjJhHdaCXqZmarGfZxIRhg/s+HmaKCRIF7Uf9b8kex4/41hNO5LWyY5Ws3CrGUV1xorWEbnNP//zZBqNkKsWpV1LSuotV41dguDaFi9VC7z9PMnSCYSqHglhG4iwV+Z8HC7EVSubQD1Cr6/Op1Yg8cWqzDPijX4HhupKJZJL8UN629rucSahVLxTWvNYg3DaFKmmiKr5TWBK95jte3vq8Z6az0cWiCkZv/uLaSSScqVCucujeMHfj02lHGL70a1yHdtEtI0F3zTJEQsV/wb+6S0fLX0Tlt/Jmo/06KJMku00metYp1WtYYNWMTGJn6j4jRmyE2vW6trrrLreDWFqMWNy/PSNP1cCIkUgoRjkrAlUij27txCuVzhmedfoVyusHvHBkxD4NgGCXuZQVVpddNk57a2gDfLW/4u+zytN/vNbWdvzpBbFbn1Rq+meK1ZcC1rrxOkr5oQhezYtgnTkAShYv26Qf7ia0+QSGS4cGmUDz/2MI5l1A3AmXNXUErGxfU2Q+qNkYK1Del62YeKFvJt0YIeahr2EstWZwUAvcE3C61X9eF1FtYGt7tWFqta6no3y5qV1sgWRW5SvKa1X3rNrDvQguOvnkEI8D2PfL7A4YO7OX9hhL179nLuwlXOnD2P5SQjSjfbbCo3i9ueI3otiH5d+RqIvOszEZoGIvs4aRMN2ZuoMefWZ75EIzeFaODopraqoYFOVYuGVKi5Ry1qKxG0XoGlE2t0Pm5klFtrgK0dDoFYs09ca+XZTgrQJByHkWuTDPb3smPbBhYWlrg+MUs2m0Vh1JMOrZuJ0evneauIYd5pCiiaaCMaGO9FPYqqK1WdFV7Uvo9HGBsGkOo7d1dcYF3nga5ffSGWCcGJX0+reluurhKChkXRtY6JhNr2S8SaheM1g/81QAw3S9aU0tE2eDdEiBClFL4fxsxjCs8LsGqsqKvuT2nO2sRtbwHrcKGIjsLzPHQYIgwDEd9gIS3CIAQUtpOIOFLcajTTalhYpk21UsaxHbzARQhQGNimACRB4GE5qagYLQRSRUMafhjiVstYlo3ScUkjnrkNQh0vrAaBia88hOEghcK0HDyvimlaKyb3Vs2uVwlNxZuEbTV1XZSHISW+p+jr6+RDH7gXgMWlEp0daaQ0+eo3nmJyeoGk4xA9L80zOKusrbq9OyGivsVbEHo+O7duYNeOTbxx5hLdnRkG+nt4+fhJtm/bQiLh8PxLJ6l6Afv3bGPzpvW8fuo8o2MTPPzAEY6/epb777kT1/UpVypcvTaJUrB18yaee+kMqVQy4vyWJr7v0dWV5f677+bi5TEKxTJHDu/h2edexnaSZLNp1g0NMHptDGkYbN28njdOXyKdTnLyjUscPbKLyyPXWVrKI0wnGv1cDQGzWs5/g6RmLatZQ2EHQUgul+Izn3iUU6cu8K0nnsf1wTJNPvi+u/jMJx7ld//nVymVvCh7Rqxan7yV5ZhbyIxgN4bEK7MIQnLZNLMzM9x1x0HOnr9MGIbce89RpqZnMAyJaRlMTEyQzXVQLpfZtnk9OvQ5csd+qtUqUkiCIGDL5vWUKxW6O7NkM2mchEM2nUArTRhoqq7LkYM72bxpHZcuXWHnjq2MXL3O9q0b0MDhgzvxfB+lNH29vYxdn2Lf7i309/cgpebg/l34fsD99x6hK5fhysg4tmUtL9BpqffdrFDd+ncrETMCw5BUykUe+8CDXLo0yvbtm3nPvUd46eVX+fmf+RTd3R0cf+U0hw/s4pXXzpFIJho2Ka1h7aLi/LucIZW164BaNGS10mJsfIod27fy5LMvUypX6O3p4dSZ87iux+T0Ant3b+N9D93L7Ow8w0MDXBoZ5667DlIuV1m/bpDZuXn8UHHx8igb1w2wYf0gF69cZ6i/m0MHdpHNJKm4ZRIJi6mZeb79xPPcdddBkkmHkdFxurs7kRI8z2dqeo6NG4ZAB0zNLGCYJqYh6cxlAJidmcbzfC5euR61HhuK0PoG7rQJcbMaqHU1ly2izomTTNHdleHipRGq1Sqlcol/+qs/g+f5VCoul6+MksulSKdtlArinrFu6oXfDFb2rnHB+k1M8DcmGZVyhR9+/AH6+zq5MpLg7kfuZnGxwJWrRXZu24hhGrz48hvMLyzx4R96AGlIrlyFZ58/ybE793Hx8ijbtkR/983vvkBnRxbTsrg2Ns3U1DRBKOntyXL4wA5eee0Ctm2xYXiY8Zgz5n0P3c3iYp5SKWIzXT88wPjEDKZpcO+xg4yNTQLw9HPHkdLg7rvvjIvD0YIYdC154qadjVW3PzWtJWuYYRCrzzUYhuSb33mhngx94P33oeLbq4VAxlzRUqxstzXCyd79MaC+GWNgdEESyQTPPP8qVox8/vOvPkky6VAqlZmdi9itZufz2KbJt554AcdxqLqBnptbFDOzeSqey+xcniDUOgyUeP74WdCKVDqNaUQoG8MwqVR9LAuujIxRKJSYnV9EhYLu7ixL+RJCStyKy8JigZnZPFJKOjpSzM8XcByDjo4eXj99kVNnr5BMOvURACX0mlD9my1gvGkfWUeZt1utMDe3xP69OygUKziOzamzI+zesYF8vsyBvVuj2ZZSiWw2S6Dk2nuYeZdvShINQ9drl2HqG+EQQpAvVdGqWl9ks1QoY5smoQ7Ruort2KA0+aIH+QpIQ6RTScIwxLZsFpbKAMK0rTpnDAJUGJEB5ZfyLC4uRvEaMD45jWmaCGEyM7OIZZhoQizTZmJyPvo+VMzMLGKYFuVqiCUEbqgJdUixWEELgWGaK7ZrNjLR3yj4v1FS0GQRgWQiyRNPvcxP/eQPc+rUBS6PjOHYJiPXptmyaZiDB3byu7/3pyQTyRg9I5uR4Eo1DTq1C9G1jkdcuDOkiSbAMC1UGJCwrWhRn5SAGUGrAFNKhCEbqGglCo1hyDojf9MixBre0JAYmNH7CY1lRbi5aJjbarhZqul7w7LQREocFbUFpogINXUMPBBxOyb6TGLFVNtaYIcbARAafYUCpGmRL7r8jz/8Bo9/8D6+8LmPUyyVyKTTKBXwh3/8VyyVXJxEMuLP0Wu8RzsGXAUfKQSlQonPfOL9XLh4lXMXr/LZTz3OX/7Vk8zOL0Z1N6I4S6/Am9eY5PWKLZyi7uiNlipQrb0ilzPypvWpy5VaESudEqusQq1P9em4eL0qHemqsx3cZOCoNWIOdbTlfWGhwO/+r6+xbqifTCZJsVhhfHIaKQ1sO0G07cFYVaGbFDsmhHp3u2B9Yxdcu4+h57Nvz1Y6O9K4rsvWzetQKmD7lnVMTU1h2w5hGA/YrHKH9SqQreVlzauU/VdscW3Bf636+mL1HkXtd+JNLm28ybLuteBiUYstxLIEkGRicp4gDBDSwLGdeECJ+hLHVuBDkyK2XXCDu9LRgp/NG/qR0mTnji2Ypsnk1Dy7d23i9dMXo/aTlGuOc4lVr2qTM7xBO+LmcBpxg1+Lt3hHbzbEfqMEBSHr2z1Ny8K0LdAqXpzduJiwmXFr1ez83QxIrbtgcfMyjNYCKU2+++RLbNgwTmdHhkqlwquvneLonYfoyGUYm5zDlja3k6wO41ou4msEEcWzpJGGZi2cY3NyxO21L7i5jrVyKAkdEYhfvTbB1WvRcvDO7n5OnRvBlGa0CPqds3n+Fg8xNMQcLdWU+prZm7KE6ne/CzYIUc0gprXn1UX0JJvmcrcwYpO3G55ebislXC1zbhozQDQ9zysILt8hMPx3SCG6kZpDN6yOasQDNltL0ZIYtAI2b08X/OauwVqzJtxihTRvKR2SaHYBjd5gGRG9PO6xvOtMNJDNLtcOG49pbDPXYF6rBqANgIGaF2t4izir1atntfVjxHKZpvH4FYgf3ZAlN5eNaPgMrWih2nus9sDVtoxGf9OIb6x9Bt00Cbei7MKtmwl+2xUwxIBVFqFoLZoSTyFbi8cNZD6ipY5Vh5hHd6HGh1xriSGoj3mKtTCItTHQ+H1qG5winWuu6608djl7ry9ejMGiK4iLRGOdkJa27rLlr9n3GrCWGvvBGhlc/cGpZx3LQ1C1Q1SdSk7Xr/c7gSHhHVEHjOpzy0y1nu9jW3YLl/KN6mHLMx1uJWJSdRKJFRawBvlvvPmiwQIiBFoFuF6I7dj1ORTWsICiwQLWrJPrRnvgHCdiogp9Hy10zEy1ugVsVr7aZ5ZUK1VM24g6QjfoK4smCxiZ3yDwCAMdP/CSRMKJkDC1EAexRh2T24mcqDbHEUHK0QEJW7Jz6waCIGhmd19z8GeZ7Fui+fFPP8aPf/oxAr+KjCndViq9XvUhUKFHRy7Dxz/yEFLqt7Q2Q0qN53l85Ifew7E7dlGtVHCrLvffc4AjB3dSLldiKl+9xgMYK58MCUNNsVDkofsP0dfdged7TbPAN4puJJLQ9+ntTPGZH3kfX/jcR7jj4DY8txSz/TefQuOw661gRpC3hpVNrzKbK6lUAvbs3MzPffHjWKZEh6pOALlaBtfK+i6l5PDB7Rw+uL2xALmcLTfGc6tcikBBKumwb88WbNMgVPotzexopdm6ZZgf+/QH6ezIUq3k2bhhkKHBfvwgWJt0qNbeEwKUJpOy+dTHH+Gzn3yUXCaBDvWq88w3ks9+5sNMTs3x3e+/zOM/9ADrhgcbdoqIFZa8rne3BUm5aFyRF1NHhJpMJsljH7iPdUO9PPbofZTKFXzfbS41NBRMW7NC161QKkVf1UolHu6OyjfElByiBafXKkopKlUdYemEauBSWd7atJKSIS4zmQZzc4ucvXCVT338/QSeRxCGBL5f3yV8s8vi+wFbNg0yPT3Ha6cuxnA0Ve8U3awiqHSI7Vh8/6mXefL5k5w+fY5iKdrCHgYhrXqsASVuHWOWfNs7IXrldBcIQiVIpxIEocJ1q5iGZMumQd73wFHCMCbiWY62V2SCnudxcN8OujqzdHVmufvoQe66Yy/vuecIuUyECBZvwoLUhssNEWCIRhLv5iSh2TTWZoQVuVyWb37rGWzb4sEH7yafL2GYxpuiRNRK49gWb5y5zNe//VzDkhl5050/tWRIS0Gg4MTJS4Rehc/9+McpFIqcOn8VJ+EsM6TqZQS6FrdsKvOdQVBZ29U2Nj7DidfOAfDk0y/SkcvQ3ZXBiEswDdF2UzG65v7CUNGRTZBKJXBsmxePv0EiYdHd1UHghW+pYO0HGs/XBKGqr8uqr826CfuCaVn8rz/+Oo++7z0MDnRTjXmuuVEfOo4mlNbYlkkum2jO5t+EAteyX7TGMjX/4Md/GNu2+a+/+5VoT1zjwsda4+TtB8C885IQRDRmaUhJLpfGcRKksx28ceYyhUIZYca80oQrJ8o0aK1IJBO8dOIcr54a4fVTV3jiyRe45+gBJqdmuXh5jGTCWUb/6jV3eAKQTAh6OlP0dufo6bCJRzzqVng1T6xjM2JISTqdZHx8gqefPc5j77+nvreu2QXoNYr0JgqDIBA4jhMTrasbJ1GimQ7O932++PmPY9smf/qX36avt4tUwmjYFdLotDXidkDDiJvEQEorTFMzPj7Dq29colKp4iQSLCwuNa2jEq2DOmJ5oV8i6fAXX/0eQRAyPDzEpk2buXTpEl1dnbpUKglR23656tVWSEOwlC8xMTnDRz/8CEoFBIHmy3/xhC4UK8IwRL3coUXDTjstEDI6x2vXp8gXKmQynTz34qvs3rWJYrHUQO+x4hOscO8RGENydXSSYtnFMGPlYTmOXVESEvWCH6lUor4R4Kc/93EAvvr1Jxkdn4k4EnXzOSx/nttmTYMjEk4aVauGiqApk1RhEPP8RVsvRSPBpTaX64axH9HUVlhpfD9AxuhkoSSJhIHrxaz8QsZF2GYAa/SzECk0SkkCFb1GlLgIDFGLw0ST+1p+AAQIFYFUQx8haqxWEt+vRmsSpFXDMTfQz4l6sbsptIi7PCr048K4iW5BDK3wIy2sB2FQxTTNmB+w1mGRdQhXjYdRsNwFithKbos1Dc0pv4g3Z0ZBt4FhGvXiriFNdN2FyaZYpx7HxEqoVYBtGcvORQqqrhdz4xHh5kTjDt64eBu/ptIaRIhlmU0QMR1x39ZvlG7ZNxkpkIy3XlpR/RENQuEkUqAD0GFM3auicWzBSnbShl3KCKLZEpYRL1q30Lk1jhPVlS/6OLZlRcpbj7RUfSwzOsxYw53r22gqTiwPSNf2rXm+i+95hCrQUkhhmBaOZSNNY/kG1G6eXl6yImqcLUGIH/jx+taovmjZNnbD4hrN8g7eRg2onUPge7iuSxiGSCkwTAvHTsUAWL3cX9XE45eiYQ44usm+5+H7XsTfYhg4jhMPPIk1kCzNVln5Aa7r1sMPy7IxLQdpWM20bw3zxI3Ubkpp3GqVMPBRWmlDmqJ2DhrRUkPVK4zCbYEHFDqoL572gpBSYYlycQnfdfF9X4QqGgZKJJNkO7rJZLOI2goqYdSBNNGN8CmVypSLRcqlPJ7rEqoosbEdh3Q2R7ajG9uJBnTQqokjWQqB5/uUS0UKiwtUK2VCVbv50Tl0dPWQyWSjjrbWIJY3skdPQ0C1WmVpYZZSsYjv+/WtSrVzyHV2Y1sWoTaW23EN2XXoBxQKBfILs/XP0HoO6XQnEglKRfvjGkZApQgpF0sszs9QrVRq5yAsy8I0TTK5TrIdnVi2g1KrFKZuN47o6Ma7LM3NkM8vocKQSrkc/c6QeNUqpUKBcrGI291HT39/DBaoQbcAHVIsFFian6VaKeO6VVSoouNDRaVcplQsUirk6R9aTzKVQqkGYsm4h5tfmGNxYb7peACvWqVSLlHI5+kbGKKrpzfiho7daeQOo3OYmbxOpVxqPr7hHCqlEr0DQySS6RhKH9GQCDSu5zM7dZ2lhQWCWHmlIVGhwqtWcatVysUiPf0enV198bC5angIQ5YWF5ibnqRUKKw43rQsKpUK1UqJ7r5BEokUQolmZ3RbWUAhCIKAwtIiiwvz0ebyapWhdevZsH6Y7p5ulAq5dPESly5eBmaQhqSnty++ThHbU7VcrCtfpVymo6uLrVs20dffB8Dc3DzHXzpOqVhkemKMwXUbcRynvrQmCAIK+cW68jlOgk2bNrJx04Z6WeP733uSwPeYiXlSenr7arNpgKRaKtWVD2Db9q1s3LSRZDJJ1fU58cqrLMzNUshHTP/9Q+sia6wVQkT1xoXZybry9Q8NsXPnDrq7OiiWKly+eIGRK1cBWJibRkhJZ2cvjZRH5VKemYnr9Wuwe/cu1m9YT6lYZHx8nJOvnsQECvk8AL0D63DsZNPAO7cFOZE0hGk6KAS+V2V+ZjKOuQKO3HWEn/iJHyWRTFCuVNmyZTP/6Fd+mcsjI1y5dBmlQpxECsuJs+EwpLAwx9LSIr7nMrRhI1/8wo8zNDRMqVQik83yq//oV5Cm5MQrrxKGIUJoUpkcGhOEpFSMrKfruqTTGT77Y5/myJ0HKVc8fM/nS1/6AocPH+L733uKMAwIg4BkKoNl2UihCQOfuZlJSsUiQkge//CH+NCHfoiq6+FWq3zg0ffzmU9/ku8/9QyVcokwDDGkSTKdooa3KBULzExN1q/BT33+J7Etg2KxxMGDe/mFX/gFTrx2kqmJyXhVa4CTSmLZCdAhKvSYmZygVCowtGEjv/gLP8P69YMsLhbo7enil3/pF8mXy5w5dTreJxdiWjZO0kEK3chj/e4kJ2pqxdVwacrHDzxdLpdRKiSb6+C+++7hzNnzmKbJxz7yKGfPXeCb3/prvvSlL5DOZqmUS5SLxTqeMgx8SsUCge8hpcH73vseSqUqs3PzfObTnyYMFb/1X/87jz/+OLv37CbwfarlMq4bcQdqFeKWi9TO4a5jRxkcGODc+RE+9NgH2bx5I7/xG/8fmzdt5gMffD8qVPi+T6mYR8SZe7VaoVwsEvg+27dv4667jvD6G2d46IF7OXb0Dv74y39KobDAj332U6hQocKQcikfgQNEtOWpsDRP4Ht09fTy+OPv58qVK2zatJkPPfYo33viaZ5++ml+6vOfw04kUCrEc12qlUocf0rK5TKF/BKmZfOxj34Iz/Xw/ZBPfuLjnL9wmS//yZ/w8R/+CEPr1qNUiO/7VMoFfM+L74fithzLDLxApFIp9h/YhzRMLl26zOVLVwAYHh7itddOMjszzbWxSe44cgf5pUVmZuZR8cakWpfg6LFjpFIJ5ufnuXDhEhcvXWb/vr2cPXOWhaUCpikZXr8ewzSZnJrG9zwSyQxoRblc4sCBfXR2dWJbJi++9DIvvPAyW7dsYOz6BK+88hp/2PEnABw8fJDr45O41QoqVJiWSaVUZv2G9WzZsgmA106e4tvf+k68IDvLG2+c4o++/JdkcznuOHKY6xNTFJaWCHwPJ5HC98p0d3Vy97E7AbhwcZTnnnmW9Rs38d4H7+fc+QuYlsmGjes5fOgg18bGWVyYR4UBYejVk5QPPf5DBEFAsVjg+PETTE1OMNDfzaWLl8kvLeJ5Hrt3b8exDcYnpqLrHwTYWt+ypph5awdsJEnHwEulOHrXHZiWhWFIpqamOX3qDE8//SyFfJ7cnt3s2rGNvt4eRkZGIgXUGqk1lhXt/z10aB/9ff0AvHLiVV56cZbvfPf7XBu9xsDgAHt2bWdoMM/lbIaZ2TnCMMqEzbjmt2PXTg4dPEAYBoyOXuOb3/gWzz33IlOTEQvWwX17cN0y6UyWuYUC1UoJxXLwv2HjRj7w6KOUKyU81+MbX/9rThw/QTqTplIusW/vLvr6eunIpiiWylTjRKsWY3ZlUzz2wfcSKkUQGLz4/AucP38BKSVLCwts2Lieo3feRU93D77vkc8vIQ2zPhNsG5r3PXwfiUQ66shcG2N8Yorvff85pibH2bN3N0fvPMDgYD9+oJiZncdJJAlVoKOZQ3F79YKjKS1Nd3c3vuczcm2CpaU8mUyWz/7oZ9i7bw9vnD5Pb/8Adx87QjKVIp/PMzszR6hCpDRQSpNOZzAti9HR68zPz2Kagh/52GPc9573cPXKZRKpFA88cB893R1Uqx6FpcX6psvaYpl0Nsfk5DQzM1MEQZX777+fj37sI4xfv06hVOGBB9/D5k1DGKaJW62gtcK2k8tLFVMZivk80zORsu7Zs5fPfvZT+L7H+PgU99x7D0eOHCGVTCOlge+5WI4Tt+ei7UaeH3Dt+hSlcsCGjRv47Gc/QzadZHTkCrv37Obhh95DT28PyaSD50edItu2QYeYhoHneYxcvU6xWCWb7eKTn/gQmzZt5NzZc2zcuIFH3vcQ27ZuIpPJIqXE933SSQcppLhV7vdtbcV1dXaOWo4TteJMWyQSGTQBjm1z+uSJeuZ27713c/jwPubnFymXq4RKkc2kePL7z3D+/HlMy6Z/cB2dXX2EKBzbZnz0EtMTE9iJBHfccZj77z9GuVwlXyji+wGDA30cP36Cl19+BRWG9A0Mk8nlSCQyKBFSKRa4fO4M0pDs3LmTBx+6n2QiwczcAq7rsX54gEtXRnnqyacp5JfI5jrIdfWS6+iKMtgg4NqVi5QKBYbWree9Dz/A8NAAU1MzVKoufb3deJ7H17/+baYmx5HSoLu3l66efhzHIVSwMDfF9MQ4TiLBAw/cz+HD+5icnKVcqZDLZujoyPGNb3ybM6dPo0JFrqOD3sFhEqkMhmFQLha4euk8SoUcPXaMBx+4m1LZI5/PY9sWGzcM893vPcvzzz2PV61iJxIMrtuAk0jGK700Qptveyvu7cuCE4lfMUzT0FpjmKYwTQe0wDQlQRhSKhaihXpK4fkBnZ2d/NzP/RyXL13ga1/9BjOz8xiGSVdXN8l0BtNO1HumpmWRX5zHNE28MNp0HirNP/nVf0TgeXz5j/+UkavXAE0mGxFVptMZDCOi0bVsi1KxAAgCpbBMk3Klyhe/8NNs3rSJL3/5zzh1+ixutRp1JEyLXGdX3X2bpkkYhGit6uDTcrnMhz/8OA89+AB/9fVv8NwLJ1haXMCQ0Sb3bEc3yWQy3nwU2QLbMqPuh1KUK1XuPnaYn/iJz/HkU0/zxHe/z/j18Trzf7ajg2Q6i2k5dcre3p5OQqUpFkt4vs+WLRv5whe+yMWLF/jG17/F+fMXUWGAUiGpVIpUJkeiZomRtyQLviVgBMdOCMu2owkGCcmEw9lTr7O0sEAylSLb0cG6oQEsy2ZhcZGxmBzcth3S2Q4yHV2YtfXz2iedTDI1NcHopQvYiQTpdIbh4UEymQyVSplLl66gwhBpGCSSSbp7B6IeLTJeZCgJvAoXz51GhSHpTIb+/j66OjsJVcjly1epVpZjtr6hdVFHpD5oBFLC9dErFPJ5Eo5Dd3cnPb29mKbF6OgYc3OzEau979PXP0CuqycqoQgJWiGFweLiDIXFBTzPJZfrYHh4AMdxmJqc5NrYOIaUuG6VbK6Dnv5BEokkhmmj4im3IKhiy5Dr41EosC6+BktLeS5fugwQgX0tm4HhDSSSSRKJREx6LnWNmdF3q+7C/NSmt8MCvu0uOPADbVoWqXQ6en+lI6XLJHnj9ZNMT0zUOwi1boJp2ViWRUdXN9mObizLjp7YOAGQQtPb08X4taucP39+xXk4TgRPSmUydHb3kUimEfGkWTSHoUilkxq/JE6dPkOlXIpjzDAGmEbvb0hJZ29/rHwmGqOOxDEMiWMZXL1ygfnZ2fqxKlTYiQSWZaHCkM7uPnJd3UjDwYj5BGUMrrBsyC/MMDU5VS8LNR7vViPl6+4bqPe3o5ZgRFMihSIMPJYWF5ifmcJ1q3WAh5NIxBbcondwHalUCsOyMaLdKBoVlfalIfFc721TwLfFBd91xx324lL+F5XSdhAEKgw8qWMSSGFI4fo+pmmyc+c2HMfGjyH4pmlGPdRMhp7+QTLZXNRMF2bzdk00ruuxbsMGBgcH8PwYaCmiHqyTSNLR3Utndx+W4yCk2dT710Lgeq7IZnNs2rQJw5D4foBhmFiWjeM4ZLKddPf1k0wmEaYZ0wmKOte6DhVaaDZvXEcy3UkQRpsqbcfBcRySqRQ9/YNkc7kI8WOYTdzQQmtUqOnq6aGjqydmsteR1U4ksB2Hrp5+unr7MSwb06y1AOXyCjOi98tls5i2g1bRnLJj2ziJBB1d3fT2D0Wu3zARhgla6SAIhOu6BEEQaq2lFGL68N5dv3b2/Hnv77ULbrSCO3fv+VKhWPlNIUFrEaK1kcnlcBIJrYUQSoFj22RSCTw/1NVqVajAjxB0snEOw1yr0g1ALpuOXY2LHwQRh2DjXLFc+5kLVUjCSZJOWrhuhGbxA4XQCuQyojjC060cVEcrhBRk0ymCUGvP90UYBCgVuVhdyzbXWhgYf4ZkwsGyTHw/IAh8wjCMFE1rQq2Rwlh7vECrGvpGC0IRBGFUcooHrlSo0EJG10EHOggC4bnVBhSCFpbgV8+dPf0favfu720W3Co7d+/5UrFc+U0dFdBCIbSRzuRwHCdavaJVbUoJKQ10TKqt8VtXWsV+QwohtK7j5ZuJT1aycAnBqsxIWqNjeEHj8VLIVc9Ba7H8vs2QZL2MkkCv+hka/3b1yZD6+cqGh6UR1t94rvVr8BaOr73/aspnoP/lhXNn/vm7ogyzmiXctXvvPy6Uy/9eCIlSOhRCG4ZpI0U0A6nRslVnVjBgte4sFAiBUDqCNouWDQYrdVLXcZt1RL8UQtXeu/X4VbZaNb1//f8t711rP9bGESJcbPQ5ldayPq5M3aOLtbiClvcKCiWkEGGoVn3/1uO1Uoh6pr18vFJKSENquQxMbVK+v+vY75ZYwLWUMGYHMHQYYpjWWBgG5bXhW3JYCzJai7CFXcDQYQhCnL/BKSigX0jZ3Xo8WhumaXhB4F++QYFehUGwxTBtJ6JyWPX95xNOYkWcUHWrgRTSrrqVjG3ZIM2Vxys1D0yv8f7KMMxMpVJabxgGhumsdfysYZipxt9ZppmrutUgDIJ0qEIHwHZSoWWZoWU7RqgC2ZnJ/udXX3npl99O5bsl1MCNSpgvlv99tGgyunG5TOZf9XR1/rf+3u5gtWPXr1+nvvqNbz/j+uGhuHpRq2IAar67s/PnH37g3q+MjV1fcQOnZ+fNZ597dmHHrj3/olgs/jNhGE3Hm6bhrR8e/NS1kStfu+vOI6nVjv/jP/j9/MMffPynC4Xib9aOr4V0OgzJZjP/8As/9flvBGGYWO38p6emvL/6xje/uJRf+mdmvP+kfg5hSCaT+ZcXzp355/fde1/XatdgenbevHZ9/NeKpdI/iDL5etgYZeuS3/mzP/jdL/3hn32lq/az3t5eB2B8fFwef+VE99Wro7+0sDj/aSeRTCZTUU20M5v5T7dC+W6JAjZ+wJ2793zJc72fD8Pw1Q0bNvzrZ5956tybiSM91/t5wIt/ZCOYXb9u3T95+qknT9zs+Pvuf2DX+MT4r6PJNfzYTqfT/+bUGyf/4M18hh279vwL3/M+0ngOlm1/5c3GTu954MGfGhu7/kutn2F4aPjn38w1uPue+x6Zmp76pz/oZ3jPAw/ecfXq6C8ZhrHXcZw/tJ3Ef3z9tVf02618t5IcvS7Xr1421m3aGgJs37VPJhOOnpyaZHBgcMXf1i7O9auXjYnrY3Urd9d9D/qNx6/2Pq+/9opuzOpefvZJC2Bo3XoFsG7T1rBvcFis9r6rnUPt+LdyDpWqKy6eO6VqnwGg9jlqx9fO8cChI6L1fVsVpPEchtatV7Xr2Hps4/sDNJ5D4zFvt/LdcukbHBa1f7fv2vc3Aka82eNr7/lmf/53+bl/0HP427hWtff6m75WW9rSlra0pS1taUtb2tKWtrSlLW1pS1va0pa2tKUtbWlLW9rSlra0pS1taUtb2tKWtrSlLW1pS1va0pa2tKUtbWlLW9rSlra0pS1taUtb2tKWd7/8/ztw30VG7rjyAAAAAElFTkSuQmCC",SmokeAlarmDevice:"data:image/png;base64,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",WaterLeakageSensor:"data:image/png;base64,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",MotionLightSensor:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAACgCAYAAACLz2ctAAAnj0lEQVR42u19aZAd13Xed+693W+dAWZAkAJBEFwELqBDLZQDCgTBxaxSXJKsyBXFSpVTjispu1KWHcsp+09ULkty9oqTVCWKEmexHSdVWSw5UqxoscUNVMhosyKSAoFgJwhiITDz9tfd95786O3e7n6DAUgZM5g+VSCIwbyHN91fn/U73wVqq6222mqrrbbaaqutttpqq6222mqrrbbaaqutttpqq6222mqrrbbaaqutttpqq6222mqrrbbaaqutttpqq6222mqrrbbaaqutttpqq6222mqrrbbaaqutttoso/oSXJm9fPAwAcDcXDe7dv3+gAFg9z27uL5CNQDfEpDNzXUpiiIiEjQajfSVguvYiVOSSBCzYaUU79i+zdRXtgbgTMC1Wk0BALfv3KFnAgrC1zrqgGjeU6rpXEii5dOnX+s1ms3gXe+4b1r1HqdOnxFRFFENyBqAGaiqwHDq1TPbGbgNzO8E0T1SiNtAdCsR5o3hBQCtircbM/MYwIiIToPNCRLysBB4MYqily5cuHS8CMxjJ07J8XhiNnLo3nAATL2Q7emOnzi1mUjsEVI8RiT2ArifDW9iMAAGmMHJpWI2K1xMkV1RKeL/EUImv9MPGPx9AH8cRdEzO7bf/MpKn6kG4HUIPABIvd3xE6dbSoknAPxlBj3BbN4WAywFGRlmwwAZgEUaaOPfecZ1o8STcfI7GUEgQCgSgBQSJAiCKADw7UjrzzObL9hgPHbilNxIQKSNBrxTp1+7G6CfBegjbPQdAGLvxiYCAG1ABBAoBRml/2HKEVZ5ITmGKCfwS76UvcIAgCBiIlJSqgyMWpuvCkn/4cj/O/Y/9j20R28kINL1XlikN/HkqdfeJQT9itb6o0RQhgECIsNMsWdjIiJizhBDGagA54spwtLLRw7cGAQqfH/sFi3vyQCMDUYlBRj4AYP/6euvn/+9NF+83oFI12txYQFvtzb6N4joI4IAE6d0IQCZgMF2bGmILcLO+poDKqsKtr/GDjgZDCKygzMTgThHshFCQEkllRTQzMeJ8Pe23XTjb1/vxQpdb15PCkF333WnOX7i1GYGfkMQ/QIDKkYFRcxGpaDLQcNESewsAKUUYmcDNA3mhJVRkr/GCtfp140gYqU8paRAZPj/RmH4aztv3f6V69Ub0vXo9V76weGPtFrN3xKCbkmysBBglaMmS+kcMMUgdEGWh1wq44jYAV/RUxa94WxAxmAEQMwMZtJSgD3PV1IQwij6/ek0+Pidd+y8cL15w+sCgMdPnla33bo9On7i1OYgjP6VUt5HhQDYIAIgQUxgSmDEBKIsNFb5tzKAMANoACHGceo9E4+a/k3BG1b9e1REdJITMABoQVJ6voIgOhNF0c/fsn3bF9Pi6npoZtP1MDLbsX2bOXjoyOO+7/8uEd0iKC0uIOObmt3XPFQ6YEn+mvPv4gJo4tDKMy9bluslITgN7/l7sfVvuGC388dC6Zy+S+R7nqekwDSM/sWtt2z7xeslJK9bAL5y6Ii4+647DQAcPHTklzzP++dSCIAojPM8okp02aE1KYWrQ2dVrldx6Zjz9iDcxo1bLa8ciqsKmxTCBCYGtBBSep6CMfzsdDL5yTvv2Hkh9f41AK8R+I6dOPXPmPG3hCAwswZDgmyvF/+WNefIDaU5fmaALHVjK4ZqdiFjAzJ5fV6cVAPR/ljsAp8Tb03MYCFibygEnQmC8P237rj5u+sZhLRei41XDh0RIPrvnud9WAgRsmHJYEEZ+IjKwLBvcgoU62ZndQlXXBmyX+iE3XJ+iMsAlVYqRqyix/GgdvEU+p7nMRAQ4S9s33bTk+sVhGK9eb7bd+7Q3/3eSw2p5Nc8z/swEYXGsGKwoDjfI9vz2b277GtElpcqtv7Y/Xt2nRkjD61cAhOt8hnnwq/86yn4nM8L23kTA+wFYaDBxieir796+swHb7t1e3T85GlVe8Afcth95dARIZX8mhDycSJK2iuUVAicBdOKG7hyLlfwYMyMOKxX9fd4xdeWG9EVns4pTorhuJwyMKefwfaE0J5SUkgJo/VP3LJ92xfXmycU66XaTXM+IcWXhJCPCyFCZvYSmgqDOL6rRPGNypwLpwyDvBbJPJoNjzIQOH+TigJhVmvF9Wim4oVZ3VPKB6n05/ijJ/mqk1oQA5BhFGmjNYSUXzh95uxj680TinWW//22EPJ9MfiMRzHgYs/n1hyJ56AMd3ZKSFbxEWPM5gzEYC2HYLZACaffl4G8It/L88z87+0wnr8HVcyaq/qGSfaahWPKQMiMz586/drdt926PTp24pSsQ/BbWHQcOnz0E0KKT0upClMNUA4mcivaqoYcEUourbLKpYoxnFscxP8eV1S4RbICg0vtGK4oiGcVMGyFZbtQgROOpVSSiI7qKHzgtp07ltZDs5rWw4TjxMnT7wvD8MtSKYtRkhUcTt5GVF2xFtu7KCWLLhqcHIzZqppnkxWKLcHq1svlpiFXnFtm14RIhFJITwj6n9tvvumDdQh+k0XHbbduj069emZ7EAT/SUgJgI0LPnJ6fO7NIyvP4viVpUwvi8GlW0o2AMj2rJwxqsgBbLHwyf1eHq7t9uSMxrT9vZUjwKRaztnaWU7IbDxtdMiMD5w+c+7X0whSA/AqTBvDADCZTv6dkHJLzGRJRmscoystEty+r01KpvxXwvpLc8MUIFwsMJiT1Cr1fvF7FmuJGNA2RYsKYMl6NslMhqqL8GLxQlXFSByCqQTZ9OfKChMwG6WNBhv+5MlXzzx0+84dei2DUKzVvG/3Pbv44KEjv0Sg9wkhQorbLWxXtjRjQpGDsLpSjVsaCSAdT2iHZCq6QqfOIEHO+zNbhQhTXmzAohwS5RNCpopMswLEVjUcF/Fc8vRJiyZNdskYrQ0bSCk/c/jwEe/2nTt0us9cA3CVzeYjx07eAeAfCiHBDJnXgEmlUQE+Stosbpsj77vZ4dUkXi1tcOQYzKtdZsqmsa6HQ5YXIssVs8FZ0iFJvBZV53FpCOWq5jS7RIUsjeCqlpDjOdOLIbXWodb6/ma7/WkASNdOawCuNgRr/XeVUk0QRfFSEDGRHXrJypfsMEvgzGNYIdTutqThjIprH9b9JHsIxm6Bk23JUQbcFKjF0mBWdevwFzhteNsEbXImIy57Jn2g8p899ep5j5BV/JnFx0+eem337Tt36HQ/pgbgCqH37rvuNAcPHXmcgI9KKQ0BkghMxFm7JQcOJV6KrTyNQcW2RSGXSguLPH+sIhmUq1TOkZZ5pgx46X13JnyF0OyshFjBV+RTwJy2VQ61Niir2ttceIExWhtjfGbzj4BcQqQG4AzLuW38m8k+rYa1AkmZR+CsenXbHrCKCs7IonkV67ZQcmyw08ROQUOU9rfZoa04PMJ0EUmQ24+2PR3ZDAi2+905SCnuqacPiJVUlHJCyjroxQSVLYosGIAwxhgp5ftPnDz9vt337OK1VpCIteT9gJhOL0i8l4TQzFCcVL32sCInBdgTB4sckIbF1FtYRUm8V85WyEPmRYsEUWO41Lsp5WEWsLlUHBRrILI+P+d5JeeviYv/nAzBFQxBdtg6XCqWLI9JzIYNM6RSfwcAxuOJqQG4gveTkj4uZELps8gF9mCeqNzSyMMzZ/ldkZaXRrGcfZxMMZwQmYI0915Z/ljh3cjxUim4cw9VLBjSaQ2VmfjVs2jrDQg2S6c4KqTiGoDlBdmAzcNr0QuKteT9Dh468rgg8V4hpGEmYU87mGMGc8aYEvHlNQbOIlHuKXPvlXq7lIZPqZcrNYtzP8YFyrwDGmuezAkRn00h1WP781DiUd3CwZiUrJAjPQ+vbE0N2ekXOvNlsh8Bq0FtfdTUCyqlPgYAKpso1QAEAATTIClO6WNCSBDZuR8VcqmclJRWvVXjXSfJtwoCojQ0V9SoGWmmmHsVQ2ACVIeDkFSndg7HgCCqbGSndZAQ9hcKrRaGxU20Ku/CNnwF6FKAEjMxmAQbQBvzgZOnXnvXju3bzFqpiMVaoVodOXbyDmb+cRICzFCItTGoSPt0PFaxgGCXP8dJhemotaAcmrnQdoHTF6ymzjsEGoupwlZfMN+Wi4EoLI9Wemu2inMr/+PCqHDlPZMytSt2kEyGTRhPmPTPAEAURVQD0GqQTsbjvySImkQUFdN6pzdrcwjIBiHsXkYeUjlVqapqyXHW1rE9mTPU4AKlkFHdy0O5Sex452wq4g5Eym7Y/h6buV14QGbuIVuJbv5DMQDJzFDK++DxE6dba2WbTqyV4oOIfiomHICYmZhzjh8RKomacQ/N9Wiw23wWenMgcZKL2fQ/topKdkFi4UQQICRBSoKSElJKKCUhhYQQBJF8ljQvZZuhwC65lUt7J5RhhdmuvtkipboPCBU9IRc66Q7ImcAmYuY7ElWwNUFUENd67AbE+i1E4t1CCDCzSLRTsnBlGOWb56Y61lojZVtoRdJLOUWkQgun0OrJ8jSCpwSkklBSZuCTIvmzkvA9H57y4HsKnhcDEohbOdmmnIUN26Pmjpsyj1256lncJYZFiHHGeEUPyQQmMglzJoyin1grRcg1pW77DZ8AYDQePyGlAEARwIos8ihlnHukQo9ZUp/3YjnzenkSz2XKX3FywDx7VSTzeNIhPeRVq0kcVuz5soIIEkrGIkhhFEFrnacTVAjflUtOBT6iozqDwvSm/F5UJME6nAUiNgCBHvvu915q3L5zx3RDe8C0Kaoj/WERJ2kUr1UW2yp5q8FmBZO1zW2LCjkVckXxUIW6IkhlEmoJJuFeGYB19npBgBQCUgqQIEgiKCGghIAQAlIQPE/B95S13ETlPqNdHFlpbBZiM69ZoP1zXjnnnMWcCMGFEV4SkcmwYSHozi1bFt8D5PqJGw6ALx88TLvv2cVHjp64AcB9ScgiR6PCJgPAbuxaZFDKw7KdtBcnJ5WaAxVUK6IYfKmUm2FAmzgNkNJDq+Gj4Sl4Ktb0kyIGnu978BKwCUGQUkASQUgJT3mJZC8jVSEqDNdgTbGTqhkVzUe7wk8a3g4pl0tcwsy7mmzkEiWRZO9aqIavWQiWMeK4Pxjc2/AbW0lIA47H+TYYCkR5tzlbEC4whrN7ZueK6bQjfa0xFVIYltcEA5HOd9CUFPA9D9PpGOfPXUS/v4zl5SVoHaHb7cL3m/A8DwuLN2Bh8xZ4noLWGlIKQBtoAjzPQxRpaKMLpTxnxYqtPlPcmivRFa0I4fZC7UZ16YfjWGGBoKPoEQD/+Fo3pa+ZBzx//gIBQBAEPyoEgQ0bU6lIAIt9Up4FU0oOxUoCaFwqLKr+jbRVo7VBPL0ySQgVePX0cfzpn34TZ868CgBoNBogISCERLPZxGQyxsGDL+Lo0VfQHwwgpUzmuvkTJCUVRoScF6tVH4zhpBhUWY6grNZquX+ikiCSYBgw457jJ063rvXS0jUD4PZbbo77gM3WfSIWFcq8lRDImrZCIB9jcXE0RtVV8czCo9yILibyxhgw4nyv2fQxHPbw0kvfwRsXzsPzPATBFFEUQimF6XSKC29cwGQyQbPZQrfTQb/fw7Gjh3Dy5PGkLWPPrQWklA790K6S0uVzVGyKZvmelWoQUYl4m14cLhImOGuKptTVndrobfbpTxsqBKf9P230n6N4XEGZt7IavuVAYgtKVuR35C6c28UHwWbCFBYuM/aMARtGo9HAoH8J3/zW82g2W2i3Wri0tIQwDNDr96CUB2bGYNDHYNBHs9mCEAJaa3S7XfR6SxgMeti1a3f8mUxavAiwkDCsC9MOy9tzoYkCu7dJ7rTF+TPD4Uw61UzanmIwkxECSkm5C8DR5Ngx3nBtmOdf+PacFOKWJIQSoaSTV2gql5fEK3L0SsmzGfJnBQdhYLSBEAJsIhw/fjQDVhCGWFxYADMjCEO02220mi2MJ2P0+3102h10u3MYDPoYjoa4ceuN0DrCxYvncMMNN2EchWAwBMXjQY7cPmMartOfiSyhpDQKWKRT6+eqqubJld/k4toqtGEIQfR2AF+5loWIuJYH/o3H45uM4W1ZVBCF2UDFnjaz+6swZCjQ6Vd3XWPwaRhtoLWB73s4evQQoijCXHcOJhmdtFpttNsdtFttEAitVhuLC1uwZXEL5uc3YW5uExYWFtFsNNHr9dDudLG0dAm9/gBSCau/SFmjOpvEWJ7aJBt3nDSxsyUnqzdIVGxukxVh2ZmLZ7tchSNOtNG7kgu/sULw+XPnKdmkvkFKUZCjsNMeyhaGHNIyuU3kbB+M3TBthyrmy0CQY/B5voelpWUcP3EM8/OboHWEMAwxHA4RhmH2itFohCAI0Go1MRgOMZlM0G61IKXEZDrBxYtvYDgaotvpYDqd4t5770cEDZPRwQSItPM5hSBLtzAhMdjECqLSIpPLxyikFyn7xwAk2EagABM8pbbExZEwGwqAUsrY5QmxmLAKDFIRZ0dNw6KoU/mcDipsVKYN4lyvwyUM86wamQ20Zmij0ZINLC+dg+f5MQiEQKfTged5CMMQ83Pz6HQ66PV7GE/G8H0fiwtbMB6PsLS8hM2bNuOGLR0QEabTKZrNJoJgivF4CM9vIdJRyiBErsxfHDEyiupxZG3vlZacqEr8KJ8WkXBSEWYmJgForReAa7srck1zQCJaFHFbQgOkbC9Y9FqzuhRU+F67PZP2yOw94EpPyAYmqUCNMQiCCbYsbsFoPIIggU63gyiKMJ6MsWnTZszPb8amTYu4dOk8Fha2wm90MB9N4Ps+iAQ63S6azRbOnnsdxjA8z8N4PESz2UYYuUSJ0s+IipXm4v4ysaPEmj2UbC87s1WkFDXQ4+fTGN4CXNtzjq8JAFPyiRRiU7r/UxxN2dK5zNUTjbwVwzOLFtvDgKtp78YAbOLiYzQa49LSEtqtFoIgQK+3jGmwCQ2/gTAMceGN8zDJ9w4GAywsbMWg/wbCMMR0OkWv38P8dAyjDYbDIfr9PprNJprNFhYWtiajvYLwUFFHiQBhSxoRJU12LpxIl6wUGI69nFWmlPfsGSVVTcLmZw+8oB7etyfakLNgz/caaduKrUXxqkLD5sVVSnFQub9HM3VbXBZoDMI4DQqCMcIwhBASnueBSCCKIoRRiE67kwCvB60jtNsdnD37Gs68/hqCIO4FEhGWl5chpXRCdxBMoZkTGn484ssYgpTLfbg60XDywdSMI5qQC2RlGYcpEi64UixTEHndua7csGwYq6qlYugthdsK/T3mcjizx1AlyZcsba+amQJaR5CC4Ptx/jc/N4+57hwmkzG63S42bV5EFIa4ePECPM/HDVtvwWTSw4Xz5+D7TczPb0a73ca5c6/DGIP5uXn4no/JdAJKXJQ2ceskrYKdT0JlDdUi+Jwq3yrGuESuIJfnmLcC41HkGtFGu6YADINwyi2Dqr0uLlxMW7G0MjfkoqxaRR45g12Xfk8YRSBmRFGEwXCARqOBht+AYca58+cRRRq+7yMMQ5w7fxZBMIUQEmEY4Oy51zEaD5M5ssalpSW0Wi10O10AQBSFiZcz+aQCK9H+XRoaJ/slpihBV6kpaFO8yjvR6cjRMIfddnPjjeJSQog2ZrlYVBgugg+Xb9IzrkAgfPaeh440iAhKKYRhiDAMwczwPQ9aa5w7fxaDQR9SKgyHQ7x+9nWMRkMQCQRBgDNnzqA/6CeLSAb9fj/LF+fmNyWg0M6qZ1XakBVRNjW/0Hinwl50mWzovs6WheN8j2lp1647ww3rAZn5YtoCqwaFlf/MaOQRFW8ECpp8uBJJOAgDLC4sotdbhpQKRIROpwulPCz3ltHtziW/utmfm80m5ubmce78WXTaHbRaLSjlxWAUAu1WG5s334AgCAAS1WfPFU+D4GLakCz5plt2jj+3luLThqitbZiCl1Mx7RiD2kTLNjVuw3hArTUn4eiiiRcoqLI3bC0YlZRbKiIPYTYRgWi2SGwa4g0bTEODbncuHsexQa/fw2QygVISDd/H0vIShsMBOAnV586fxXA4ABAzZAbDQfL3Bu1WG0vLSxCC0Gy24ka2XWlUnc3kUPTzfLBaWbionsB5z49RIPBmXEqywvolAEhmwRvHA269cWuibMYXwjCM0uNUbTnnqhX/qsjqqqGwyyJOfMNKkxAiASF0Vl6GYYDGXBd+o4HRaAQAGAwH8H0fJiEfjMfjLBfs93uYTqfYsmULAGAyGWMyGWN+bh4kBEajIbbe+y4EYQRj2Jp2iJKMdWmxKq/TrYcu16Sefdii26AvFHAZVcPz1NmEfiayHYONFIJbrdZZBveZeUEIwUm4peKIrUoZ2e1zFRbNyeIY8yzw2QgXTvI+nQTYuvVmnH71GOKDpCWU8kBE8D0P48kEc3NzaPgNtNttjEZxw7qVeDmtNZrNFibTCe7adQ82L2zGcDCyGseisggqy37AmWYg4zMmTXNLjiQ+KMDuDFDlsrrdnA+C8Gj87xveUEVImm986Y/+11BH+jjHLGF29nBRrmDZmn2mxE6uAFi+cUYzK01XxkM4rY0gmEJr4G1vuxmCCJHWWUHSbDbR8H1EYRj3AltteJ6HpeUlRFH85067jYuXLmJh8wJ23HoHhoPRZdIAVALSbSORQ1Gztz7Y6hvaQuqp+FFGgs30E+P73mo2X7GVKTZUI/rpZ74hPvWpT5ggDA5FWmfnUFUdUlC6cTTrhCG3ncMFTuAsLxNToiwWLGKyAaiBt73tZot4Os5oU8u9XsYPJCJMJmOMxiMYozEYDhPw7UK/P4pp+Cl7hUSZ1Uzl6U4p22B3DlzMi51wy+SE3nQ1NKdvsWBmLSQdx0bdihNCpknQizqKSq06R1GAXdwxk3PSZTFB54KqwuUKkfhYLglPKseLpCB8+51344YtN2AynWI6nUIpD61WPPXwPB+ddgfNZgvj8RjGGNx55y68/a4fwXA4hDEmXlwngpACRBWDBybH07FbgcBWB67iP2bsaOewnaruZ7zzH4NSnzn96pnXbEH4DZUDGqNTrajvhFEELlTClZts2aKSOx9eycPxiu/JToiSSkIqDzoKMxAOhyN4vo+bb7kDRk8wnUwQBFNIKTEejxAEU/h+AzduvQmNRgPtzgKElOj1elBSQSmV7JuIUu5H5IbP0tGvxcEh56xn5zRhu00TnwlfKQfMWcLHgoheenDPA/1rfZjNNQNgWglPxuPvttutS8xmgUiYZHxEXNkuqV4kn1VkXLYXyORwDDPAANDJ5IIICIMAURhAeT78xhxa7bl4bTPV+BAewBrGCEynUwgp2fd8EkKAkiKGhJg5gakQayjtIhQLMXe6UV7Asp/YjGWd0KyNMWDDBzb0Wubue3Zx0gA987+f/9b3ojB81PMb5QPts5OKeHYrZcatWKHurRgeEIQQ8DwJwwaAB2M0YExGdwqDAGEQ5NOJZKbFJhYY8BoNNBsNeEqRSDbmpBSINW/IWpl0vXfl7gdRfEI1F05rsompPCMkp4M8snUGKV28E2ANw/yNa12AXHM2zMU3LgoACMPwT4IgrD5O3BrNzawiV3iGaUY4rvKucctFwZMKQsb/n4KMKBcfymhcWsNoDRIiA1/D9yETT6o8mYHPXa0sh8ZyLusynwVZZ8Q5W/epqgJZKLYUI1xPy8wsDOPVpUtL3wSA9BTSDQnAdCJijPnj6XQKZpbFM0+L8ryYURDPVEEgXOa41VyqXohYyUAqCZVUxcrz4Hk+pPJAQjgrkUQE5floNVvotjtoNVvwvFghQSqVFBw0wy/PDsdlJpB1Egrlyhz5BIfBhXaVc3xEDNyYCGMMADrw4J4H+qk41IYF4CP79xoA+PqfPPl/wjB8WUdhdkgGVVSqlaqmxbYNXSY/XGEiIiVBChnLbnhe7AkpBmLqET3Pj381Gmi3O5jrdtDpdNBqNeH5HoRUICELeg6zzxkmoKR+gELlnyk7VKmgFpQiHK3D7BXEFKsiCDYGYRh9DsjFoTY0H/DAcy/IfQ/t0T/2xGOfm0wmu7tzvmGTbRJS1WI5W6e0mRLZtIrW7871Zu6HkEAsURgfwi6FgDYm3hXm/IwbKVRcMUsJTwmQUAWeokuOFSuMArkIRir8JJRPdAyvPO/OpiREzlK/JYskGPxqv9f7MrA2FPPFGjgRiZN55H8ZT6ZgY1RxS5BmVHlcCs08w/tVlydcOD09ngsjEReSUErB8zz4no9Go0GNRoOajSb8ho+G78PzFEh4lVyK8uegVa2HOnxZuIxwQW6xUtSidPQTE/Y1cgKCMUZjOgm++uCeB/rpeXwbHoCP7N9rXj54mB5/7OEXozD4WhAEICJDhZMwLnPbcAVcxEq952wQQzIToow9nIJSHjyl4HteluPFuoGyIp2jGcUSr6pqcmuI/L0M28M3lwKZydGVBN3T0QcxmKXWGtro31kL1e+aUslPq+HpNPjsaDziZA+WV4suuoo562yqVpJ1CZE0piWUIkgVV7Q58OiycKo8lN3OzKi8DWedQpb1PcuslqqHx9a8zublHMsdgw0biiL91Dvvv+/ZVBi+BmBi+x7aowHgqSef/sPRaPSD6XQiicgUWOkzHR6vpsqdwb0rixqlS+Pp73GOF4NOVBz/sLqHgiuKkqIM3Szlh1lCSvY6QnGhK23ZUExzYx1FANFngLV1cuaaOUM2LUaeOfD8T3c67d9bWFjUbFhZakSzuW9cxRG8DAULlxetXOm706ayvT5qz6ffxLpCac8FlUKa5PRIK3aumZmJiCJjtAqm0+/svveuB4D6sMIVvSAb858TL6hIkOaCF6SqS07FH4pWOLAGM3VnSl+j2V7XXgp3D9ShVfX2ZnsDKj1F9lERZJ3UCVop/HMm5BuFERj0D4C1oYy/Zk/LPPDcC/KR/XtNFEafHA6GlUGXV+HIGVwZZ9n5f3dhmyrfjlYVJ2a2msk91mt1IkmlJw4lokuiM108ZKciJmijI6W1fuq+e3f9N8A+kbQGYKUXfPngYXrs0X3/dTQefXU0HEghEgWflVkFV5RkUIWH5FmHBRbKjVksnZlimIUHYlXRmaoU+6l08GZGNK3IkhOxdxmGEcIo/HUgPxajBiAuq5wFo/Wv9fsDGK2VpZzPV6lBM9ND8ipcE1doVFdNLKqkgfmKsu78JMzinohxKmD3QG0uz70JgI6ikKIo+vfvvP++Z9PDwGsArqIveOC5F+Sjj+z7XhBMf3O5t5ws08bp3wp594qK+LOLjjdXh1W1UlZ6EKooWFRIPkvMH87VE8hey7RWNym9PDENRhsdqel0eubCG2/8KrD2zglec1XwLHv2wPPfXFjY/J52pxsZw+n23GUaILzqniC9RVdgNe9VVOy6kpvEM5Rf8xEesZUy6MlkrMbjyYceePf9X0g7DGvx/oq1CrwDz70gAUDr6G/0B4MgCgMlBJni/WBefT7IhRkW0VvzLK6mEV45l14tuCuY0Y5XjWlW6UE/OggCNQ2Czzzw7vu/cOzEqTULvjUNwH0P7dHPHnhBPfrIvu+FYfTX37h0CcZoLqqx2Ztxl2VcEUqiRFc10uOrgC3jzaSxs19lLf0SURSFgZpMJ9/8/B/84S+u5dC7bkLw0898Qzyyf6956pnn/nW30/25xcXFiAHFnB5oGNPMrzSsrbYh/ObDdtnjUaGavZqPbb2OU/AZHanhaHTp0qWldz+6f+/xtRx617wHRGF35NH9D/38cDj84nJvWYn4TOEk9sQV8lsJvlncvCvZ7V2JoeOEVL4SGZEZe1pE2mitRqMRRsPRX3x0/97jzx54Qa118K0LAO6+Zxc//cw3BADMb9r0kUF/8K1er6eEoAhUodt9hWCc+a38ZkMLzVR1dc9YL4f01XSGkkKYADLGaDkej7G03Pur733wPc9ca9XT6yoEF2fFTz793KJS8tlN8/O7u3PzETNb4fiH+/P8WZzmQqsUo0N6+CVrMRoO0ev3/+a+vXs+e+zEKbnWph3r2gPaRcmB516Qjz3y0MUo0g8v93ov93s9RURRskBGl3N+b7blwlfkQoGreSaKpyLNAh8BUQq+fn/wsfUIvnXlAas8oSD6o7n57oObNy1EIJLGGPu84Rn8mLeGtXINzKl2dRSqwXCI8Xjy1/Y++J7fXY/gW5cAtEF4+PAR77UzZ/+g0+l8cPPCZi2EJGNYpFJv1v7YitXs1YBxNa+5WpC7VXLWYE4P99FhMFX9/iAajkYfeuTh935pvYJv3QLQBiEAPPX0gX/SaDR/ZXFxAZ7fiDiemKDMJbxawPAP51JVvS1XLtQRQIYIZjIeqV6vf3Q0Gn3o8ccefnE9FRzXFQCBvEcIAM8ceP6nlRSf7Xa7nW53Lkq0QoWlFUp/ZiB686UGu1M2iuI2yxCj8fjzYPzMg3se6K938K17AAKxvvHFNy6KfQ/t0U8+deDtQoj/2G63Hty0aROU50fJsnsFv/gqkPPDcoSu57VPxTMENtNgqoaDYTSdTn/5ob1//l8WI0ANQKwF0kLuDZ586sDfbjT8T3Y63U6n24UQImJmmbLoS0RAmk25/zMtMrJDLuNwG4WBGo8nGI1GTw1Ho1944vH9L6cnja6FlcoagCuE5CefOvB2EvSrDb/xc51OG+1OB0LI2COydUYWskPIr9LdXb7IuWzXJW+7MBGMjkI1Go0xGo1eDqPo7+/f9+DvFx+y68WuKwDOKFDeQSQ+7fv+Bzud+LxfqWRoDGRyQmfZK76ZmMu2guvMaM+W1jgoPrcVqccbDodnDJtPffXLX/s3n/rUJ0zx4aoBuE68oZSSciA+96CQ4pelVD/VbrfQbrXgeX6UuB6R7M/S5fmGV41NR9KeiEy8g2VUGASYTCeYTqZHtda/denSpd/5wPvfN7yecr0NB0AbiIAlhPTksz8iBP2s7zf+iuepbc1mC42GD6W8yBLSE4Uwmp2L5YTWGdHXCuv2lJeJ4qMQ2BgVRfHpmkEQRtPp5MkgCP+tUt7n0hB7vQNvwwBwFhCff+Hbc+Px+Melkj+ppNrveWqb7zfgZ5ovyhDBUL74LkqCzuXLydZRZPnenTHSmFhpfxoE0JGOoij6fhAEnwvC8HNPPL7/5ar0YSPYhgHgrNAMAE8+/dyiEOJBNvrHpFT7pRT3ep7XUZ4HKQSUUpBSZiqqrviKfe61TmTkGGEUwWiNSEcIQw025uh0On1JKvmlYBocePyxh1+saiVttPux4QBYvOlaay4m91/56te3zc/P75pMJj9Kgu4SQtzmKe8WZl4AeJ6E8IQQ0hVdNxqMPhEth2F4kcFH2JjDxvD3tTEvTsbjE2leZ3u7qn+/BuAGBSOQKzSgos+4vLzU8DxvXiq1oKTwcvCxFlIOmo3GG41mM3jXO+6bruR9NzroagCuApDnz50nKSUBwOKWRXOljd+nn/mGEEIKIrDWmrfeuJWvl+ZxDcA1AE7MWB2oQVZbbbXVVltttdVWW2211VZbbbXVVltttdVWW2211VZbbbXVVltttdVWW2211VZbbbXVVltttdVWW2211VZbbbXVVltttdVWW2211VZbbbXVVltttdVWW2211fYm7P8DYE6Yl9S34s0AAAAASUVORK5CYII=",WindowDoorSensor:"data:image/png;base64,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",CFMT:"data:image/png;base64,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",PowerTagE:"data:image/png;base64,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",ButtonPanel:"data:image/png;base64,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",BoilerInterface:"data:image/png;base64,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"};const m4="data:image/svg+xml,"+encodeURIComponent(''),b4=Object.assign({},y4);const w4={autoResize:!0,height:"100%",nodes:{shape:"box",color:{background:"#edf2f8",border:"#c9d5e4",highlight:{background:"#dce9f8",border:"#5288bd"}},font:{size:14,face:"system-ui, sans-serif",color:"#26364a"},margin:{top:14,bottom:14,left:18,right:18},widthConstraint:{minimum:100,maximum:160},borderWidth:1,shapeProperties:{borderRadius:12}},groups:{Controller:{color:{background:"#dceee6",border:"#91bba7"}},RoomStat:{color:{background:"#eee6f2",border:"#c9b3d5"}},iTRV:{color:{background:"#f7eadc",border:"#d9bc98"}},SmartPlug:{color:{background:"#dceef0",border:"#94bec4"}},HeatingActuator:{color:{background:"#e1e9fa",border:"#aabce0"}},UnderFloorHeating:{color:{background:"#e1e9fa",border:"#aabce0"}},Shutter:{color:{background:"#e7ebef",border:"#b4bec9"}},OnOffLight:{color:{background:"#f5efd9",border:"#d6c68e"}},DimmableLight:{color:{background:"#f5efd9",border:"#d6c68e"}}},edges:{arrows:{to:{enabled:!0,scaleFactor:.45}},color:{color:"#8a9bac",highlight:"#5288bd",hover:"#5288bd",inherit:!1},smooth:{enabled:!0,type:"cubicBezier",forceDirection:"horizontal",roundness:.45},width:1.5,font:{align:"horizontal",color:"#66788a",size:11,face:"system-ui, sans-serif",strokeWidth:0}},interaction:{hover:!0,dragView:!0,dragNodes:!0,selectConnectedEdges:!0,zoomView:!0,keyboard:!1},physics:{enabled:!1}};const A4="data:image/svg+xml,"+encodeURIComponent('');async function k4(t,e,i){const n=i||(await t.callWS({type:"wiser/hubs"}))[0];if(!n)return;const[o,r]=await Promise.all([t.callWS({type:"config/entity_registry/list"}),t.callWS({type:"config/device_registry/list"})]),s=new Set(r.filter((t=>t.identifiers.some((([t,e])=>"wiser"===t&&e===n)))).map((t=>t.id))),a=o.filter((i=>{if("wiser"!==i.platform||!i.entity_id.startsWith("sensor."))return!1;const o=t.states[i.entity_id],a=null==o?void 0:o.attributes;if(!a||null==a.node_id||Number(a.node_id)!==e.id||void 0===a.displayed_signal_strength)return!1;if("Controller"!==e.group&&a.product_type!==e.group)return!1;const l=r.find((t=>t.id===i.device_id));return!!l&&(s.has(l.id)||null!=l.via_device_id&&s.has(l.via_device_id)||l.identifiers.some((([t,e])=>"wiser"===t&&e.startsWith(`${n} Wiser `))))}));return 1===a.length?a[0].entity_id:void 0}function E4(t,e){const i=t=>"number"==typeof t&&Number.isFinite(t);return 0===t&&0===e?{}:{rssi:i(t)?t:void 0,lqi:i(e)?e:void 0}}function C4(t,e="horizontal",i,n="none"){var o,r;const s=new Map,a=t.nodes.filter((t=>"Controller"===t.group)),l=(a.length?a:t.nodes.slice(0,1)).map((t=>t.id));l.forEach((t=>s.set(t,0)));for(let e=0;e"Area"!==t.group)),s=new Map(r.map((t=>[t.id,t]))),a=new Map,l=new Map;for(const e of r){const n=t.edges.find((t=>t.from===e.id&&s.has(t.to)&&i.has(t.to)&&i.has(e.id)&&i.get(t.to){var i;const n=c.get(t);if(n)return n;const o=null!==(i=a.get(t))&&void 0!==i?i:[],r=Math.max(e?115:65,4*ai(s.get(t).label).length+30),l=Math.max(0,...o.map((t=>d(t).radius))),u=o.length?Math.max(r+l+h,o.length>1?(l+h/2)/Math.sin(Math.PI/o.length):0):0,f={radius:u+(o.length?l:r),orbit:u};return c.set(t,f),f},u=[],f=(t,e,i,o)=>{var r;u.push(Object.assign(Object.assign({},s.get(t)),{x:e,y:i}));const l=[...null!==(r=a.get(t))&&void 0!==r?r:[]],h=null==n?void 0:n[t],c=t=>{const e=null==n?void 0:n[t];if(e&&h)return((Math.atan2(e.y-h.y,e.x-h.x)-o)%(2*Math.PI)+2*Math.PI)%(2*Math.PI)};l.sort(((t,e)=>{const i=Number(a.has(e))-Number(a.has(t));if(i)return i;const n=c(t),o=c(e);return void 0!==n&&void 0!==o&&Math.abs(n-o)>1e-6?n-o:s.get(t).label.localeCompare(s.get(e).label)})),l.forEach(((n,r)=>{const s=o+2*r*Math.PI/l.length,a=d(t).orbit;f(n,e+Math.cos(s)*a,i+Math.sin(s)*a,s)}))},p=r.filter((t=>!l.has(t.id))).sort(((t,e)=>Number("Controller"===e.group)-Number("Controller"===t.group)||t.label.localeCompare(e.label)));let v=0;if(p.forEach(((t,e)=>{const i=d(t.id).radius,n=e?v+i+h:0;f(t.id,n,0,0),v=n+i})),e)for(const[t,e]of a){const i=u.find((e=>e.id===t)),n=(t,e=t.x,i=t.y)=>{const n=ai(t.label),o=Math.max(40,4.5*n.length+12);return{left:e-o,right:e+o,top:i-42,bottom:i+72}},o=(t,e)=>t.lefte.left&&t.tope.top;for(const t of e.filter((t=>!a.has(t)))){const r=u.find((e=>e.id===t));if(!r.area_id)continue;const l=e.filter((t=>a.has(t)&&s.get(t).area_id===r.area_id)).map((t=>u.find((e=>e.id===t)))).sort(((t,e)=>Math.hypot(t.x-r.x,t.y-r.y)-Math.hypot(e.x-r.x,e.y-r.y)));let h=!1;for(const t of l){const e=Math.atan2(t.y-i.y,t.x-i.x),s=Math.max(150,(n(t).right-n(t).left+n(r).right-n(r).left)/2+20),l=[0,1,2,3].map((t=>({inward:s+90*t,side:65})));for(let t=1;t<5;t++)for(const e of[1,0,2])l.push({inward:s+90*e,side:65+130*t});for(const s of l){if(h)break;for(const l of[1,-1]){const c=s.inward,d=l*s.side,f=t.x-Math.cos(e)*c-Math.sin(e)*d,p=t.y-Math.sin(e)*c+Math.cos(e)*d,v=n(r,f,p);if(u.some((t=>t.id!==r.id&&("Controller"===t.group||a.has(t.id)||t.area_id===r.area_id)&&o(v,n(t)))))continue;const g=n(t),y={left:Math.min(v.left,g.left)-18,right:Math.max(v.right,g.right)+18,top:Math.min(v.top,g.top)-110,bottom:Math.max(v.bottom,g.bottom)+18};if(!o(y,n(i))){r.x=f,r.y=p,h=!0;break}}}if(h)break}}}for(const e of t.nodes.filter((t=>"Area"===t.group))){const t=u.filter((t=>{var i,n;return"Controller"!==t.group&&(null!==(i=t.area_id)&&void 0!==i?i:"")===(null!==(n=e.area_id)&&void 0!==n?n:"")}));u.push(Object.assign(Object.assign({},e),{x:t.length?(Math.min(...t.map((t=>t.x)))+Math.max(...t.map((t=>t.x))))/2:0,y:t.length?Math.min(...t.map((t=>t.y)))-110:0}))}return e&&li(u,new Set(a.keys())),{nodes:u,edges:t.edges.map((t=>Object.assign({},t)))}}(t,"area"===n,s,i);const h=new Map,c=Math.max(0,...s.values())+1;for(const e of t.nodes){if("Area"===e.group)continue;const t=null!==(o=s.get(e.id))&&void 0!==o?o:c;h.set(t,[...null!==(r=h.get(t))&&void 0!==r?r:[],e])}const d=[];for(const[o,r]of[...h].sort((([t],[e])=>t-e))){const s="vertical"===e?"x":"y";r.sort(((e,n)=>{var o,r;const a=e=>{var i,n,o;const r=null===(i=t.edges.find((t=>t.from===e)))||void 0===i?void 0:i.to;return null!==(o=null===(n=d.find((t=>t.id===r)))||void 0===n?void 0:n[s])&&void 0!==o?o:0},l=a(e.id)-a(n.id);if(l)return l;const h=null===(o=null==i?void 0:i[e.id])||void 0===o?void 0:o[s],c=null===(r=null==i?void 0:i[n.id])||void 0===r?void 0:r[s];return Number.isFinite(h)&&Number.isFinite(c)&&h!==c?h-c:e.label.localeCompare(n.label)})),r.forEach(((t,i)=>{let s=i-(r.length-1)/2;d.push(Object.assign(Object.assign({},t),{x:"vertical"===e?s*("area"===n?230:170):o*("area"===n?300:270),y:"vertical"===e?o*("area"===n?300:150):s*("area"===n?260:110)}))}))}for(const e of t.nodes.filter((t=>"Area"===t.group))){const t=d.filter((t=>{var i,n;return"Controller"!==t.group&&(null!==(i=t.area_id)&&void 0!==i?i:"")===(null!==(n=e.area_id)&&void 0!==n?n:"")}));d.push(Object.assign(Object.assign({},e),{x:t.length?(Math.min(...t.map((t=>t.x)))+Math.max(...t.map((t=>t.x))))/2:0,y:t.length?Math.min(...t.map((t=>t.y)))-110:0}))}return{nodes:d,edges:t.edges.map((t=>Object.assign({},t)))}}const x4=t=>{class i extends t{connectedCallback(){super.connectedCallback(),this.__checkSubscribed()}disconnectedCallback(){if(super.disconnectedCallback(),this.__unsubs){for(;this.__unsubs.length;){const t=this.__unsubs.pop();t instanceof Promise?t.then((t=>t())):null!=t&&t()}this.__unsubs=void 0}}updated(t){super.updated(t),t.has("hass")&&this.__checkSubscribed()}hassSubscribe(){return[]}__checkSubscribed(){void 0===this.__unsubs&&this.isConnected&&void 0!==this.hass&&(this.__unsubs=this.hassSubscribe())}}return e([Ln({attribute:!1})],i.prototype,"hass",void 0),i};var I4={"common.version":"Version","card.title":"Zigbee network","card.description":"An interactive map of your Wiser Zigbee network","card.hub":"Wiser Hub","card.devices_one":"{count} device","card.devices_other":"{count} devices","card.connections_one":"{count} connection","card.connections_other":"{count} connections","card.controls":"Network controls","card.fit":"Fit view","card.tidy":"Tidy layout","card.link_labels":"Link labels","card.save_layout":"Save layout","card.load_error":"Unable to load the network. Try refreshing.","card.updating":"Updating network…","card.empty":"No devices found","card.unknown_device":"Unknown device","card.hint":"Double-click to zoom in or out. Drag to rearrange. Tap a device for Zigbee details. Long-press for More info.","map.accessible_only":"Interactive Zigbee network map. Double-click a device or empty area to zoom in, and double-click again to zoom out. Drag to rearrange. Tap a device for Zigbee details. Long-press for More info.","map.accessible_list":"Interactive Zigbee network map. Device and connection details are available in the list below. Tap a device for Zigbee details. Long-press for More info.","map.accessible_details":"Interactive Zigbee network map. Tap a device for Zigbee details. Long-press for More info.","layout.storage_error":"Browser storage unavailable. Copy the layout into your card configuration.","layout.device_list":"All devices & connections","editor.auto_update":"Auto refresh","editor.show_device_list":"Show all devices & connections","editor.orientation":"Network view","editor.loading":"Loading Home Assistant controls…","signal.connected":"Connected","signal.online":"Online","signal.offline":"Offline","signal.no_signal":"No signal","signal.very_good":"Very good","signal.good":"Good","signal.poor":"Poor","zigbee.type":"Device type","zigbee.node":"Zigbee node ID","zigbee.parent":"Parent node ID","zigbee.channel":"Zigbee channel","zigbee.signal":"Signal quality","zigbee.device_rssi":"Device RSSI","zigbee.device_lqi":"Device LQI","zigbee.hub_rssi":"Hub RSSI","zigbee.hub_lqi":"Hub LQI","editor.map_height":"Map height","card.show_detailed_view":"Show detailed view","card.zoom_in":"Zoom in","card.zoom_out":"Zoom out","editor.group_by":"Group","card.unassigned_area":"Unassigned","editor.show_labels":"Show link labels","editor.link_status":"Link status","editor.links":"Links","editor.both":"Both","signal.medium":"Medium","layout.config_save_error":"Unable to save this card’s configuration. Use the card editor to save, or copy the layout YAML for a YAML dashboard.","editor.magnifier":"Magnifying glass","editor.lens_size":"Lens size","layout.copy_error":"Unable to copy the layout. Check clipboard permissions and try again.","panel.menu":"Toggle sidebar","panel.settings":"Panel settings","panel.description":"Customize this panel. Dashboard cards keep their own settings.","panel.editor_error":"Unable to open the editor. Close this dialog and try again.","panel.save_error":"Unable to save settings to Home Assistant. Please try again.","layout.paste_error":"Unable to paste these settings. Copy settings and layout from a Wiser Zigbee card or panel first.","layout.paste_save_error":"Unable to save the pasted settings and layout. Nothing has been changed.","layout.paste_hint":"Paste the settings and layout copied from a Wiser Zigbee card or panel below."};const S4={"en-US":I4,"en-GB":{"common.version":"Version","card.title":"Zigbee network","card.description":"An interactive map of your Wiser Zigbee network","card.hub":"Wiser Hub","card.devices_one":"{count} device","card.devices_other":"{count} devices","card.connections_one":"{count} connection","card.connections_other":"{count} connections","card.controls":"Network controls","card.fit":"Fit view","card.tidy":"Tidy layout","card.link_labels":"Link labels","card.save_layout":"Save layout","card.load_error":"Unable to load the network. Try refreshing.","card.updating":"Updating network…","card.empty":"No devices found","card.unknown_device":"Unknown device","card.hint":"Double-click to zoom in or out. Drag to rearrange. Tap a device for Zigbee details. Long-press for More info.","map.accessible_only":"Interactive Zigbee network map. Double-click a device or empty area to zoom in, and double-click again to zoom out. Drag to rearrange. Tap a device for Zigbee details. Long-press for More info.","map.accessible_list":"Interactive Zigbee network map. Device and connection details are available in the list below. Tap a device for Zigbee details. Long-press for More info.","map.accessible_details":"Interactive Zigbee network map. Tap a device for Zigbee details. Long-press for More info.","layout.storage_error":"Browser storage unavailable. Copy the layout into your card configuration.","layout.device_list":"All devices & connections","editor.auto_update":"Auto refresh","editor.show_device_list":"Show all devices & connections","editor.orientation":"Network view","editor.loading":"Loading Home Assistant controls…","signal.connected":"Connected","signal.online":"Online","signal.offline":"Offline","signal.no_signal":"No signal","signal.very_good":"Very good","signal.good":"Good","signal.poor":"Poor","zigbee.type":"Device type","zigbee.node":"Zigbee node ID","zigbee.parent":"Parent node ID","zigbee.channel":"Zigbee channel","zigbee.signal":"Signal quality","zigbee.device_rssi":"Device RSSI","zigbee.device_lqi":"Device LQI","zigbee.hub_rssi":"Hub RSSI","zigbee.hub_lqi":"Hub LQI","editor.map_height":"Map height","card.show_detailed_view":"Show detailed view","card.zoom_in":"Zoom in","card.zoom_out":"Zoom out","editor.group_by":"Group","card.unassigned_area":"Unassigned","editor.show_labels":"Show link labels","editor.link_status":"Link status","editor.links":"Links","editor.both":"Both","signal.medium":"Medium","layout.config_save_error":"Unable to save this card’s configuration. Use the card editor to save, or copy the layout YAML for a YAML dashboard.","editor.magnifier":"Magnifying glass","editor.lens_size":"Lens size","layout.copy_error":"Unable to copy the layout. Check clipboard permissions and try again.","panel.menu":"Toggle sidebar","panel.settings":"Panel settings","panel.description":"Customise this panel. Dashboard cards keep their own settings.","panel.editor_error":"Unable to open the editor. Close this dialogue and try again.","panel.save_error":"Unable to save settings to Home Assistant. Please try again.","layout.paste_error":"Unable to paste these settings. Copy settings and layout from a Wiser Zigbee card or panel first.","layout.paste_save_error":"Unable to save the pasted settings and layout. Nothing has been changed.","layout.paste_hint":"Paste the settings and layout copied from a Wiser Zigbee card or panel below."},de:{"common.version":"Version","card.title":"Zigbee-Netzwerk","card.description":"Eine interaktive Karte Ihres Wiser-Zigbee-Netzwerks","card.hub":"Wiser Hub","card.devices_one":"{count} Gerät","card.devices_other":"{count} Geräte","card.connections_one":"{count} Verbindung","card.connections_other":"{count} Verbindungen","card.controls":"Netzwerksteuerung","card.fit":"Ansicht einpassen","card.tidy":"Layout anordnen","card.link_labels":"Verbindungsbeschriftungen","card.save_layout":"Layout speichern","card.load_error":"Das Netzwerk konnte nicht geladen werden. Bitte aktualisieren.","card.updating":"Netzwerk wird aktualisiert…","card.empty":"Keine Geräte gefunden","card.unknown_device":"Unbekanntes Gerät","card.hint":"Zum Vergrößern oder Verkleinern doppelklicken. Zum Anordnen ziehen. Für Zigbee-Details auf ein Gerät tippen. Für weitere Informationen gedrückt halten.","map.accessible_only":"Interaktive Zigbee-Netzwerkkarte. Zum Vergrößern auf ein Gerät oder eine freie Stelle doppelklicken, zum Verkleinern erneut doppelklicken. Zum Anordnen ziehen. Für Zigbee-Details auf ein Gerät tippen. Für weitere Informationen gedrückt halten.","map.accessible_list":"Interaktive Zigbee-Netzwerkkarte. Geräte- und Verbindungsdetails stehen in der Liste darunter. Für Zigbee-Details auf ein Gerät tippen. Für weitere Informationen gedrückt halten.","map.accessible_details":"Interaktive Zigbee-Netzwerkkarte. Für Zigbee-Details auf ein Gerät tippen. Für weitere Informationen gedrückt halten.","layout.storage_error":"Browserspeicher nicht verfügbar. Kopieren Sie das Layout in Ihre Kartenkonfiguration.","layout.device_list":"Alle Geräte und Verbindungen","editor.auto_update":"Automatisch aktualisieren","editor.show_device_list":"Alle Geräte und Verbindungen anzeigen","editor.orientation":"Netzwerkansicht","editor.loading":"Home-Assistant-Steuerelemente werden geladen…","signal.connected":"Verbunden","signal.online":"Online","signal.offline":"Offline","signal.no_signal":"Kein Signal","signal.very_good":"Sehr gut","signal.good":"Gut","signal.poor":"Schwach","zigbee.type":"Gerätetyp","zigbee.node":"Zigbee-Knoten-ID","zigbee.parent":"Übergeordnete Knoten-ID","zigbee.channel":"Zigbee-Kanal","zigbee.signal":"Signalqualität","zigbee.device_rssi":"Geräte-RSSI","zigbee.device_lqi":"Geräte-LQI","zigbee.hub_rssi":"Hub-RSSI","zigbee.hub_lqi":"Hub-LQI","editor.map_height":"Kartenhöhe","card.show_detailed_view":"Detailansicht anzeigen","card.zoom_in":"Vergrößern","card.zoom_out":"Verkleinern","editor.group_by":"Gruppieren","card.unassigned_area":"Nicht zugewiesen","editor.show_labels":"Verbindungsbeschriftungen anzeigen","editor.link_status":"Verbindungsstatus","editor.links":"Verbindungen","editor.both":"Beides","signal.medium":"Mittel","layout.config_save_error":"Die Kartenkonfiguration konnte nicht gespeichert werden. Speichere im Karteneditor oder kopiere das Layout-YAML für ein YAML-Dashboard.","editor.magnifier":"Lupe","editor.lens_size":"Lupengröße","layout.copy_error":"Das Layout konnte nicht kopiert werden. Prüfe die Berechtigungen für die Zwischenablage und versuche es erneut.","panel.menu":"Seitenleiste umschalten","panel.settings":"Panel-Einstellungen","panel.description":"Dieses Panel anpassen. Dashboard-Karten behalten ihre eigenen Einstellungen.","panel.editor_error":"Der Editor konnte nicht geöffnet werden. Schließe den Dialog und versuche es erneut.","panel.save_error":"Einstellungen konnten nicht in Home Assistant gespeichert werden. Bitte versuche es erneut.","layout.paste_error":"Diese Einstellungen können nicht eingefügt werden. Kopiere zuerst Einstellungen und Layout von einer Wiser-Zigbee-Karte oder einem Panel.","layout.paste_save_error":"Die eingefügten Einstellungen und das Layout konnten nicht gespeichert werden. Es wurde nichts geändert.","layout.paste_hint":"Füge unten die von einer Wiser-Zigbee-Karte oder einem Panel kopierten Einstellungen und das Layout ein."},fr:{"common.version":"Version","card.title":"Réseau Zigbee","card.description":"Une carte interactive de votre réseau Zigbee Wiser","card.hub":"Hub Wiser","card.devices_one":"{count} appareil","card.devices_other":"{count} appareils","card.connections_one":"{count} connexion","card.connections_other":"{count} connexions","card.controls":"Commandes du réseau","card.fit":"Ajuster la vue","card.tidy":"Réorganiser la disposition","card.link_labels":"Libellés des connexions","card.save_layout":"Enregistrer la disposition","card.load_error":"Impossible de charger le réseau. Essayez de l’actualiser.","card.updating":"Actualisation du réseau…","card.empty":"Aucun appareil trouvé","card.unknown_device":"Appareil inconnu","card.hint":"Double-cliquez pour zoomer ou dézoomer. Faites glisser pour réorganiser. Appuyez sur un appareil pour afficher ses détails Zigbee. Maintenez-le enfoncé pour afficher Plus d’informations.","map.accessible_only":"Carte interactive du réseau Zigbee. Double-cliquez sur un appareil ou une zone vide pour zoomer, puis à nouveau pour dézoomer. Faites glisser pour réorganiser. Appuyez sur un appareil pour afficher ses détails Zigbee. Maintenez-le enfoncé pour afficher Plus d’informations.","map.accessible_list":"Carte interactive du réseau Zigbee. Les détails des appareils et des connexions figurent dans la liste ci-dessous. Appuyez sur un appareil pour afficher ses détails Zigbee. Maintenez-le enfoncé pour afficher Plus d’informations.","map.accessible_details":"Carte interactive du réseau Zigbee. Appuyez sur un appareil pour afficher ses détails Zigbee. Maintenez-le enfoncé pour afficher Plus d’informations.","layout.storage_error":"Stockage du navigateur indisponible. Copiez la disposition dans la configuration de votre carte.","layout.device_list":"Tous les appareils et connexions","editor.auto_update":"Actualisation automatique","editor.show_device_list":"Afficher tous les appareils et connexions","editor.orientation":"Vue du réseau","editor.loading":"Chargement des commandes Home Assistant…","signal.connected":"Connecté","signal.online":"En ligne","signal.offline":"Hors ligne","signal.no_signal":"Aucun signal","signal.very_good":"Très bon","signal.good":"Bon","signal.poor":"Faible","zigbee.type":"Type d’appareil","zigbee.node":"ID du nœud Zigbee","zigbee.parent":"ID du nœud parent","zigbee.channel":"Canal Zigbee","zigbee.signal":"Qualité du signal","zigbee.device_rssi":"RSSI de l’appareil","zigbee.device_lqi":"LQI de l’appareil","zigbee.hub_rssi":"RSSI du hub","zigbee.hub_lqi":"LQI du hub","editor.map_height":"Hauteur de la carte","card.show_detailed_view":"Afficher la vue détaillée","card.zoom_in":"Zoom avant","card.zoom_out":"Zoom arrière","editor.group_by":"Grouper","card.unassigned_area":"Non attribué","editor.show_labels":"Afficher les libellés des liaisons","editor.link_status":"État des liaisons","editor.links":"Liaisons","editor.both":"Les deux","signal.medium":"Moyenne","layout.config_save_error":"Impossible d’enregistrer la configuration de cette carte. Utilisez l’éditeur de carte ou copiez le YAML de disposition pour un tableau de bord YAML.","editor.magnifier":"Loupe","editor.lens_size":"Taille de la loupe","layout.copy_error":"Impossible de copier la disposition. Vérifiez les autorisations du presse-papiers et réessayez.","panel.menu":"Afficher ou masquer la barre latérale","panel.settings":"Paramètres du panneau","panel.description":"Personnalisez ce panneau. Les cartes du tableau de bord conservent leurs propres paramètres.","panel.editor_error":"Impossible d’ouvrir l’éditeur. Fermez cette boîte de dialogue et réessayez.","panel.save_error":"Impossible d’enregistrer les paramètres dans Home Assistant. Veuillez réessayer.","layout.paste_error":"Impossible de coller ces paramètres. Copiez d’abord les paramètres et la disposition d’une carte ou d’un panneau Wiser Zigbee.","layout.paste_save_error":"Impossible d’enregistrer les paramètres et la disposition collés. Aucune modification n’a été effectuée.","layout.paste_hint":"Collez ci-dessous les paramètres et la disposition copiés depuis une carte ou un panneau Wiser Zigbee."}},M4={"panel.cancel":"ui.common.cancel","panel.retry":"ui.common.retry","common.copy":"ui.common.copy","common.paste":"ui.panel.lovelace.editor.card.generic.paste","editor.theme_mode":"ui.panel.lovelace.editor.card.map.theme_mode","editor.theme_auto":"ui.panel.lovelace.editor.card.map.theme_modes.auto","editor.theme_dark":"ui.panel.lovelace.editor.card.map.theme_modes.dark","editor.theme_light":"ui.panel.lovelace.editor.card.map.theme_modes.light","common.copied":"ui.common.copied","common.saved":"ui.common.successfully_saved","editor.icons":"ui.panel.lovelace.editor.features.types.climate-preset-modes.style_list.icons","editor.pie":"ui.panel.lovelace.editor.card.energy-devices-graph.mode_options.pie","common.invalid_configuration":"ui.panel.lovelace.editor.condition-editor.visibility_status.invalid.headline","editor.none":"ui.common.none","editor.area":"ui.panel.lovelace.editor.card.area.name","common.refresh":"ui.common.refresh","common.close":"ui.common.close","common.save":"ui.common.save","common.title":"ui.panel.lovelace.editor.card.generic.title","common.loading":"ui.init.loading","editor.horizontal":"ui.panel.lovelace.editor.card.tile.content_layout_options.horizontal","editor.vertical":"ui.panel.lovelace.editor.card.tile.content_layout_options.vertical","signal.unknown":"state.default.unknown"},O4={"zigbee.type":"ui.panel.config.zha.visualization.device_type","card.unassigned_area":"ui.panel.config.automation.editor.unassigned","signal.medium":"ui.panel.config.matter.visualization.strength.medium","common.version":"ui.panel.config.zwave_js.visualization.version","card.empty":"ui.panel.config.zha.groups.no_devices_found","card.unknown_device":"ui.panel.config.integrations.config_entry.unknown_via_device","signal.connected":"ui.panel.config.serial.connected","signal.online":"ui.panel.config.zha.configuration_page.status_online","signal.offline":"ui.panel.config.zha.configuration_page.status_offline"},D4=[...new Set(Object.values(Object.assign(Object.assign({},M4),O4)).map((t=>{var e;return null===(e=/^ui\.panel\.([^.]+)\./.exec(t))||void 0===e?void 0:e[1]})).filter((t=>!!t)))];function R4(t){var e;const i=((null===(e=null==t?void 0:t.locale)||void 0===e?void 0:e.language)||(null==t?void 0:t.language)||("undefined"!=typeof document?document.documentElement.lang:"")||"en-US").replace(/_/g,"-").toLowerCase();return"en-gb"===i?"en-GB":"de"===i||i.startsWith("de-")?"de":"fr"===i||i.startsWith("fr-")?"fr":"en-US"}function B4(t,e,i={}){var n;const o=R4(e);let r;const s=M4[t]||O4[t];if(s){const i=null===(n=null==e?void 0:e.localize)||void 0===n?void 0:n.call(e,s);if(i&&i!==s&&(r=i),M4[t])return null!=r?r:""}return r||(r=S4[o][t]||I4[t]||t),r.replace(/\{(\w+)\}/g,((t,e)=>{var n;return String(null!==(n=i[e])&&void 0!==n?n:t)}))}function z4(t,e,i){const n=R4(i);return B4(`card.${t}_${"one"===new Intl.PluralRules(n).select(e)?"one":"other"}`,i,{count:new Intl.NumberFormat(n).format(e)})}function P4(t,e){if(!t)return B4("signal.connected",e);const i=t.match(/^([a-z\s_-]+?)(\s*\([\d.,]+%\))?$/i);if(!i)return t;const n={connected:"connected",online:"online",offline:"offline",nosignal:"no_signal",verygood:"very_good",good:"good",poor:"poor",medium:"medium",unknown:"unknown"}[i[1].replace(/[\s_-]/g,"").toLowerCase()];return n?B4(`signal.${n}`,e)+(i[2]||""):t}function F4(t,e){const i=t.match(/\(([\d.,]+)%\)\s*$/);if(!i)return P4(t,e);const n=Number(i[1].replace(",","."));return!Number.isFinite(n)||n<0||n>100?P4(t,e):new Intl.NumberFormat(R4(e),{style:"percent",maximumFractionDigits:1}).format(n/100)}function T4(t){for(const e of["ha-icon","ha-button","ha-icon-button","ha-tooltip","ha-expansion-panel","ha-button-toggle-group","ha-alert","ha-dropdown","ha-dropdown-item","ha-slider"])customElements.get(e)||customElements.whenDefined(e).then((()=>{t.isConnected&&t.requestUpdate()}))}class N4 extends Bn{constructor(){super(...arguments),this.hideHubSelector=!1,this.hideMapHeight=!1,this._hubs=[],this._formReady=!!customElements.get("ha-form"),this.boundLayoutSaveHandler=this.save_layout.bind(this),this.computeLabel=t=>this.t("name"===t.name?"common.title":"hub"===t.name?"card.hub":"show_detailed_view"===t.name?"card.show_detailed_view":`editor.${t.name}`)}t(t){return B4(t,this.hass)}setConfig(t){var e;this._config=Object.assign(Object.assign({},t),{auto_update:null===(e=t.auto_update)||void 0===e||e}),this.loadNativeForm()}connectedCallback(){super.connectedCallback(),T4(this),window.addEventListener("wiser-zigbee-save-layout",this.boundLayoutSaveHandler)}disconnectedCallback(){window.removeEventListener("wiser-zigbee-save-layout",this.boundLayoutSaveHandler),super.disconnectedCallback()}updated(t){var e;t.has("hass")&&this.hass&&!t.get("hass")&&(e=this.hass,e.callWS({type:"wiser/hubs"})).then((t=>{this._hubs=t})).catch((()=>{this._hubs=[]}))}async loadNativeForm(){if(customElements.get("ha-form"))this._formReady=!0;else{if(this.loadingForm)return this.loadingForm;this.loadingForm=(async()=>{const t=(await window.loadCardHelpers()).createCardElement({type:"button"});await t.constructor.getConfigElement(),await customElements.whenDefined("ha-form"),this._formReady=!0})();try{await this.loadingForm}catch(t){this.loadingForm=void 0}}}render(){var t,e,i,n,o,r,s,a,l,h,c;if(!this.hass||!this._config)return qi``;if(!this._formReady)return qi`

${this.t("editor.loading")}

`;const d=[...new Set([...this._hubs,...this._config.hub?[this._config.hub]:[]])],u=Object.assign(Object.assign({},this._config),{hub:this._config.hub||this._hubs[0],name:null!==(t=this._config.name)&&void 0!==t?t:this.t("card.title"),theme_mode:null!==(e=this._config.theme_mode)&&void 0!==e?e:"auto",show_detailed_view:!(null!==(i=this._config.map_only)&&void 0!==i&&i),map_height:null!==(n=this._config.map_height)&&void 0!==n?n:null,show_device_list:null===(o=this._config.show_device_list)||void 0===o||o,show_labels:null!==(r=this._config.show_labels)&&void 0!==r&&r,magnifier:null!==(s=this._config.magnifier)&&void 0!==s&&s}),f=[{name:"hub",required:!0,disabled:0===d.length,selector:{select:{options:d,mode:"dropdown"}}},{name:"name",selector:{text:{}}},{name:"map_height",selector:{number:{min:100,max:2e3,step:1,mode:"box",unit_of_measurement:"px"}}}],p=[{name:"show_labels",selector:{boolean:{}}},{name:"magnifier",selector:{boolean:{}}},{name:"auto_update",selector:{boolean:{}}},{name:"show_detailed_view",selector:{boolean:{}}},{name:"show_device_list",selector:{boolean:{}},disabled:!u.show_detailed_view}];return qi` !(this.hideHubSelector&&"hub"===t.name||this.hideMapHeight&&"map_height"===t.name)))} - .computeLabel=${this.computeLabel} - @value-changed=${this.valueChanged} - > - ({value:t,label:this.t(`editor.${t}`)})))}}}]} - .computeLabel=${this.computeLabel} - @value-changed=${this.valueChanged} - > - ({value:t,label:this.t(`editor.${t}`)})))}}}]} - .computeLabel=${this.computeLabel} - @value-changed=${this.valueChanged} - > - ({value:t,label:this.t(`editor.${t}`)})))}}}]} - .computeLabel=${this.computeLabel} - @value-changed=${this.valueChanged} - > - ({value:t,label:this.t(`editor.theme_${t}`)})))}}}]} - .computeLabel=${this.computeLabel} - @value-changed=${this.valueChanged} - > -
- ${p.map((t=>qi``))} -
-
${this.t("common.version")}: ${"3.0.0-dev.84"}
`}setOrientation(t){var e;this._config&&["horizontal","vertical","pie"].includes(t)&&(null!==(e=this._config.orientation)&&void 0!==e?e:"vertical")!==t&&(this._config=Object.assign(Object.assign({},this._config),{orientation:t}),Gn(this,"config-changed",{config:this._config}))}valueChanged(t){var e,i,n,o;if(t.stopPropagation(),!this._config||!t.detail.value)return;const r=Object.assign({},t.detail.value);"show_detailed_view"in r&&(r.map_only=!r.show_detailed_view,delete r.show_detailed_view),!("map_height"in r)||null!=r.map_height&&""!==r.map_height||(r.map_height=null);const s=Object.assign(Object.assign({},this._config),r);(s.hub||this._hubs[0])===(this._config.hub||this._hubs[0])&&(null!==(e=s.group_by)&&void 0!==e?e:"none")===(null!==(i=this._config.group_by)&&void 0!==i?i:"none")&&(null!==(n=s.orientation)&&void 0!==n?n:"vertical")===(null!==(o=this._config.orientation)&&void 0!==o?o:"vertical")||(delete s.layout_data,delete s.layout_orientation,delete s.layout_group_by),null==this._config.name&&s.name===this.t("card.title")&&delete s.name,this._config=ei(s),Gn(this,"config-changed",{config:this._config})}save_layout(t){var e,i,n,o,r,s,a,l,h,c,d,u;this._config&&(null!==(e=t.detail.hub)&&void 0!==e?e:"")===(null!==(i=this._config.hub)&&void 0!==i?i:"")&&(null!==(n=t.detail.orientation)&&void 0!==n?n:"horizontal")===(null!==(o=this._config.orientation)&&void 0!==o?o:"vertical")&&(null!==(r=t.detail.group_by)&&void 0!==r?r:"none")===(null!==(s=this._config.group_by)&&void 0!==s?s:"none")&&(null!==(a=t.detail.layout_id)&&void 0!==a?a:"")===(null!==(l=this._config.layout_id)&&void 0!==l?l:"")&&(null!==(h=t.detail.name)&&void 0!==h?h:"Wiser Zigbee Network")===(null!==(c=this._config.name)&&void 0!==c?c:"Wiser Zigbee Network")&&(this._config=ei(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},this._config),"boolean"==typeof t.detail.magnifier?{magnifier:t.detail.magnifier}:{}),"boolean"==typeof t.detail.map_only?{map_only:t.detail.map_only}:{}),"boolean"==typeof t.detail.show_labels?{show_labels:t.detail.show_labels}:{}),t.detail.preferences_only?{}:{layout_data:t.detail.layout_data,orientation:null!==(d=t.detail.orientation)&&void 0!==d?d:"vertical",group_by:null!==(u=t.detail.group_by)&&void 0!==u?u:"none",layout_orientation:void 0,layout_group_by:void 0})),Gn(this,"config-changed",{config:this._config}))}}N4.styles=mn` - :host { - color: var(--primary-text-color); - } - .switches { - display: grid; - gap: 0; - } - .orientation-control { - display: block; - margin: 16px 0 8px; - } - .version { - margin-top: 24px; - color: var(--secondary-text-color); - font-size: 12px; - } - `,e([Ln({attribute:!1})],N4.prototype,"hass",void 0),e([Ln({attribute:!1})],N4.prototype,"hideHubSelector",void 0),e([Ln({attribute:!1})],N4.prototype,"hideMapHeight",void 0),e([Un()],N4.prototype,"_config",void 0),e([Un()],N4.prototype,"_hubs",void 0),e([Un()],N4.prototype,"_formReady",void 0),customElements.get("wiser-zigbee-card-editor")||customElements.define("wiser-zigbee-card-editor",N4);class j4 extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this.shadowRoot.innerHTML=`\n \n
\n

Wiser Zigbee

\n \n \n \n
\n \n

Customize this panel. Dashboard cards keep their own settings.

\n
\n
\n Cancel\n Save\n
\n
\n

Loading Wiser Zigbee network…

`,this.shadowRoot.getElementById("menu").addEventListener("click",(()=>{this.dispatchEvent(new CustomEvent("hass-toggle-menu",{bubbles:!0,composed:!0}))})),this.shadowRoot.getElementById("settings").addEventListener("click",(()=>this._openEditor())),this.shadowRoot.getElementById("cancel").addEventListener("click",(()=>this._closeEditor())),this.shadowRoot.getElementById("save").addEventListener("click",(()=>this._saveEditor())),this.shadowRoot.getElementById("editor-dialog").addEventListener("closed",(()=>this._closeEditor())),this.shadowRoot.getElementById("editor-dialog").addEventListener("close-dialog",(()=>this._closeEditor())),this._editors=[],this._cards=[],this._generation=0}_t(t){return B4(t,this._hass)}set hass(t){const e=this._hass;this._hass=t,this._localizeControls();for(const e of this._cards)e.hass=t;for(const e of this._editors)e.hass=t;this.shadowRoot.getElementById("settings").hidden=!t?.user?.is_admin,!t||e&&e.language===t.language||this._loadTranslations().catch((t=>{this.shadowRoot.getElementById("editor-dialog").open&&(this.shadowRoot.getElementById("editor-error").textContent=this._t("panel.editor_error")),console.error("Unable to load Wiser editor translations",t)}))}async _loadTranslations(){const t=this._hass;if(!t?.loadFragmentTranslation)return;if(this._translationLoad?.language===t.language)return this._translationLoad.promise;const e={language:t.language};return this._translationLoad=e,e.promise=(async()=>{let i;for(const n of D4)if(i=await t.loadFragmentTranslation(n)||i,this._translationLoad!==e)return this._loadTranslations();i&&(this.hass={...this._hass,localize:i})})().catch((t=>{throw this._translationLoad===e&&(this._translationLoad=void 0),t})),e.promise}_localizeControls(){const t=this.shadowRoot;for(const[e,i]of[["menu","panel.menu"],["settings","panel.settings"]])t.getElementById(e).setAttribute("aria-label",this._t(i)),t.getElementById(e).title=this._t(i);t.getElementById("cancel").textContent=this._t("panel.cancel"),t.getElementById("save").textContent=this._t("common.save"),t.getElementById("editor-description").textContent=this._t("panel.description");const e=t.getElementById("editor-dialog");e.setAttribute("header-title",this._t("panel.settings")),e.heading=this._t("panel.settings")}set panel(t){const e=t.config;JSON.stringify(e)!==JSON.stringify(this._config)&&(this._config=e,this._loadCards())}_cardConfig(t){return{layout_id:`wiser-zigbee-panel:${t}`,...this._config.card_configs?.[t],type:"custom:wiser-zigbee-card",hub:t,map_height:null}}async saveZigbeeCardConfig(t,e){if(!this._hass?.user?.is_admin||!this._cards.includes(t))throw new Error("Only administrators can save panel settings");const i=this._config.hubs[this._cards.indexOf(t)],n={...e,type:"custom:wiser-zigbee-card",hub:i,map_height:null};return await this._hass.callWS({type:"wiser/zigbee_panel/configure",configs:{[i]:n}}),this._config={...this._config,card_configs:{...this._config.card_configs,[i]:n}},i===this._activeHub&&this.setAttribute("theme-mode",Pn(n.theme_mode)),n}_selectHub(t){this._activeHub=t,this.setAttribute("theme-mode",Pn(this._config.card_configs?.[t]?.theme_mode)),this._cards.forEach(((e,i)=>{const n=this._config.hubs[i]===t;e.hidden=!n,this._tabs[i].setAttribute("aria-selected",String(n)),this._tabs[i].tabIndex=n?0:-1}))}_renderHubTabs(){const t=this._config.hubs,e=this.shadowRoot.getElementById("hub-tabs");e.hidden=0===t.length,this._tabs=t.map(((e,i)=>{const n=document.createElement("ha-button");n.setAttribute("appearance","plain"),n.className="hub-tab",n.textContent=e,n.id=`hub-tab-${i}`,n.setAttribute("role","tab"),n.setAttribute("aria-controls",`hub-panel-${i}`),n.addEventListener("click",(()=>this._selectHub(e))),n.addEventListener("keydown",(e=>{let n;if("ArrowRight"===e.key)n=(i+1)%t.length;else if("ArrowLeft"===e.key)n=(i+t.length-1)%t.length;else if("Home"===e.key)n=0;else{if("End"!==e.key)return;n=t.length-1}e.preventDefault(),this._selectHub(t[n]),this._tabs[n].focus()}));const o=this._cards[i];return o.id=`hub-panel-${i}`,o.setAttribute("role","tabpanel"),o.setAttribute("aria-labelledby",n.id),n})),e.replaceChildren(...this._tabs),this._selectHub(t.includes(this._activeHub)?this._activeHub:t[0])}_closeEditor(){this.shadowRoot.getElementById("editor-dialog").open=!1,this._editors=[],this.shadowRoot.getElementById("editors").replaceChildren()}async _openEditor(){const t=this.shadowRoot.getElementById("editor-dialog");if(t.open||!this._cards.length||!this._hass?.user?.is_admin)return;const e=this.shadowRoot.getElementById("editors"),i=this.shadowRoot.getElementById("editor-error"),n=this.shadowRoot.getElementById("save");this._drafts={},this._editors=[],i.textContent="",e.replaceChildren(),n.disabled=!0,t.heading=this._t("panel.settings"),"headerTitle"in(customElements.get("ha-dialog")?.prototype||{})||this.shadowRoot.getElementById("editor-actions").removeAttribute("slot"),t.open=!0;try{if(await this._loadTranslations(),!t.open)return;if(!window.loadCardHelpers){const t=document.createElement("partial-panel-resolver"),e=t._getRoutes?.({lovelace:{component_name:"lovelace",url_path:"lovelace"}});await(e?.routes?.lovelace?.load?.())}const i=customElements.get("wiser-zigbee-card");for(const n of this._config.hubs){const o=await i.getConfigElement();if(!t.open)return;const r=this._cardConfig(n);this._drafts[n]=r,o.hass=this._hass,o.hideHubSelector=!0,o.hideMapHeight=!0,o.setConfig({...r}),o.addEventListener("config-changed",(t=>{t.stopPropagation(),this._drafts[n]={...t.detail.config,type:"custom:wiser-zigbee-card",hub:n}}));const s=document.createElement("section"),a=document.createElement("h3");a.textContent=n,s.replaceChildren(...this._config.hubs.length>1?[a,o]:[o]),e.append(s),this._editors.push(o)}n.disabled=!1}catch(t){i.textContent=this._t("panel.editor_error"),console.error("Unable to open Wiser editor",t)}}async _saveEditor(){const t=this.shadowRoot.getElementById("save");t.disabled=!0;try{await this._hass.callWS({type:"wiser/zigbee_panel/configure",configs:this._drafts}),this._config={...this._config,card_configs:{...this._config.card_configs,...this._drafts}},this._closeEditor(),this._editors=[],this._loadCards()}catch(t){const e="invalid_config"===t?.code&&"string"==typeof t.message?` ${t.message}`:"";this.shadowRoot.getElementById("editor-error").textContent=this._t("panel.save_error")+e,console.error("Unable to save Wiser panel settings",t)}finally{t.disabled=!1}}async _loadCards(){const t=++this._generation,e=this._config,i=this.shadowRoot.querySelector("main");try{const n=customElements.get("wiser-zigbee-card");if(1!==n?.panelApiVersion)throw new Error("Wiser Zigbee needs its matching Zigbee card build. Update the card resource and refresh the browser.");if(t!==this._generation)return;const o=e.hubs.map((t=>{const e=document.createElement("wiser-zigbee-card");return e.setConfig(this._cardConfig(t)),e.hass=this._hass,e}));this._cards=o,i.replaceChildren(...o),this._renderHubTabs(),this.shadowRoot.getElementById("settings").disabled=!o.length}catch(e){if(t!==this._generation)return;this._cards=[],this.shadowRoot.getElementById("hub-tabs").hidden=!0,this.shadowRoot.getElementById("settings").disabled=!0;const n=document.createElement("p");n.setAttribute("role","alert"),n.textContent=e.message||"Unable to load Wiser Zigbee network. Please try again.";const o=document.createElement("ha-button");o.textContent=this._t("panel.retry"),o.addEventListener("click",(()=>this._loadCards())),i.replaceChildren(n,o),console.error("Unable to load Wiser Zigbee network",e)}}}function L4(t,e,i=4){return t.lefte.left&&t.tope.top}function U4(t,e,i,n){const o=n?{x:t.x,y:t.y+.45*(e.y-t.y)}:{x:t.x+.45*(e.x-t.x),y:t.y},r=n?{x:e.x,y:e.y+.45*(t.y-e.y)}:{x:e.x+.45*(t.x-e.x),y:e.y},s=1-i;return{x:s*s*s*t.x+3*s*s*i*o.x+3*s*i*i*r.x+i*i*i*e.x,y:s*s*s*t.y+3*s*s*i*o.y+3*s*i*i*r.y+i*i*i*e.y}}customElements.get("wiser-zigbee-panel")||customElements.define("wiser-zigbee-panel",j4),window.customCards=window.customCards||[],window.customCards.some((t=>"wiser-zigbee-card"===t.type))||window.customCards.push({type:"wiser-zigbee-card",name:"Wiser Zigbee Card",description:B4("card.description")});class Q4 extends(x4(Bn)){constructor(){super(...arguments),this.autoHeight=!0,this.themeMode="auto",this.loading=!1,this.error="",this.showLabels=!1,this.savingConfig=!1,this.pastingSettings=!1,this.pasteDialogOpen=!1,this.pasteError="",this.magnifier=new ti,this.magnifierHeld=!1,this.layoutStatus="",this.textColor="",this.statusPalette="",this.displayLanguage="",this.collapsedAreas=new Set,this.areaPositions={},this.infoRequest=0,this.fitAfterHeightChange=!1,this.requestId=0,this.pendingLoad=!0}t(t){return B4(t,this.hass)}deviceName(t){return t?"Controller"===t.group&&"Wiser Hub"===t.label?this.t("card.hub"):t.label.replace(/\n/g," "):this.t("card.unknown_device")}get visibleData(){var t,e;const i=null!==(t=this.mapData)&&void 0!==t?t:this.zigbeeData;return i&&"area"===(null===(e=this.config)||void 0===e?void 0:e.group_by)?function(t,e){const i=t.nodes.filter((t=>{var i;return"Controller"===t.group||"Area"===t.group||!e.has(null!==(i=t.area_id)&&void 0!==i?i:"")})),n=new Set(i.map((t=>t.id)));return{nodes:i,edges:t.edges.filter((t=>n.has(t.from)&&n.has(t.to)))}}(i,this.collapsedAreas):i}static async getConfigElement(){return document.createElement("wiser-zigbee-card-editor")}static getStubConfig(){return{}}setConfig(t){var e,i,n;if(!t)throw new Error(this.t("common.invalid_configuration"));this.magnifier.hide(),this.suppliedConfig=t;const o=Object.assign(Object.assign({},t),{auto_update:null===(e=t.auto_update)||void 0===e||e}),r=this.config,s=this.mapHeight,a=r&&this.network&&[...new Set([...Object.keys(r),...Object.keys(o)])].filter((t=>"map_height"!==t&&"theme_mode"!==t)).every((t=>JSON.stringify(r[t])===JSON.stringify(o[t])));if(this.config=o,this.autoHeight=null===this.mapHeight,this.themeMode=Pn(t.theme_mode),this.showLabels=null!==(i=t.show_labels)&&void 0!==i&&i,void 0===t.map_only)try{const t=localStorage.getItem(`${this.layoutKey}:map-only`);null!==t&&(this.config.map_only="true"===t)}catch(t){}if(void 0===t.show_labels)try{this.showLabels="true"===localStorage.getItem(`${this.layoutKey}:labels`)}catch(t){}a?this.fitAfterHeightChange||(this.fitAfterHeightChange=s!==this.mapHeight):(this.cancelDeviceInfo(),this.areaDrag=void 0,this.mapData=void 0,this.collapsedAreas.clear(),this.areaPositions={},this.fitAfterHeightChange=!1,null===(n=this.network)||void 0===n||n.destroy(),this.network=void 0,this.infoReturnView=void 0,this.zoomReturnView=void 0,this.layoutStatus="",this.pendingLoad=!0,this.requestId++)}get orientation(){var t,e;return"pie"===(null===(t=this.config)||void 0===t?void 0:t.orientation)?"pie":"horizontal"===(null===(e=this.config)||void 0===e?void 0:e.orientation)?"horizontal":"vertical"}get mapHeight(){var t;const e=null===(t=this.config)||void 0===t?void 0:t.map_height;return null==e||""===e?null:"number"==typeof e&&Number.isFinite(e)?Math.min(2e3,Math.max(100,Math.round(e))):null}getGridOptions(){var t;return null===this.mapHeight?{columns:12,rows:(null===(t=this.config)||void 0===t?void 0:t.map_only)?6:9,min_rows:3}:{columns:12}}getCardSize(){var t;return(null===(t=this.config)||void 0===t?void 0:t.map_only)?"vertical"===this.orientation?6:8:"vertical"===this.orientation?7:9}hassSubscribe(){return[this.hass.connection.subscribeMessage((t=>{var e;"wiser_updated"===t.event&&(null===(e=this.config)||void 0===e?void 0:e.auto_update)&&!g4(this)&&this.loadData()}),{type:"wiser_updated"})]}connectedCallback(){super.connectedCallback(),T4(this),this.pendingLoad=!0,this.requestUpdate()}disconnectedCallback(){var t;clearTimeout(this.magnifierHoldTimer),this.magnifier.hide(),clearTimeout(this.activeIconTimer),this.activeIcon=void 0,this.cancelDeviceInfo(),super.disconnectedCallback(),this.requestId++,null===(t=this.network)||void 0===t||t.destroy(),this.network=void 0,this.areaDrag=void 0,this.infoReturnView=void 0,this.zoomReturnView=void 0}updated(t){if(super.updated(t),this.positionAreaIcons(),(t.has("hass")||t.has("themeMode"))&&this.network){(getComputedStyle(this).getPropertyValue("--primary-text-color").trim()||"#273448")===this.textColor&&ci(getComputedStyle(this))===this.statusPalette&&R4(this.hass)===this.displayLanguage||this.drawNetwork(!0)}this.fitAfterHeightChange&&this.network&&(this.fitAfterHeightChange=!1,this.network.setSize("100%","100%"),this.fitNetwork()),(t.has("selected")||t.has("selectedEntity")||t.has("config"))&&this.focusAboveInfo(),this.pendingLoad&&this.hass&&this.config&&(this.pendingLoad=!1,this.loadData())}async loadData(){var t,e,i,n,o;if(!this.hass||!this.config)return;const r=++this.requestId;this.loading=!0,this.error="";try{let l=await(s=this.hass,a=this.config.hub,s.callWS({type:"wiser/zigbee",hub:a}));"area"===this.config.group_by&&(l=await async function(t,e,i){const[n,o,r,s]=await Promise.all([t.callWS({type:"config/entity_registry/list"}),t.callWS({type:"config/device_registry/list"}),t.callWS({type:"config/area_registry/list"}),i?Promise.resolve([i]):t.callWS({type:"wiser/hubs"})]),a={"config/entity_registry/list":n,"config/device_registry/list":o,"wiser/hubs":s},l=Object.assign(Object.assign({},t),{callWS:async t=>a[t.type]});return Object.assign(Object.assign({},e),{nodes:await Promise.all(e.nodes.map((async t=>{const e=await k4(l,t,s[0]),i=n.find((t=>t.entity_id===e)),a=o.find((t=>t.id===(null==i?void 0:i.device_id))),h=r.find((t=>t.area_id===((null==a?void 0:a.area_id)||(null==i?void 0:i.area_id))));return Object.assign(Object.assign({},t),{area_id:null==h?void 0:h.area_id,area_name:null==h?void 0:h.name,area_icon:null==h?void 0:h.icon})})))})}(this.hass,l,this.config.hub));const h=C4("area"===this.config.group_by?function(t,e){const i=t.nodes.map((t=>Object.assign({},t))),n=new Set(i.map((t=>t.id))),o=[...new Set(i.filter((t=>"Controller"!==t.group)).map((t=>{var e;return null!==(e=t.area_id)&&void 0!==e?e:""})))].sort(),r=t.edges.map((t=>Object.assign({},t)));for(const r of o){const o=t.nodes.filter((t=>{var e;return"Controller"!==t.group&&(null!==(e=t.area_id)&&void 0!==e?e:"")===r}));let s=2166136261;for(const t of r||"__unassigned__")s=Math.imul(s^t.charCodeAt(0),16777619);let a=-(s>>>0)-1;for(;n.has(a);)a--;n.add(a),i.push({id:a,group:"Area",area_id:r,area_icon:o[0].area_icon||"mdi:floor-plan",label:o[0].area_name||e,x:0,y:0})}return{nodes:i,edges:r}}(l,this.t("card.unassigned_area")):l,this.orientation,void 0,this.config.group_by);if(r!==this.requestId||!this.isConnected)return;let c=(null!==(t=this.config.layout_orientation)&&void 0!==t?t:this.orientation)===this.orientation&&(null!==(i=null!==(e=this.config.layout_group_by)&&void 0!==e?e:this.config.group_by)&&void 0!==i?i:"none")===(null!==(n=this.config.group_by)&&void 0!==n?n:"none")?this.config.layout_data:void 0;if(!c||"object"!=typeof c||Array.isArray(c))try{const t=JSON.parse(localStorage.getItem(this.layoutKey)||"null");t&&"object"==typeof t&&!Array.isArray(t)&&(c=t)}catch(t){}const d=Object.assign(Object.assign({},this.areaPositions),null===(o=this.network)||void 0===o?void 0:o.getPositions());h.nodes=h.nodes.map((t=>{var e;return Object.assign(Object.assign({},t),null!==(e=null==d?void 0:d[t.id])&&void 0!==e?e:this.validPosition(c&&"object"==typeof c?c[t.id]:void 0))})),this.zigbeeData="area"===this.config.group_by?l:h,this.mapData=h,await this.updateComplete,this.drawNetwork()}catch(t){r===this.requestId&&(this.error="card.load_error")}finally{r===this.requestId&&(this.loading=!1)}var s,a}drawNetwork(t=!1){var e,i,n,o;if(!this.zigbeeData)return;const r=t?Object.assign(Object.assign({},this.areaPositions),null===(e=this.network)||void 0===e?void 0:e.getPositions()):void 0,s=this.visibleData;t&&"area"===(null===(i=this.config)||void 0===i?void 0:i.group_by)&&(this.areaPositions=null!=r?r:{});const a=getComputedStyle(this).getPropertyValue("--primary-text-color").trim()||"#273448";this.textColor=a;const l=getComputedStyle(this);this.statusPalette=ci(l);const h=null!==(o=null===(n=this.config)||void 0===n?void 0:n.link_status)&&void 0!==o?o:"links",c="links"===h||"both"===h,d="icons"===h||"both"===h;this.displayLanguage=R4(this.hass);const u={nodes:s.nodes.map((t=>{var e,i,n,o;const s=function(t,e){if("Controller"===t.group||"Area"===t.group)return!1;const i=e.edges.filter((e=>e.from===t.id));return!i.length||i.every((t=>{const i=t.label.split("(")[0].replace(/[\s_-]/g,"").toLowerCase();return["nosignal","offline","disconnected","noconnection"].includes(i)||!e.nodes.some((e=>e.id===t.to))}))}(t,this.zigbeeData),h=s?"Offline":null===(e=this.zigbeeData.edges.find((e=>e.from===t.id)))||void 0===e?void 0:e.label,c=d&&"Area"!==t.group&&"Controller"!==t.group?hi(h,!0,l):void 0,u="Area"===t.group?A4:null!==(i=b4[t.group])&&void 0!==i?i:m4;return Object.assign(Object.assign(Object.assign({},t),null!==(n=null==r?void 0:r[t.id])&&void 0!==n?n:{}),{shape:"image",image:si(u,c,s),brokenImage:si(m4,c,s),size:32,label:"Area"===t.group?`${t.label} ${this.collapsedAreas.has(null!==(o=t.area_id)&&void 0!==o?o:"")?"▸":"▾"}`:"Controller"===t.group?this.deviceName(t):ai(t.label),font:{color:a}})})),edges:s.edges.map((t=>{const e=hi(t.label,c,l);return Object.assign(Object.assign({},t),{label:"",color:{color:e,highlight:e,hover:e,inherit:!1}})}))};if(this.network){const t={position:this.network.getViewPosition(),scale:this.network.getScale()};this.hoveredEdge=void 0,this.network.setData(u),this.network.moveTo(Object.assign(Object.assign({},t),{animation:!1})),void 0!==this.selected&&u.nodes.some((t=>t.id===this.selected))?this.network.selectNodes([this.selected]):this.selected=void 0}else this.network=new v4(this.shadowRoot.getElementById("zigbee-network"),u,Object.assign(Object.assign({},w4),{edges:Object.assign(Object.assign({},w4.edges),{smooth:{enabled:!0,type:"cubicBezier",forceDirection:"pie"===this.orientation?"none":this.orientation,roundness:.45}})})),this.network.on("hoverEdge",(t=>this.hoverLink(t.edge))),this.network.on("blurEdge",(()=>this.hoverLink())),this.network.on("click",(t=>this.deviceClick(t.nodes[0]))),this.network.on("hold",(t=>this.deviceHold(t.nodes[0]))),this.network.on("doubleClick",(t=>{var e;this.cancelDeviceInfo(),this.toggleDeviceZoom(t.nodes[0],null===(e=t.pointer)||void 0===e?void 0:e.canvas)})),this.network.on("beforeDrawing",(t=>{this.moveAreaDevices(),this.drawAreaGroups(t)})),this.network.on("afterDrawing",(t=>{this.positionAreaIcons(),this.drawLinkLabels(t),this.magnifier.refresh()})),this.network.on("dragStart",(t=>this.startAreaDrag(t.nodes[0]))),this.network.on("dragEnd",(()=>{this.moveAreaDevices(),this.areaDrag=void 0})),this.network.on("resize",(()=>this.fitNetwork())),this.fitNetwork(),this.requestUpdate()}startAreaDrag(t){var e,i,n,o;if(this.closeDeviceInfo(!1),this.areaDrag=void 0,!this.network||"area"!==(null===(e=this.config)||void 0===e?void 0:e.group_by))return;const r=null===(i=this.mapData)||void 0===i?void 0:i.nodes.find((e=>e.id===t&&"Area"===e.group));if(!r)return;const s=this.currentPositions(),a={};for(const t of this.mapData.nodes)"Area"!==t.group&&"Controller"!==t.group&&(null!==(n=t.area_id)&&void 0!==n?n:"")===(null!==(o=r.area_id)&&void 0!==o?o:"")&&s[t.id]&&(a[t.id]=Object.assign({},s[t.id]));this.areaDrag={headerId:r.id,origin:Object.assign({},s[r.id]),members:a,dx:0,dy:0}}moveAreaDevices(){const t=this.areaDrag;if(!t||!this.network)return;const e=this.network.getPositions(),i=e[t.headerId];if(!i)return;const n=i.x-t.origin.x,o=i.y-t.origin.y;if(n!==t.dx||o!==t.dy){t.dx=n,t.dy=o,this.areaPositions[t.headerId]=Object.assign({},i);for(const[i,r]of Object.entries(t.members)){const t={x:r.x+n,y:r.y+o};this.areaPositions[i]=t,e[i]&&this.network.moveNode(Number(i),t.x,t.y)}}}areaBounds(t){var e,i,n;if(!this.network||"area"!==(null===(e=this.config)||void 0===e?void 0:e.group_by))return[];const o=null!==(n=null===(i=this.visibleData)||void 0===i?void 0:i.nodes)&&void 0!==n?n:[],r=null!=t?t:document.createElement("canvas").getContext("2d"),s=this.network.getPositions(),a=new Set(o.filter((t=>"Area"===t.group)).map((t=>{var e;return null!==(e=t.area_id)&&void 0!==e?e:""})));return[...a].map((t=>{const e=o.filter((e=>{var i;return"Controller"!==e.group&&(null!==(i=e.area_id)&&void 0!==i?i:"")===t})),i=e.map((t=>{var e;const i=s[t.id];if(!i)return this.network.getBoundingBox(t.id);const n={left:i.x-32,right:i.x+32,top:i.y-32,bottom:i.y+60};if(!r)return n;const o="Area"===t.group?`${t.label} ${this.collapsedAreas.has(null!==(e=t.area_id)&&void 0!==e?e:"")?"▸":"▾"}`:ai(t.label);r.save(),r.font="bold 14px system-ui, sans-serif";const a=o.split("\n"),l=Math.max(...a.map((t=>r.measureText(t).width)))/2;return r.restore(),n.left=Math.min(n.left,i.x-l),n.right=Math.max(n.right,i.x+l),n.bottom=Math.max(n.bottom,i.y+32+14*(a.length+1)),n})),n=e.findIndex((t=>"Area"===t.group)),a=e[n],l=a&&s[a.id],h=i.filter(((t,e)=>e!==n));if(l&&h.length&&!this.areaDrag&&"vertical"===this.orientation){const t=(Math.min(...h.map((t=>t.left)))+Math.max(...h.map((t=>t.right))))/2,e=t-l.x;Math.abs(e)>.01&&(this.network.moveNode(a.id,t,l.y),this.areaPositions[a.id]={x:t,y:l.y},i[n].left+=e,i[n].right+=e)}return{left:Math.min(...i.map((t=>t.left)))-18,right:Math.max(...i.map((t=>t.right)))+18,top:Math.min(...i.map((t=>t.top)))-18,bottom:Math.max(...i.map((t=>t.bottom)))+18}}))}drawAreaGroups(t){const e=this.areaBounds(t);if(!e.length||!this.network)return;const i=getComputedStyle(this).getPropertyValue("--primary-text-color").trim()||this.textColor;t.save();for(const n of e)t.beginPath(),t.roundRect(n.left,n.top,n.right-n.left,n.bottom-n.top,14),t.fillStyle=i,t.globalAlpha=.04,t.fill(),t.strokeStyle=i,t.lineWidth=1/this.network.getScale(),t.globalAlpha=.22,t.stroke();t.restore()}positionAreaIcons(){var t,e;if(!this.network||"area"!==(null===(t=this.config)||void 0===t?void 0:t.group_by))return;const i=this.network.getPositions(),n=64*this.network.getScale();null===(e=this.shadowRoot)||void 0===e||e.querySelectorAll(".area-icons ha-icon").forEach((t=>{const e=i[Number(t.dataset.node)];if(!e)return;const o=this.network.canvasToDOM(e);t.style.left=`${o.x}px`,t.style.top=`${o.y}px`,t.style.width=`${n}px`,t.style.height=`${n}px`,t.style.setProperty("--mdc-icon-size",`${n}px`),t.style.setProperty("--ha-icon-size",`${n}px`)}))}cancelDeviceInfo(){clearTimeout(this.deviceTapTimer),this.deviceTapTimer=void 0,this.infoRequest++,this.selectedEntity=void 0}closeDeviceInfo(t=!0){var e;this.cancelDeviceInfo(),this.selected=void 0;const i=this.infoReturnView;this.infoReturnView=void 0,t&&(null===(e=this.network)||void 0===e||e.unselectAll(),i&&this.network&&(this.zoomReturnView=i.zoomReturnView,this.network.moveTo({position:i.position,scale:i.scale,animation:!1})))}deviceClick(t){clearTimeout(this.deviceTapTimer),void 0!==t?this.deviceTapTimer=setTimeout((()=>{var e,i;const n=null===(e=this.mapData)||void 0===e?void 0:e.nodes.find((e=>e.id===t));"Area"===(null==n?void 0:n.group)?this.toggleArea(null!==(i=n.area_id)&&void 0!==i?i:""):this.showDeviceDetails(t)}),300):this.closeDeviceInfo()}toggleArea(t){var e;this.closeDeviceInfo(!1),this.areaPositions=Object.assign(Object.assign({},this.areaPositions),null===(e=this.network)||void 0===e?void 0:e.getPositions()),this.collapsedAreas.has(t)?this.collapsedAreas.delete(t):this.collapsedAreas.add(t),this.drawNetwork(!0)}async deviceHold(t){var e,i;this.closeDeviceInfo();const n=null===(e=this.zigbeeData)||void 0===e?void 0:e.nodes.find((e=>e.id===t));if(!n||!this.hass)return;const o=this.infoRequest;try{const t=await k4(this.hass,n,null===(i=this.config)||void 0===i?void 0:i.hub);t&&o===this.infoRequest&&this.isConnected&&Gn(this,"hass-more-info",{entityId:t})}catch(t){}}showDeviceDetails(t){void 0!==t?(!this.infoReturnView&&this.network&&(this.infoReturnView={position:this.network.getViewPosition(),scale:this.network.getScale(),zoomReturnView:this.zoomReturnView}),this.cancelDeviceInfo(),this.selected=t,void 0!==t&&this.openDeviceInfo(t,this.infoRequest)):this.closeDeviceInfo()}async openDeviceInfo(t,e){var i,n;const o=null===(i=this.zigbeeData)||void 0===i?void 0:i.nodes.find((e=>e.id===t));if(o&&this.hass)try{const i=await k4(this.hass,o,null===(n=this.config)||void 0===n?void 0:n.hub);i&&e===this.infoRequest&&this.isConnected&&this.selected===t&&(this.selectedEntity=i)}catch(t){}}toggleDeviceZoom(t,e){if(!this.network)return;const i=!window.matchMedia("(prefers-reduced-motion: reduce)").matches&&{duration:250,easingFunction:"easeInOutQuad"};if(this.zoomReturnView)return this.network.moveTo(Object.assign(Object.assign({},this.zoomReturnView),{animation:i})),void(this.zoomReturnView=void 0);if(!(void 0!==t||e&&Number.isFinite(e.x)&&Number.isFinite(e.y)))return;this.zoomReturnView={position:this.network.getViewPosition(),scale:this.network.getScale()};const n=Math.max(2*this.zoomReturnView.scale,1.25);void 0!==t?this.network.focus(t,{scale:n,locked:!1,animation:i}):this.network.moveTo({position:e,scale:n,animation:i})}focusAboveInfo(){var t,e,i;if(!(null===(t=this.config)||void 0===t?void 0:t.map_only)||void 0===this.selected||!this.network)return;const n=null===(e=this.shadowRoot)||void 0===e?void 0:e.getElementById("zigbee-network"),o=null===(i=this.shadowRoot)||void 0===i?void 0:i.querySelector("footer.map-info");if(!n||!o||o.hidden)return;const r=n.getBoundingClientRect(),s=Math.min(r.bottom,o.getBoundingClientRect().top-12);s<=r.top||this.network.focus(this.selected,{scale:this.network.getScale(),offset:{x:0,y:(s-r.top-r.height)/2},locked:!1,animation:!1})}zoomStep(t){this.network&&(this.prepareGestureZoom(),this.network.moveTo({position:this.network.getViewPosition(),scale:Math.min(10,Math.max(.01,this.network.getScale()*t)),animation:!1}))}prepareGestureZoom(){var t;this.network&&(this.closeDeviceInfo(!1),null!==(t=this.zoomReturnView)&&void 0!==t||(this.zoomReturnView={position:this.network.getViewPosition(),scale:this.network.getScale()}))}touchZoomStart(t){t.touches.length>=2&&this.prepareGestureZoom()}panZoomedView(t){if(t.ctrlKey||t.metaKey)return void this.prepareGestureZoom();if(t.stopPropagation(),!this.network||!this.zoomReturnView)return;t.preventDefault();const e=t.currentTarget,i=this.network.getScale(),n=this.network.getViewPosition(),o=1===t.deltaMode?16:2===t.deltaMode?e.clientWidth:1,r=1===t.deltaMode?16:2===t.deltaMode?e.clientHeight:1,s=t.shiftKey&&0===t.deltaX?t.deltaY*o:t.deltaX*o,a=t.shiftKey&&0===t.deltaX?0:t.deltaY*r;this.network.moveTo({position:{x:n.x+s/i,y:n.y+a/i},scale:i,animation:!1})}fitNetwork(){var t,e,i;if(this.zoomReturnView=void 0,!this.network)return;const n=null===(t=this.shadowRoot)||void 0===t?void 0:t.getElementById("zigbee-network");if(!n||!n.clientWidth||!n.clientHeight)return;this.network.redraw();const o=function(t,e,i,n=8){const o=t.filter((t=>Object.values(t).every(Number.isFinite)));if(!o.length||e<=2*n||i<=2*n)return;const r=Math.min(...o.map((t=>t.left))),s=Math.max(...o.map((t=>t.right))),a=Math.min(...o.map((t=>t.top))),l=Math.max(...o.map((t=>t.bottom))),h={x:(r+s)/2,y:(a+l)/2},c=2*Math.max(Math.abs(r-h.x),Math.abs(s-h.x)),d=2*Math.max(Math.abs(a-h.y),Math.abs(l-h.y));return{position:h,scale:Math.min((e-2*n)/Math.max(c,1),(i-2*n)/Math.max(d,1))}}([...(null!==(i=null===(e=this.visibleData)||void 0===e?void 0:e.nodes)&&void 0!==i?i:[]).map((t=>this.network.getBoundingBox(t.id))),...this.areaBounds()],n.clientWidth,n.clientHeight);o&&this.network.moveTo(Object.assign(Object.assign({},o),{animation:!1}))}hoverLink(t){var e;this.hoveredEdge!==t&&(this.hoveredEdge=t,this.showLabels||null===(e=this.network)||void 0===e||e.redraw())}drawLinkLabels(t){var e,i,n;if(!this.showLabels&&void 0===this.hoveredEdge||!this.network||!this.zigbeeData)return;const o=this.network,r=null===(e=this.shadowRoot)||void 0===e?void 0:e.getElementById("zigbee-network");if(!r)return;const s=o.getScale(),a=o.getPositions(),l=this.visibleData.nodes.map((t=>{const e=o.getBoundingBox(t.id),i=o.canvasToDOM({x:e.left,y:e.top}),n=o.canvasToDOM({x:e.right,y:e.bottom});return{left:i.x,top:i.y,right:n.x,bottom:n.y}})),h=(null===(i=this.config)||void 0===i?void 0:i.map_only)?null===(n=this.shadowRoot)||void 0===n?void 0:n.querySelector("footer.map-info"):void 0;if(h&&!h.hidden){const t=r.getBoundingClientRect(),e=h.getBoundingClientRect();l.push({left:e.left-t.left,right:e.right-t.left,top:e.top-t.top,bottom:e.bottom-t.top})}t.save(),t.font=14/s+"px system-ui, sans-serif";const c=[];for(const e of this.visibleData.edges){if(!e.label||!this.showLabels&&e.id!==this.hoveredEdge)continue;if(!a[e.from]||!a[e.to])continue;const i=F4(e.label,this.hass);c.push({id:e.id,text:i,width:t.measureText(i).width*s,from:o.canvasToDOM(a[e.from]),to:o.canvasToDOM(a[e.to])})}const d=function(t,e,i,n,o){const r=[];for(const s of t){let t;for(const a of[0,14,-14,26,-26,40,-40]){for(const l of[.5,.4,.6,.3,.7,.2,.8]){const h=U4(s.from,s.to,l,o),c=U4(s.from,s.to,l-.01,o),d=U4(s.from,s.to,l+.01,o),u=d.x-c.x,f=d.y-c.y,p=Math.hypot(u,f)||1,v={x:h.x-f/p*a,y:h.y+u/p*a},g={left:v.x-s.width/2-6,right:v.x+s.width/2+6,top:v.y-13,bottom:v.y+13};if(!(g.left<4||g.top<4||g.right>i-4||g.bottom>n-4||[...e,...r].some((t=>L4(g,t))))){t=Object.assign(Object.assign({},g),{id:s.id,text:s.text,anchor:h,center:v});break}}if(t)break}t&&r.push(t)}return r}(c,l,r.clientWidth,r.clientHeight,"vertical"===this.orientation),u=getComputedStyle(this),f=t=>u.getPropertyValue(t).trim(),p=f("--ha-tooltip-background-color")||f("--ha-color-surface-default")||f("--card-background-color")||"#fff",v=f("--ha-tooltip-text-color")||f("--primary-text-color")||this.textColor,g=parseFloat(f("--ha-tooltip-border-radius")||f("--ha-border-radius-md"))||4;t.textAlign="center",t.textBaseline="middle";for(const e of d){const i=o.DOMtoCanvas(e.center),n=o.DOMtoCanvas(e.anchor),r=o.DOMtoCanvas({x:e.left,y:e.top});t.strokeStyle=this.textColor,t.lineWidth=.5/s,t.beginPath(),t.moveTo(n.x,n.y),t.lineTo(i.x,i.y),t.stroke(),t.fillStyle=p,t.beginPath(),t.roundRect(r.x,r.y,(e.right-e.left)/s,(e.bottom-e.top)/s,Math.min(g,(e.bottom-e.top)/2)/s),t.fill(),t.fillStyle=v,t.fillText(e.text,i.x,i.y)}t.restore()}toggleLabels(){this.showLabels=!this.showLabels,this.drawNetwork(!0),this.saveLayoutClick(!0)}tidyLayout(){var t,e,i,n;this.zigbeeData&&(this.mapData=C4(null!==(t=this.mapData)&&void 0!==t?t:this.zigbeeData,this.orientation,null===(e=this.network)||void 0===e?void 0:e.getPositions(),null===(i=this.config)||void 0===i?void 0:i.group_by),this.areaPositions={},"area"!==(null===(n=this.config)||void 0===n?void 0:n.group_by)&&(this.zigbeeData=this.mapData),this.closeDeviceInfo(!1),this.areaDrag=void 0,this.drawNetwork(),this.spaceRenderedAreas(),this.fitNetwork())}spaceRenderedAreas(){var t,e;if(!this.network||"area"!==(null===(t=this.config)||void 0===t?void 0:t.group_by)||"pie"!==this.orientation)return;this.network.redraw();const i=this.visibleData,n=this.network.getPositions(),o=i.nodes.map((t=>Object.assign(Object.assign({},t),n[t.id]))),r=[...new Set(i.nodes.filter((t=>"Area"===t.group)).map((t=>{var e;return null!==(e=t.area_id)&&void 0!==e?e:""})))],s=this.areaBounds(),a=new Map(r.map(((t,e)=>[t,s[e]])));li(o,new Set(i.edges.map((t=>t.to))),(t=>{var e;const i=t[0],o=n[i.id],r=i.x-o.x,s=i.y-o.y,l="Controller"===i.group?this.network.getBoundingBox(i.id):a.get(null!==(e=i.area_id)&&void 0!==e?e:"");return{left:l.left+r,right:l.right+r,top:l.top+s,bottom:l.bottom+s}}));for(const t of o){if(t.x===n[t.id].x&&t.y===n[t.id].y)continue;this.network.moveNode(t.id,t.x,t.y),this.areaPositions[t.id]={x:t.x,y:t.y};const i=null===(e=this.mapData)||void 0===e?void 0:e.nodes.find((e=>e.id===t.id));i&&(i.x=t.x,i.y=t.y)}this.network.redraw()}get layoutKey(){var t,e,i,n,o,r,s;const a=`wiser-zigbee-layout:${JSON.stringify([location.pathname,null!==(e=null===(t=this.config)||void 0===t?void 0:t.hub)&&void 0!==e?e:"",null!==(n=null===(i=this.config)||void 0===i?void 0:i.name)&&void 0!==n?n:"Wiser Zigbee Network",null!==(r=null===(o=this.config)||void 0===o?void 0:o.layout_id)&&void 0!==r?r:""])}`,l="pie"===this.orientation?`${a}:pie`:"vertical"===this.orientation?`${a}:horizontal`:a;return"area"===(null===(s=this.config)||void 0===s?void 0:s.group_by)?`${l}:area-topology`:l}validPosition(t){return t&&Number.isFinite(t.x)&&Number.isFinite(t.y)?{x:t.x,y:t.y}:void 0}currentPositions(){var t,e;if(!this.network)return;const i={};for(const n of null!==(e=null===(t=this.mapData)||void 0===t?void 0:t.nodes)&&void 0!==e?e:[])i[n.id]={x:n.x,y:n.y};return Object.assign(Object.assign(Object.assign({},i),this.areaPositions),this.network.getPositions())}prepareConfirmation(t,e){var i,n;return function(t,e){if(!t)return()=>{};const i=t.ownerDocument,n=t.getBoundingClientRect(),o=getComputedStyle(t),r=["--ha-tooltip-background-color","--ha-tooltip-text-color","--ha-color-surface-default","--primary-text-color","--ha-font-family-body","--ha-tooltip-border-radius","--ha-border-radius-md"].map((t=>[t,o.getPropertyValue(t)]));return()=>{const t=i.createElement("div"),o=i.createElement("span"),s=i.createElement("ha-tooltip"),a=`wiser-confirm-${Math.random().toString(36).slice(2)}`;t.style.cssText=`position:fixed;left:${n.left}px;top:${n.top}px;width:${n.width}px;height:${n.height}px;pointer-events:none;z-index:1000`,r.forEach((([e,i])=>{i&&t.style.setProperty(e,i)})),o.id=a,o.style.cssText="display:block;width:100%;height:100%",s.for=a,s.trigger="manual",s.setAttribute("placement","bottom"),s.textContent=e,s.setAttribute("role","status"),t.append(o,s),i.body.append(t),s.open=!0,setTimeout((()=>t.remove()),2500)}}(null!==(n=null===(i=this.shadowRoot)||void 0===i?void 0:i.querySelector(`[data-action="${t}"]`))&&void 0!==n?n:null,this.t(e))}async copyLayout(){var t,e,i,n,r,s,a,l,h,c,d,u,f,p;const v=this.prepareConfirmation("common.copy","common.copied"),g=this.currentPositions();var y;if(g)try{const m=(y={name:null!==(e=null===(t=this.config)||void 0===t?void 0:t.name)&&void 0!==e?e:this.t("card.title"),auto_update:null===(n=null===(i=this.config)||void 0===i?void 0:i.auto_update)||void 0===n||n,theme_mode:this.themeMode,map_only:null!==(s=null===(r=this.config)||void 0===r?void 0:r.map_only)&&void 0!==s&&s,show_device_list:null===(l=null===(a=this.config)||void 0===a?void 0:a.show_device_list)||void 0===l||l,show_labels:this.showLabels,magnifier:null!==(c=null===(h=this.config)||void 0===h?void 0:h.magnifier)&&void 0!==c&&c,link_status:null!==(u=null===(d=this.config)||void 0===d?void 0:d.link_status)&&void 0!==u?u:"links",map_height:this.mapHeight,orientation:this.orientation,group_by:null!==(p=null===(f=this.config)||void 0===f?void 0:f.group_by)&&void 0!==p?p:"none",layout_data:g},Ye(Xe(y),{schema:Ke,noRefs:!0,lineWidth:-1,quotingType:'"'}));await async function(t){var e,i;if(o(),null===(e=navigator.clipboard)||void 0===e?void 0:e.writeText)try{return await navigator.clipboard.writeText(t),void o(t)}catch(t){}const n=document.createElement("textarea");n.value=t,n.readOnly=!0,n.style.cssText="position:fixed;top:0;left:0;opacity:0;pointer-events:none";const r=document.activeElement;try{if(document.body.appendChild(n),n.focus({preventScroll:!0}),n.select(),!document.execCommand("copy"))throw new Error("Clipboard copy failed");o(t)}finally{n.remove(),null===(i=null==r?void 0:r.focus)||void 0===i||i.call(r,{preventScroll:!0})}}(m),this.layoutStatus="",v()}catch(t){this.layoutStatus="layout.copy_error"}}async pasteLayout(t){var e,o;if(this.pastingSettings||this.savingConfig||!this.suppliedConfig)return;const r=this.suppliedConfig;if(this.pastingSettings=!0,void 0===t)try{t=await async function(){try{return await navigator.clipboard.readText()}catch(t){let e=!1;try{const t=sessionStorage.getItem(n);if(e=!0,null!==t)return t}catch(t){}if(!e&&void 0!==i)return i;throw t}}()}catch(t){return this.pasteError="",this.pasteDialogOpen=!0,this.pastingSettings=!1,await this.updateComplete,void(null===(o=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector("#settings-paste"))||void 0===o||o.focus())}let s;try{s=function(t){if(t.length>1048576)throw new Error("Text too large");return Xe(qe(t,{schema:Ke}))}(t)}catch(t){return this.layoutStatus="layout.paste_error",this.pasteError="layout.paste_error",void(this.pastingSettings=!1)}try{if(this.suppliedConfig!==r||!this.isConnected)return;const t=await ni(this,r,Object.assign(Object.assign({},s),{layout_orientation:void 0,layout_group_by:void 0}));if(this.suppliedConfig!==r||!this.isConnected)return;this.setConfig(t),this.layoutStatus="common.saved",this.pasteDialogOpen=!1,this.pasteError=""}catch(t){this.layoutStatus="layout.paste_save_error",this.pasteError="layout.paste_save_error"}finally{this.pastingSettings=!1}}pasteSettingsDialog(){return qi`{this.pasteDialogOpen=!1}} - @close-dialog=${()=>{this.pasteDialogOpen=!1}} - > -

${this.t("layout.paste_hint")}

- - ${this.pasteError?qi`

${this.t(this.pasteError)}

`:""} -
- {this.pasteDialogOpen=!1}}>${this.t("panel.cancel")} - {var t,e,i;this.pasteLayout(null!==(i=null===(e=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("#settings-paste"))||void 0===e?void 0:e.value)&&void 0!==i?i:"")}}>${this.t("common.save")} -
-
`}settingsTransferControl(){var t,e;const i=`${this.t("common.copy")} / ${this.t("common.paste")}`;return qi`{"copy"===t.detail.item.value?this.copyLayout():"paste"===t.detail.item.value&&this.pasteLayout()}} - > - - - ${this.t("common.copy")} - - - ${this.t("common.paste")} - - `}async saveLayoutClick(t=!1){var e,i,n,o,r,s,a,l;if(this.pastingSettings)return;const h=this.currentPositions();if(!h||!this.config)return;const c=t?()=>{}:this.prepareConfirmation("card.save_layout","common.saved");try{t||localStorage.setItem(this.layoutKey,JSON.stringify(h)),localStorage.setItem(`${this.layoutKey}:labels`,JSON.stringify(this.showLabels)),localStorage.setItem(`${this.layoutKey}:map-only`,JSON.stringify(null!==(e=this.config.map_only)&&void 0!==e&&e)),this.layoutStatus=""}catch(t){this.layoutStatus="layout.storage_error"}if(t||g4(this))Gn(this,"wiser-zigbee-save-layout",{layout_data:h,show_labels:this.showLabels,map_only:null!==(s=this.config.map_only)&&void 0!==s&&s,magnifier:null!==(a=this.config.magnifier)&&void 0!==a&&a,preferences_only:t,hub:this.config.hub,name:this.config.name,orientation:this.orientation,layout_id:this.config.layout_id,group_by:null!==(l=this.config.group_by)&&void 0!==l?l:"none"}),t||this.layoutStatus||c();else{if(this.savingConfig||!this.suppliedConfig)return;this.savingConfig=!0;try{this.suppliedConfig=await ni(this,this.suppliedConfig,{show_labels:this.showLabels,magnifier:null!==(i=this.config.magnifier)&&void 0!==i&&i,map_only:null!==(n=this.config.map_only)&&void 0!==n&&n,layout_data:h,orientation:this.orientation,group_by:null!==(o=this.config.group_by)&&void 0!==o?o:"none",layout_orientation:void 0,layout_group_by:void 0}),this.config=Object.assign(Object.assign({},this.suppliedConfig),{auto_update:null===(r=this.suppliedConfig.auto_update)||void 0===r||r}),this.layoutStatus="",c()}catch(t){this.layoutStatus="layout.config_save_error"}finally{this.savingConfig=!1}}}renderZigbeeDetails(t){var e,i,n,o;const r=this.selectedEntity?null===(i=null===(e=this.hass)||void 0===e?void 0:e.states[this.selectedEntity])||void 0===i?void 0:i.attributes:void 0,s=null===(o=null===(n=this.zigbeeData)||void 0===n?void 0:n.edges.find((e=>e.from===t.id)))||void 0===o?void 0:o.to,a=E4(null==r?void 0:r.device_reception_RSSI,null==r?void 0:r.device_reception_LQI),l=E4(null==r?void 0:r.controller_reception_RSSI,null==r?void 0:r.controller_reception_LQI),h=[["zigbee.type",t.group],["zigbee.node",t.id],["zigbee.parent",s],["zigbee.channel",null==r?void 0:r.zigbee_channel],["zigbee.signal",(null==r?void 0:r.displayed_signal_strength)?P4(r.displayed_signal_strength,this.hass):void 0],["zigbee.device_rssi",null==a.rssi?void 0:`${a.rssi} dBm`],["zigbee.device_lqi",a.lqi],["zigbee.hub_rssi",null==l.rssi?void 0:`${l.rssi} dBm`],["zigbee.hub_lqi",l.lqi]];return qi`
- ${h.filter((([,t])=>null!=t)).map((([t,e])=>qi`
- ${this.t(t)}${e} -
`))} -
`}toggleViewMode(){this.config&&(this.config=Object.assign(Object.assign({},this.config),{map_only:!this.config.map_only}),this.saveLayoutClick(!0))}async openMagnifierMenu(t){var e;clearTimeout(this.magnifierHoldTimer),this.magnifierHeld=!0;const i=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector("#magnifier-menu");i&&(await i.updateComplete,i.anchorElement=t.querySelector("ha-icon-button"),i.open=!0)}magnifierControl(){var t,e;return qi`{if(!this.network||0!==t.button)return;clearTimeout(this.magnifierHoldTimer),this.magnifierHeld=!1;const e=t.currentTarget;this.magnifierHoldTimer=setTimeout((()=>{this.openMagnifierMenu(e)}),500)}} - @pointerup=${()=>clearTimeout(this.magnifierHoldTimer)} - @pointerleave=${()=>clearTimeout(this.magnifierHoldTimer)} - @pointercancel=${()=>clearTimeout(this.magnifierHoldTimer)} - @contextmenu=${t=>{t.preventDefault(),this.network&&this.openMagnifierMenu(t.currentTarget)}} - @keydown=${t=>{"ArrowDown"===t.key&&this.network&&(t.preventDefault(),this.openMagnifierMenu(t.currentTarget))}} - >${this.layoutIcon("editor.magnifier","M9.5 3a6.5 6.5 0 1 0 3.98 11.64L19.85 21 21 19.85l-6.36-6.37A6.5 6.5 0 0 0 9.5 3m0 2a4.5 4.5 0 1 1 0 9 4.5 4.5 0 0 1 0-9m-1 1v2.5H6V10h2.5v2.5H10V10h2.5V8.5H10V6Z",(()=>{var t;this.config=Object.assign(Object.assign({},this.config),{magnifier:!(null===(t=this.config)||void 0===t?void 0:t.magnifier)}),this.magnifier.hide(),this.saveLayoutClick(!0)}),null!==(e=null===(t=this.config)||void 0===t?void 0:t.magnifier)&&void 0!==e&&e)} - {this.magnifier.setZoom(Number(t.detail.item.value)),this.requestUpdate()}} - @wa-after-hide=${()=>{var t,e,i;const n=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("#magnifier-menu");(null==n?void 0:n.anchorElement)&&(n.anchorElement.selected=null!==(i=null===(e=this.config)||void 0===e?void 0:e.magnifier)&&void 0!==i&&i)}} - > -
-
- ${[2,3,4].map((t=>qi`${t}×`))} -
-
t.stopPropagation()} - @keydown=${t=>{"Escape"!==t.key&&"Tab"!==t.key&&t.stopPropagation()}} - > - {this.magnifier.setSize(Number(t.target.value)),this.requestUpdate()}} - > - ${this.magnifier.size} px -
-
-
`}layoutIcon(t,e,i,n,o=!this.network){const r=this.t(t),s=null!=n?n:"common.refresh"===t?this.loading:this.activeIcon===t;return qi`{o||("editor.magnifier"===t&&this.magnifierHeld?this.magnifierHeld=!1:(void 0===n&&"common.refresh"!==t&&(clearTimeout(this.activeIconTimer),this.activeIcon=t,this.activeIconTimer=setTimeout((()=>{this.activeIcon=void 0}),500)),i()))}} - >`}render(){var t,e,i,n,o,r,s,a,l,h,c,d,u,f,p,v,g,y,m,b;const w=null!==(e=null===(t=this.zigbeeData)||void 0===t?void 0:t.nodes)&&void 0!==e?e:[],A=null!==(n=null===(i=this.zigbeeData)||void 0===i?void 0:i.edges)&&void 0!==n?n:[],k=w.find((t=>t.id===this.selected));return qi` -
-
WISER · ZIGBEE
-
- ${this.layoutIcon("common.refresh","M17.65,6.35C16.2,4.9 14.21,4 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20C15.73,20 18.84,17.45 19.73,14H17.65C16.83,16.33 14.61,18 12,18A6,6 0 0,1 6,12A6,6 0 0,1 12,6C13.66,6 15.14,6.69 16.22,7.78L13,11H20V4L17.65,6.35Z",(()=>{this.loadData()}),void 0,this.loading)} - ${this.layoutIcon("card.fit","M3 3H9V5H5V9H3V3M15 3H21V9H19V5H15V3M3 15H5V19H9V21H3V15M19 15H21V21H15V19H19V15Z",(()=>this.fitNetwork()))} - ${this.layoutIcon("card.zoom_in","M19 13H13V19H11V13H5V11H11V5H13V11H19V13Z",(()=>this.zoomStep(1.1)))} - ${this.layoutIcon("card.zoom_out","M19 13H5V11H19V13Z",(()=>this.zoomStep(.8)))} - ${this.layoutIcon("card.tidy","M3 3H10V10H3V3M14 3H21V10H14V3M3 14H10V21H3V14M14 14H21V21H14V14Z",(()=>this.tidyLayout()))} - ${this.layoutIcon("card.link_labels","M17.63 5.84C17.27 5.33 16.67 5 16 5H5C3.9 5 3 5.9 3 7V17C3 18.1 3.9 19 5 19H16C16.67 19 17.27 18.67 17.63 18.16L22 12L17.63 5.84Z",(()=>this.toggleLabels()),this.showLabels)} - ${this.magnifierControl()} - ${this.layoutIcon("card.show_detailed_view","M3 3H21V21H3V3M5 5V7H19V5H5M5 9V19H19V9H5Z",(()=>this.toggleViewMode()),!(null!==(s=null===(r=this.config)||void 0===r?void 0:r.map_only)&&void 0!==s&&s),!this.config)} - ${this.settingsTransferControl()} - ${this.layoutIcon("card.save_layout","M17,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V7L17,3M12,19A3,3 0 0,1 9,16A3,3 0 0,1 12,13A3,3 0 0,1 15,16A3,3 0 0,1 12,19M15,9H5V5H15V9Z",(()=>this.saveLayoutClick()))} -
-
- ${this.layoutStatus?qi`

- ${this.t(this.layoutStatus)} -

`:""} -
-
- ${""===(null===(l=this.config)||void 0===l?void 0:l.name)?"":qi`

${null!==(c=null===(h=this.config)||void 0===h?void 0:h.name)&&void 0!==c?c:this.t("card.title")}

`} -

- ${z4("devices",w.length,this.hass)} - · ${z4("connections",A.length,this.hass)} -

-
-
-
-
{var e;(null===(e=this.config)||void 0===e?void 0:e.magnifier)&&this.magnifier.show(t.currentTarget,t)}} - @pointerleave=${()=>this.magnifier.hide()} - @pointerdown=${()=>this.magnifier.hide()} - @wheel=${this.panZoomedView} - @touchstart=${this.touchZoomStart} - role="img" - aria-label=${this.t((null===(d=this.config)||void 0===d?void 0:d.map_only)?"map.accessible_only":!1!==(null===(u=this.config)||void 0===u?void 0:u.show_device_list)?"map.accessible_list":"map.accessible_details")} - >
- ${"area"===(null===(f=this.config)||void 0===f?void 0:f.group_by)?qi` - - `:""} - ${this.error?qi``:this.loading?qi`
- ${this.t("card.updating")} -
`:w.length?"":qi`
${this.t("card.empty")}
`} -
-
- ${k?qi`
- ${this.deviceName(k)} ${function(t,e,i,n=!1){return qi`${t}`}(this.t("common.close"),(()=>{this.closeDeviceInfo()}))} -
- ${this.renderZigbeeDetails(k)} - ${A.filter((t=>t.from===k.id||t.to===k.id)).map((t=>qi`
- ${this.deviceName(w.find((e=>e.id===(t.from===k.id?t.to:t.from))))}${P4(t.label,this.hass)} -
`))}`:qi`

${this.t("card.hint")}

`} - ${(null===(m=this.config)||void 0===m?void 0:m.map_only)||!1===(null===(b=this.config)||void 0===b?void 0:b.show_device_list)?"":(E=this.t("layout.device_list"),C=qi` ${w.map((t=>qi`
- ${this.deviceName(t)} ${A.filter((e=>e.from===t.id)).map((t=>qi`
- → - ${this.deviceName(w.find((e=>e.id===t.to)))}${P4(t.label,this.hass)} -
`))} -
`))}`,qi`
${C}
`)} -
-
${this.pasteSettingsDialog()}`;var E,C}}return Q4.panelApiVersion=1,Q4.styles=mn` - ${yn(Fn)} - :host { - display: block; - min-width: 0; - max-width: 100%; - --wiser-muted: var(--secondary-text-color, #7d8795); - } - ha-card { - display: block; - overflow: hidden; - border-radius: var(--ha-card-border-radius, 20px); - color: var(--primary-text-color, #273448); - background: var(--ha-card-background, var(--card-background-color, #fff)); - } - :host([auto-height]) { - height: 100%; - min-height: 0; - } - ha-card.auto-height { - height: 100%; - box-sizing: border-box; - display: flex; - flex-direction: column; - } - .auto-height > .brand-row, - .auto-height > header, - .auto-height > .save-status { - flex-shrink: 0; - } - .auto-height .map { - flex: 1 1 340px; - min-height: 100px; - } - .auto-height #zigbee-network { - position: absolute; - inset: 0; - height: 100%; - } - .auto-height > footer:not(.map-info) { - flex: 0 1 auto; - min-height: 0; - max-height: 45%; - overflow-y: auto; - } - [hidden] { - display: none !important; - } - #settings-paste { - box-sizing: border-box; - width: 100%; - min-height: 200px; - resize: vertical; - color: var(--primary-text-color); - background: var(--secondary-background-color); - border: 1px solid var(--divider-color); - border-radius: 8px; - padding: 12px; - font: 14px monospace; - } - .paste-actions { display: flex; justify-content: flex-end; gap: 8px; } - .brand-row { - display: flex; - flex-wrap: wrap; - gap: 4px; - align-items: center; - justify-content: space-between; - padding: 12px 12px 0 24px; - } - .layout-actions { - display: flex; - flex-wrap: wrap; - margin-left: auto; - } - .layout-icon { - --ha-icon-button-size: 36px; - --mdc-icon-button-size: 36px; - --mdc-icon-size: 20px; - --ha-icon-size: 20px; - border-radius: 50%; - } - .brand-row .eyebrow { - margin: 0; - } - .brand-row .layout-icon { - color: var(--wiser-muted); - --mdc-icon-button-icon-color: var(--wiser-muted); - } - .save-status { - padding: 0 24px; - } - - .map-only .map { - margin: 4px 12px; - } - header { - display: flex; - align-items: center; - justify-content: space-between; - gap: 16px; - padding: 8px 24px 18px; - } - .eyebrow { - font-size: 10px; - letter-spacing: 1.8px; - font-weight: 700; - color: var(--wiser-muted); - margin-bottom: 8px; - } - h2 { - font-size: 20px; - line-height: 1.3; - font-weight: 600; - margin: 0; - letter-spacing: -0.4px; - } - p { - margin: 8px 0 0; - font-size: 12px; - color: var(--wiser-muted); - } - p span { - margin: 0 6px; - } - .map { - position: relative; - margin: 0 12px; - background: transparent; - } - #zigbee-network { - width: 100%; - height: 340px; - } - .area-icons { - position: absolute; - inset: 0; - overflow: hidden; - pointer-events: none; - color: var(--primary-text-color); - } - .area-icons ha-icon, .magnifier-area-icons ha-icon { - position: absolute; - transform: translate(-50%, -50%); - pointer-events: none; - } - #magnifier-menu { position: absolute; } - .magnifier-options { display: flex; align-items: stretch; } - .magnifier-zoom-options { width: 64px; display: flex; flex-direction: column; } - .lens-size-control { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 4px; - padding: 4px 8px; - border-left: 1px solid var(--divider-color); - color: var(--primary-text-color); - } - .lens-size-control ha-slider { - display: block; - width: 36px; - min-width: 0; - height: 80px; - min-height: 0; - flex: none; - } - .lens-size-control ha-slider::part(slider) { - justify-content: center; - padding: 8px 0; - margin: 0; - } - .lens-size-control ha-slider::part(track) { height: 64px; } - .lens-size-control span { font-size: 12px; color: var(--secondary-text-color); } - .map-magnifier { - position: absolute; - z-index: 2; - overflow: hidden; - border-radius: 50%; - outline: 2px solid var(--primary-color); - box-shadow: 0 3px 12px rgb(0 0 0 / 35%); - background: var(--ha-card-background, var(--card-background-color, #fff)); - pointer-events: none; - } - .magnifier-area-icons { - position: absolute; - left: 0; - top: 0; - transform-origin: 0 0; - color: var(--primary-text-color); - pointer-events: none; - } - .message { - position: absolute; - top: 12px; - left: 12px; - right: 12px; - text-align: center; - padding: 10px; - border-radius: 8px; - background: var(--card-background-color, #fff); - font-size: 12px; - pointer-events: none; - } - footer { - padding: 16px 24px 20px; - } - ha-card.map-only { - position: relative; - } - .map-only footer.map-info { - position: absolute; - z-index: 1; - inset: auto 12px 12px; - box-sizing: border-box; - max-height: 60%; - overflow-y: auto; - overscroll-behavior: contain; - padding: 16px; - border: 1px solid var(--divider-color); - border-radius: var(--ha-card-border-radius, 12px); - background: var(--ha-card-background, var(--card-background-color, #fff)); - color: var(--primary-text-color); - box-shadow: var(--ha-card-box-shadow, 0 2px 8px rgb(0 0 0 / 15%)); - } - .map-info .selection { - position: sticky; - top: -16px; - padding: 8px 0; - background: var(--ha-card-background, var(--card-background-color, #fff)); - } - .hint { - margin: 0; - line-height: 1.5; - } - .selection, - .connection { - display: flex; - justify-content: space-between; - align-items: center; - gap: 12px; - font-size: 12px; - } - .connection { - padding: 8px 0; - color: var(--wiser-muted); - } - .connection strong { - font-weight: 500; - text-align: right; - } - ha-expansion-panel { - display: block; - margin-top: 14px; - --ha-card-background: transparent; - } - .panel-content { - padding: 0 12px 12px; - } - ha-textarea { - display: block; - width: 100%; - margin-top: 12px; - } - ha-button { - flex-shrink: 0; - } - .panel-content ha-button { - margin-top: 12px; - } - .device { - border-top: 1px solid var(--divider-color); - padding: 12px 0; - } - @media (max-width: 400px) { - [hidden] { - display: none !important; - } - .map-brand { - padding: 24px 24px 0; - } - .map-only .map { - margin: 4px 12px; - } - header { - padding: 20px 16px 16px; - } - footer { - padding: 16px; - } - h2 { - font-size: 18px; - } - } - `,e([Ln({type:Boolean,reflect:!0,attribute:"auto-height"})],Q4.prototype,"autoHeight",void 0),e([Ln({attribute:"theme-mode",reflect:!0})],Q4.prototype,"themeMode",void 0),e([Un()],Q4.prototype,"config",void 0),e([Un()],Q4.prototype,"zigbeeData",void 0),e([Un()],Q4.prototype,"loading",void 0),e([Un()],Q4.prototype,"error",void 0),e([Un()],Q4.prototype,"showLabels",void 0),e([Un()],Q4.prototype,"pastingSettings",void 0),e([Un()],Q4.prototype,"pasteDialogOpen",void 0),e([Un()],Q4.prototype,"pasteError",void 0),e([Un()],Q4.prototype,"activeIcon",void 0),e([Un()],Q4.prototype,"selected",void 0),e([Un()],Q4.prototype,"selectedEntity",void 0),e([Un()],Q4.prototype,"layoutStatus",void 0),e([Qn({capture:!0,passive:!0})],Q4.prototype,"touchZoomStart",null),e([Qn({capture:!0,passive:!1})],Q4.prototype,"panZoomedView",null),customElements.get("wiser-zigbee-card")||customElements.define("wiser-zigbee-card",Q4),t.WiserZigbeeCard=Q4,t}({}); diff --git a/tests/test_frontend_version.py b/tests/test_frontend_version.py index 835cb11d..fa22ca6f 100644 --- a/tests/test_frontend_version.py +++ b/tests/test_frontend_version.py @@ -40,10 +40,6 @@ def test_missing_file_returns_missing(self): with TemporaryDirectory() as directory: self.assertEqual(module.card_version(Path(directory) / "missing.js"), "missing") - def test_installed_bundle_has_readable_version(self): - version = module.card_version(ROOT / "custom_components/wiser/frontend/wiser-schedule-card.js") - self.assertRegex(version, r"^\d+\.\d+\.\d+") - def test_explicit_version_marker(self): self.assertEqual(self.version('/*! WISER-CARD-VERSION wiser-schedule-card 4.0.0-dev.9 */\nconst library="3.3.3";'), "4.0.0-dev.9") diff --git a/tests/test_schedule_card_hide_hw_schedule.py b/tests/test_schedule_card_hide_hw_schedule.py index b9e4bcd0..d5bd4679 100644 --- a/tests/test_schedule_card_hide_hw_schedule.py +++ b/tests/test_schedule_card_hide_hw_schedule.py @@ -1,22 +1,12 @@ -"""Integration contract for the externally built schedule card/panel bundle. - -Card behaviour is tested in the wiser-schedule-card source repository. -""" +"""Integration contracts for schedule operations used by the external card.""" from pathlib import Path import unittest ROOT = Path(__file__).resolve().parents[1] / "custom_components/wiser" -CARD = ROOT / "frontend/wiser-schedule-card.js" WEBSOCKETS = ROOT / "websockets.py" class ScheduleCardBundleTest(unittest.TestCase): - def test_matching_card_and_panel_are_bundled_together(self): - source = CARD.read_text() - self.assertIn('wiser-schedules-panel', source) - self.assertIn('wiser-schedule-card-editor', source) - self.assertIn('panelApiVersion', source) - def test_delete_websocket_reconciles_ambiguous_hub_errors(self): websocket_source = WEBSOCKETS.read_text() diff --git a/tests/test_zigbee_version.py b/tests/test_zigbee_version.py index f0467078..6854e166 100644 --- a/tests/test_zigbee_version.py +++ b/tests/test_zigbee_version.py @@ -41,13 +41,6 @@ def test_zigbee_banner_ignores_library_versions(self): def test_zigbee_dev_version(self): self.assertEqual(self.version('const cardBuild="3.0.0-dev.7";console.info(`WISER-ZIGBEE-CARD ${translate("common.version")} ${cardBuild}`)'), "3.0.0-dev.7") - def test_installed_zigbee_bundle_has_readable_version(self): - version = module.card_version(ROOT / "custom_components/wiser/frontend/wiser-zigbee-card.js") - source = (ROOT / "custom_components/wiser/frontend/wiser-zigbee-card.js").read_text() - marker = re.search(r"/\*! WISER-CARD-VERSION wiser-zigbee-card (\S+) \*/", source) - self.assertIsNotNone(marker) - self.assertEqual(version, marker[1]) - def test_modern_editor_footer_with_inlined_version(self): source = 'const library="3.3.3";html`
${this.t("common.version")}: ${"3.0.0-dev.65"}
`' self.assertEqual(self.version(source), "3.0.0-dev.65") From 2d4020c51ec74bb339b4aec81093f4b84888f7d7 Mon Sep 17 00:00:00 2001 From: asantaga Date: Mon, 28 Sep 2026 07:01:35 +0100 Subject: [PATCH 034/154] added contributing text --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f84af2d8..5aaf906c 100755 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ See [CHANGELOG.md](CHANGELOG.md) for the full release history. Releases before v3.3.5 are listed on our wiki [here](https://github.com/asantaga/wiserHomeAssistantPlatform/wiki/Full-Change-Log). -## Building +## Building and Contributing To build a stable release package, run: @@ -67,3 +67,11 @@ For a prerelease package, use `--channel dev` instead. The build downloads publi The output is `dist/wiser.zip`. The accompanying `dist/card-releases.json` records the card releases and checksums included in the package. Missing or invalid card assets fail the build. The **Publish** GitHub Actions workflow runs the same build and attaches `wiser.zip` when an integration release is published. Preview runs provide a downloadable **wiser-package** artifact without publishing a release. + +## Contributing + +We welcome and greatly appreciate all issues, pull requests, and bug fixes. Please base your PR on the `dev` branch — all development happens there. `dev` is merged into master only when we cut a production release, tagged `vX.Y.Z` (e.g. `v3.4.20`). We also publish release candidates sourced from dev, tagged `vX.Y.Z-rcN` (e.g. `v4.0.0-rc1`). + + + +Wiser Home Assistant Integration Team \ No newline at end of file From daea9fad9aca4ba2d344e358110836704e6bc78c Mon Sep 17 00:00:00 2001 From: asantaga Date: Mon, 28 Sep 2026 08:36:47 +0100 Subject: [PATCH 035/154] docs: add CONTRIBUTING.md Move contributor guidance out of the README into a dedicated CONTRIBUTING.md covering bug reports, repository layout, branching, development setup, tests, code style, versioning, and packaging. Co-Authored-By: Claude Opus 5 --- CONTRIBUTING.md | 161 ++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 6 +- 2 files changed, 164 insertions(+), 3 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..23567a6a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,161 @@ +# Contributing + +Thanks for helping out with the Wiser Home Assistant integration. Issues, pull +requests, and bug fixes are all welcome and greatly appreciated. + +## Before you start + +- **Search the [issues](https://github.com/asantaga/wiserHomeAssistantPlatform/issues) + first.** If your problem is already reported, add your details there rather + than opening a duplicate. +- For anything larger than a bug fix, open an issue to discuss the approach + before writing code. It saves everyone a wasted PR. +- Check the [Wiki](https://github.com/asantaga/wiserHomeAssistantPlatform/wiki) + for setup and usage documentation. + +## Reporting bugs + +Please include: + +- The integration version (Settings → Devices & Services → Wiser), and your + Home Assistant version. +- Your hub model (v1 or v2) and firmware version. +- A **diagnostics download** from the integration's device page — it redacts + secrets and captures the hub data we need. +- Relevant log output. Add this to `configuration.yaml`, restart, and reproduce: + + ```yaml + logger: + default: warning + logs: + custom_components.wiser: debug + aioWiserHeatAPI: debug + ``` + +## Where things live + +| What | Where | +| --- | --- | +| Integration source | `custom_components/wiser/` | +| Hub communication | the separate `aioWiserHeatAPI` library, pinned in `manifest.json` | +| Frontend panel/card plumbing | `custom_components/wiser/frontend/` | +| Schedules and Zigbee cards | separate repositories ([wiser-schedule-card](https://github.com/andyblac/wiser-schedule-card), [wiser-zigbee-card](https://github.com/andyblac/wiser-zigbee-card)) | +| Tests | `tests/` | +| Packaging scripts | `scripts/` | + +Two things that trip people up: + +- If a change is really about how we talk to the hub, it probably belongs in + `aioWiserHeatAPI`, not here. +- **Card bundles are not committed to this repository.** They are downloaded + from the card repositories' GitHub releases at build time. Do not add built + `.js` card assets to `custom_components/wiser/frontend/`. + +## Branching and pull requests + +- **Base every PR on `dev`.** All development happens there; `master` only + receives `dev` when we cut a release. +- Name your branch after the issue it fixes, e.g. `issue123`. +- Keep a PR to one logical change. Unrelated fixes are much easier to review as + separate PRs. +- Reference the issue in the PR description (`Fixes #123`). +- Add or update tests for behaviour you change, and add a `CHANGELOG.md` entry + under the unreleased/current heading, matching the existing style (one line, + ending with a link to the issue and/or PR). + +Releases are tagged from `master` as `vX.Y.Z` (e.g. `v3.4.20`). Release +candidates are cut from `dev` and tagged `vX.Y.Z-rcN` (e.g. `v4.0.0-rc1`). + +## Development setup + +Run the integration against a real Home Assistant instance. The quickest route +is a development instance (container or venv) with the integration mounted or +symlinked into place: + +```sh +ln -s /path/to/wiserHomeAssistantPlatform/custom_components/wiser \ + /path/to/ha-config/custom_components/wiser +``` + +Restart Home Assistant after each change — Home Assistant does not hot-reload +custom components. + +The minimum supported Home Assistant version is declared in `hacs.json` +(currently 2025.5); don't use APIs newer than that without raising the minimum +deliberately. + +## Tests + +Tests use plain `unittest` and stub out the Home Assistant runtime, so they run +without installing Home Assistant. Install the small set of helper dependencies +first: + +```sh +python -m pip install -r tests/requirements.txt +``` + +Run the whole suite from the repository root: + +```sh +python -m unittest discover -s tests -p 'test_*.py' +``` + +Or a single file while iterating: + +```sh +python -m unittest discover -s tests -p test_sensor.py +``` + +CI (the **Publish** workflow) runs the packaging and frontend tests, and the +**Validate** workflow runs HACS validation and `hassfest`. Both must pass. + +## Code style + +There is no enforced formatter config in this repository, so match the +surrounding code, which follows Home Assistant core conventions: + +- `from __future__ import annotations` at the top, type hints on new functions. +- Docstrings on every module, class, and function. +- Import grouping and ordering as in the existing modules. +- New user-visible strings go in `strings.json` and the files under + `translations/`; new icons go in `icons.json`. + +## Versioning + +`version` in `custom_components/wiser/manifest.json` must stay parseable by HACS +and Home Assistant. Use `X.Y.Z` for releases, `X.Y.Z-rcN` for release +candidates, and `X.Y.ZbN` for beta builds on `dev`. Do not invent suffixes such +as `Dev` — HACS and Home Assistant reject them, and the integration will fail to +load with `does not have a valid version key`. + +## Building a package + +```sh +# Stable release package +python3 scripts/build.py --release --channel stable + +# Prerelease package +python3 scripts/build.py --release --channel dev +``` + +The output is `dist/wiser.zip`, with `dist/card-releases.json` recording the +card releases and checksums included. Stable builds use stable card releases; +prerelease builds use the newest prerelease of each card, falling back to its +newest stable release. Missing or invalid card assets fail the build. + +To see which card releases would be selected without downloading anything: + +```sh +python3 scripts/fetch_card_releases.py --channel dev --plan +``` + +The **Publish** workflow runs the same build and attaches `wiser.zip` when a +release is published. + +## Licence + +By contributing, you agree that your contributions are licensed under the +project's MIT licence (see [LICENSE](LICENSE)). + +Thanks again, +Wiser Home Assistant Integration Team diff --git a/README.md b/README.md index 5aaf906c..adb0e750 100755 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ See [CHANGELOG.md](CHANGELOG.md) for the full release history. Releases before v3.3.5 are listed on our wiki [here](https://github.com/asantaga/wiserHomeAssistantPlatform/wiki/Full-Change-Log). -## Building and Contributing +## Building To build a stable release package, run: @@ -70,8 +70,8 @@ The **Publish** GitHub Actions workflow runs the same build and attaches `wiser. ## Contributing -We welcome and greatly appreciate all issues, pull requests, and bug fixes. Please base your PR on the `dev` branch — all development happens there. `dev` is merged into master only when we cut a production release, tagged `vX.Y.Z` (e.g. `v3.4.20`). We also publish release candidates sourced from dev, tagged `vX.Y.Z-rcN` (e.g. `v4.0.0-rc1`). - +We welcome and greatly appreciate all issues, pull requests, and bug fixes. Please base your PR on the `dev` branch — all development happens there. +See [CONTRIBUTING.md](CONTRIBUTING.md) for how to report a bug, set up a development environment, run the tests, and get a pull request merged. Wiser Home Assistant Integration Team \ No newline at end of file From 79414445aba090ee3c041662cbf05f1ad277a32b Mon Sep 17 00:00:00 2001 From: asantaga Date: Mon, 28 Sep 2026 08:41:12 +0100 Subject: [PATCH 036/154] added contributing.md --- CONTRIBUTING.md | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 23567a6a..aef7027d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,7 +20,7 @@ Please include: - The integration version (Settings → Devices & Services → Wiser), and your Home Assistant version. - Your hub model (v1 or v2) and firmware version. -- A **diagnostics download** from the integration's device page — it redacts +- Depending on the bug we may ask for a **diagnostics download** from the integration's device page — it redacts secrets and captures the hub data we need. - Relevant log output. Add this to `configuration.yaml`, restart, and reproduce: @@ -45,8 +45,8 @@ Please include: Two things that trip people up: -- If a change is really about how we talk to the hub, it probably belongs in - `aioWiserHeatAPI`, not here. +- If a change is really about how we talk to the hub, it probably belongs in + [aioWiserHeatAPI](https://github.com/msp1974/aioWiserHeatAPI) git repo, not here. - **Card bundles are not committed to this repository.** They are downloaded from the card repositories' GitHub releases at build time. Do not add built `.js` card assets to `custom_components/wiser/frontend/`. @@ -84,30 +84,6 @@ The minimum supported Home Assistant version is declared in `hacs.json` (currently 2025.5); don't use APIs newer than that without raising the minimum deliberately. -## Tests - -Tests use plain `unittest` and stub out the Home Assistant runtime, so they run -without installing Home Assistant. Install the small set of helper dependencies -first: - -```sh -python -m pip install -r tests/requirements.txt -``` - -Run the whole suite from the repository root: - -```sh -python -m unittest discover -s tests -p 'test_*.py' -``` - -Or a single file while iterating: - -```sh -python -m unittest discover -s tests -p test_sensor.py -``` - -CI (the **Publish** workflow) runs the packaging and frontend tests, and the -**Validate** workflow runs HACS validation and `hassfest`. Both must pass. ## Code style From 38149c1c34047411c7294c9aac5cb83aa845e4f4 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Mon, 21 Sep 2026 15:37:46 +0100 Subject: [PATCH 037/154] Update publish actions to Node 24 and pin Ubuntu runner --- .github/workflows/publish.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index e59b6da2..5ff0312d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -19,7 +19,7 @@ permissions: jobs: package: name: Build Wiser integration - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v5 - uses: actions/setup-python@v6 @@ -48,7 +48,7 @@ jobs: --schedule-repository "$SCHEDULE_REPOSITORY" --zigbee-repository "$ZIGBEE_REPOSITORY" - name: Upload release package for inspection - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v7 with: name: wiser-package path: | @@ -60,15 +60,15 @@ jobs: name: Attach package to published release if: github.event_name == 'release' needs: package - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 permissions: contents: write steps: - - uses: actions/download-artifact@v6 + - uses: actions/download-artifact@v8 with: name: wiser-package path: dist - - uses: softprops/action-gh-release@v2 + - uses: softprops/action-gh-release@v3 with: files: dist/wiser.zip fail_on_unmatched_files: true From e60e656061e88453abb15a467bacb2fc75a24474 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Sun, 20 Sep 2026 14:37:01 +0100 Subject: [PATCH 038/154] Select newest published card release for dev builds --- scripts/fetch_card_releases.py | 4 ++-- tests/test_card_releases.py | 25 ++++++++++++++++++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/scripts/fetch_card_releases.py b/scripts/fetch_card_releases.py index 66123468..2668ab14 100644 --- a/scripts/fetch_card_releases.py +++ b/scripts/fetch_card_releases.py @@ -37,10 +37,10 @@ def list_releases(repository): def select_release(releases, channel): + """Select the most recently published release allowed by the channel.""" published = [r for r in releases if not r.get("draft") and r.get("published_at")] stable = [r for r in published if not r.get("prerelease")] - beta = [r for r in published if r.get("prerelease")] - candidates = (beta or stable) if channel == "dev" else stable + candidates = published if channel == "dev" else stable if not candidates: raise ValueError(f"No published {'prerelease or stable' if channel == 'dev' else 'stable'} release available") return max(candidates, key=lambda r: r["published_at"]) diff --git a/tests/test_card_releases.py b/tests/test_card_releases.py index 26f3e451..9213843a 100644 --- a/tests/test_card_releases.py +++ b/tests/test_card_releases.py @@ -21,12 +21,27 @@ def release(tag, date, prerelease=False, card="zigbee", draft=False, asset=True) class CardReleaseTest(unittest.TestCase): def setUp(self): - self.beta = release("v3-beta", "2026-09-01T00:00:00Z", True) - self.stable = release("v2", "2026-09-02T00:00:00Z") + self.beta = release("v2.0.0-beta.1", "2026-09-01T00:00:00Z", True) + self.stable = release("v2.0.1", "2026-09-02T00:00:00Z") self.releases = [self.stable, self.beta, release("draft", "2026-09-03T00:00:00Z", True, draft=True)] - def test_dev_prefers_latest_prerelease_even_if_stable_is_newer(self): - self.assertEqual(FETCH.select_release(self.releases, "dev"), self.beta) + def test_dev_selects_newer_stable_over_older_prerelease(self): + self.assertEqual(FETCH.select_release(self.releases, "dev"), self.stable) + + def test_dev_selects_newer_prerelease_over_older_stable(self): + newer_beta = release("v2.1.0-beta.1", "2026-09-04T00:00:00Z", True) + releases = [newer_beta, *self.releases] + self.assertEqual(FETCH.select_release(releases, "dev"), newer_beta) + self.assertEqual(FETCH.select_release(releases, "stable"), self.stable) + + def test_unpublished_releases_are_excluded(self): + unpublished = release("v4.0.0", None) + for channel in ("dev", "stable"): + with self.subTest(channel=channel): + self.assertEqual( + FETCH.select_release([unpublished, *self.releases], channel), + self.stable, + ) def test_stable_excludes_prereleases_and_drafts(self): self.assertEqual(FETCH.select_release(self.releases, "stable"), self.stable) @@ -55,7 +70,7 @@ def test_plan_does_not_download_or_write(self): report = FETCH.fetch_cards("dev", out, {"zigbee": "andyblac/wiser-zigbee-card"}, plan=True) download.assert_not_called() self.assertFalse(out.exists()) - self.assertEqual(report[0]["tag"], "v3-beta") + self.assertEqual(report[0]["tag"], "v2.0.1") def test_download_failure_does_not_replace_either_card(self): with TemporaryDirectory() as directory: From 199cc943d552ae730ff151acd8970ec06d7ca4e8 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Mon, 21 Sep 2026 14:54:59 +0100 Subject: [PATCH 039/154] Honor HACS prerelease preference for card updates --- README.md | 2 +- custom_components/wiser/update.py | 58 ++++++++++++++++++++++++++----- tests/test_card_updates.py | 32 +++++++++++++++-- 3 files changed, 81 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index adb0e750..fe6d2ff8 100755 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ To build a stable release package, run: python3 scripts/build.py --release --channel stable ``` -For a prerelease package, use `--channel dev` instead. The build downloads published Schedules and Zigbee card assets from GitHub. Stable builds use stable card releases; prerelease builds use the newest published prerelease of each card, falling back to its newest stable release when none exists. +For a prerelease package, use `--channel dev` instead. The build downloads published Schedules and Zigbee card assets from GitHub. Stable builds use stable card releases; prerelease builds use the most recently published stable or prerelease card release. In a running installation, card update entities follow the HACS **Pre-release** switch for this integration; without that option they offer stable card releases only. The output is `dist/wiser.zip`. The accompanying `dist/card-releases.json` records the card releases and checksums included in the package. Missing or invalid card assets fail the build. diff --git a/custom_components/wiser/update.py b/custom_components/wiser/update.py index 4ebb2f8d..25c7f3f3 100644 --- a/custom_components/wiser/update.py +++ b/custom_components/wiser/update.py @@ -26,26 +26,36 @@ _LOGGER = logging.getLogger(__name__) _MANAGER = "wiser_card_updates" _MAX_DOWNLOAD = 20 * 1024 * 1024 +_HACS_REPOSITORY_ID = "159080189" _CARDS = { "schedule": ("andyblac/wiser-schedule-card", "wiser-schedule-card.js", "wiser-schedules-panel"), "zigbee": ("andyblac/wiser-zigbee-card", "wiser-zigbee-card.js", "wiser-zigbee-panel"), } -def _release_version(tag): - """Only accept stable semantic versions from published releases.""" - match = re.fullmatch(r"v?(\d+\.\d+\.\d+(?:\+[0-9A-Za-z.-]+)?)", tag) +def _release_version(tag, allow_prerelease=False): + """Accept semantic card versions allowed by the selected release channel.""" + match = re.fullmatch( + r"v?(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?)", + tag, + ) if not match: + raise ValueError(f"Unsupported card release version: {tag}") + if "-" in match[1].split("+", 1)[0] and not allow_prerelease: raise ValueError(f"Unsupported stable card release version: {tag}") return match[1] -def _validate_release(card, release): +def _validate_release(card, release, allow_prerelease=False): """Validate release metadata before exposing an installable update.""" repository, filename, _ = _CARDS[card] - if release.get("draft") or release.get("prerelease") or not release.get("published_at"): + if ( + release.get("draft") + or (release.get("prerelease") and not allow_prerelease) + or not release.get("published_at") + ): raise ValueError("Expected a published stable card release") - version = _release_version(release["tag_name"]) + version = _release_version(release["tag_name"], allow_prerelease) assets = [ asset for asset in release["assets"] if asset["name"] == filename and asset.get("state") == "uploaded" @@ -69,6 +79,31 @@ def _validate_release(card, release): } +def _prereleases_enabled(hass): + """Follow HACS' prerelease preference for this integration when available.""" + registry = er.async_get(hass) + entity_id = registry.async_get_entity_id( + "switch", "hacs", _HACS_REPOSITORY_ID + ) + states = getattr(hass, "states", None) + return bool(entity_id and states and states.is_state(entity_id, "on")) + + +def _select_release(card, releases, allow_prerelease): + """Select the highest valid published release allowed by the channel.""" + selected = None + for metadata in releases: + try: + release = _validate_release(card, metadata, allow_prerelease) + except (ValueError, KeyError, TypeError): + continue + if selected is None or newer_version(release["version"], selected["version"]): + selected = release + if selected is None: + raise ValueError("No verified card release is available") + return selected + + def _validate_download(card, release, contents): """Verify the file before changing the currently installed card.""" _, filename, component = _CARDS[card] @@ -154,14 +189,21 @@ async def _check_card(self, card): if card in self.pending_refresh: installed = self.pending_refresh[card][0] try: + allow_prerelease = _prereleases_enabled(self.hass) + endpoint = "releases?per_page=100" if allow_prerelease else "releases/latest" session = async_get_clientsession(self.hass) async with session.get( - f"https://api.github.com/repos/{repository}/releases/latest", + f"https://api.github.com/repos/{repository}/{endpoint}", headers={"Accept": "application/vnd.github+json", "User-Agent": "Wiser-Home-Assistant"}, timeout=aiohttp.ClientTimeout(total=20), ) as response: response.raise_for_status() - release = _validate_release(card, await response.json()) + metadata = await response.json() + release = ( + _select_release(card, metadata, True) + if allow_prerelease + else _validate_release(card, metadata) + ) return {"installed": installed, "release": release, "error": None} except (aiohttp.ClientError, TimeoutError, ValueError, KeyError, TypeError) as err: _LOGGER.warning("Unable to check %s card releases: %s", card, err) diff --git a/tests/test_card_updates.py b/tests/test_card_updates.py index 62e462dc..ce9630de 100644 --- a/tests/test_card_updates.py +++ b/tests/test_card_updates.py @@ -90,6 +90,7 @@ async def resource(hass, filename): self.hass = SimpleNamespace( data={}, config=SimpleNamespace(path=lambda *args: str(self.directory.joinpath(*args))), async_add_executor_job=AsyncMock(side_effect=lambda fn, *args: fn(*args)), + states=SimpleNamespace(is_state=Mock(return_value=False)), ) self.coordinator = self.updates.CardUpdateCoordinator(self.hass) @@ -98,11 +99,11 @@ def payload(self, card="zigbee", version="2.0.0"): return (f"/*! WISER-CARD-VERSION {filename[:-3]} {version} */\n" f"customElements.define('{component}', class extends HTMLElement {{}});").encode() - def metadata(self, card="zigbee", version="2.0.0"): + def metadata(self, card="zigbee", version="2.0.0", prerelease=False): contents = self.payload(card, version) repo, filename, _ = self.updates._CARDS[card] return { - "tag_name": f"v{version}", "published_at": "2026-09-20", "draft": False, "prerelease": False, + "tag_name": f"v{version}", "published_at": "2026-09-20", "draft": False, "prerelease": prerelease, "assets": [{"name": filename, "state": "uploaded", "size": len(contents), "digest": "sha256:" + sha256(contents).hexdigest(), "browser_download_url": f"https://github.com/{repo}/releases/download/v{version}/{filename}"}], @@ -168,6 +169,33 @@ def test_rejects_prereleases_and_foreign_download_urls(self): with self.subTest(change=change), self.assertRaises(ValueError): self.updates._validate_release("zigbee", metadata) + def test_accepts_prerelease_only_when_enabled(self): + metadata = self.metadata(version="2.1.0-beta.1", prerelease=True) + with self.assertRaises(ValueError): + self.updates._validate_release("zigbee", metadata) + release = self.updates._validate_release( + "zigbee", metadata, allow_prerelease=True + ) + self.assertEqual(release["version"], "2.1.0-beta.1") + + async def test_hacs_prerelease_switch_enables_card_prereleases(self): + self.registry.async_get_entity_id.return_value = "switch.wiser_pre_release" + self.hass.states.is_state.return_value = True + releases = [ + self.metadata(version="2.0.1"), + self.metadata(version="2.1.0-beta.1", prerelease=True), + ] + self.session.get.return_value = self.response(json_data=releases) + state = await self.coordinator._check_card("zigbee") + self.assertEqual(state["release"]["version"], "2.1.0-beta.1") + self.assertIn("/releases?per_page=100", self.session.get.call_args.args[0]) + + async def test_card_updates_remain_stable_without_hacs_prereleases(self): + self.session.get.return_value = self.response(json_data=self.metadata()) + state = await self.coordinator._check_card("zigbee") + self.assertEqual(state["release"]["version"], "2.0.0") + self.assertIn("/releases/latest", self.session.get.call_args.args[0]) + def test_rejects_bad_checksum_and_wrong_version_or_panel(self): release = self.updates._validate_release("zigbee", self.metadata()) with self.assertRaises(ValueError): From 207471fc671582158a6a0ec696b140e649ce20e3 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Mon, 28 Sep 2026 15:03:03 +0100 Subject: [PATCH 040/154] Fix circuit state normalization --- custom_components/wiser/sensor.py | 19 +++-- custom_components/wiser/strings.json | 24 +++++- custom_components/wiser/translations/de.json | 24 +++++- .../wiser/translations/en-GB.json | 24 +++++- custom_components/wiser/translations/en.json | 24 +++++- custom_components/wiser/translations/fr.json | 24 +++++- tests/test_sensor.py | 81 ++++++++++++++++++- 7 files changed, 198 insertions(+), 22 deletions(-) diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index 41f313bc..55fa4366 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -11,7 +11,7 @@ from datetime import datetime, timedelta import logging -from aioWiserHeatAPI.const import TEXT_UNKNOWN +from aioWiserHeatAPI.const import TEXT_OFF, TEXT_ON, TEXT_UNKNOWN from homeassistant.components.sensor import ( SensorDeviceClass, @@ -22,9 +22,10 @@ ATTR_BATTERY_LEVEL, EntityCategory, LIGHT_LUX, + STATE_OFF, + STATE_ON, STATE_UNAVAILABLE, STATE_UNKNOWN, - STATE_ON, UnitOfTemperature, UnitOfTime, UnitOfElectricCurrent, @@ -74,6 +75,11 @@ _LOGGER = logging.getLogger(__name__) +ON_OFF_STATES = { + TEXT_ON: STATE_ON, + TEXT_OFF: STATE_OFF, +} + OPENTHERM_TEMPERATURE_SENSOR_KEYS = frozenset( { @@ -855,26 +861,27 @@ def _handle_coordinator_update(self) -> None: self._device = self._data.wiserhub.heating_channels.get_by_id( self._device_id ) - self._state = ( + raw_state = ( self._device.heating_relay_status if self._device.heating_relay_status != TEXT_UNKNOWN else self._device.demand_on_off_output ) else: self._device = self._data.wiserhub.hotwater - self._state = self._device.current_state + raw_state = self._device.current_state + self._state = ON_OFF_STATES.get(raw_state) self.async_write_ha_state() @property def icon(self): """Return icon.""" if self._sensor_type == "Heating": - if self._state == "Off": + if self._state == STATE_OFF: return "mdi:radiator-disabled" return "mdi:radiator" # Hot water circuit - if self._state == "Off": + if self._state == STATE_OFF: return "mdi:fire-off" return "mdi:fire" diff --git a/custom_components/wiser/strings.json b/custom_components/wiser/strings.json index 441be7e9..c2343191 100755 --- a/custom_components/wiser/strings.json +++ b/custom_components/wiser/strings.json @@ -320,9 +320,27 @@ "signal": { "name": "Signal" }, "cloud": { "name": "Cloud" }, "heating_operation_mode": { "name": "Heating operation mode" }, - "heating": { "name": "Heating" }, - "heating_channel": { "name": "Heating channel {channel}" }, - "hot_water": { "name": "Hot water" }, + "heating": { + "name": "Heating", + "state": { + "off": "[%key:common::state::off%]", + "on": "[%key:common::state::on%]" + } + }, + "heating_channel": { + "name": "Heating channel {channel}", + "state": { + "off": "[%key:common::state::off%]", + "on": "[%key:common::state::on%]" + } + }, + "hot_water": { + "name": "Hot water", + "state": { + "off": "[%key:common::state::off%]", + "on": "[%key:common::state::on%]" + } + }, "hot_water_operation_mode": { "name": "Hot water operation mode" }, "target_temperature": { "name": "Target temperature" }, "floor_temperature": { "name": "Floor temperature" }, diff --git a/custom_components/wiser/translations/de.json b/custom_components/wiser/translations/de.json index 1e8c010a..62a64d6f 100644 --- a/custom_components/wiser/translations/de.json +++ b/custom_components/wiser/translations/de.json @@ -318,9 +318,27 @@ "signal": { "name": "Signal" }, "cloud": { "name": "Cloud" }, "heating_operation_mode": { "name": "Heizungsbetriebsart" }, - "heating": { "name": "Heizung" }, - "heating_channel": { "name": "Heizkanal {channel}" }, - "hot_water": { "name": "Warmwasser" }, + "heating": { + "name": "Heizung", + "state": { + "off": "Aus", + "on": "Ein" + } + }, + "heating_channel": { + "name": "Heizkanal {channel}", + "state": { + "off": "Aus", + "on": "Ein" + } + }, + "hot_water": { + "name": "Warmwasser", + "state": { + "off": "Aus", + "on": "Ein" + } + }, "hot_water_operation_mode": { "name": "Warmwasserbetriebsart" }, "target_temperature": { "name": "Zieltemperatur" }, "floor_temperature": { "name": "Fußbodentemperatur" }, diff --git a/custom_components/wiser/translations/en-GB.json b/custom_components/wiser/translations/en-GB.json index 9a84bef2..9eb79303 100644 --- a/custom_components/wiser/translations/en-GB.json +++ b/custom_components/wiser/translations/en-GB.json @@ -318,9 +318,27 @@ "signal": { "name": "Signal" }, "cloud": { "name": "Cloud" }, "heating_operation_mode": { "name": "Heating operation mode" }, - "heating": { "name": "Heating" }, - "heating_channel": { "name": "Heating channel {channel}" }, - "hot_water": { "name": "Hot water" }, + "heating": { + "name": "Heating", + "state": { + "off": "Off", + "on": "On" + } + }, + "heating_channel": { + "name": "Heating channel {channel}", + "state": { + "off": "Off", + "on": "On" + } + }, + "hot_water": { + "name": "Hot water", + "state": { + "off": "Off", + "on": "On" + } + }, "hot_water_operation_mode": { "name": "Hot water operation mode" }, "target_temperature": { "name": "Target temperature" }, "floor_temperature": { "name": "Floor temperature" }, diff --git a/custom_components/wiser/translations/en.json b/custom_components/wiser/translations/en.json index 737e882a..d88547e2 100755 --- a/custom_components/wiser/translations/en.json +++ b/custom_components/wiser/translations/en.json @@ -318,9 +318,27 @@ "signal": { "name": "Signal" }, "cloud": { "name": "Cloud" }, "heating_operation_mode": { "name": "Heating operation mode" }, - "heating": { "name": "Heating" }, - "heating_channel": { "name": "Heating channel {channel}" }, - "hot_water": { "name": "Hot water" }, + "heating": { + "name": "Heating", + "state": { + "off": "Off", + "on": "On" + } + }, + "heating_channel": { + "name": "Heating channel {channel}", + "state": { + "off": "Off", + "on": "On" + } + }, + "hot_water": { + "name": "Hot water", + "state": { + "off": "Off", + "on": "On" + } + }, "hot_water_operation_mode": { "name": "Hot water operation mode" }, "target_temperature": { "name": "Target temperature" }, "floor_temperature": { "name": "Floor temperature" }, diff --git a/custom_components/wiser/translations/fr.json b/custom_components/wiser/translations/fr.json index e8ff6c12..f7c5407f 100644 --- a/custom_components/wiser/translations/fr.json +++ b/custom_components/wiser/translations/fr.json @@ -318,9 +318,27 @@ "signal": { "name": "Signal" }, "cloud": { "name": "Cloud" }, "heating_operation_mode": { "name": "Mode de fonctionnement du chauffage" }, - "heating": { "name": "Chauffage" }, - "heating_channel": { "name": "Canal de chauffage {channel}" }, - "hot_water": { "name": "Eau chaude" }, + "heating": { + "name": "Chauffage", + "state": { + "off": "Éteint", + "on": "Allumé" + } + }, + "heating_channel": { + "name": "Canal de chauffage {channel}", + "state": { + "off": "Éteint", + "on": "Allumé" + } + }, + "hot_water": { + "name": "Eau chaude", + "state": { + "off": "Éteint", + "on": "Allumé" + } + }, "hot_water_operation_mode": { "name": "Mode de fonctionnement de l’eau chaude" }, "target_temperature": { "name": "Température cible" }, "floor_temperature": { "name": "Température du sol" }, diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 79d8b8dc..c9102fcb 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -29,7 +29,9 @@ def _module(name: str, **attributes: object) -> ModuleType: def _load_sensor_module() -> ModuleType: """Load the sensor module with only the imports needed by this test.""" _module("aioWiserHeatAPI") - _module("aioWiserHeatAPI.const", TEXT_UNKNOWN="Unknown") + _module( + "aioWiserHeatAPI.const", TEXT_OFF="Off", TEXT_ON="On", TEXT_UNKNOWN="Unknown" + ) _module("aioWiserHeatAPI.wiserhub", TEMP_MINIMUM=5, TEMP_OFF="Off") _module("homeassistant") @@ -56,6 +58,7 @@ class SensorEntity: LIGHT_LUX="lx", STATE_UNAVAILABLE="unavailable", STATE_UNKNOWN="unknown", + STATE_OFF="off", STATE_ON="on", EntityCategory=SimpleNamespace(DIAGNOSTIC="diagnostic"), UnitOfTemperature=SimpleNamespace(CELSIUS="°C"), @@ -410,6 +413,82 @@ def test_power_display_name_does_not_change_historical_unique_id_input( self.assertEqual(energy._sensor_type, "Equipment Total Energy ") +class WiserSystemCircuitStateTest(unittest.TestCase): + """Tests for normalized heating and hot-water circuit states.""" + + @classmethod + def setUpClass(cls) -> None: + cls.sensor_module = _load_sensor_module() + + def _sensor( + self, + sensor_type: str, + *, + heating_state="Off", + demand_state="Off", + hot_water_state="Off", + ): + heating_channel = SimpleNamespace( + heating_relay_status=heating_state, + demand_on_off_output=demand_state, + ) + sensor = object.__new__(self.sensor_module.WiserSystemCircuitState) + sensor._sensor_type = sensor_type + sensor._device_id = 1 + sensor._data = SimpleNamespace( + wiserhub=SimpleNamespace( + heating_channels=SimpleNamespace( + get_by_id=lambda _device_id: heating_channel + ), + hotwater=SimpleNamespace(current_state=hot_water_state), + ) + ) + sensor.async_write_ha_state = Mock() + return sensor + + def test_heating_state_is_normalized(self) -> None: + sensor = self._sensor("Heating", heating_state="On") + + sensor._handle_coordinator_update() + + self.assertEqual(sensor.native_value, "on") + + def test_unknown_heating_relay_uses_normalized_demand_output(self) -> None: + sensor = self._sensor( + "Heating", heating_state="Unknown", demand_state="Off" + ) + + sensor._handle_coordinator_update() + + self.assertEqual(sensor.native_value, "off") + + def test_hot_water_state_is_normalized(self) -> None: + sensor = self._sensor("Hot Water", hot_water_state="On") + + sensor._handle_coordinator_update() + + self.assertEqual(sensor.native_value, "on") + + def test_unknown_or_unexpected_state_is_not_reported_as_off(self) -> None: + sensor = self._sensor("Hot Water", hot_water_state="Unknown") + + sensor._handle_coordinator_update() + + self.assertIsNone(sensor.native_value) + + def test_circuit_states_have_translations(self) -> None: + files = [ + SOURCE_PATH.parent / "strings.json", + *(SOURCE_PATH.parent / "translations").glob("*.json"), + ] + + for path in files: + with self.subTest(path=path.name): + sensors = json.loads(path.read_text())["entity"]["sensor"] + for key in ("heating", "heating_channel", "hot_water"): + self.assertEqual(set(sensors[key]["state"]), {"off", "on"}) + + class WiserBatterySensorAvailabilityTest(unittest.TestCase): """Regression tests for battery availability when level text is absent.""" From d96552f22831dc25e25b770f5adc399f6a2292db Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Mon, 28 Sep 2026 16:00:34 +0100 Subject: [PATCH 041/154] Expose OpenTherm room demand attributes --- custom_components/wiser/climate.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/custom_components/wiser/climate.py b/custom_components/wiser/climate.py index 638bb232..3371fa7a 100755 --- a/custom_components/wiser/climate.py +++ b/custom_components/wiser/climate.py @@ -498,7 +498,6 @@ def extra_state_attributes(self): attrs["away_mode_supressed"] = self._room.away_mode_suppressed attrs["heating_type"] = self._room.heating_type attrs["number_of_heating_actuators"] = self._room.number_of_heating_actuators - attrs["demand_type"] = self._room.demand_type # Status attrs["target_temperature_origin"] = self._room.target_temperature_origin @@ -509,12 +508,17 @@ def extra_state_attributes(self): attrs["control_output_state"] = "On" if self._room.is_heating else "Off" attrs["heating_rate"] = self._room.heating_rate + # OpenTherm + if self._data.wiserhub.system.opentherm.connection_status == "Connected": + attrs["demand_type"] = self._room.demand_type + attrs["percentage_demand"] = self._room.percentage_demand + attrs["is_calling_for_heat"] = self._room.is_calling_for_heat + # If boosted show boost end time if self._room.is_boosted: attrs["boost_end"] = self._room.boost_end_time attrs["boost_time_remaining"] = int(self._room.boost_time_remaining / 60) - attrs["percentage_demand"] = self._room.percentage_demand attrs["comfort_mode_score"] = self._room.comfort_mode_score attrs["control_direction"] = self._room.control_direction attrs["displayed_setpoint"] = self._room.displayed_setpoint From 97c9e187e95ac0e18b38b82cc7b1ffe6a598e7a0 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Tue, 29 Sep 2026 11:55:11 +0100 Subject: [PATCH 042/154] Fix light capability entity migration --- custom_components/wiser/__init__.py | 24 ++++++++++++++++++++---- custom_components/wiser/binary_sensor.py | 8 ++++++++ custom_components/wiser/helpers.py | 13 ++++++++++++- tests/test_light_unique_id_migration.py | 8 ++++++++ 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index 31ca0564..d8aca6aa 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -161,10 +161,26 @@ def _migrate(entry: er.RegistryEntry) -> dict | None: new_unique_id = mapping.get(entry.unique_id) if not new_unique_id: return None - # async_update_entity raises if the target unique_id already exists, so - # a partially-migrated setup can't be allowed to abort config entry - # setup: skip and keep the pre-fix entity as an orphan instead. - if ent_reg.async_get_entity_id(entry.domain, entry.platform, new_unique_id): + # The original migration could create the target entry while the + # capability binary sensors continued to register with their old + # unique_id. Keep the canonical target (which retains the original + # entity_id and history) and remove the later legacy-ID duplicate. + target_entity_id = ent_reg.async_get_entity_id( + entry.domain, entry.platform, new_unique_id + ) + if target_entity_id: + target_entry = ent_reg.async_get(target_entity_id) + if ( + target_entry + and target_entry.config_entry_id == config_entry.entry_id + ): + _LOGGER.info( + "Wiser: removing duplicate legacy entity %s; target is %s", + entry.entity_id, + target_entity_id, + ) + ent_reg.async_remove(entry.entity_id) + return None _LOGGER.warning( "Wiser: not migrating unique_id %s -> %s, target already exists", entry.unique_id, diff --git a/custom_components/wiser/binary_sensor.py b/custom_components/wiser/binary_sensor.py index 8fa2150f..c05d8469 100644 --- a/custom_components/wiser/binary_sensor.py +++ b/custom_components/wiser/binary_sensor.py @@ -17,6 +17,7 @@ get_hub_device_info, get_hub_via_device_info, get_identifier, + get_light_binary_sensor_unique_id, get_unique_id, ) from .opentherm import ( @@ -487,6 +488,13 @@ def name(self): """Return the name of the sensor.""" return f"{ENTITY_PREFIX} {self._light.name} {self._sensor_type}" + @property + def unique_id(self): + """Return the per-channel light capability sensor unique ID.""" + return get_light_binary_sensor_unique_id( + self._data, self._light, self._sensor_type + ) + class WiserStateIsTiltSupported(BaseBinarySensor): """Shutter Istilt supported sensor.""" diff --git a/custom_components/wiser/helpers.py b/custom_components/wiser/helpers.py index 24cc8b09..7b38c94b 100644 --- a/custom_components/wiser/helpers.py +++ b/custom_components/wiser/helpers.py @@ -255,6 +255,17 @@ def get_unique_id(data, device_type, entity_type, device_id): ) +def get_light_binary_sensor_unique_id(data, light, sensor_type): + """Return the per-channel unique ID for a light capability sensor.""" + light_name = f"{ENTITY_PREFIX} {light.name}" + return get_unique_id( + data, + "binary_sensor", + sensor_type, + f"{light_name} {sensor_type}", + ) + + def build_light_unique_id_migration(data) -> dict: """Map pre-#683 light unique_ids to the new per-channel light_id scheme. @@ -308,7 +319,7 @@ def build_light_unique_id_migration(data) -> dict: for stype in LIGHT_BINARY_SENSOR_TYPES: mapping[ get_unique_id(data, "binary_sensor", stype, f"{old_name} {stype}") - ] = get_unique_id(data, "binary_sensor", stype, f"{new_name} {stype}") + ] = get_light_binary_sensor_unique_id(data, light, stype) # Drop no-ops where the two id spaces happen to coincide for a light. return {old: new for old, new in mapping.items() if old != new} diff --git a/tests/test_light_unique_id_migration.py b/tests/test_light_unique_id_migration.py index 554cd1f1..253faed8 100644 --- a/tests/test_light_unique_id_migration.py +++ b/tests/test_light_unique_id_migration.py @@ -143,6 +143,8 @@ def test_away_switch_maps_name_and_id(self) -> None: def test_capability_binary_sensors_map_name(self) -> None: mapping = self._mapping() + data = _hub_data() + light = data.wiserhub.devices.lights.all[0] old = self._unique_id( "binary_sensor", "Is Dimmable", @@ -152,6 +154,12 @@ def test_capability_binary_sensors_map_name(self) -> None: "binary_sensor", "Is Dimmable", "Wiser Diele Is Dimmable" ) self.assertEqual(mapping[old], new) + self.assertEqual( + self.helpers.get_light_binary_sensor_unique_id( + data, light, "Is Dimmable" + ), + new, + ) def test_no_room_light_uses_type_and_name(self) -> None: mapping = self._mapping() From 3b8bef5d9cc331d38b2aaf4ceca29402a8c40ab5 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Tue, 29 Sep 2026 12:09:45 +0100 Subject: [PATCH 043/154] Keep OpenTherm room attributes available --- custom_components/wiser/climate.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/custom_components/wiser/climate.py b/custom_components/wiser/climate.py index 3371fa7a..c6414153 100755 --- a/custom_components/wiser/climate.py +++ b/custom_components/wiser/climate.py @@ -509,7 +509,8 @@ def extra_state_attributes(self): attrs["heating_rate"] = self._room.heating_rate # OpenTherm - if self._data.wiserhub.system.opentherm.connection_status == "Connected": + opentherm = getattr(self._data.wiserhub.system, "opentherm", None) + if opentherm is not None and opentherm.enabled: attrs["demand_type"] = self._room.demand_type attrs["percentage_demand"] = self._room.percentage_demand attrs["is_calling_for_heat"] = self._room.is_calling_for_heat From b1646eee6e7defb6cc94e73c45329266a6fdeb15 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Tue, 29 Sep 2026 16:09:01 +0100 Subject: [PATCH 044/154] Unify Wiser frontend panels --- .github/workflows/publish.yml | 3 + README.md | 13 +- custom_components/wiser/__init__.py | 9 +- custom_components/wiser/config_flow.py | 14 +- custom_components/wiser/const.py | 25 +- custom_components/wiser/frontend/cards.json | 26 ++ .../wiser/frontend/entry_updates.py | 21 +- custom_components/wiser/frontend/panel.py | 138 ------- .../wiser/frontend/schedules_sidebar.py | 32 -- .../wiser/frontend/wiser-icons.js | 19 +- .../wiser/frontend/wiser-logo.png | Bin 0 -> 27031 bytes .../wiser/frontend/wiser-panel.js | 369 ++++++++++++++++++ .../wiser/frontend/wiser_sidebar.py | 329 ++++++++++++++++ .../wiser/frontend/zigbee_sidebar.py | 41 -- custom_components/wiser/strings.json | 6 +- custom_components/wiser/translations/de.json | 6 +- .../wiser/translations/en-GB.json | 6 +- custom_components/wiser/translations/en.json | 6 +- custom_components/wiser/translations/fr.json | 6 +- custom_components/wiser/update.py | 23 +- custom_components/wiser/websockets.py | 45 ++- scripts/build.py | 57 ++- scripts/fetch_card_releases.py | 130 +++++- tests/test_build.py | 55 ++- tests/test_card_releases.py | 72 +++- tests/test_card_updates.py | 44 ++- tests/test_schedules_sidebar.py | 299 -------------- tests/test_sidebar_icons.py | 6 + tests/test_ui_options.py | 30 +- tests/test_wiser_sidebar.py | 340 ++++++++++++++++ tests/test_zigbee_sidebar.py | 289 -------------- 31 files changed, 1544 insertions(+), 915 deletions(-) create mode 100644 custom_components/wiser/frontend/cards.json delete mode 100644 custom_components/wiser/frontend/panel.py delete mode 100644 custom_components/wiser/frontend/schedules_sidebar.py create mode 100644 custom_components/wiser/frontend/wiser-logo.png create mode 100644 custom_components/wiser/frontend/wiser-panel.js create mode 100644 custom_components/wiser/frontend/wiser_sidebar.py delete mode 100644 custom_components/wiser/frontend/zigbee_sidebar.py delete mode 100644 tests/test_schedules_sidebar.py create mode 100644 tests/test_wiser_sidebar.py delete mode 100644 tests/test_zigbee_sidebar.py diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index e59b6da2..ea2e385a 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -42,11 +42,13 @@ jobs: CARD_CHANNEL: ${{ github.event_name == 'release' && (github.event.release.prerelease && 'dev' || 'stable') || inputs.channel || 'dev' }} SCHEDULE_REPOSITORY: ${{ vars.WISER_SCHEDULE_CARD_REPOSITORY || 'andyblac/wiser-schedule-card' }} ZIGBEE_REPOSITORY: ${{ vars.WISER_ZIGBEE_CARD_REPOSITORY || 'andyblac/wiser-zigbee-card' }} + PANEL_CONFIG_REPOSITORY: ${{ vars.WISER_PANEL_CONFIG_REPOSITORY || 'andyblac/WiserFrontendPanelConfig' }} run: >- python scripts/build.py --release --channel "$CARD_CHANNEL" --schedule-repository "$SCHEDULE_REPOSITORY" --zigbee-repository "$ZIGBEE_REPOSITORY" + --panel-config-repository "$PANEL_CONFIG_REPOSITORY" - name: Upload release package for inspection uses: actions/upload-artifact@v5 with: @@ -54,6 +56,7 @@ jobs: path: | dist/wiser.zip dist/card-releases.json + dist/panel-config-release.json if-no-files-found: error publish: diff --git a/README.md b/README.md index adb0e750..be9be431 100755 --- a/README.md +++ b/README.md @@ -64,7 +64,16 @@ python3 scripts/build.py --release --channel stable For a prerelease package, use `--channel dev` instead. The build downloads published Schedules and Zigbee card assets from GitHub. Stable builds use stable card releases; prerelease builds use the newest published prerelease of each card, falling back to its newest stable release when none exists. -The output is `dist/wiser.zip`. The accompanying `dist/card-releases.json` records the card releases and checksums included in the package. Missing or invalid card assets fail the build. +The frontend card registry is maintained separately in +[`andyblac/WiserFrontendPanelConfig`](https://github.com/andyblac/WiserFrontendPanelConfig). +Local development builds prefer that sibling repository's validated +`dist/cards.json`; release builds download its published `cards.json` asset. A +snapshot is packaged as `frontend/cards.json`, so Home Assistant startup never +depends on GitHub being available. + +The output is `dist/wiser.zip`. The accompanying `dist/card-releases.json` and +`dist/panel-config-release.json` files record the card and registry artifacts +included in the package. Missing or invalid assets fail the build. The **Publish** GitHub Actions workflow runs the same build and attaches `wiser.zip` when an integration release is published. Preview runs provide a downloadable **wiser-package** artifact without publishing a release. @@ -74,4 +83,4 @@ We welcome and greatly appreciate all issues, pull requests, and bug fixes. Plea See [CONTRIBUTING.md](CONTRIBUTING.md) for how to report a bug, set up a development environment, run the tests, and get a pull request merged. -Wiser Home Assistant Integration Team \ No newline at end of file +Wiser Home Assistant Integration Team diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index 31ca0564..1328eee3 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -46,7 +46,7 @@ from .entity_migration import migrate_entity_unique_ids from .frontend import JSModuleRegistration from .frontend.entry_updates import async_handle_entry_update, integration_reload_settings -from .frontend.schedules_sidebar import async_update_schedules_panel +from .frontend.wiser_sidebar import async_update_wiser_panel from .helpers import ( build_light_unique_id_migration, get_device_name, @@ -56,7 +56,6 @@ get_legacy_room_identifier, ) from .services import async_setup_services -from .frontend.zigbee_sidebar import async_update_zigbee_panel from .websockets import async_register_websockets from .update import async_unload_card_updates @@ -234,8 +233,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): # Register custom cards moodule_register = JSModuleRegistration(hass) await moodule_register.async_register() - await async_update_schedules_panel(hass) - await async_update_zigbee_panel(hass) + await async_update_wiser_panel(hass) _LOGGER.info( "Wiser Component Setup Completed (%s)", coordinator.wiserhub.system.name @@ -394,8 +392,7 @@ async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry): if unload_ok: await async_unload_card_updates(hass, config_entry) hass.data[DOMAIN].pop(config_entry.entry_id) - await async_update_schedules_panel(hass) + await async_update_wiser_panel(hass) update_hub_device_names(hass) - await async_update_zigbee_panel(hass) return unload_ok diff --git a/custom_components/wiser/config_flow.py b/custom_components/wiser/config_flow.py index e815f334..f8ecd960 100755 --- a/custom_components/wiser/config_flow.py +++ b/custom_components/wiser/config_flow.py @@ -39,7 +39,6 @@ from homeassistant.helpers.service_info.zeroconf import ZeroconfServiceInfo from .const import ( - CONF_SHOW_ZIGBEE_SIDEBAR, CONF_AUTOMATIONS_HW_AUTO_MODE, CONF_AUTOMATIONS_HW_BOOST_MODE, CONF_AUTOMATIONS_HW_CLIMATE, @@ -56,7 +55,7 @@ CONF_OPENTHERM_SENSORS, CONF_RESTORE_MANUAL_TEMP_OPTION, CONF_SETPOINT_MODE, - CONF_SHOW_SCHEDULES_SIDEBAR, + CONF_SHOW_WISER_SIDEBAR, CUSTOM_DATA_STORE, DEFAULT_BOOST_TEMP, DEFAULT_BOOST_TEMP_TIME, @@ -294,12 +293,11 @@ async def async_step_ui_options(self, user_input=None): ), ): BooleanSelector(), vol.Optional( - CONF_SHOW_SCHEDULES_SIDEBAR, - default=self.config_entry.options.get(CONF_SHOW_SCHEDULES_SIDEBAR, False), - ): BooleanSelector(), - vol.Optional( - CONF_SHOW_ZIGBEE_SIDEBAR, - default=self.config_entry.options.get(CONF_SHOW_ZIGBEE_SIDEBAR, False), + CONF_SHOW_WISER_SIDEBAR, + default=self.config_entry.options.get( + CONF_SHOW_WISER_SIDEBAR, + True, + ), ): BooleanSelector(), } ), diff --git a/custom_components/wiser/const.py b/custom_components/wiser/const.py index aad1203e..141065da 100755 --- a/custom_components/wiser/const.py +++ b/custom_components/wiser/const.py @@ -6,26 +6,31 @@ """ from enum import StrEnum +import json +from pathlib import Path VERSION = "4.0.0-rc1" DOMAIN = "wiser" CONF_LEGACY_NAMING = "legacy_naming" DATA_WISER_CONFIG = "wiser_config" URL_BASE = "/wiser" -CONF_SHOW_SCHEDULES_SIDEBAR = "show_schedules_sidebar" CONF_SCHEDULES_PANEL_CONFIG = "schedules_panel_config" -CONF_SHOW_ZIGBEE_SIDEBAR = "show_zigbee_sidebar" CONF_ZIGBEE_PANEL_CONFIG = "zigbee_panel_config" +CONF_SHOW_WISER_SIDEBAR = "show_wiser_sidebar" +CONF_WISER_PANEL_CONFIG = "wiser_panel_config" + +def _load_card_manifest(): + """Load the shared card registry used by packaging and runtime setup.""" + return json.loads( + (Path(__file__).parent / "frontend/cards.json").read_text("utf-8") + ) + + +CARD_MANIFEST = _load_card_manifest() JSMODULES = [ - { - "name": "Wiser Schedule Card", - "filename": "wiser-schedule-card.js", - }, - { - "name": "Wiser Zigbee Card", - "filename": "wiser-zigbee-card.js", - }, + {"name": card["name"], "filename": card["filename"]} + for card in CARD_MANIFEST ] WISER_PLATFORMS = [ diff --git a/custom_components/wiser/frontend/cards.json b/custom_components/wiser/frontend/cards.json new file mode 100644 index 00000000..7fb45206 --- /dev/null +++ b/custom_components/wiser/frontend/cards.json @@ -0,0 +1,26 @@ +[ + { + "id": "schedule", + "name": "Wiser Schedule Card", + "filename": "wiser-schedule-card.js", + "repository": "andyblac/wiser-schedule-card", + "component": "wiser-schedule-card", + "panel": "wiser-schedules-panel" + }, + { + "id": "zigbee", + "name": "Wiser Zigbee Card", + "filename": "wiser-zigbee-card.js", + "repository": "andyblac/wiser-zigbee-card", + "component": "wiser-zigbee-card", + "panel": "wiser-zigbee-panel" + }, + { + "id": "rooms", + "name": "Wiser Rooms Card", + "filename": "wiser-rooms-card.js", + "repository": "andyblac/wiser-rooms-card", + "component": "wiser-rooms-card", + "panel": "wiser-rooms-panel" + } +] diff --git a/custom_components/wiser/frontend/entry_updates.py b/custom_components/wiser/frontend/entry_updates.py index 3e8bf391..6169630d 100644 --- a/custom_components/wiser/frontend/entry_updates.py +++ b/custom_components/wiser/frontend/entry_updates.py @@ -1,8 +1,13 @@ """Apply panel preferences live and reload other integration settings.""" -from .schedules_sidebar import async_update_schedules_panel -from .zigbee_sidebar import async_update_zigbee_panel -from ..const import CONF_SCHEDULES_PANEL_CONFIG, CONF_ZIGBEE_PANEL_CONFIG, DOMAIN +from .wiser_sidebar import async_update_wiser_panel +from ..const import ( + CONF_SCHEDULES_PANEL_CONFIG, + CONF_SHOW_WISER_SIDEBAR, + CONF_WISER_PANEL_CONFIG, + CONF_ZIGBEE_PANEL_CONFIG, + DOMAIN, +) def integration_reload_settings(entry): @@ -10,7 +15,12 @@ def integration_reload_settings(entry): return ( dict(entry.data), {key: value for key, value in entry.options.items() - if key not in {CONF_SCHEDULES_PANEL_CONFIG, CONF_ZIGBEE_PANEL_CONFIG}}, + if key not in { + CONF_SCHEDULES_PANEL_CONFIG, + CONF_SHOW_WISER_SIDEBAR, + CONF_WISER_PANEL_CONFIG, + CONF_ZIGBEE_PANEL_CONFIG, + }}, ) @@ -19,7 +29,6 @@ async def async_handle_entry_update(hass, entry): loaded = hass.data.get(DOMAIN, {}).get(entry.entry_id) settings = integration_reload_settings(entry) if loaded is not None and loaded.get("reload_settings") == settings: - await async_update_schedules_panel(hass) - await async_update_zigbee_panel(hass) + await async_update_wiser_panel(hass) return await hass.config_entries.async_reload(entry.entry_id) diff --git a/custom_components/wiser/frontend/panel.py b/custom_components/wiser/frontend/panel.py deleted file mode 100644 index 19201a0f..00000000 --- a/custom_components/wiser/frontend/panel.py +++ /dev/null @@ -1,138 +0,0 @@ -"""Shared lifecycle and settings persistence for Wiser sidebar panels.""" - -from __future__ import annotations - -import math -from dataclasses import dataclass - -from homeassistant.components import frontend, panel_custom - -from . import async_card_resource -from ..const import DATA, DOMAIN - - -@dataclass(frozen=True) -class SidebarPanel: - """Describe a sidebar panel and the card settings it accepts.""" - - path: str - state_key: str - component: str - title: str - icon: str - filename: str - enabled_option: str - config_option: str - hub_error: str - setting_error: str - - -def _enabled_entries(hass, panel): - """Yield loaded, enabled hubs that opted into this panel.""" - loaded = hass.data.get(DOMAIN, {}) - for entry in hass.config_entries.async_entries(DOMAIN): - if ( - entry.entry_id in loaded - and not entry.disabled_by - and entry.options.get(panel.enabled_option, False) - ): - yield loaded[entry.entry_id][DATA].wiserhub.system.name, entry - - -async def async_update_panel(hass, panel): - """Register, refresh, or remove a panel according to its enabled hubs.""" - entries = list(_enabled_entries(hass, panel)) - if not entries: - if panel.state_key in hass.data: - frontend.async_remove_panel(hass, panel.path) - hass.data.pop(panel.state_key) - return - - _, module_url, _ = await async_card_resource(hass, panel.filename) - state = { - "hubs": [hub for hub, _ in entries], - "card_configs": { - hub: dict(entry.options.get(panel.config_option, {})) - for hub, entry in entries - }, - "card_url": module_url, - } - if state == hass.data.get(panel.state_key): - return - - if panel.state_key in hass.data: - # Keep the route registered while notifying clients of new settings. - frontend.async_register_built_in_panel( - hass, - component_name="custom", - frontend_url_path=panel.path, - sidebar_title=panel.title, - sidebar_icon=panel.icon, - config={ - **state, - "_panel_custom": { - "name": panel.component, - "module_url": module_url, - "embed_iframe": False, - "trust_external": False, - }, - }, - update=True, - ) - else: - await panel_custom.async_register_panel( - hass, - frontend_url_path=panel.path, - webcomponent_name=panel.component, - sidebar_title=panel.title, - sidebar_icon=panel.icon, - module_url=module_url, - config=dict(state), - ) - # Only record successfully applied settings so failed updates can be retried. - hass.data[panel.state_key] = state - - -def _is_json_value(value, depth=0): - """Accept finite JSON data, including future card options.""" - if depth > 64: - return False - if type(value) in (str, bool, int, type(None)): - return True - if type(value) is float: - return math.isfinite(value) - if type(value) is list: - return all(_is_json_value(item, depth + 1) for item in value) - if type(value) is dict: - return all( - type(key) is str and _is_json_value(item, depth + 1) - for key, item in value.items() - ) - return False - - -def save_panel_config(hass, panel, configs): - """Validate every hub's settings before persisting any options. - - Cards own their display options. Only validate JSON structure here so new - card settings do not require an integration release. - """ - if type(configs) is not dict: - raise ValueError(panel.setting_error) - entries = dict(_enabled_entries(hass, panel)) - updates = [] - for hub, config in configs.items(): - if hub not in entries: - raise ValueError(panel.hub_error) - if type(config) is not dict or not _is_json_value(config): - raise ValueError(panel.setting_error) - settings = {} - for key, value in config.items(): - if key in {"type", "hub"}: - continue - settings[key] = value - updates.append((entries[hub], settings)) - for entry, settings in updates: - hass.config_entries.async_update_entry( - entry, options={**entry.options, panel.config_option: settings} - ) diff --git a/custom_components/wiser/frontend/schedules_sidebar.py b/custom_components/wiser/frontend/schedules_sidebar.py deleted file mode 100644 index c10d3b25..00000000 --- a/custom_components/wiser/frontend/schedules_sidebar.py +++ /dev/null @@ -1,32 +0,0 @@ -"""Manage the shared Wiser schedules sidebar panel.""" - -from .panel import SidebarPanel, async_update_panel, save_panel_config -from ..const import ( - CONF_SHOW_SCHEDULES_SIDEBAR, CONF_SCHEDULES_PANEL_CONFIG, -) - -PANEL_PATH = "wiser-schedules" -PANEL_STATE = "wiser_schedules_panel" - -_SCHEDULES_PANEL = SidebarPanel( - path=PANEL_PATH, - state_key=PANEL_STATE, - component="wiser-schedules-panel", - title="Wiser Schedules", - icon="mdi:calendar-clock", - filename="wiser-schedule-card.js", - enabled_option=CONF_SHOW_SCHEDULES_SIDEBAR, - config_option=CONF_SCHEDULES_PANEL_CONFIG, - hub_error="Hub is not enabled in the schedules panel", - setting_error="Invalid schedule card setting", -) - - -async def async_update_schedules_panel(hass): - """Show schedules for loaded hubs that have opted into the sidebar.""" - await async_update_panel(hass, _SCHEDULES_PANEL) - - -def save_schedules_panel_config(hass, configs): - """Validate all submitted settings before updating integration options.""" - save_panel_config(hass, _SCHEDULES_PANEL, configs) diff --git a/custom_components/wiser/frontend/wiser-icons.js b/custom_components/wiser/frontend/wiser-icons.js index 2be7ccc3..a8567e3e 100644 --- a/custom_components/wiser/frontend/wiser-icons.js +++ b/custom_components/wiser/frontend/wiser-icons.js @@ -1,9 +1,22 @@ // Wiser sidebar icons. Loaded globally so icons work before a card is opened. (() => { - const path = "M11.1000 5.0000L11.1000 8.0000A.9 .9 0 0 0 12.9000 8.0000L12.9000 5.0000A.9 .9 0 0 0 11.1000 5.0000Z M5.1364 19.6364L8.1364 16.6364A.9 .9 0 0 0 6.8636 15.3636L3.8636 18.3636A.9 .9 0 0 0 5.1364 19.6364Z M20.1364 18.3636L17.1364 15.3636A.9 .9 0 0 0 15.8636 16.6364L18.8636 19.6364A.9 .9 0 0 0 20.1364 18.3636Z M7.0699 12.6966L12.5699 8.1966A.9 .9 0 0 0 11.4301 6.8034L5.9301 11.3034A.9 .9 0 0 0 7.0699 12.6966Z M11.4301 8.1966L16.9301 12.6966A.9 .9 0 0 0 18.0699 11.3034L12.5699 6.8034A.9 .9 0 0 0 11.4301 8.1966Z M7.1000 11.0000L7.1000 17.0000A.9 .9 0 0 0 8.9000 17.0000L8.9000 11.0000A.9 .9 0 0 0 7.1000 11.0000Z M8.0000 17.9000L16.0000 17.9000A.9 .9 0 0 0 16.0000 16.1000L8.0000 16.1000A.9 .9 0 0 0 8.0000 17.9000Z M16.9000 17.0000L16.9000 11.0000A.9 .9 0 0 0 15.1000 11.0000L15.1000 17.0000A.9 .9 0 0 0 16.9000 17.0000Z M9.75 3.25a2.25 2.25 0 1 0 4.5 0a2.25 2.25 0 1 0-4.5 0Z M1.0 20.25a2.25 2.25 0 1 0 4.5 0a2.25 2.25 0 1 0-4.5 0Z M18.5 20.25a2.25 2.25 0 1 0 4.5 0a2.25 2.25 0 1 0-4.5 0Z"; + const icons = { + // W glyph traced from the official Wiser wordmark. + wiser: { + path: "M391,155 L399,149 L414,144 L457,143 L478,149 L487,155 L497,167 L524,249 L629,600 L632,604 L744,103 L755,83 L765,72 L780,62 L796,57 L817,57 L834,62 L851,72 L865,86 L711,699 L703,714 L690,727 L678,732 L607,732 L591,727 L577,713 L439,272 L300,713 L286,727 L270,732 L199,732 L183,724 L170,708 L166,699 L12,86 L26,72 L43,62 L60,57 L81,57 L97,62 L112,72 L122,83 L132,101 L154,191 L245,604 L248,600 L375,178 L384,161Z", + viewBox: "0 0 877 768", + }, + zigbee: { + path: "M11.1000 5.0000L11.1000 8.0000A.9 .9 0 0 0 12.9000 8.0000L12.9000 5.0000A.9 .9 0 0 0 11.1000 5.0000Z M5.1364 19.6364L8.1364 16.6364A.9 .9 0 0 0 6.8636 15.3636L3.8636 18.3636A.9 .9 0 0 0 5.1364 19.6364Z M20.1364 18.3636L17.1364 15.3636A.9 .9 0 0 0 15.8636 16.6364L18.8636 19.6364A.9 .9 0 0 0 20.1364 18.3636Z M7.0699 12.6966L12.5699 8.1966A.9 .9 0 0 0 11.4301 6.8034L5.9301 11.3034A.9 .9 0 0 0 7.0699 12.6966Z M11.4301 8.1966L16.9301 12.6966A.9 .9 0 0 0 18.0699 11.3034L12.5699 6.8034A.9 .9 0 0 0 11.4301 8.1966Z M7.1000 11.0000L7.1000 17.0000A.9 .9 0 0 0 8.9000 17.0000L8.9000 11.0000A.9 .9 0 0 0 7.1000 11.0000Z M8.0000 17.9000L16.0000 17.9000A.9 .9 0 0 0 16.0000 16.1000L8.0000 16.1000A.9 .9 0 0 0 8.0000 17.9000Z M16.9000 17.0000L16.9000 11.0000A.9 .9 0 0 0 15.1000 11.0000L15.1000 17.0000A.9 .9 0 0 0 16.9000 17.0000Z M9.75 3.25a2.25 2.25 0 1 0 4.5 0a2.25 2.25 0 1 0-4.5 0Z M1.0 20.25a2.25 2.25 0 1 0 4.5 0a2.25 2.25 0 1 0-4.5 0Z M18.5 20.25a2.25 2.25 0 1 0 4.5 0a2.25 2.25 0 1 0-4.5 0Z", + viewBox: "0 0 24 24", + }, + }; window.customIcons = window.customIcons || {}; window.customIcons["wiser"] = { - getIcon: async (name) => name === "zigbee" ? { path, viewBox: "0 0 24 24" } : {}, - getIconList: async () => [{ name: "zigbee", keywords: ["wiser", "home", "network"] }], + getIcon: async (name) => icons[name] || {}, + getIconList: async () => [ + { name: "wiser", keywords: ["wiser", "logo", "brand"] }, + { name: "zigbee", keywords: ["wiser", "home", "network"] }, + ], }; })(); diff --git a/custom_components/wiser/frontend/wiser-logo.png b/custom_components/wiser/frontend/wiser-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..a696c59df0e204eafb5efe2409c013fb8e92a235 GIT binary patch literal 27031 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 + :host { display:flex; flex-direction:column; height:100vh; height:100dvh; + min-width:0; min-height:0; overflow:hidden; color:var(--primary-text-color); + background:var(--primary-background-color); } + header { display:flex; flex:0 0 64px; align-items:center; gap:16px; min-width:0; + padding:0 16px; background:var(--app-header-background-color); + color:var(--app-header-text-color); } + .brand { display:block; flex:0 0 auto; width:96px; height:auto; } + #menu { flex-shrink:0; color:inherit; } + #menu ha-icon { color:var(--app-header-text-color, var(--primary-text-color)); } + #panel-tabs { display:flex; flex:1; min-width:0; margin-inline-start:24px; + align-self:stretch; overflow-x:auto; } + #panel-tabs[hidden], .panel-view[hidden] { display:none; } + #settings { flex-shrink:0; margin-inline-start:auto; color:inherit; } + #settings[hidden] { display:none; } + #settings ha-icon { color:var(--app-header-text-color, var(--primary-text-color)); } + .panel-tab { flex:0 0 auto; min-height:48px; padding:0 24px; border:0; + border-bottom:2px solid transparent; background:transparent; + color:var(--secondary-text-color); font:inherit; cursor:pointer; } + .panel-tab[aria-selected="true"] { color:var(--app-header-text-color, var(--primary-text-color)); + border-bottom-color:currentColor; } + .panel-tab:focus-visible { outline:2px solid currentColor; outline-offset:-4px; } + .panel-tab[draggable="true"] { cursor:grab; } + .panel-tab.dragging { opacity:.45; cursor:grabbing; } + .panel-tab.drop-before { box-shadow:inset 3px 0 var(--primary-color); } + .panel-tab.drop-after { box-shadow:inset -3px 0 var(--primary-color); } + .tab-name-input { box-sizing:border-box; width:120px; min-width:72px; + padding:6px 8px; border:1px solid var(--primary-color); border-radius:4px; + color:var(--primary-text-color); font:inherit; + background:var(--card-background-color, var(--primary-background-color)); } + main { display:flex; flex:1; min-width:0; min-height:0; overflow:hidden; } + .panel-view { flex:1; min-width:0; min-height:0; } + .message { padding:24px; } + @media (max-width:600px) { + header { gap:8px; padding:0 8px; } + .brand { display:none; } + #panel-tabs { margin-inline-start:0; } + .panel-tab { padding:0 14px; } + } + +
+ + + + Wiser + + +
+

Loading Wiser…

`; + this.shadowRoot.getElementById("menu").addEventListener("click", () => { + this.dispatchEvent(new CustomEvent("hass-toggle-menu", { bubbles:true, composed:true })); + }); + this.shadowRoot.getElementById("settings").addEventListener("click", () => { + const view = this._views.find((candidate) => !candidate.hidden); + if (typeof view?._openEditor === "function") void view._openEditor(); + }); + this._views = []; + this._tabs = []; + this._generation = 0; + this._draggedPanelId = undefined; + try { + this._activePanel = window.sessionStorage.getItem(WISER_ACTIVE_PANEL_KEY) || undefined; + } catch (_error) { + this._activePanel = undefined; + } + } + + set hass(hass) { + this._hass = hass; + this._syncSettings(); + this._syncTabEditing(); + for (const view of this._views) { + if (!view.hidden) view.hass = hass; + } + } + + set panel(panel) { + if (!this._tabPreferences) { + this._tabPreferences = panel.config.panels.map(({ id, title }) => ({ + id, + title, + })); + } + const config = this._mergeTabPreferences(panel.config); + if (JSON.stringify(config) === JSON.stringify(this._config)) return; + this._config = config; + void this._loadPanels(); + } + + _mergeTabPreferences(config) { + const preferences = new Map( + this._tabPreferences.map((tab, index) => [tab.id, { ...tab, index }]) + ); + const discoveredOrder = new Map( + config.panels.map((panel, index) => [panel.id, index]) + ); + const panels = config.panels + .map((panel) => ({ + ...panel, + title: preferences.get(panel.id)?.title || panel.title, + })) + .sort((left, right) => { + const leftOrder = preferences.get(left.id)?.index; + const rightOrder = preferences.get(right.id)?.index; + return ( + (leftOrder ?? preferences.size + discoveredOrder.get(left.id)) - + (rightOrder ?? preferences.size + discoveredOrder.get(right.id)) + ); + }); + return { ...config, panels }; + } + + _selectPanel(id) { + this._activePanel = id; + try { + window.sessionStorage.setItem(WISER_ACTIVE_PANEL_KEY, id); + } catch (_error) { + // Session storage can be unavailable in restricted browser contexts. + } + this._views.forEach((view, index) => { + const selected = this._config.panels[index].id === id; + view.hidden = !selected; + if (selected) view.hass = this._hass; + this._tabs[index].setAttribute("aria-selected", String(selected)); + this._tabs[index].tabIndex = selected ? 0 : -1; + }); + this._syncSettings(); + } + + _syncSettings() { + const view = this._views.find((candidate) => !candidate.hidden); + this.shadowRoot.getElementById("settings").hidden = !( + this._hass?.user?.is_admin && typeof view?._openEditor === "function" + ); + } + + _syncTabEditing() { + const editable = Boolean(this._hass?.user?.is_admin); + for (const tab of this._tabs) { + tab.draggable = editable; + tab.title = editable + ? "Drag to reorder. Double-click to rename." + : ""; + } + } + + _clearDropIndicators() { + for (const tab of this._tabs) { + tab.classList.remove("drop-before", "drop-after"); + } + } + + _applyPanels(panels) { + const viewsById = new Map( + this._config.panels.map((panel, index) => [panel.id, this._views[index]]) + ); + this._tabPreferences = panels.map(({ id, title }) => ({ id, title })); + this._config = { ...this._config, panels }; + this._views = panels.map((panel) => viewsById.get(panel.id)); + this.shadowRoot.querySelector("main").replaceChildren(...this._views); + this._renderTabs(); + } + + async _persistTabs(previousPanels) { + try { + await this._hass.callWS({ + type: "wiser/panel/configure_tabs", + tabs: this._config.panels.map(({ id, title }) => ({ id, title })), + }); + } catch (error) { + this._applyPanels(previousPanels); + this.dispatchEvent( + new CustomEvent("hass-notification", { + bubbles: true, + composed: true, + detail: { + message: "Unable to save the Wiser panel tab layout.", + }, + }) + ); + console.error("Unable to save Wiser panel tabs", error); + } + } + + _movePanel(panelId, targetId, after) { + if (!this._hass?.user?.is_admin || panelId === targetId) return; + const previousPanels = [...this._config.panels]; + const panels = [...previousPanels]; + const sourceIndex = panels.findIndex((panel) => panel.id === panelId); + if (sourceIndex < 0) return; + const [panel] = panels.splice(sourceIndex, 1); + const targetIndex = panels.findIndex((candidate) => candidate.id === targetId); + if (targetIndex < 0) return; + panels.splice(targetIndex + (after ? 1 : 0), 0, panel); + if (panels.every((candidate, index) => candidate === previousPanels[index])) return; + this._applyPanels(panels); + void this._persistTabs(previousPanels); + } + + _startRename(panelId, tab) { + if (!this._hass?.user?.is_admin || tab.querySelector("input")) return; + const panel = this._config.panels.find((candidate) => candidate.id === panelId); + if (!panel) return; + + const input = document.createElement("input"); + input.className = "tab-name-input"; + input.value = panel.title; + input.maxLength = 64; + input.setAttribute("aria-label", `Rename ${panel.title} tab`); + input.addEventListener("click", (event) => event.stopPropagation()); + input.addEventListener("dblclick", (event) => event.stopPropagation()); + + let finished = false; + const finish = (save) => { + if (finished) return; + finished = true; + const title = input.value.trim(); + if (!save || !title || title === panel.title) { + tab.textContent = panel.title; + this._syncTabEditing(); + return; + } + const previousPanels = this._config.panels.map((item) => ({ ...item })); + const panels = this._config.panels.map((item) => + item.id === panelId ? { ...item, title } : item + ); + this._applyPanels(panels); + void this._persistTabs(previousPanels); + }; + + input.addEventListener("keydown", (event) => { + event.stopPropagation(); + if (event.key === "Enter") { + event.preventDefault(); + finish(true); + } else if (event.key === "Escape") { + event.preventDefault(); + finish(false); + } + }); + input.addEventListener("blur", () => finish(true)); + tab.draggable = false; + tab.replaceChildren(input); + input.focus(); + input.select(); + } + + _renderTabs() { + const panels = this._config.panels; + const container = this.shadowRoot.getElementById("panel-tabs"); + container.hidden = panels.length === 0; + this._tabs = panels.map((panel, index) => { + const tab = document.createElement("button"); + tab.type = "button"; + tab.className = "panel-tab"; + tab.textContent = panel.title; + tab.id = `wiser-panel-tab-${index}`; + tab.setAttribute("role", "tab"); + tab.setAttribute("aria-controls", `wiser-panel-view-${index}`); + tab.addEventListener("click", () => this._selectPanel(panel.id)); + tab.addEventListener("dblclick", (event) => { + event.preventDefault(); + this._startRename(panel.id, tab); + }); + tab.addEventListener("dragstart", (event) => { + if (!this._hass?.user?.is_admin) { + event.preventDefault(); + return; + } + this._draggedPanelId = panel.id; + tab.classList.add("dragging"); + event.dataTransfer.effectAllowed = "move"; + event.dataTransfer.setData("text/plain", panel.id); + }); + tab.addEventListener("dragover", (event) => { + if (!this._draggedPanelId || this._draggedPanelId === panel.id) return; + event.preventDefault(); + event.dataTransfer.dropEffect = "move"; + this._clearDropIndicators(); + const bounds = tab.getBoundingClientRect(); + const after = event.clientX >= bounds.left + bounds.width / 2; + tab.classList.add(after ? "drop-after" : "drop-before"); + }); + tab.addEventListener("drop", (event) => { + if (!this._draggedPanelId) return; + event.preventDefault(); + const bounds = tab.getBoundingClientRect(); + const after = event.clientX >= bounds.left + bounds.width / 2; + const draggedPanelId = this._draggedPanelId; + this._draggedPanelId = undefined; + this._clearDropIndicators(); + this._movePanel(draggedPanelId, panel.id, after); + }); + tab.addEventListener("dragend", () => { + this._draggedPanelId = undefined; + this._clearDropIndicators(); + tab.classList.remove("dragging"); + }); + tab.addEventListener("keydown", (event) => { + let next; + if (event.key === "ArrowRight") next = (index + 1) % panels.length; + else if (event.key === "ArrowLeft") next = (index + panels.length - 1) % panels.length; + else if (event.key === "Home") next = 0; + else if (event.key === "End") next = panels.length - 1; + else return; + event.preventDefault(); + this._selectPanel(panels[next].id); + this._tabs[next].focus(); + }); + const view = this._views[index]; + view.id = `wiser-panel-view-${index}`; + view.setAttribute("role", "tabpanel"); + view.setAttribute("aria-labelledby", tab.id); + return tab; + }); + container.replaceChildren(...this._tabs); + this._syncTabEditing(); + const selected = panels.some((panel) => panel.id === this._activePanel) + ? this._activePanel : panels[0]?.id; + if (selected) this._selectPanel(selected); + } + + async _loadPanels() { + const generation = ++this._generation; + const main = this.shadowRoot.querySelector("main"); + try { + for (const panel of this._config.panels) { + if (!customElements.get(panel.component)) await import(panel.module_url); + await customElements.whenDefined(panel.component); + } + if (generation !== this._generation) return; + this._views = this._config.panels.map((panel) => { + const view = document.createElement(panel.component); + view.className = "panel-view"; + view.setAttribute("nested", ""); + view.hass = this._hass; + view.panel = { config: panel.config }; + return view; + }); + main.replaceChildren(...this._views); + this._renderTabs(); + } catch (error) { + if (generation !== this._generation) return; + this._views = []; + this.shadowRoot.getElementById("panel-tabs").hidden = true; + const message = document.createElement("p"); + message.className = "message"; + message.setAttribute("role", "alert"); + message.textContent = error?.message || "Unable to load Wiser panels."; + main.replaceChildren(message); + console.error("Unable to load Wiser panels", error); + } + } +} + +if (!customElements.get("wiser-panel")) { + customElements.define("wiser-panel", WiserPanel); +} diff --git a/custom_components/wiser/frontend/wiser_sidebar.py b/custom_components/wiser/frontend/wiser_sidebar.py new file mode 100644 index 00000000..54256d75 --- /dev/null +++ b/custom_components/wiser/frontend/wiser_sidebar.py @@ -0,0 +1,329 @@ +"""Manage the single shared Wiser sidebar panel.""" + +from __future__ import annotations + +import math +import re +from pathlib import Path + +from homeassistant.components import frontend, panel_custom + +from . import async_card_resource, card_version +from ..const import ( + CONF_SCHEDULES_PANEL_CONFIG, + CONF_SHOW_WISER_SIDEBAR, + CONF_WISER_PANEL_CONFIG, + CONF_ZIGBEE_PANEL_CONFIG, + DATA, + DOMAIN, + JSMODULES, + URL_BASE, +) + +PANEL_PATH = "wiser" +PANEL_STATE = "wiser_sidebar_panel" +PANEL_COMPONENT = "wiser-panel" +PANEL_FILENAME = "wiser-panel.js" +_OBSOLETE_PANELS = { + "wiser_schedules_panel": "wiser-schedules", + "wiser_zigbee_panel": "wiser-zigbee-panel", +} +_PANEL_COMPONENT = re.compile( + r"customElements\.define\(\s*[\"'](wiser-[a-z0-9-]+-panel)[\"']" +) +_LEGACY_CONFIG_OPTIONS = { + "wiser-schedules-panel": CONF_SCHEDULES_PANEL_CONFIG, + "wiser-zigbee-panel": CONF_ZIGBEE_PANEL_CONFIG, +} +_PANEL_TABS_CONFIG = "_panel_tabs" + + +def _panel_enabled(options): + """Return the unified preference, enabled by default.""" + return options.get(CONF_SHOW_WISER_SIDEBAR, True) + + +def _enabled_entries(hass): + """Yield loaded hubs enabled for the shared Wiser panel.""" + loaded = hass.data.get(DOMAIN, {}) + for entry in hass.config_entries.async_entries(DOMAIN): + if ( + entry.entry_id in loaded + and not entry.disabled_by + and _panel_enabled(entry.options) + ): + yield loaded[entry.entry_id][DATA].wiserhub.system.name, entry + + +def _panel_title(component): + """Derive a readable tab title from the panel custom element.""" + name = component.removeprefix("wiser-").removesuffix("-panel") + return name.replace("-", " ").title() + + +def _panel_id(filename): + """Derive a stable panel id from its card bundle.""" + return Path(filename).stem.removeprefix("wiser-").removesuffix("-card") + + +def _stored_config(entry, panel_id, component): + """Return generic settings, with compatibility for existing panels.""" + generic = entry.options.get(CONF_WISER_PANEL_CONFIG, {}) + if isinstance(generic, dict) and isinstance(generic.get(panel_id), dict): + return dict(generic[panel_id]) + legacy = _LEGACY_CONFIG_OPTIONS.get(component) + return dict(entry.options.get(legacy, {})) if legacy else {} + + +async def _discover_panels(hass, entries): + """Find panel-capable custom elements in every packaged card bundle.""" + panels = [] + hubs = [hub for hub, _ in entries] + for module in JSMODULES: + filename = module["filename"] + path, module_url, _ = await async_card_resource(hass, filename) + try: + source = await hass.async_add_executor_job(path.read_text, "utf-8") + except OSError: + continue + match = _PANEL_COMPONENT.search(source) + if not match: + continue + component = match.group(1) + panel_id = _panel_id(filename) + panels.append( + { + "id": panel_id, + "title": _panel_title(component), + "component": component, + "module_url": module_url, + "config": { + "hubs": hubs, + "hub_ids": { + hub: entry.entry_id for hub, entry in entries + }, + "card_configs": { + hub: _stored_config(entry, panel_id, component) + for hub, entry in entries + }, + "card_url": module_url, + }, + } + ) + stored_tabs = None + for _, entry in entries: + generic = entry.options.get(CONF_WISER_PANEL_CONFIG, {}) + if isinstance(generic, dict) and isinstance( + generic.get(_PANEL_TABS_CONFIG), list + ): + stored_tabs = generic[_PANEL_TABS_CONFIG] + break + + if not stored_tabs: + return panels + + preferences = { + item["id"]: item + for item in stored_tabs + if isinstance(item, dict) and isinstance(item.get("id"), str) + } + for panel in panels: + title = preferences.get(panel["id"], {}).get("title") + if isinstance(title, str) and title.strip(): + panel["title"] = title.strip() + + order = {item["id"]: index for index, item in enumerate(stored_tabs)} + discovered_order = {panel["id"]: index for index, panel in enumerate(panels)} + panels.sort( + key=lambda panel: ( + order.get(panel["id"], len(order) + discovered_order[panel["id"]]) + ) + ) + return panels + + +async def async_update_wiser_panel(hass): + """Register, refresh, or remove the single Wiser sidebar panel.""" + for state_key, path in _OBSOLETE_PANELS.items(): + if state_key in hass.data: + frontend.async_remove_panel(hass, path) + hass.data.pop(state_key) + entries = list(_enabled_entries(hass)) + if not entries: + if PANEL_STATE in hass.data: + frontend.async_remove_panel(hass, PANEL_PATH) + hass.data.pop(PANEL_STATE) + return + + panels = await _discover_panels(hass, entries) + panel_path = Path(__file__).parent / PANEL_FILENAME + panel_version = await hass.async_add_executor_job(card_version, panel_path) + panel_url = f"{URL_BASE}/{PANEL_FILENAME}?v={panel_version}" + # Include the shell URL so an integration reload refreshes a changed shell bundle. + state = {"panels": panels, "module_url": panel_url} + if state == hass.data.get(PANEL_STATE): + return + + config = { + **state, + "_panel_custom": { + "name": PANEL_COMPONENT, + "module_url": panel_url, + "embed_iframe": False, + "trust_external": False, + }, + } + if PANEL_STATE in hass.data: + frontend.async_register_built_in_panel( + hass, + component_name="custom", + frontend_url_path=PANEL_PATH, + sidebar_title="Wiser", + sidebar_icon="wiser:wiser", + config=config, + update=True, + ) + else: + await panel_custom.async_register_panel( + hass, + frontend_url_path=PANEL_PATH, + webcomponent_name=PANEL_COMPONENT, + sidebar_title="Wiser", + sidebar_icon="wiser:wiser", + module_url=panel_url, + config=state, + ) + hass.data[PANEL_STATE] = state + + +def _is_json_value(value, depth=0): + """Accept finite JSON data, including future card options.""" + if depth > 64: + return False + if type(value) in (str, bool, int, type(None)): + return True + if type(value) is float: + return math.isfinite(value) + if type(value) is list: + return all(_is_json_value(item, depth + 1) for item in value) + if type(value) is dict: + return all( + type(key) is str and _is_json_value(item, depth + 1) + for key, item in value.items() + ) + return False + + +def _save_panel_config(hass, configs, config_option, hub_error, setting_error): + """Validate every hub's card settings before persisting any options.""" + if type(configs) is not dict: + raise ValueError(setting_error) + entries = dict(_enabled_entries(hass)) + updates = [] + for hub, config in configs.items(): + if hub not in entries: + raise ValueError(hub_error) + if type(config) is not dict or not _is_json_value(config): + raise ValueError(setting_error) + settings = { + key: value + for key, value in config.items() + if key not in {"type", "hub", "hubs"} + } + updates.append((entries[hub], settings)) + for entry, settings in updates: + hass.config_entries.async_update_entry( + entry, options={**entry.options, config_option: settings} + ) + + +def save_schedules_panel_config(hass, configs): + """Save Schedule panel settings for each loaded hub.""" + _save_panel_config( + hass, + configs, + CONF_SCHEDULES_PANEL_CONFIG, + "Hub is not available in the Wiser panel", + "Invalid schedule card setting", + ) + + +def save_zigbee_panel_config(hass, configs): + """Save Zigbee panel settings for each loaded hub.""" + _save_panel_config( + hass, + configs, + CONF_ZIGBEE_PANEL_CONFIG, + "Hub is not available in the Wiser panel", + "Invalid Zigbee card setting", + ) + + +def save_rooms_panel_config(hass, configs): + """Save Rooms panel settings under the generic panel registry option.""" + if type(configs) is not dict: + raise ValueError("Invalid rooms card setting") + entries = dict(_enabled_entries(hass)) + updates = [] + for hub, config in configs.items(): + if hub not in entries: + raise ValueError("Hub is not available in the Wiser panel") + if type(config) is not dict or not _is_json_value(config): + raise ValueError("Invalid rooms card setting") + settings = { + key: value + for key, value in config.items() + if key not in {"type", "hub", "hubs", "_panel_hide_title"} + } + entry = entries[hub] + generic = entry.options.get(CONF_WISER_PANEL_CONFIG, {}) + if not isinstance(generic, dict): + generic = {} + updates.append((entry, {**generic, "rooms": settings})) + for entry, generic in updates: + hass.config_entries.async_update_entry( + entry, + options={**entry.options, CONF_WISER_PANEL_CONFIG: generic}, + ) + + +def save_wiser_panel_tabs(hass, tabs): + """Save the shared panel tab order and custom titles for every hub.""" + if type(tabs) is not list: + raise ValueError("Invalid Wiser panel tabs") + + known_ids = {_panel_id(module["filename"]) for module in JSMODULES} + saved_tabs = [] + seen = set() + for tab in tabs: + if type(tab) is not dict: + raise ValueError("Invalid Wiser panel tab") + panel_id = tab.get("id") + title = tab.get("title") + if ( + type(panel_id) is not str + or panel_id not in known_ids + or panel_id in seen + or type(title) is not str + or not title.strip() + or len(title.strip()) > 64 + ): + raise ValueError("Invalid Wiser panel tab") + seen.add(panel_id) + saved_tabs.append({"id": panel_id, "title": title.strip()}) + + entries = list(_enabled_entries(hass)) + for _, entry in entries: + generic = entry.options.get(CONF_WISER_PANEL_CONFIG, {}) + if not isinstance(generic, dict): + generic = {} + hass.config_entries.async_update_entry( + entry, + options={ + **entry.options, + CONF_WISER_PANEL_CONFIG: { + **generic, + _PANEL_TABS_CONFIG: saved_tabs, + }, + }, + ) diff --git a/custom_components/wiser/frontend/zigbee_sidebar.py b/custom_components/wiser/frontend/zigbee_sidebar.py deleted file mode 100644 index 607da209..00000000 --- a/custom_components/wiser/frontend/zigbee_sidebar.py +++ /dev/null @@ -1,41 +0,0 @@ -"""Manage the shared Wiser zigbee sidebar panel.""" - -import logging - -from .panel import SidebarPanel, async_update_panel, save_panel_config -from ..const import CONF_SHOW_ZIGBEE_SIDEBAR, CONF_ZIGBEE_PANEL_CONFIG - -_LOGGER = logging.getLogger(__name__) - -PANEL_PATH = "wiser-zigbee-panel" -PANEL_STATE = "wiser_zigbee_panel" - -_ZIGBEE_PANEL = SidebarPanel( - path=PANEL_PATH, - state_key=PANEL_STATE, - component="wiser-zigbee-panel", - title="Wiser Zigbee", - icon="wiser:zigbee", - filename="wiser-zigbee-card.js", - enabled_option=CONF_SHOW_ZIGBEE_SIDEBAR, - config_option=CONF_ZIGBEE_PANEL_CONFIG, - hub_error="Hub is not enabled in the zigbee panel", - setting_error="Invalid Zigbee card setting", -) - - -async def async_update_zigbee_panel(hass): - """Show zigbee for loaded hubs that have opted into the sidebar.""" - try: - await async_update_panel(hass, _ZIGBEE_PANEL) - except ValueError as err: - # A sidebar route can already belong to a user dashboard. This - # optional UI must not fail setup after entity platforms loaded. - _LOGGER.warning( - "Unable to register Wiser Zigbee sidebar at %s: %s", PANEL_PATH, err - ) - - -def save_zigbee_panel_config(hass, configs): - """Validate all submitted settings before updating integration options.""" - save_panel_config(hass, _ZIGBEE_PANEL, configs) diff --git a/custom_components/wiser/strings.json b/custom_components/wiser/strings.json index 441be7e9..d217cd35 100755 --- a/custom_components/wiser/strings.json +++ b/custom_components/wiser/strings.json @@ -49,8 +49,7 @@ "title": "UI options", "data": { "legacy_naming": "Legacy naming", - "show_schedules_sidebar": "Show Wiser Schedules in sidebar", - "show_zigbee_sidebar": "Show Wiser Zigbee in sidebar" + "show_wiser_sidebar": "Show Wiser in sidebar" }, "data_description": { "legacy_naming": "Include room names in Wiser device names. If enabled, using Home Assistant to regenerate entity IDs with the default format in Settings → System → Entity ID format (Home Assistant 2026.8 and later) will duplicate area names when the area and Wiser room names match. Changing this option does not rename existing entity IDs." @@ -226,7 +225,8 @@ "entity": { "update": { "schedule_card": { "name": "Wiser Schedules Card" }, - "zigbee_card": { "name": "Wiser Zigbee Card" } + "zigbee_card": { "name": "Wiser Zigbee Card" }, + "rooms_card": { "name": "Wiser Rooms Card" } }, "climate": { "heating": { diff --git a/custom_components/wiser/translations/de.json b/custom_components/wiser/translations/de.json index 1e8c010a..a66a179f 100644 --- a/custom_components/wiser/translations/de.json +++ b/custom_components/wiser/translations/de.json @@ -49,8 +49,7 @@ "title": "UI-Optionen", "data": { "legacy_naming": "Bisherige Namensgebung", - "show_schedules_sidebar": "Wiser-Zeitpläne in der Seitenleiste anzeigen", - "show_zigbee_sidebar": "Wiser Zigbee in der Seitenleiste anzeigen" + "show_wiser_sidebar": "Wiser in der Seitenleiste anzeigen" }, "data_description": { "legacy_naming": "Raumnamen in Wiser-Gerätenamen aufnehmen. Wenn diese Option aktiviert ist, werden Bereichsnamen beim Neuerstellen der Entitäts-IDs mit dem Standardformat unter Einstellungen → System → Entitäts-ID-Format (Home Assistant 2026.8 und neuer) doppelt verwendet, wenn Bereichs- und Wiser-Raumname übereinstimmen. Diese Option ändert keine bestehenden Entitäts-IDs." @@ -226,7 +225,8 @@ "entity": { "update": { "schedule_card": { "name": "Wiser-Zeitplankarte" }, - "zigbee_card": { "name": "Wiser-Zigbee-Karte" } + "zigbee_card": { "name": "Wiser-Zigbee-Karte" }, + "rooms_card": { "name": "Wiser-Raumkarte" } }, "climate": { "heating": { diff --git a/custom_components/wiser/translations/en-GB.json b/custom_components/wiser/translations/en-GB.json index 9a84bef2..e56148c2 100644 --- a/custom_components/wiser/translations/en-GB.json +++ b/custom_components/wiser/translations/en-GB.json @@ -49,8 +49,7 @@ "title": "UI options", "data": { "legacy_naming": "Legacy naming", - "show_schedules_sidebar": "Show Wiser Schedules in sidebar", - "show_zigbee_sidebar": "Show Wiser Zigbee in sidebar" + "show_wiser_sidebar": "Show Wiser in sidebar" }, "data_description": { "legacy_naming": "Include room names in Wiser device names. If enabled, using Home Assistant to regenerate entity IDs with the default format in Settings → System → Entity ID format (Home Assistant 2026.8 and later) will duplicate area names when the area and Wiser room names match. Changing this option does not rename existing entity IDs." @@ -226,7 +225,8 @@ "entity": { "update": { "schedule_card": { "name": "Wiser Schedules Card" }, - "zigbee_card": { "name": "Wiser Zigbee Card" } + "zigbee_card": { "name": "Wiser Zigbee Card" }, + "rooms_card": { "name": "Wiser Rooms Card" } }, "climate": { "heating": { diff --git a/custom_components/wiser/translations/en.json b/custom_components/wiser/translations/en.json index 737e882a..117d467d 100755 --- a/custom_components/wiser/translations/en.json +++ b/custom_components/wiser/translations/en.json @@ -49,8 +49,7 @@ "title": "UI options", "data": { "legacy_naming": "Legacy naming", - "show_schedules_sidebar": "Show Wiser Schedules in sidebar", - "show_zigbee_sidebar": "Show Wiser Zigbee in sidebar" + "show_wiser_sidebar": "Show Wiser in sidebar" }, "data_description": { "legacy_naming": "Include room names in Wiser device names. If enabled, using Home Assistant to regenerate entity IDs with the default format in Settings → System → Entity ID format (Home Assistant 2026.8 and later) will duplicate area names when the area and Wiser room names match. Changing this option does not rename existing entity IDs." @@ -226,7 +225,8 @@ "entity": { "update": { "schedule_card": { "name": "Wiser Schedules Card" }, - "zigbee_card": { "name": "Wiser Zigbee Card" } + "zigbee_card": { "name": "Wiser Zigbee Card" }, + "rooms_card": { "name": "Wiser Rooms Card" } }, "climate": { "heating": { diff --git a/custom_components/wiser/translations/fr.json b/custom_components/wiser/translations/fr.json index e8ff6c12..5f7657ed 100644 --- a/custom_components/wiser/translations/fr.json +++ b/custom_components/wiser/translations/fr.json @@ -49,8 +49,7 @@ "title": "Options de l’interface", "data": { "legacy_naming": "Nommage historique", - "show_schedules_sidebar": "Afficher les programmes Wiser dans la barre latérale", - "show_zigbee_sidebar": "Afficher Wiser Zigbee dans la barre latérale" + "show_wiser_sidebar": "Afficher Wiser dans la barre latérale" }, "data_description": { "legacy_naming": "Inclure le nom des pièces dans le nom des appareils Wiser. Si cette option est activée, la régénération des identifiants d’entité avec le format par défaut dans Paramètres → Système → Format des identifiants d’entité (Home Assistant 2026.8 et versions ultérieures) répétera le nom de la zone si celui-ci correspond au nom de la pièce Wiser. Cette option ne renomme pas les identifiants d’entité existants." @@ -226,7 +225,8 @@ "entity": { "update": { "schedule_card": { "name": "Carte des programmes Wiser" }, - "zigbee_card": { "name": "Carte Zigbee Wiser" } + "zigbee_card": { "name": "Carte Zigbee Wiser" }, + "rooms_card": { "name": "Carte des pièces Wiser" } }, "climate": { "heating": { diff --git a/custom_components/wiser/update.py b/custom_components/wiser/update.py index 4ebb2f8d..992b882c 100644 --- a/custom_components/wiser/update.py +++ b/custom_components/wiser/update.py @@ -17,18 +17,20 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.update_coordinator import CoordinatorEntity, DataUpdateCoordinator -from .const import DOMAIN +from .const import CARD_MANIFEST, DOMAIN from .frontend import JSModuleRegistration, async_card_resource from .frontend.card_files import newer_version, prune_card_cache, store_card -from .frontend.schedules_sidebar import async_update_schedules_panel -from .frontend.zigbee_sidebar import async_update_zigbee_panel +from .frontend.wiser_sidebar import async_update_wiser_panel _LOGGER = logging.getLogger(__name__) _MANAGER = "wiser_card_updates" _MAX_DOWNLOAD = 20 * 1024 * 1024 _CARDS = { - "schedule": ("andyblac/wiser-schedule-card", "wiser-schedule-card.js", "wiser-schedules-panel"), - "zigbee": ("andyblac/wiser-zigbee-card", "wiser-zigbee-card.js", "wiser-zigbee-panel"), + card["id"]: (card["repository"], card["filename"], card["component"]) + for card in CARD_MANIFEST +} +_PANEL_COMPONENTS = { + card["id"]: card["panel"] for card in CARD_MANIFEST if card.get("panel") } @@ -84,7 +86,13 @@ def _validate_download(card, release, contents): marker = re.search( rf"/\*!\s*WISER-CARD-VERSION {re.escape(filename[:-3])}\s+(\S+)\s*\*/", source ) - if not marker or marker[1] != release["version"] or component not in source: + panel_component = _PANEL_COMPONENTS.get(card) + if ( + not marker + or marker[1] != release["version"] + or component not in source + or (panel_component and panel_component not in source) + ): raise ValueError("Card version or sidebar component does not match the release") @@ -209,8 +217,7 @@ async def install(self, card): self.pending_refresh.setdefault(card, (installed, active_path)) registration = JSModuleRegistration(self.hass) await registration.async_register() - await async_update_schedules_panel(self.hass) - await async_update_zigbee_panel(self.hass) + await async_update_wiser_panel(self.hass) active_path, _, installed = await async_card_resource(self.hass, filename) _, previous_path = self.pending_refresh.pop(card) state["installed"] = installed diff --git a/custom_components/wiser/websockets.py b/custom_components/wiser/websockets.py index e2b3cb38..bc71ba8a 100644 --- a/custom_components/wiser/websockets.py +++ b/custom_components/wiser/websockets.py @@ -10,8 +10,12 @@ from aioWiserHeatAPI.schedule import WiserScheduleTypeEnum from homeassistant.helpers.dispatcher import async_dispatcher_connect from .const import DATA, DOMAIN -from .frontend.schedules_sidebar import save_schedules_panel_config -from .frontend.zigbee_sidebar import save_zigbee_panel_config +from .frontend.wiser_sidebar import ( + save_rooms_panel_config, + save_schedules_panel_config, + save_wiser_panel_tabs, + save_zigbee_panel_config, +) _LOGGER = logging.getLogger(__name__) @@ -108,6 +112,41 @@ def websocket_configure_zigbee_panel(hass, connection, msg): return connection.send_result(msg["id"]) + @callback + @websocket_api.websocket_command({ + vol.Required("type"): "wiser/rooms_panel/configure", + vol.Required("configs"): {str: dict}, + }) + @websocket_api.require_admin + def websocket_configure_rooms_panel(hass, connection, msg): + """Save Rooms panel preferences in the generic panel registry option.""" + try: + save_rooms_panel_config(hass, msg["configs"]) + except ValueError as err: + connection.send_error(msg["id"], "invalid_config", str(err)) + return + connection.send_result(msg["id"]) + + @callback + @websocket_api.websocket_command({ + vol.Required("type"): "wiser/panel/configure_tabs", + vol.Required("tabs"): [ + { + vol.Required("id"): str, + vol.Required("title"): str, + } + ], + }) + @websocket_api.require_admin + def websocket_configure_wiser_panel_tabs(hass, connection, msg): + """Save the unified Wiser panel tab order and custom titles.""" + try: + save_wiser_panel_tabs(hass, msg["tabs"]) + except ValueError as err: + connection.send_error(msg["id"], "invalid_config", str(err)) + return + connection.send_result(msg["id"]) + # Get Hubs @websocket_api.websocket_command( { @@ -574,6 +613,8 @@ async def websocket_get_zigbee_data( async_register_command(hass, websocket_configure_schedules_panel) async_register_command(hass, websocket_configure_zigbee_panel) + async_register_command(hass, websocket_configure_rooms_panel) + async_register_command(hass, websocket_configure_wiser_panel_tabs) async_register_command(hass, websocket_get_hubs) async_register_command(hass, websocket_get_suntimes) async_register_command(hass, websocket_get_schedules) diff --git a/scripts/build.py b/scripts/build.py index 23d03b83..502cee4e 100644 --- a/scripts/build.py +++ b/scripts/build.py @@ -7,12 +7,25 @@ import tempfile from zipfile import ZIP_DEFLATED, ZipFile -from fetch_card_releases import CARD_REPOSITORIES, fetch_cards +from fetch_card_releases import ( + CARD_REPOSITORIES, + PANEL_CONFIG_REPOSITORY, + fetch_cards, + fetch_panel_config, +) ROOT = Path(__file__).resolve().parents[1] -def build(source, output, local_root, channel, repositories, release=False): +def build( + source, + output, + local_root, + channel, + repositories, + release=False, + panel_config_repository=PANEL_CONFIG_REPOSITORY, +): """Stage a fresh integration and replace the ZIP only after a successful build.""" # Stable builds and explicit releases must never package local card builds. if release or channel == "stable": @@ -24,8 +37,30 @@ def build(source, output, local_root, channel, repositories, release=False): source, staging, ignore=shutil.ignore_patterns("__pycache__", "*.pyc", ".DS_Store"), ) + manifest, config_record = fetch_panel_config( + channel, + source / "frontend/cards.json", + local_root=local_root, + release=release, + repository=panel_config_repository, + ) + (staging / "frontend/cards.json").write_text( + json.dumps(manifest, indent=2) + "\n" + ) + definitions = {card["id"]: card for card in manifest} + selected_repositories = { + card_id: repositories.get(card_id, card["repository"]) + for card_id, card in definitions.items() + } report = fetch_cards( - channel, staging / "frontend", repositories, local_root=local_root + channel, + staging / "frontend", + selected_repositories, + local_root=local_root, + definitions=definitions, + ) + (staging / "frontend/panel-config-release.json").write_text( + json.dumps(config_record, indent=2) + "\n" ) archive_path = Path(temporary) / "wiser.zip" with ZipFile(archive_path, "w", compression=ZIP_DEFLATED) as archive: @@ -40,6 +75,10 @@ def build(source, output, local_root, channel, repositories, release=False): staging / "frontend/card-releases.json", output.parent / "card-releases.json", ) + shutil.copyfile( + staging / "frontend/panel-config-release.json", + output.parent / "panel-config-release.json", + ) return report @@ -53,13 +92,23 @@ def main(): parser.add_argument("--output", type=Path, default=ROOT / "dist/wiser.zip") parser.add_argument("--schedule-repository", default=CARD_REPOSITORIES["schedule"]) parser.add_argument("--zigbee-repository", default=CARD_REPOSITORIES["zigbee"]) + parser.add_argument("--rooms-repository", default=CARD_REPOSITORIES["rooms"]) + parser.add_argument( + "--panel-config-repository", default=PANEL_CONFIG_REPOSITORY + ) args = parser.parse_args() try: report = build( ROOT / "custom_components/wiser", args.output, args.local_root, args.channel, - {"schedule": args.schedule_repository, "zigbee": args.zigbee_repository}, + { + **CARD_REPOSITORIES, + "schedule": args.schedule_repository, + "zigbee": args.zigbee_repository, + "rooms": args.rooms_repository, + }, release=args.release, + panel_config_repository=args.panel_config_repository, ) except Exception as error: parser.exit(1, f"Build failed: {error}\n") diff --git a/scripts/fetch_card_releases.py b/scripts/fetch_card_releases.py index 66123468..aefa6b66 100644 --- a/scripts/fetch_card_releases.py +++ b/scripts/fetch_card_releases.py @@ -10,10 +10,103 @@ from urllib.parse import urlparse from urllib.request import Request, urlopen +ROOT = Path(__file__).resolve().parents[1] +PANEL_CONFIG_REPOSITORY = "andyblac/WiserFrontendPanelConfig" +PANEL_CONFIG_FILENAME = "cards.json" +CARD_MANIFEST = json.loads( + (ROOT / "custom_components/wiser/frontend/cards.json").read_text("utf-8") +) CARD_REPOSITORIES = { - "schedule": "andyblac/wiser-schedule-card", - "zigbee": "andyblac/wiser-zigbee-card", + card["id"]: card["repository"] for card in CARD_MANIFEST } +CARD_DEFINITIONS = {card["id"]: card for card in CARD_MANIFEST} + + +def validate_card_manifest(manifest): + """Validate an externally maintained frontend card registry.""" + if not isinstance(manifest, list) or not manifest: + raise ValueError("cards.json must contain at least one card") + ids = set() + filenames = set() + required = {"id", "name", "filename", "repository", "component", "panel"} + for index, card in enumerate(manifest): + if not isinstance(card, dict) or not required.issubset(card): + raise ValueError(f"Card {index} is missing required fields") + for field in ("id", "name", "filename", "repository", "component"): + if not isinstance(card[field], str) or not card[field].strip(): + raise ValueError(f"Card {index} has invalid {field}") + if not re.fullmatch(r"[a-z0-9-]+", card["id"]): + raise ValueError(f"Invalid card id: {card['id']}") + if not re.fullmatch(r"wiser-[a-z0-9-]+-card\.js", card["filename"]): + raise ValueError(f"Invalid card filename: {card['filename']}") + if not re.fullmatch(r"[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+", card["repository"]): + raise ValueError(f"Invalid repository: {card['repository']}") + if not re.fullmatch(r"wiser-[a-z0-9-]+", card["component"]): + raise ValueError(f"Invalid component: {card['component']}") + if card["panel"] is not None and not re.fullmatch( + r"wiser-[a-z0-9-]+-panel", card["panel"] + ): + raise ValueError(f"Invalid panel component for {card['id']}") + if card["id"] in ids: + raise ValueError(f"Duplicate card id: {card['id']}") + if card["filename"] in filenames: + raise ValueError(f"Duplicate card filename: {card['filename']}") + ids.add(card["id"]) + filenames.add(card["filename"]) + return manifest + + +def fetch_panel_config( + channel, + packaged_path, + local_root=None, + release=False, + repository=PANEL_CONFIG_REPOSITORY, +): + """Load the panel registry from a local build, package snapshot, or release.""" + local = ( + Path(local_root) / repository.rsplit("/", 1)[-1] / "dist" / PANEL_CONFIG_FILENAME + if local_root is not None and not release + else None + ) + if local is not None and local.is_file(): + contents = local.read_bytes() + record = { + "repository": repository, + "source": "local", + "asset": PANEL_CONFIG_FILENAME, + "path": str(local.resolve()), + "digest": "sha256:" + sha256(contents).hexdigest(), + } + elif not release and Path(packaged_path).is_file(): + path = Path(packaged_path) + contents = path.read_bytes() + record = { + "repository": repository, + "source": "packaged", + "asset": PANEL_CONFIG_FILENAME, + "path": str(path.resolve()), + "digest": "sha256:" + sha256(contents).hexdigest(), + } + else: + selected = select_release(list_releases(repository), channel) + asset = select_asset(selected, PANEL_CONFIG_FILENAME) + contents, digest = download_asset(repository, asset) + record = { + "repository": repository, + "source": "release", + "tag": selected["tag_name"], + "prerelease": selected["prerelease"], + "asset": PANEL_CONFIG_FILENAME, + "asset_id": asset["id"], + "url": asset["browser_download_url"], + "digest": digest, + } + try: + manifest = json.loads(contents) + except (TypeError, json.JSONDecodeError) as error: + raise ValueError("Invalid cards.json") from error + return validate_card_manifest(manifest), record def list_releases(repository): @@ -71,12 +164,21 @@ def download_asset(repository, asset): return contents, digest -def fetch_cards(channel, output_dir, repositories, plan=False, local_root=None): +def fetch_cards( + channel, + output_dir, + repositories, + plan=False, + local_root=None, + definitions=None, +): + definitions = CARD_DEFINITIONS if definitions is None else definitions report = [] payloads = {} # Resolve and validate every source before replacing any staged assets. for card, repository in repositories.items(): - filename = f"wiser-{card}-card.js" + definition = definitions[card] + filename = definition["filename"] local = ( Path(local_root) / repository.rsplit("/", 1)[-1] / "dist" / filename if local_root is not None else None @@ -102,11 +204,11 @@ def fetch_cards(channel, output_dir, repositories, plan=False, local_root=None): if not plan: if not contents or contents.lstrip().lower().startswith((b"Wiser", source) + self.assertIn('view.setAttribute("nested", "")', source) + self.assertIn("panel.module_url", source) + self.assertLess( + source.index("view.hass = this._hass"), + source.index("view.panel = { config: panel.config }"), + ) + self.assertIn('tab.addEventListener("dragstart"', source) + self.assertIn('tab.addEventListener("dblclick"', source) + self.assertIn('type: "wiser/panel/configure_tabs"', source) + self.assertIn("_mergeTabPreferences(panel.config)", source) + + def test_new_panel_websocket_commands_are_registered(self): + source = (ROOT / "websockets.py").read_text() + self.assertIn( + "async_register_command(hass, websocket_configure_rooms_panel)", + source, + ) + self.assertIn( + "async_register_command(hass, websocket_configure_wiser_panel_tabs)", + source, + ) + + def test_manifest_addition_drives_registration_and_packaging(self): + cards = json.loads((ROOT / "frontend/cards.json").read_text()) + self.assertEqual( + {card["id"] for card in cards}, {"schedule", "zigbee", "rooms"} + ) + + def test_panel_settings_save_without_standalone_sidebar_modules(self): + self.add_hub("schedule-hub", {}) + self.add_hub("zigbee-hub", {}) + self.hass.config_entries.async_update_entry = Mock() + self.sidebar.save_schedules_panel_config( + self.hass, + {"schedule-hub": {"type": "custom:wiser-schedule-card", "home_screen": "overview"}}, + ) + self.sidebar.save_zigbee_panel_config( + self.hass, + {"zigbee-hub": {"hub": "zigbee-hub", "orientation": "pie"}}, + ) + calls = self.hass.config_entries.async_update_entry.call_args_list + self.assertEqual( + calls[0].kwargs["options"], + {"schedules_panel_config": {"home_screen": "overview"}}, + ) + self.assertEqual( + calls[1].kwargs["options"], + {"zigbee_panel_config": {"orientation": "pie"}}, + ) + + def test_invalid_panel_settings_do_not_partially_save(self): + self.add_hub("first", {}) + self.add_hub("second", {}) + self.hass.config_entries.async_update_entry = Mock() + with self.assertRaises(ValueError): + self.sidebar.save_schedules_panel_config( + self.hass, + {"first": {"home_screen": "overview"}, "second": {"bad": float("nan")}}, + ) + self.hass.config_entries.async_update_entry.assert_not_called() + + def test_rooms_panel_settings_use_generic_registry_and_drop_hub_filter(self): + entry = self.add_hub( + "hub", + {"wiser_panel_config": {"future": {"enabled": True}}}, + ) + self.hass.config_entries.async_update_entry = Mock() + self.sidebar.save_rooms_panel_config( + self.hass, + { + "hub": { + "type": "custom:wiser-rooms-card", + "hubs": ["entry"], + "_panel_hide_title": True, + "room_columns": 4, + } + }, + ) + self.hass.config_entries.async_update_entry.assert_called_once_with( + entry, + options={ + "wiser_panel_config": { + "future": {"enabled": True}, + "rooms": {"room_columns": 4}, + } + }, + ) + + def test_panel_tab_layout_is_saved_for_every_enabled_hub(self): + first = self.add_hub( + "first", + {"wiser_panel_config": {"rooms": {"room_columns": 4}}}, + ) + second = self.add_hub("second", {}) + self.hass.config_entries.async_update_entry = Mock() + + tabs = [ + {"id": "rooms", "title": "Heating"}, + {"id": "schedule", "title": "Schedules"}, + {"id": "zigbee", "title": "Devices"}, + ] + self.sidebar.save_wiser_panel_tabs(self.hass, tabs) + + calls = self.hass.config_entries.async_update_entry.call_args_list + self.assertEqual([call.args[0] for call in calls], [first, second]) + self.assertEqual( + calls[0].kwargs["options"]["wiser_panel_config"], + { + "rooms": {"room_columns": 4}, + "_panel_tabs": tabs, + }, + ) + self.assertEqual( + calls[1].kwargs["options"]["wiser_panel_config"], + {"_panel_tabs": tabs}, + ) + + def test_invalid_or_duplicate_panel_tabs_are_rejected(self): + self.add_hub("hub", {}) + self.hass.config_entries.async_update_entry = Mock() + + invalid_tabs = [ + {"id": "rooms", "title": "Heating"}, + {"id": "rooms", "title": "Duplicate"}, + ] + with self.assertRaises(ValueError): + self.sidebar.save_wiser_panel_tabs(self.hass, invalid_tabs) + self.hass.config_entries.async_update_entry.assert_not_called() + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_zigbee_sidebar.py b/tests/test_zigbee_sidebar.py deleted file mode 100644 index 185974e1..00000000 --- a/tests/test_zigbee_sidebar.py +++ /dev/null @@ -1,289 +0,0 @@ -"""Test sidebar panel lifecycle without Home Assistant runtime dependencies.""" - -import importlib.util -from pathlib import Path -import sys -from types import ModuleType, SimpleNamespace -import unittest -from unittest.mock import AsyncMock, Mock, patch - - -ROOT = Path(__file__).resolve().parents[1] / "custom_components/wiser" - - -class ZigbeeSidebarTest(unittest.IsolatedAsyncioTestCase): - def setUp(self): - self.frontend = ModuleType("homeassistant.components.frontend") - self.frontend.async_remove_panel = Mock() - self.frontend.async_register_built_in_panel = Mock() - self.custom = ModuleType("homeassistant.components.panel_custom") - self.custom.async_register_panel = AsyncMock() - components = ModuleType("homeassistant.components") - components.frontend = self.frontend - components.panel_custom = self.custom - constants = ModuleType("sidebar_test.const") - constants.CONF_SHOW_ZIGBEE_SIDEBAR = "show_zigbee_sidebar" - constants.CONF_ZIGBEE_PANEL_CONFIG = "zigbee_panel_config" - version_module = ModuleType("sidebar_test.frontend.zigbee_version") - self.version_reader = Mock(return_value="4.5.6-beta.2") - version_module.card_version = self.version_reader - async def card_resource(hass, filename): - path = ROOT / "frontend" / filename - version = await hass.async_add_executor_job(self.version_reader, path) - return path, f"/wiser/{filename}?v={version}", version - version_module.async_card_resource = card_resource - version_module.__path__ = [str(ROOT / "frontend")] - constants.DATA = "data" - constants.DOMAIN = "wiser" - constants.URL_BASE = "/wiser" - constants.JSMODULES = [ - {"filename": "wiser-zigbee-card.js"} - ] - with patch.dict(sys.modules, { - "homeassistant": ModuleType("homeassistant"), - "homeassistant.components": components, - "sidebar_test": ModuleType("sidebar_test"), - "sidebar_test.frontend": version_module, - "sidebar_test.const": constants, - }): - spec = importlib.util.spec_from_file_location( - "sidebar_test.frontend.zigbee_sidebar", ROOT / "frontend/zigbee_sidebar.py" - ) - self.sidebar = importlib.util.module_from_spec(spec) - spec.loader.exec_module(self.sidebar) - self.entries = [] - self.hass = SimpleNamespace( - data={"wiser": {}}, - async_add_executor_job=AsyncMock(side_effect=lambda fn, *args: fn(*args)), - config_entries=SimpleNamespace(async_entries=lambda _: self.entries), - ) - - def add_hub(self, name, enabled=None, loaded=True, disabled=False): - entry = SimpleNamespace( - entry_id=name, disabled_by=disabled, data={"host": "hub.local"}, - options={} if enabled is None else {"show_zigbee_sidebar": enabled}, - ) - self.entries.append(entry) - if loaded: - self.hass.data["wiser"][name] = { - "data": SimpleNamespace(wiserhub=SimpleNamespace( - system=SimpleNamespace(name=name) - )) - } - return entry - - async def test_default_disabled_and_unloaded_hubs_do_not_register(self): - self.add_hub("default") - self.add_hub("off", False) - self.add_hub("unloaded", True, loaded=False) - self.add_hub("disabled", True, disabled=True) - await self.sidebar.async_update_zigbee_panel(self.hass) - self.custom.async_register_panel.assert_not_called() - self.frontend.async_remove_panel.assert_not_called() - - async def test_enable_registers_dedicated_panel_once(self): - self.add_hub("hub", True) - await self.sidebar.async_update_zigbee_panel(self.hass) - await self.sidebar.async_update_zigbee_panel(self.hass) - self.custom.async_register_panel.assert_awaited_once() - args = self.custom.async_register_panel.call_args.kwargs - self.assertEqual(args["frontend_url_path"], "wiser-zigbee-panel") - self.assertEqual(args["webcomponent_name"], "wiser-zigbee-panel") - self.assertEqual(args["sidebar_icon"], "wiser:zigbee") - self.assertEqual(args["config"]["hubs"], ["hub"]) - self.assertEqual(args["config"]["card_url"], "/wiser/wiser-zigbee-card.js?v=4.5.6-beta.2") - - async def test_disable_last_hub_removes_panel(self): - entry = self.add_hub("hub", True) - await self.sidebar.async_update_zigbee_panel(self.hass) - entry.options["show_zigbee_sidebar"] = False - await self.sidebar.async_update_zigbee_panel(self.hass) - self.frontend.async_remove_panel.assert_called_once_with(self.hass, "wiser-zigbee-panel") - self.assertNotIn(self.sidebar.PANEL_STATE, self.hass.data) - - async def test_unload_keeps_other_hub_then_removes_last(self): - self.add_hub("first", True) - self.add_hub("second", True) - await self.sidebar.async_update_zigbee_panel(self.hass) - self.hass.data["wiser"].pop("first") - await self.sidebar.async_update_zigbee_panel(self.hass) - self.assertEqual( - self.frontend.async_register_built_in_panel.call_args.kwargs["config"]["hubs"], - ["second"], - ) - self.hass.data["wiser"].pop("second") - await self.sidebar.async_update_zigbee_panel(self.hass) - self.assertNotIn(self.sidebar.PANEL_STATE, self.hass.data) - - async def test_registration_failure_can_be_retried(self): - self.add_hub("hub", True) - self.custom.async_register_panel.side_effect = ValueError("Overwriting panel wiser-zigbee-panel owned by lovelace") - with self.assertLogs(self.sidebar._LOGGER, level="WARNING") as logs: - await self.sidebar.async_update_zigbee_panel(self.hass) - self.assertIn("owned by lovelace", logs.output[0]) - self.frontend.async_remove_panel.assert_not_called() - self.assertNotIn(self.sidebar.PANEL_STATE, self.hass.data) - self.custom.async_register_panel.side_effect = None - await self.sidebar.async_update_zigbee_panel(self.hass) - self.assertEqual(self.hass.data[self.sidebar.PANEL_STATE]["hubs"], ["hub"]) - - async def test_saved_config_is_sent_to_panel(self): - entry = self.add_hub("hub", True) - entry.options["zigbee_panel_config"] = {"show_labels": True} - await self.sidebar.async_update_zigbee_panel(self.hass) - self.assertEqual( - self.custom.async_register_panel.call_args.kwargs["config"]["card_configs"], - {"hub": {"show_labels": True}}, - ) - - def test_save_preserves_other_options(self): - entry = self.add_hub("hub", True) - entry.options["scan_interval"] = 30 - self.hass.config_entries.async_update_entry = Mock() - self.sidebar.save_zigbee_panel_config(self.hass, { - "hub": {"type": "custom:wiser-zigbee-card", "hub": "hub", "show_labels": True}, - }) - options = self.hass.config_entries.async_update_entry.call_args.kwargs["options"] - self.assertEqual(options["scan_interval"], 30) - self.assertTrue(options["show_zigbee_sidebar"]) - self.assertEqual(options["zigbee_panel_config"], {"show_labels": True}) - - def test_theme_modes_are_saved(self): - self.add_hub("hub", True) - self.hass.config_entries.async_update_entry = Mock() - for mode in ("auto", "dark", "light"): - with self.subTest(mode=mode): - self.sidebar.save_zigbee_panel_config(self.hass, { - "hub": {"theme_mode": mode}, - }) - options = self.hass.config_entries.async_update_entry.call_args.kwargs["options"] - self.assertEqual(options["zigbee_panel_config"], {"theme_mode": mode}) - - def test_invalid_settings_do_not_partially_save(self): - self.add_hub("first", True) - self.add_hub("second", True) - self.hass.config_entries.async_update_entry = Mock() - with self.assertRaises(ValueError): - self.sidebar.save_zigbee_panel_config(self.hass, { - "first": {"name": "Valid"}, "second": {"future_option": float("nan")}, - }) - self.hass.config_entries.async_update_entry.assert_not_called() - - def test_current_external_card_editor_options_are_supported(self): - self.add_hub("hub", True) - self.hass.config_entries.async_update_entry = Mock() - settings = {"orientation": "pie", "map_only": True, "show_labels": True, "layout_data": {"1": {"x": 12, "y": -30}}} - self.sidebar.save_zigbee_panel_config(self.hass, {"hub": settings}) - self.assertEqual( - self.hass.config_entries.async_update_entry.call_args.kwargs["options"]["zigbee_panel_config"], - settings, - ) - - async def test_future_card_options_round_trip_without_backend_schema_changes(self): - entry = self.add_hub("hub", True) - def update_entry(entry, *, options): - entry.options = options - self.hass.config_entries.async_update_entry = Mock(side_effect=update_entry) - settings = { - "future_display_option": {"enabled": True, "values": [1, 0.5, None, "new"]}, - "orientation": "future-layout", - "theme_mode": "future-theme", - } - self.sidebar.save_zigbee_panel_config(self.hass, {"hub": settings}) - self.assertEqual(entry.options["zigbee_panel_config"], settings) - await self.sidebar.async_update_zigbee_panel(self.hass) - self.assertEqual( - self.custom.async_register_panel.call_args.kwargs["config"]["card_configs"], - {"hub": settings}, - ) - - def test_invalid_json_settings_are_rejected(self): - self.add_hub("hub", True) - self.hass.config_entries.async_update_entry = Mock() - cyclic = {} - cyclic["self"] = cyclic - for settings in [ - None, [], "invalid", {1: "non-string key"}, - {"future": {"nested": float("nan")}}, - {"future": [float("inf")]}, {"future": object()}, - {"future": {1, 2}}, cyclic, - ]: - with self.subTest(settings=type(settings)), self.assertRaises(ValueError): - self.sidebar.save_zigbee_panel_config(self.hass, {"hub": settings}) - for configs in (None, [], "invalid"): - with self.assertRaises(ValueError): - self.sidebar.save_zigbee_panel_config(self.hass, configs) - self.hass.config_entries.async_update_entry.assert_not_called() - - async def test_saved_settings_update_panel_without_removing_route(self): - entry = self.add_hub("hub", True) - await self.sidebar.async_update_zigbee_panel(self.hass) - entry.options = {**entry.options, "zigbee_panel_config": {"orientation": "pie"}} - await self.sidebar.async_update_zigbee_panel(self.hass) - self.frontend.async_remove_panel.assert_not_called() - self.frontend.async_register_built_in_panel.assert_called_once() - update = self.frontend.async_register_built_in_panel.call_args.kwargs - self.assertTrue(update["update"]) - self.assertEqual(update["frontend_url_path"], "wiser-zigbee-panel") - self.assertEqual(update["config"]["card_configs"]["hub"], {"orientation": "pie"}) - - async def test_bundle_version_change_updates_panel_without_settings_change(self): - self.add_hub("hub", True) - await self.sidebar.async_update_zigbee_panel(self.hass) - self.version_reader.assert_called_with(ROOT / "frontend/wiser-zigbee-card.js") - self.version_reader.return_value = "4.5.6-beta.3" - await self.sidebar.async_update_zigbee_panel(self.hass) - update = self.frontend.async_register_built_in_panel.call_args.kwargs - self.assertEqual(update["config"]["card_url"], "/wiser/wiser-zigbee-card.js?v=4.5.6-beta.3") - self.assertEqual(update["config"]["_panel_custom"]["module_url"], update["config"]["card_url"]) - - async def test_existing_lovelace_dashboard_is_not_overwritten(self): - self.add_hub("hub", True) - dashboard = object() - panels = {"wiser-zigbee": dashboard} - - async def register(hass, **kwargs): - path = kwargs["frontend_url_path"] - if path in panels: - raise ValueError(f"Overwriting panel {path} owned by lovelace") - panels[path] = kwargs - - self.custom.async_register_panel.side_effect = register - await self.sidebar.async_update_zigbee_panel(self.hass) - self.assertIs(panels["wiser-zigbee"], dashboard) - self.assertIn("wiser-zigbee-panel", panels) - self.frontend.async_remove_panel.assert_not_called() - - async def test_update_conflict_does_not_abort_and_can_be_retried(self): - entry = self.add_hub("hub", True) - await self.sidebar.async_update_zigbee_panel(self.hass) - previous = self.hass.data[self.sidebar.PANEL_STATE] - entry.options["zigbee_panel_config"] = {"show_labels": True} - self.frontend.async_register_built_in_panel.side_effect = ValueError("owned by lovelace") - with self.assertLogs(self.sidebar._LOGGER, level="WARNING"): - await self.sidebar.async_update_zigbee_panel(self.hass) - self.assertIs(self.hass.data[self.sidebar.PANEL_STATE], previous) - self.frontend.async_register_built_in_panel.side_effect = None - await self.sidebar.async_update_zigbee_panel(self.hass) - self.assertTrue(self.hass.data[self.sidebar.PANEL_STATE]["card_configs"]["hub"]["show_labels"]) - - async def test_disabled_hub_with_same_name_cannot_override_settings(self): - enabled = self.add_hub("enabled", True) - enabled.options["zigbee_panel_config"] = {"show_labels": True} - disabled = self.add_hub("disabled", True, disabled=True) - disabled.options["zigbee_panel_config"] = {"show_labels": False} - self.hass.data["wiser"]["disabled"]["data"].wiserhub.system.name = "enabled" - await self.sidebar.async_update_zigbee_panel(self.hass) - self.assertEqual( - self.custom.async_register_panel.call_args.kwargs["config"]["card_configs"], - {"enabled": {"show_labels": True}}, - ) - - def test_disabled_hub_settings_cannot_be_saved(self): - self.add_hub("disabled", True, disabled=True) - self.hass.config_entries.async_update_entry = Mock() - with self.assertRaises(ValueError): - self.sidebar.save_zigbee_panel_config( - self.hass, {"disabled": {"show_labels": True}} - ) - self.hass.config_entries.async_update_entry.assert_not_called() From f3dfd4447be8796284eb1ef8e2eb3ad32b2b3c98 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Tue, 29 Sep 2026 18:59:52 +0100 Subject: [PATCH 045/154] Fix Wiser panel refresh by separating UI and static routes --- .../wiser/frontend/wiser_sidebar.py | 4 +++- tests/test_wiser_sidebar.py | 24 +++++++++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/custom_components/wiser/frontend/wiser_sidebar.py b/custom_components/wiser/frontend/wiser_sidebar.py index 54256d75..bd21f402 100644 --- a/custom_components/wiser/frontend/wiser_sidebar.py +++ b/custom_components/wiser/frontend/wiser_sidebar.py @@ -20,7 +20,9 @@ URL_BASE, ) -PANEL_PATH = "wiser" +# Keep the UI route outside URL_BASE: a direct request to the static-file +# directory returns 403 instead of loading the Home Assistant frontend. +PANEL_PATH = "wiser-panel" PANEL_STATE = "wiser_sidebar_panel" PANEL_COMPONENT = "wiser-panel" PANEL_FILENAME = "wiser-panel.js" diff --git a/tests/test_wiser_sidebar.py b/tests/test_wiser_sidebar.py index 00b2b02b..b7fd6b09 100644 --- a/tests/test_wiser_sidebar.py +++ b/tests/test_wiser_sidebar.py @@ -116,7 +116,7 @@ async def test_single_option_registers_one_panel_with_discovered_panel_cards(sel self.custom.async_register_panel.assert_awaited_once() args = self.custom.async_register_panel.call_args.kwargs - self.assertEqual(args["frontend_url_path"], "wiser") + self.assertEqual(args["frontend_url_path"], "wiser-panel") self.assertEqual(args["webcomponent_name"], "wiser-panel") self.assertEqual(args["sidebar_icon"], "wiser:wiser") self.assertEqual( @@ -138,6 +138,26 @@ async def test_single_option_registers_one_panel_with_discovered_panel_cards(sel {"orientation": "pie"}, ) + async def test_panel_route_stays_outside_static_resources_on_register_and_update(self): + self.add_hub("hub", {}) + await self.sidebar.async_update_wiser_panel(self.hass) + registered = self.custom.async_register_panel.call_args.kwargs + route = "/" + registered["frontend_url_path"] + static_root = self.sidebar.URL_BASE.rstrip("/") + self.assertNotEqual(route, static_root) + self.assertFalse(route.startswith(static_root + "/")) + self.assertTrue(registered["module_url"].startswith(static_root + "/")) + + # Changing enabled hubs refreshes the same UI route, with static URLs intact. + self.add_hub("another-hub", {}) + await self.sidebar.async_update_wiser_panel(self.hass) + updated = self.frontend.async_register_built_in_panel.call_args.kwargs + self.assertEqual(updated["frontend_url_path"], registered["frontend_url_path"]) + self.assertTrue(updated["update"]) + self.assertEqual( + updated["config"]["_panel_custom"]["module_url"], registered["module_url"] + ) + async def test_sidebar_is_enabled_by_default(self): self.add_hub("hub", {}) await self.sidebar.async_update_wiser_panel(self.hass) @@ -194,7 +214,7 @@ async def test_no_enabled_hubs_removes_existing_shared_panel(self): self.hass.data[self.sidebar.PANEL_STATE] = {"panels": []} self.add_hub("hub", {"show_wiser_sidebar": False}) await self.sidebar.async_update_wiser_panel(self.hass) - self.frontend.async_remove_panel.assert_called_once_with(self.hass, "wiser") + self.frontend.async_remove_panel.assert_called_once_with(self.hass, "wiser-panel") self.assertNotIn(self.sidebar.PANEL_STATE, self.hass.data) def test_shell_owns_panel_tabs_and_embeds_each_child_panel(self): From 600ccfeca574452968e0411af58ad3a3e1057497 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Tue, 29 Sep 2026 21:24:26 +0100 Subject: [PATCH 046/154] Discover frontend cards from external registry --- .github/workflows/publish.yml | 4 - .gitignore | 3 + CHANGELOG.md | 2 + CONTRIBUTING.md | 9 +- README.md | 11 +- custom_components/wiser/const.py | 17 +- custom_components/wiser/frontend/__init__.py | 37 +--- .../wiser/frontend/card_files.py | 2 +- .../wiser/frontend/entry_updates.py | 14 +- custom_components/wiser/frontend/manifest.py | 38 ++++ custom_components/wiser/frontend/registry.py | 116 +++++++++++ .../wiser/frontend/wiser_sidebar.py | 107 ++--------- custom_components/wiser/strings.json | 5 - custom_components/wiser/translations/de.json | 5 - .../wiser/translations/en-GB.json | 5 - custom_components/wiser/translations/en.json | 5 - custom_components/wiser/translations/fr.json | 5 - custom_components/wiser/update.py | 76 +++++--- custom_components/wiser/websockets.py | 47 +---- docs/frontend-registry.md | 96 ++++++++++ scripts/build.py | 22 +-- scripts/fetch_card_releases.py | 118 +++++------- .../fixtures/frontend_cards.json | 0 tests/test_build.py | 47 ++++- tests/test_card_releases.py | 32 ++-- tests/test_card_updates.py | 180 ++++++++++++++++-- tests/test_frontend_version.py | 72 ++++--- tests/test_sidebar_icons.py | 1 + tests/test_wiser_sidebar.py | 103 ++++++---- tests/test_zigbee_version.py | 56 ------ 30 files changed, 749 insertions(+), 486 deletions(-) create mode 100644 custom_components/wiser/frontend/manifest.py create mode 100644 custom_components/wiser/frontend/registry.py create mode 100644 docs/frontend-registry.md rename custom_components/wiser/frontend/cards.json => tests/fixtures/frontend_cards.json (100%) delete mode 100644 tests/test_zigbee_version.py diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index ea2e385a..2b961bf6 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -40,14 +40,10 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CARD_CHANNEL: ${{ github.event_name == 'release' && (github.event.release.prerelease && 'dev' || 'stable') || inputs.channel || 'dev' }} - SCHEDULE_REPOSITORY: ${{ vars.WISER_SCHEDULE_CARD_REPOSITORY || 'andyblac/wiser-schedule-card' }} - ZIGBEE_REPOSITORY: ${{ vars.WISER_ZIGBEE_CARD_REPOSITORY || 'andyblac/wiser-zigbee-card' }} PANEL_CONFIG_REPOSITORY: ${{ vars.WISER_PANEL_CONFIG_REPOSITORY || 'andyblac/WiserFrontendPanelConfig' }} run: >- python scripts/build.py --release --channel "$CARD_CHANNEL" - --schedule-repository "$SCHEDULE_REPOSITORY" - --zigbee-repository "$ZIGBEE_REPOSITORY" --panel-config-repository "$PANEL_CONFIG_REPOSITORY" - name: Upload release package for inspection uses: actions/upload-artifact@v5 diff --git a/.gitignore b/.gitignore index 2335833c..0c3e6d66 100755 --- a/.gitignore +++ b/.gitignore @@ -109,3 +109,6 @@ venv.bak/ .mypy_cache/ *.DS_Store .vscode/settings.json + +# Generated from the external frontend registry during packaging +/custom_components/wiser/frontend/cards.json diff --git a/CHANGELOG.md b/CHANGELOG.md index f9daeb98..d4a5da5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ For releases before v3.3.5, see the [Full Change Log](https://github.com/asantag ### Added +- Discover new cards and panels from published WiserFrontendPanelConfig registry releases at runtime, with independent card installation, offline caching, and a generic panel-settings API. + - Added configurable OpenTherm monitoring and controls, including relative modulation, a Delta-T sensor, expanded telemetry, and categorized diagnostics - PR [#697](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/697). - Added a configurable Wiser Schedules sidebar panel - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). - Added a Wiser Zigbee sidebar panel with a custom sidebar icon - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index aef7027d..d521f9e6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -39,7 +39,7 @@ Please include: | Integration source | `custom_components/wiser/` | | Hub communication | the separate `aioWiserHeatAPI` library, pinned in `manifest.json` | | Frontend panel/card plumbing | `custom_components/wiser/frontend/` | -| Schedules and Zigbee cards | separate repositories ([wiser-schedule-card](https://github.com/andyblac/wiser-schedule-card), [wiser-zigbee-card](https://github.com/andyblac/wiser-zigbee-card)) | +| Frontend cards and panels | repositories declared in [WiserFrontendPanelConfig](https://github.com/andyblac/WiserFrontendPanelConfig) | | Tests | `tests/` | | Packaging scripts | `scripts/` | @@ -116,10 +116,11 @@ python3 scripts/build.py --release --channel dev The output is `dist/wiser.zip`, with `dist/card-releases.json` recording the card releases and checksums included. Stable builds use stable card releases; -prerelease builds use the newest prerelease of each card, falling back to its -newest stable release. Missing or invalid card assets fail the build. +prerelease builds use the most recently published stable or prerelease of each +card. Missing or invalid card assets fail the build. -To see which card releases would be selected without downloading anything: +To see which card releases would be selected without downloading card bundles +(the registry metadata is still fetched): ```sh python3 scripts/fetch_card_releases.py --channel dev --plan diff --git a/README.md b/README.md index a5e8e9a2..df76f741 100755 --- a/README.md +++ b/README.md @@ -62,14 +62,19 @@ To build a stable release package, run: python3 scripts/build.py --release --channel stable ``` -For a prerelease package, use `--channel dev` instead. The build downloads published Schedules and Zigbee card assets from GitHub. Stable builds use stable card releases; prerelease builds use the most recently published stable or prerelease card release. In a running installation, card update entities follow the HACS **Pre-release** switch for this integration; without that option they offer stable card releases only. +For a prerelease package, use `--channel dev` instead. The build downloads every card defined by the external frontend registry from GitHub. Stable builds use stable card releases; prerelease builds use the most recently published stable or prerelease card release. In a running installation, card update entities follow the HACS **Pre-release** switch for this integration; without that option they offer stable card releases only. The frontend card registry is maintained separately in [`andyblac/WiserFrontendPanelConfig`](https://github.com/andyblac/WiserFrontendPanelConfig). Local development builds prefer that sibling repository's validated `dist/cards.json`; release builds download its published `cards.json` asset. A -snapshot is packaged as `frontend/cards.json`, so Home Assistant startup never -depends on GitHub being available. +snapshot is generated as `frontend/cards.json` in the package; no card list is +maintained in this integration repository. At runtime the integration checks +published registry releases daily and caches the last valid registry. New cards +appear as independent update entities and can be installed without updating the +integration. Installed cards and the cached registry remain available offline. +See [Adding frontend cards and panels](docs/frontend-registry.md) for the release +workflow and shared panel API. The output is `dist/wiser.zip`. The accompanying `dist/card-releases.json` and `dist/panel-config-release.json` files record the card and registry artifacts diff --git a/custom_components/wiser/const.py b/custom_components/wiser/const.py index 141065da..93f5a81a 100755 --- a/custom_components/wiser/const.py +++ b/custom_components/wiser/const.py @@ -14,24 +14,23 @@ CONF_LEGACY_NAMING = "legacy_naming" DATA_WISER_CONFIG = "wiser_config" URL_BASE = "/wiser" -CONF_SCHEDULES_PANEL_CONFIG = "schedules_panel_config" -CONF_ZIGBEE_PANEL_CONFIG = "zigbee_panel_config" CONF_SHOW_WISER_SIDEBAR = "show_wiser_sidebar" CONF_WISER_PANEL_CONFIG = "wiser_panel_config" def _load_card_manifest(): """Load the shared card registry used by packaging and runtime setup.""" - return json.loads( - (Path(__file__).parent / "frontend/cards.json").read_text("utf-8") - ) + try: + return json.loads( + (Path(__file__).parent / "frontend/cards.json").read_text("utf-8") + ) + except FileNotFoundError: + # Source checkouts have no card definitions; builds inject the registry. + return [] CARD_MANIFEST = _load_card_manifest() -JSMODULES = [ - {"name": card["name"], "filename": card["filename"]} - for card in CARD_MANIFEST -] + WISER_PLATFORMS = [ "binary_sensor", diff --git a/custom_components/wiser/frontend/__init__.py b/custom_components/wiser/frontend/__init__.py index 03616dda..31bbaac7 100644 --- a/custom_components/wiser/frontend/__init__.py +++ b/custom_components/wiser/frontend/__init__.py @@ -15,49 +15,28 @@ from homeassistant.helpers.event import async_call_later from .card_files import CARD_CACHE, CARD_CACHE_URL, resolve_card +from .registry import async_load_registry, get_manifest -from ..const import JSMODULES, URL_BASE # noqa: TID252 +from ..const import URL_BASE # noqa: TID252 _LOGGER = logging.getLogger(__name__) def card_version(path: Path) -> str: - """Resolve the card's banner variable, ignoring bundled library versions.""" + """Read the standard version marker or hash an unversioned static asset.""" version_pattern = r"\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?" try: contents = path.read_bytes() except OSError: return "missing" source = contents.decode("utf-8", errors="replace") - # Explicit build metadata is authoritative; legacy parsing remains below. + # Every registry-provided bundle uses the same build metadata contract. marker = re.search( rf"/\*!\s*WISER-CARD-VERSION {re.escape(path.stem)}\s+({version_pattern})\s*\*/", source, ) if marker: return marker[1] - # New builds inline CARD_VERSION into the editor's version footer and - # no longer emit the legacy startup banner. - footer = re.search( - rf'class=["\']version["\'][^`]*?common\.version["\']\)\}}:\s*' - rf'\$\{{["\']({version_pattern})["\']\}}', - source, - ) - if path.stem == "wiser-zigbee-card" and footer: - return footer[1] - - banner_name = "WISER-ZIGBEE(?:-NETWORK)?-CARD" if path.stem == "wiser-zigbee-card" else re.escape(path.stem.upper()) - banner = re.search( - banner_name + r'[^`]*?common\.version[\"\']\)\}\s*\$\{([\w$]+)\}', - source, - ) - if banner: - assignment = re.search( - rf'(? None: async def async_register(self): """Register Wiser static paths, icons, and card resources.""" + await async_load_registry(self.hass) await self._async_register_path() icon_version = await self.hass.async_add_executor_job( card_version, Path(__file__).parent / "wiser-icons.js" @@ -146,10 +126,13 @@ async def _async_register_modules(self): if resource["url"].startswith(URL_BASE) ] - for module in JSMODULES: + for module in get_manifest(self.hass): url = f"{URL_BASE}/{module.get('filename')}" _, active_url, version = await async_card_resource(self.hass, module["filename"]) + if version == "missing": + # Newly discovered cards become resources only after installation. + continue card_registered = False @@ -204,7 +187,7 @@ def _get_resource_version(self, url: str): async def async_unregister(self): """Unload lovelace module resource.""" if self.resource_mode == MODE_STORAGE: - for module in JSMODULES: + for module in get_manifest(self.hass): url = f"{URL_BASE}/{module.get('filename')}" wiser_resources = [ resource diff --git a/custom_components/wiser/frontend/card_files.py b/custom_components/wiser/frontend/card_files.py index 51726959..8640332c 100644 --- a/custom_components/wiser/frontend/card_files.py +++ b/custom_components/wiser/frontend/card_files.py @@ -44,7 +44,7 @@ def resolve_card(config_dir, filename, version_reader): or any(c not in "0123456789abcdef" for c in digest) ): return fallback - if not newer_version(record["version"], version): + if version != "missing" and not newer_version(record["version"], version): return fallback if sha256(cached.read_bytes()).hexdigest() != digest: return fallback diff --git a/custom_components/wiser/frontend/entry_updates.py b/custom_components/wiser/frontend/entry_updates.py index 6169630d..7a6b1220 100644 --- a/custom_components/wiser/frontend/entry_updates.py +++ b/custom_components/wiser/frontend/entry_updates.py @@ -2,10 +2,8 @@ from .wiser_sidebar import async_update_wiser_panel from ..const import ( - CONF_SCHEDULES_PANEL_CONFIG, CONF_SHOW_WISER_SIDEBAR, CONF_WISER_PANEL_CONFIG, - CONF_ZIGBEE_PANEL_CONFIG, DOMAIN, ) @@ -14,13 +12,11 @@ def integration_reload_settings(entry): """Capture connection and entity options, excluding panel-only preferences.""" return ( dict(entry.data), - {key: value for key, value in entry.options.items() - if key not in { - CONF_SCHEDULES_PANEL_CONFIG, - CONF_SHOW_WISER_SIDEBAR, - CONF_WISER_PANEL_CONFIG, - CONF_ZIGBEE_PANEL_CONFIG, - }}, + { + key: value + for key, value in entry.options.items() + if key not in {CONF_SHOW_WISER_SIDEBAR, CONF_WISER_PANEL_CONFIG} + }, ) diff --git a/custom_components/wiser/frontend/manifest.py b/custom_components/wiser/frontend/manifest.py new file mode 100644 index 00000000..00a171df --- /dev/null +++ b/custom_components/wiser/frontend/manifest.py @@ -0,0 +1,38 @@ +"""Validate frontend definitions consistently during packaging and runtime.""" + +import re + + +def validate_manifest(value): + """Validate names and paths before using a remotely supplied registry.""" + if not isinstance(value, list) or not 1 <= len(value) <= 100: + raise ValueError("Frontend registry must contain between 1 and 100 cards") + seen = {key: set() for key in ("id", "filename", "component", "panel")} + patterns = { + "id": r"[a-z0-9-]+", + "filename": r"wiser-[a-z0-9-]+-card\.js", + "repository": r"[A-Za-z0-9_-]+/[A-Za-z0-9_.-]+", + "component": r"wiser-[a-z0-9-]+", + "panel": r"wiser-[a-z0-9-]+-panel", + } + result = [] + for card in value: + if not isinstance(card, dict): + raise ValueError("Invalid frontend card definition") + name = card.get("name") + if not isinstance(name, str) or not name.strip() or len(name) > 100: + raise ValueError("Invalid frontend card name") + for key, pattern in patterns.items(): + item = card.get(key) + if key == "panel" and item is None: + continue + if not isinstance(item, str) or not re.fullmatch(pattern, item): + raise ValueError(f"Invalid frontend card {key}") + if key in seen: + if item in seen[key]: + raise ValueError(f"Duplicate frontend card {key}") + seen[key].add(item) + result.append({key: card.get(key) for key in ("name", *patterns)}) + return result + + diff --git a/custom_components/wiser/frontend/registry.py b/custom_components/wiser/frontend/registry.py new file mode 100644 index 00000000..7e99cd0a --- /dev/null +++ b/custom_components/wiser/frontend/registry.py @@ -0,0 +1,116 @@ +"""Discover frontend cards independently of integration releases.""" + +from hashlib import sha256 +import json +import logging +from pathlib import Path +from urllib.parse import urlsplit + +import aiohttp +from homeassistant.helpers.aiohttp_client import async_get_clientsession + +from ..const import CARD_MANIFEST +from .card_files import _atomic_write +from .manifest import validate_manifest + +_LOGGER = logging.getLogger(__name__) +REGISTRY_REPOSITORY = "andyblac/WiserFrontendPanelConfig" +REGISTRY_CACHE = ".storage/wiser_cards/registry.json" +REGISTRY_DATA = "wiser_frontend_registry" +_MAX_SIZE = 256 * 1024 + + +def get_manifest(hass): + """Return the active registry, with bundled definitions as an offline fallback.""" + return hass.data.get(REGISTRY_DATA, CARD_MANIFEST) + + +def _merge_manifest(current, incoming): + """Keep installed cards when a release omits them; preserve their identities.""" + merged = {card["id"]: card for card in current} + for card in incoming: + previous = merged.get(card["id"]) + if previous and any( + previous[key] != card[key] for key in ("filename", "repository", "component", "panel") + ): + raise ValueError(f"Registry changes the identity of {card['id']}") + merged[card["id"]] = card + return validate_manifest(list(merged.values())) + + +def _load_cached(config_dir): + try: + cached = validate_manifest(json.loads((Path(config_dir) / REGISTRY_CACHE).read_text())) + return _merge_manifest(CARD_MANIFEST, cached) + except (OSError, ValueError, TypeError, KeyError): + return CARD_MANIFEST + + +async def async_load_registry(hass): + """Load the last valid registry without needing a network connection.""" + if REGISTRY_DATA not in hass.data: + manifest = await hass.async_add_executor_job(_load_cached, hass.config.path()) + hass.data.setdefault(REGISTRY_DATA, manifest) + return get_manifest(hass) + + +def _store_registry(config_dir, manifest): + path = Path(config_dir) / REGISTRY_CACHE + path.parent.mkdir(parents=True, exist_ok=True) + _atomic_write(path, json.dumps(manifest).encode()) + + +async def async_refresh_registry(hass, allow_prerelease=False): + """Check published registry releases, retaining the last good copy on failure.""" + await async_load_registry(hass) + try: + session = async_get_clientsession(hass) + endpoint = "releases?per_page=100" if allow_prerelease else "releases/latest" + async with session.get( + f"https://api.github.com/repos/{REGISTRY_REPOSITORY}/{endpoint}", + headers={"Accept": "application/vnd.github+json", "User-Agent": "Wiser-Home-Assistant"}, + timeout=aiohttp.ClientTimeout(total=20), + ) as response: + response.raise_for_status() + metadata = await response.json() + releases = metadata if isinstance(metadata, list) else [metadata] + releases = [item for item in releases if isinstance(item, dict) + and not item.get("draft") and item.get("published_at") + and (allow_prerelease or not item.get("prerelease"))] + if not releases: + raise ValueError("No published frontend registry release") + release = max(releases, key=lambda item: item["published_at"]) + if not isinstance(release.get("assets"), list): + raise ValueError("Invalid frontend registry release assets") + assets = [asset for asset in release["assets"] + if isinstance(asset, dict) and asset.get("name") == "cards.json" + and asset.get("state") == "uploaded"] + if len(assets) != 1: + raise ValueError("Registry release must contain one cards.json asset") + asset = assets[0] + if not isinstance(asset.get("browser_download_url"), str) or type(asset.get("size")) is not int: + raise ValueError("Invalid frontend registry asset metadata") + url = urlsplit(asset["browser_download_url"]) + if (url.scheme != "https" or url.netloc != "github.com" + or not url.path.startswith(f"/{REGISTRY_REPOSITORY}/releases/download/") + or not 0 < asset["size"] <= _MAX_SIZE): + raise ValueError("Invalid frontend registry asset") + async with session.get( + asset["browser_download_url"], timeout=aiohttp.ClientTimeout(total=20) + ) as response: + response.raise_for_status() + contents = bytearray() + async for chunk in response.content.iter_chunked(65536): + contents.extend(chunk) + if len(contents) > _MAX_SIZE: + raise ValueError("Frontend registry is too large") + if len(contents) != asset["size"]: + raise ValueError("Frontend registry size mismatch") + if asset.get("digest") and asset["digest"] != "sha256:" + sha256(contents).hexdigest(): + raise ValueError("Frontend registry checksum mismatch") + manifest = _merge_manifest(get_manifest(hass), validate_manifest(json.loads(contents))) + await hass.async_add_executor_job(_store_registry, hass.config.path(), manifest) + hass.data[REGISTRY_DATA] = manifest + except (aiohttp.ClientError, TimeoutError, OSError, ValueError, TypeError, KeyError) as err: + _LOGGER.warning("Unable to refresh Wiser frontend registry; keeping cached cards: %s", err) + return get_manifest(hass) diff --git a/custom_components/wiser/frontend/wiser_sidebar.py b/custom_components/wiser/frontend/wiser_sidebar.py index bd21f402..b50e17a3 100644 --- a/custom_components/wiser/frontend/wiser_sidebar.py +++ b/custom_components/wiser/frontend/wiser_sidebar.py @@ -3,20 +3,17 @@ from __future__ import annotations import math -import re from pathlib import Path from homeassistant.components import frontend, panel_custom from . import async_card_resource, card_version +from .registry import get_manifest from ..const import ( - CONF_SCHEDULES_PANEL_CONFIG, CONF_SHOW_WISER_SIDEBAR, CONF_WISER_PANEL_CONFIG, - CONF_ZIGBEE_PANEL_CONFIG, DATA, DOMAIN, - JSMODULES, URL_BASE, ) @@ -26,17 +23,6 @@ PANEL_STATE = "wiser_sidebar_panel" PANEL_COMPONENT = "wiser-panel" PANEL_FILENAME = "wiser-panel.js" -_OBSOLETE_PANELS = { - "wiser_schedules_panel": "wiser-schedules", - "wiser_zigbee_panel": "wiser-zigbee-panel", -} -_PANEL_COMPONENT = re.compile( - r"customElements\.define\(\s*[\"'](wiser-[a-z0-9-]+-panel)[\"']" -) -_LEGACY_CONFIG_OPTIONS = { - "wiser-schedules-panel": CONF_SCHEDULES_PANEL_CONFIG, - "wiser-zigbee-panel": CONF_ZIGBEE_PANEL_CONFIG, -} _PANEL_TABS_CONFIG = "_panel_tabs" @@ -63,36 +49,31 @@ def _panel_title(component): return name.replace("-", " ").title() -def _panel_id(filename): - """Derive a stable panel id from its card bundle.""" - return Path(filename).stem.removeprefix("wiser-").removesuffix("-card") - - -def _stored_config(entry, panel_id, component): - """Return generic settings, with compatibility for existing panels.""" +def _stored_config(entry, panel_id): + """Return settings from the shared container for any panel.""" generic = entry.options.get(CONF_WISER_PANEL_CONFIG, {}) if isinstance(generic, dict) and isinstance(generic.get(panel_id), dict): return dict(generic[panel_id]) - legacy = _LEGACY_CONFIG_OPTIONS.get(component) - return dict(entry.options.get(legacy, {})) if legacy else {} + return {} async def _discover_panels(hass, entries): - """Find panel-capable custom elements in every packaged card bundle.""" + """Find installed panel components from the active frontend registry.""" panels = [] hubs = [hub for hub, _ in entries] - for module in JSMODULES: + for module in get_manifest(hass): + component = module.get("panel") + if not component: + continue filename = module["filename"] path, module_url, _ = await async_card_resource(hass, filename) try: source = await hass.async_add_executor_job(path.read_text, "utf-8") except OSError: continue - match = _PANEL_COMPONENT.search(source) - if not match: + if component not in source: continue - component = match.group(1) - panel_id = _panel_id(filename) + panel_id = module["id"] panels.append( { "id": panel_id, @@ -100,12 +81,13 @@ async def _discover_panels(hass, entries): "component": component, "module_url": module_url, "config": { + "panel_id": panel_id, "hubs": hubs, "hub_ids": { hub: entry.entry_id for hub, entry in entries }, "card_configs": { - hub: _stored_config(entry, panel_id, component) + hub: _stored_config(entry, panel_id) for hub, entry in entries }, "card_url": module_url, @@ -146,10 +128,6 @@ async def _discover_panels(hass, entries): async def async_update_wiser_panel(hass): """Register, refresh, or remove the single Wiser sidebar panel.""" - for state_key, path in _OBSOLETE_PANELS.items(): - if state_key in hass.data: - frontend.async_remove_panel(hass, path) - hass.data.pop(state_key) entries = list(_enabled_entries(hass)) if not entries: if PANEL_STATE in hass.data: @@ -216,62 +194,19 @@ def _is_json_value(value, depth=0): return False -def _save_panel_config(hass, configs, config_option, hub_error, setting_error): - """Validate every hub's card settings before persisting any options.""" - if type(configs) is not dict: - raise ValueError(setting_error) - entries = dict(_enabled_entries(hass)) - updates = [] - for hub, config in configs.items(): - if hub not in entries: - raise ValueError(hub_error) - if type(config) is not dict or not _is_json_value(config): - raise ValueError(setting_error) - settings = { - key: value - for key, value in config.items() - if key not in {"type", "hub", "hubs"} - } - updates.append((entries[hub], settings)) - for entry, settings in updates: - hass.config_entries.async_update_entry( - entry, options={**entry.options, config_option: settings} - ) - - -def save_schedules_panel_config(hass, configs): - """Save Schedule panel settings for each loaded hub.""" - _save_panel_config( - hass, - configs, - CONF_SCHEDULES_PANEL_CONFIG, - "Hub is not available in the Wiser panel", - "Invalid schedule card setting", - ) - - -def save_zigbee_panel_config(hass, configs): - """Save Zigbee panel settings for each loaded hub.""" - _save_panel_config( - hass, - configs, - CONF_ZIGBEE_PANEL_CONFIG, - "Hub is not available in the Wiser panel", - "Invalid Zigbee card setting", - ) - - -def save_rooms_panel_config(hass, configs): - """Save Rooms panel settings under the generic panel registry option.""" +def save_panel_config(hass, panel_id, configs): + """Save settings for any registry-defined panel using the shared option.""" + if panel_id not in {card["id"] for card in get_manifest(hass) if card.get("panel")}: + raise ValueError("Unknown Wiser panel") if type(configs) is not dict: - raise ValueError("Invalid rooms card setting") + raise ValueError("Invalid panel setting") entries = dict(_enabled_entries(hass)) updates = [] for hub, config in configs.items(): if hub not in entries: raise ValueError("Hub is not available in the Wiser panel") if type(config) is not dict or not _is_json_value(config): - raise ValueError("Invalid rooms card setting") + raise ValueError("Invalid panel setting") settings = { key: value for key, value in config.items() @@ -281,7 +216,7 @@ def save_rooms_panel_config(hass, configs): generic = entry.options.get(CONF_WISER_PANEL_CONFIG, {}) if not isinstance(generic, dict): generic = {} - updates.append((entry, {**generic, "rooms": settings})) + updates.append((entry, {**generic, panel_id: settings})) for entry, generic in updates: hass.config_entries.async_update_entry( entry, @@ -294,7 +229,7 @@ def save_wiser_panel_tabs(hass, tabs): if type(tabs) is not list: raise ValueError("Invalid Wiser panel tabs") - known_ids = {_panel_id(module["filename"]) for module in JSMODULES} + known_ids = {module["id"] for module in get_manifest(hass) if module.get("panel")} saved_tabs = [] seen = set() for tab in tabs: diff --git a/custom_components/wiser/strings.json b/custom_components/wiser/strings.json index d217cd35..ed7411b1 100755 --- a/custom_components/wiser/strings.json +++ b/custom_components/wiser/strings.json @@ -223,11 +223,6 @@ "opentherm_notification_title": { "message": "Wiser OpenTherm command" } }, "entity": { - "update": { - "schedule_card": { "name": "Wiser Schedules Card" }, - "zigbee_card": { "name": "Wiser Zigbee Card" }, - "rooms_card": { "name": "Wiser Rooms Card" } - }, "climate": { "heating": { "name": "Heating" diff --git a/custom_components/wiser/translations/de.json b/custom_components/wiser/translations/de.json index a66a179f..6e3c5af3 100644 --- a/custom_components/wiser/translations/de.json +++ b/custom_components/wiser/translations/de.json @@ -223,11 +223,6 @@ "opentherm_notification_title": { "message": "Wiser-OpenTherm-Befehl" } }, "entity": { - "update": { - "schedule_card": { "name": "Wiser-Zeitplankarte" }, - "zigbee_card": { "name": "Wiser-Zigbee-Karte" }, - "rooms_card": { "name": "Wiser-Raumkarte" } - }, "climate": { "heating": { "name": "Heizung" diff --git a/custom_components/wiser/translations/en-GB.json b/custom_components/wiser/translations/en-GB.json index e56148c2..cf0308ef 100644 --- a/custom_components/wiser/translations/en-GB.json +++ b/custom_components/wiser/translations/en-GB.json @@ -223,11 +223,6 @@ "opentherm_notification_title": { "message": "Wiser OpenTherm command" } }, "entity": { - "update": { - "schedule_card": { "name": "Wiser Schedules Card" }, - "zigbee_card": { "name": "Wiser Zigbee Card" }, - "rooms_card": { "name": "Wiser Rooms Card" } - }, "climate": { "heating": { "name": "Heating" diff --git a/custom_components/wiser/translations/en.json b/custom_components/wiser/translations/en.json index 117d467d..33f5208f 100755 --- a/custom_components/wiser/translations/en.json +++ b/custom_components/wiser/translations/en.json @@ -223,11 +223,6 @@ "opentherm_notification_title": { "message": "Wiser OpenTherm command" } }, "entity": { - "update": { - "schedule_card": { "name": "Wiser Schedules Card" }, - "zigbee_card": { "name": "Wiser Zigbee Card" }, - "rooms_card": { "name": "Wiser Rooms Card" } - }, "climate": { "heating": { "name": "Heating" diff --git a/custom_components/wiser/translations/fr.json b/custom_components/wiser/translations/fr.json index 5f7657ed..c6317e60 100644 --- a/custom_components/wiser/translations/fr.json +++ b/custom_components/wiser/translations/fr.json @@ -223,11 +223,6 @@ "opentherm_notification_title": { "message": "Commande OpenTherm Wiser" } }, "entity": { - "update": { - "schedule_card": { "name": "Carte des programmes Wiser" }, - "zigbee_card": { "name": "Carte Zigbee Wiser" }, - "rooms_card": { "name": "Carte des pièces Wiser" } - }, "climate": { "heating": { "name": "Chauffage" diff --git a/custom_components/wiser/update.py b/custom_components/wiser/update.py index 9d4dd4da..de588733 100644 --- a/custom_components/wiser/update.py +++ b/custom_components/wiser/update.py @@ -17,22 +17,16 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.update_coordinator import CoordinatorEntity, DataUpdateCoordinator -from .const import CARD_MANIFEST, DOMAIN +from .const import DOMAIN from .frontend import JSModuleRegistration, async_card_resource from .frontend.card_files import newer_version, prune_card_cache, store_card from .frontend.wiser_sidebar import async_update_wiser_panel +from .frontend.registry import async_refresh_registry, get_manifest _LOGGER = logging.getLogger(__name__) _MANAGER = "wiser_card_updates" _MAX_DOWNLOAD = 20 * 1024 * 1024 _HACS_REPOSITORY_ID = "159080189" -_CARDS = { - card["id"]: (card["repository"], card["filename"], card["component"]) - for card in CARD_MANIFEST -} -_PANEL_COMPONENTS = { - card["id"]: card["panel"] for card in CARD_MANIFEST if card.get("panel") -} def _release_version(tag, allow_prerelease=False): @@ -48,9 +42,9 @@ def _release_version(tag, allow_prerelease=False): return match[1] -def _validate_release(card, release, allow_prerelease=False): +def _validate_release(definition, release, allow_prerelease=False): """Validate release metadata before exposing an installable update.""" - repository, filename, _ = _CARDS[card] + repository, filename = definition["repository"], definition["filename"] if ( release.get("draft") or (release.get("prerelease") and not allow_prerelease) @@ -91,12 +85,12 @@ def _prereleases_enabled(hass): return bool(entity_id and states and states.is_state(entity_id, "on")) -def _select_release(card, releases, allow_prerelease): +def _select_release(definition, releases, allow_prerelease): """Select the highest valid published release allowed by the channel.""" selected = None for metadata in releases: try: - release = _validate_release(card, metadata, allow_prerelease) + release = _validate_release(definition, metadata, allow_prerelease) except (ValueError, KeyError, TypeError): continue if selected is None or newer_version(release["version"], selected["version"]): @@ -106,9 +100,9 @@ def _select_release(card, releases, allow_prerelease): return selected -def _validate_download(card, release, contents): +def _validate_download(definition, release, contents): """Verify the file before changing the currently installed card.""" - _, filename, component = _CARDS[card] + filename, component = definition["filename"], definition["component"] asset = release["asset"] if len(contents) != asset["size"]: raise ValueError("Card download size does not match release metadata") @@ -118,10 +112,12 @@ def _validate_download(card, release, contents): if contents.lstrip().lower().startswith((b"${this.t("common.version")}: ${"3.0.0"}
`', + ) + for source in sources: + with self.subTest(source=source): + expected = f"sha256-{sha256(source.encode()).hexdigest()[:16]}" + self.assertEqual(self.version(source), expected) + + def test_content_hash_is_stable_and_changes_with_content(self): first = self.version('const library="3.3.3"') - self.assertTrue(first.startswith("sha256-")) self.assertEqual(first, self.version('const library="3.3.3"')) self.assertNotEqual(first, self.version('const library="4.0.0"')) def test_missing_file_returns_missing(self): with TemporaryDirectory() as directory: - self.assertEqual(module.card_version(Path(directory) / "missing.js"), "missing") - - def test_explicit_version_marker(self): - self.assertEqual(self.version('/*! WISER-CARD-VERSION wiser-schedule-card 4.0.0-dev.9 */\nconst library="3.3.3";'), "4.0.0-dev.9") - - def test_other_card_marker_is_ignored(self): - self.assertTrue(self.version('/*! WISER-CARD-VERSION wiser-zigbee-card 4.0.0 */').startswith("sha256-")) + self.assertEqual(card_version(Path(directory) / "missing.js"), "missing") diff --git a/tests/test_sidebar_icons.py b/tests/test_sidebar_icons.py index d461e52e..3e35c1ea 100644 --- a/tests/test_sidebar_icons.py +++ b/tests/test_sidebar_icons.py @@ -24,6 +24,7 @@ async def test_icons_register_after_static_path_without_lovelace(self): namespace = { "__file__": str(ROOT / "__init__.py"), "Path": Path, "card_version": version, "add_extra_js_url": register, + "async_load_registry": AsyncMock(), "URL_BASE": "/wiser", "MODE_STORAGE": "storage", } exec(compile(ast.Module(body=[method], type_ignores=[]), str(ROOT / "__init__.py"), "exec"), namespace) diff --git a/tests/test_wiser_sidebar.py b/tests/test_wiser_sidebar.py index b7fd6b09..fd2a42d1 100644 --- a/tests/test_wiser_sidebar.py +++ b/tests/test_wiser_sidebar.py @@ -51,20 +51,20 @@ async def card_resource(_hass, filename): package.async_card_resource = card_resource constants = ModuleType("wiser_sidebar_test.const") for name, value in { - "CONF_SCHEDULES_PANEL_CONFIG": "schedules_panel_config", "CONF_SHOW_WISER_SIDEBAR": "show_wiser_sidebar", "CONF_WISER_PANEL_CONFIG": "wiser_panel_config", - "CONF_ZIGBEE_PANEL_CONFIG": "zigbee_panel_config", "DATA": "data", "DOMAIN": "wiser", "URL_BASE": "/wiser", }.items(): setattr(constants, name, value) - constants.JSMODULES = [ - {"filename": "wiser-schedule-card.js"}, - {"filename": "wiser-zigbee-card.js"}, - {"filename": "wiser-rooms-card.js"}, - ] + constants.CARD_MANIFEST = json.loads( + (Path(__file__).parent / "fixtures/frontend_cards.json").read_text() + ) + + registry = ModuleType("wiser_sidebar_test.frontend.registry") + registry.get_manifest = lambda hass: constants.CARD_MANIFEST + self.manifest = constants.CARD_MANIFEST with patch.dict( sys.modules, @@ -73,12 +73,16 @@ async def card_resource(_hass, filename): "homeassistant.components": components, "wiser_sidebar_test": ModuleType("wiser_sidebar_test"), "wiser_sidebar_test.frontend": package, + "wiser_sidebar_test.frontend.registry": registry, "wiser_sidebar_test.const": constants, }, ): self.sidebar = importlib.import_module( "wiser_sidebar_test.frontend.wiser_sidebar" ) + self.entry_updates = importlib.import_module( + "wiser_sidebar_test.frontend.entry_updates" + ) self.entries = [] self.hass = SimpleNamespace( @@ -107,8 +111,10 @@ async def test_single_option_registers_one_panel_with_discovered_panel_cards(sel "hub-one", { "show_wiser_sidebar": True, - "schedules_panel_config": {"home_screen": "overview"}, - "zigbee_panel_config": {"orientation": "pie"}, + "wiser_panel_config": { + "schedule": {"home_screen": "overview"}, + "zigbee": {"orientation": "pie"}, + }, }, ) self.add_hub("hub-two", {"show_wiser_sidebar": True}) @@ -200,16 +206,6 @@ async def test_unified_setting_can_hide_sidebar(self): await self.sidebar.async_update_wiser_panel(self.hass) self.custom.async_register_panel.assert_not_awaited() - async def test_obsolete_registered_routes_are_removed(self): - self.hass.data["wiser_schedules_panel"] = {} - self.hass.data["wiser_zigbee_panel"] = {} - self.add_hub("hub", {}) - await self.sidebar.async_update_wiser_panel(self.hass) - self.assertEqual( - {call.args[1] for call in self.frontend.async_remove_panel.call_args_list}, - {"wiser-schedules", "wiser-zigbee-panel"}, - ) - async def test_no_enabled_hubs_removes_existing_shared_panel(self): self.hass.data[self.sidebar.PANEL_STATE] = {"panels": []} self.add_hub("hub", {"show_wiser_sidebar": False}) @@ -239,50 +235,83 @@ def test_shell_owns_panel_tabs_and_embeds_each_child_panel(self): def test_new_panel_websocket_commands_are_registered(self): source = (ROOT / "websockets.py").read_text() - self.assertIn( - "async_register_command(hass, websocket_configure_rooms_panel)", - source, - ) + self.assertIn("async_register_command(hass, websocket_configure_panel)", source) + self.assertNotIn("websocket_configure_rooms_panel", source) self.assertIn( "async_register_command(hass, websocket_configure_wiser_panel_tabs)", source, ) - def test_manifest_addition_drives_registration_and_packaging(self): - cards = json.loads((ROOT / "frontend/cards.json").read_text()) - self.assertEqual( - {card["id"] for card in cards}, {"schedule", "zigbee", "rooms"} + async def test_new_registry_panel_is_discovered_and_saves_generic_settings(self): + entry = self.add_hub("hub", {}) + self.manifest.append({ + "id": "new-registry-id", + "filename": "wiser-energy-card.js", "name": "Wiser Energy Card", + "panel": "wiser-energy-panel", + }) + (Path(self.temporary.name) / "wiser-energy-card.js").write_text( + 'customElements.define("wiser-energy-panel", class extends HTMLElement {})' ) + await self.sidebar.async_update_wiser_panel(self.hass) + panels = self.custom.async_register_panel.call_args.kwargs["config"]["panels"] + self.assertEqual(panels[-1]["id"], "new-registry-id") + self.assertEqual(panels[-1]["config"]["panel_id"], "new-registry-id") + self.hass.config_entries.async_update_entry = Mock() + self.sidebar.save_panel_config(self.hass, "new-registry-id", {"hub": {"columns": 3}}) + self.hass.config_entries.async_update_entry.assert_called_once_with( + entry, options={"wiser_panel_config": {"new-registry-id": {"columns": 3}}} + ) + self.sidebar.save_wiser_panel_tabs(self.hass, [{"id": "new-registry-id", "title": "Energy"}]) + self.hass.config_entries.async_update_entry.reset_mock() + with self.assertRaises(ValueError): + self.sidebar.save_panel_config(self.hass, "unknown", {"hub": {}}) + self.hass.config_entries.async_update_entry.assert_not_called() def test_panel_settings_save_without_standalone_sidebar_modules(self): self.add_hub("schedule-hub", {}) self.add_hub("zigbee-hub", {}) self.hass.config_entries.async_update_entry = Mock() - self.sidebar.save_schedules_panel_config( - self.hass, + self.sidebar.save_panel_config( + self.hass, "schedule", {"schedule-hub": {"type": "custom:wiser-schedule-card", "home_screen": "overview"}}, ) - self.sidebar.save_zigbee_panel_config( - self.hass, + self.sidebar.save_panel_config( + self.hass, "zigbee", {"zigbee-hub": {"hub": "zigbee-hub", "orientation": "pie"}}, ) calls = self.hass.config_entries.async_update_entry.call_args_list self.assertEqual( calls[0].kwargs["options"], - {"schedules_panel_config": {"home_screen": "overview"}}, + {"wiser_panel_config": {"schedule": {"home_screen": "overview"}}}, ) self.assertEqual( calls[1].kwargs["options"], - {"zigbee_panel_config": {"orientation": "pie"}}, + {"wiser_panel_config": {"zigbee": {"orientation": "pie"}}}, ) + async def test_all_panel_settings_apply_without_reloading_integration(self): + entry = self.add_hub("hub", {"scan_interval": 30}) + entry.data = {"host": "wiser.local"} + loaded = self.hass.data["wiser"][entry.entry_id] + loaded["reload_settings"] = self.entry_updates.integration_reload_settings(entry) + self.hass.config_entries.async_reload = AsyncMock() + with patch.object(self.entry_updates, "async_update_wiser_panel", AsyncMock()) as refresh: + for panel_id in ("schedule", "zigbee", "rooms", "future-panel"): + entry.options["wiser_panel_config"] = {panel_id: {"columns": 3}} + await self.entry_updates.async_handle_entry_update(self.hass, entry) + self.assertEqual(refresh.await_count, 4) + self.hass.config_entries.async_reload.assert_not_awaited() + entry.options["scan_interval"] = 60 + await self.entry_updates.async_handle_entry_update(self.hass, entry) + self.hass.config_entries.async_reload.assert_awaited_once_with(entry.entry_id) + def test_invalid_panel_settings_do_not_partially_save(self): self.add_hub("first", {}) self.add_hub("second", {}) self.hass.config_entries.async_update_entry = Mock() with self.assertRaises(ValueError): - self.sidebar.save_schedules_panel_config( - self.hass, + self.sidebar.save_panel_config( + self.hass, "schedule", {"first": {"home_screen": "overview"}, "second": {"bad": float("nan")}}, ) self.hass.config_entries.async_update_entry.assert_not_called() @@ -293,8 +322,8 @@ def test_rooms_panel_settings_use_generic_registry_and_drop_hub_filter(self): {"wiser_panel_config": {"future": {"enabled": True}}}, ) self.hass.config_entries.async_update_entry = Mock() - self.sidebar.save_rooms_panel_config( - self.hass, + self.sidebar.save_panel_config( + self.hass, "rooms", { "hub": { "type": "custom:wiser-rooms-card", diff --git a/tests/test_zigbee_version.py b/tests/test_zigbee_version.py deleted file mode 100644 index 6854e166..00000000 --- a/tests/test_zigbee_version.py +++ /dev/null @@ -1,56 +0,0 @@ -"""Version detection for installed Zigbee card bundles.""" -import importlib.util -from pathlib import Path -from tempfile import TemporaryDirectory -import unittest -import re - -ROOT = Path(__file__).resolve().parents[1] -# Test the pure reader from the registration module without loading HA. -import ast -from hashlib import sha256 -import re -from types import SimpleNamespace -source = (ROOT / "custom_components/wiser/frontend/__init__.py").read_text() -reader = next(node for node in ast.parse(source).body if isinstance(node, ast.FunctionDef) and node.name == "card_version") -namespace = {"Path": Path, "sha256": sha256, "re": re} -exec(compile(ast.Module(body=[reader], type_ignores=[]), "frontend/__init__.py", "exec"), namespace) -module = SimpleNamespace(card_version=namespace["card_version"]) - - -class ZigbeeCardVersionTest(unittest.TestCase): - def version(self, source): - with TemporaryDirectory() as directory: - path = Path(directory) / "wiser-zigbee-card.js" - path.write_text(source) - return module.card_version(path) - - def test_unknown_build_uses_stable_content_hash(self): - first = self.version('const library="3.3.3"') - self.assertTrue(first.startswith("sha256-")) - self.assertEqual(first, self.version('const library="3.3.3"')) - self.assertNotEqual(first, self.version('const library="4.0.0"')) - - def test_missing_file_returns_missing(self): - with TemporaryDirectory() as directory: - self.assertEqual(module.card_version(Path(directory) / "missing.js"), "missing") - - def test_zigbee_banner_ignores_library_versions(self): - self.assertEqual(self.version('const library="3.3.3";const $t="2.1.2";console.info(`WISER-ZIGBEE-NETWORK-CARD ${Zt("common.version")} ${$t}`)'), "2.1.2") - - def test_zigbee_dev_version(self): - self.assertEqual(self.version('const cardBuild="3.0.0-dev.7";console.info(`WISER-ZIGBEE-CARD ${translate("common.version")} ${cardBuild}`)'), "3.0.0-dev.7") - - def test_modern_editor_footer_with_inlined_version(self): - source = 'const library="3.3.3";html`
${this.t("common.version")}: ${"3.0.0-dev.65"}
`' - self.assertEqual(self.version(source), "3.0.0-dev.65") - - def test_modern_release_footer(self): - source = 'html`
${this.t("common.version")}: ${"3.0.0"}
`' - self.assertEqual(self.version(source), "3.0.0") - - def test_explicit_version_marker(self): - self.assertEqual(self.version('/*! WISER-CARD-VERSION wiser-zigbee-card 4.0.0-dev.9 */\nconst library="3.3.3";'), "4.0.0-dev.9") - - def test_other_card_marker_is_ignored(self): - self.assertTrue(self.version('/*! WISER-CARD-VERSION wiser-schedule-card 4.0.0 */').startswith("sha256-")) From 8afb70a37900eaa8ddac480c165b414180f280f1 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Wed, 30 Sep 2026 18:48:52 +0100 Subject: [PATCH 047/154] Add independently updateable frontend registry --- custom_components/wiser/const.py | 3 +- custom_components/wiser/frontend/__init__.py | 105 +++++--- custom_components/wiser/frontend/manifest.py | 32 ++- custom_components/wiser/frontend/registry.py | 260 ++++++++++++++----- custom_components/wiser/update.py | 143 +++++++++- scripts/build.py | 2 +- scripts/fetch_card_releases.py | 9 +- tests/test_build.py | 18 +- tests/test_card_updates.py | 188 ++++++++++++-- 9 files changed, 617 insertions(+), 143 deletions(-) diff --git a/custom_components/wiser/const.py b/custom_components/wiser/const.py index 93f5a81a..2af6928e 100755 --- a/custom_components/wiser/const.py +++ b/custom_components/wiser/const.py @@ -21,9 +21,10 @@ def _load_card_manifest(): """Load the shared card registry used by packaging and runtime setup.""" try: - return json.loads( + registry = json.loads( (Path(__file__).parent / "frontend/cards.json").read_text("utf-8") ) + return registry.get("cards", []) if isinstance(registry, dict) else registry except FileNotFoundError: # Source checkouts have no card definitions; builds inject the registry. return [] diff --git a/custom_components/wiser/frontend/__init__.py b/custom_components/wiser/frontend/__init__.py index 31bbaac7..f333eb3d 100644 --- a/custom_components/wiser/frontend/__init__.py +++ b/custom_components/wiser/frontend/__init__.py @@ -1,10 +1,11 @@ """Register Wiser frontend resources and independently updated card bundles.""" +import asyncio from hashlib import sha256 -import re import logging import os from pathlib import Path +import re from urllib.parse import parse_qs, urlsplit from homeassistant.components.frontend import add_extra_js_url @@ -117,6 +118,12 @@ async def _check_lovelace_resources_loaded(now): async def _async_register_modules(self): """Register modules if not already registered.""" + lock = self.hass.data.setdefault("wiser_card_resource_lock", asyncio.Lock()) + async with lock: + await self._async_register_modules_locked() + + async def _async_register_modules_locked(self): + """Register modules while holding the shared resource lock.""" _LOGGER.debug("Installing javascript modules") # Get resources already registered @@ -128,47 +135,68 @@ async def _async_register_modules(self): for module in get_manifest(self.hass): url = f"{URL_BASE}/{module.get('filename')}" + filenames = [module["filename"], *module.get("legacy_filenames", [])] _, active_url, version = await async_card_resource(self.hass, module["filename"]) if version == "missing": # Newly discovered cards become resources only after installation. continue - card_registered = False - - for resource in resources: + matching_resources = [ + resource + for resource in resources if ( - self._get_resource_path(resource["url"]) == url - or self._get_resource_path(resource["url"]).startswith( - f"{CARD_CACHE_URL}/{Path(module['filename']).stem}-" - ) - ): - card_registered = True - # check version - if resource["url"] != active_url: - # Update card version - _LOGGER.debug( - "Updating %s to version %s", - module.get("name"), - version, - ) - await self.lovelace.resources.async_update_item( - resource.get("id"), - { - "res_type": "module", - "url": active_url, - }, - ) - # Remove old gzipped files - await self.async_remove_gzip_files() - else: - _LOGGER.debug( - "%s already registered as version %s", - module.get("name"), - version, + self._get_resource_path(resource["url"]) + in {f"{URL_BASE}/{filename}" for filename in filenames} + or any( + self._get_resource_path(resource["url"]).startswith( + f"{CARD_CACHE_URL}/{Path(filename).stem}-" ) + for filename in filenames + ) + ) + ] - if not card_registered: + if matching_resources: + # Prefer the most recently listed active resource, otherwise + # migrate the most recently listed legacy resource in place. + active_resources = [ + resource + for resource in matching_resources + if resource["url"] == active_url + ] + retained = (active_resources or matching_resources)[-1] + + if retained["url"] != active_url: + _LOGGER.debug( + "Updating %s to version %s", + module.get("name"), + version, + ) + await self.lovelace.resources.async_update_item( + retained.get("id"), + {"res_type": "module", "url": active_url}, + ) + await self.async_remove_gzip_files() + else: + _LOGGER.debug( + "%s already registered as version %s", + module.get("name"), + version, + ) + + for duplicate in matching_resources: + if duplicate is retained: + continue + _LOGGER.debug( + "Removing duplicate %s resource %s", + module.get("name"), + duplicate.get("id"), + ) + await self.lovelace.resources.async_delete_item( + duplicate.get("id") + ) + else: _LOGGER.debug( "Registering %s as version %s", module.get("name"), @@ -188,13 +216,16 @@ async def async_unregister(self): """Unload lovelace module resource.""" if self.resource_mode == MODE_STORAGE: for module in get_manifest(self.hass): - url = f"{URL_BASE}/{module.get('filename')}" + filenames = [module["filename"], *module.get("legacy_filenames", [])] wiser_resources = [ resource for resource in self.lovelace.resources.async_items() - if str(resource["url"]).startswith(url) - or str(resource["url"]).startswith( - f"{CARD_CACHE_URL}/{Path(module['filename']).stem}-" + if any( + str(resource["url"]).startswith(f"{URL_BASE}/{filename}") + or str(resource["url"]).startswith( + f"{CARD_CACHE_URL}/{Path(filename).stem}-" + ) + for filename in filenames ) ] for resource in wiser_resources: diff --git a/custom_components/wiser/frontend/manifest.py b/custom_components/wiser/frontend/manifest.py index 00a171df..093f0654 100644 --- a/custom_components/wiser/frontend/manifest.py +++ b/custom_components/wiser/frontend/manifest.py @@ -3,6 +3,20 @@ import re +REGISTRY_SCHEMA_VERSION = 1 + + +def validate_registry(value): + """Validate the versioned registry while accepting legacy card arrays.""" + if isinstance(value, list): + return validate_manifest(value) + if not isinstance(value, dict): + raise ValueError("Invalid frontend registry document") + if value.get("schema_version") != REGISTRY_SCHEMA_VERSION: + raise ValueError("Unsupported frontend registry schema version") + return validate_manifest(value.get("cards")) + + def validate_manifest(value): """Validate names and paths before using a remotely supplied registry.""" if not isinstance(value, list) or not 1 <= len(value) <= 100: @@ -32,7 +46,19 @@ def validate_manifest(value): if item in seen[key]: raise ValueError(f"Duplicate frontend card {key}") seen[key].add(item) - result.append({key: card.get(key) for key in ("name", *patterns)}) + legacy_filenames = card.get("legacy_filenames", []) + if not isinstance(legacy_filenames, list): + raise ValueError("Invalid frontend card legacy filenames") + for filename in legacy_filenames: + if ( + not isinstance(filename, str) + or not re.fullmatch(patterns["filename"], filename) + or filename in seen["filename"] + ): + raise ValueError("Invalid or duplicate frontend legacy filename") + seen["filename"].add(filename) + definition = {key: card.get(key) for key in ("name", *patterns)} + if legacy_filenames: + definition["legacy_filenames"] = legacy_filenames + result.append(definition) return result - - diff --git a/custom_components/wiser/frontend/registry.py b/custom_components/wiser/frontend/registry.py index 7e99cd0a..ec719250 100644 --- a/custom_components/wiser/frontend/registry.py +++ b/custom_components/wiser/frontend/registry.py @@ -4,19 +4,22 @@ import json import logging from pathlib import Path +import re from urllib.parse import urlsplit import aiohttp from homeassistant.helpers.aiohttp_client import async_get_clientsession from ..const import CARD_MANIFEST -from .card_files import _atomic_write -from .manifest import validate_manifest +from .card_files import _atomic_write, newer_version +from .manifest import REGISTRY_SCHEMA_VERSION, validate_manifest, validate_registry _LOGGER = logging.getLogger(__name__) REGISTRY_REPOSITORY = "andyblac/WiserFrontendPanelConfig" REGISTRY_CACHE = ".storage/wiser_cards/registry.json" +REGISTRY_RELEASE_CACHE = ".storage/wiser_cards/registry-release.json" REGISTRY_DATA = "wiser_frontend_registry" +REGISTRY_VERSION_DATA = "wiser_frontend_registry_version" _MAX_SIZE = 256 * 1024 @@ -26,91 +29,210 @@ def get_manifest(hass): def _merge_manifest(current, incoming): - """Keep installed cards when a release omits them; preserve their identities.""" + """Keep omitted cards while allowing the registry to update known cards.""" merged = {card["id"]: card for card in current} for card in incoming: - previous = merged.get(card["id"]) - if previous and any( - previous[key] != card[key] for key in ("filename", "repository", "component", "panel") - ): - raise ValueError(f"Registry changes the identity of {card['id']}") merged[card["id"]] = card return validate_manifest(list(merged.values())) +def _bundled_version(): + """Return the registry release bundled by the integration build.""" + try: + record = json.loads( + (Path(__file__).parent / "panel-config-release.json").read_text() + ) + tag = record.get("tag") or record.get("version") + return _release_version(tag) if tag else "0.0.0" + except (OSError, ValueError, TypeError, KeyError): + return "0.0.0" + + def _load_cached(config_dir): try: - cached = validate_manifest(json.loads((Path(config_dir) / REGISTRY_CACHE).read_text())) - return _merge_manifest(CARD_MANIFEST, cached) + cached = validate_registry(json.loads((Path(config_dir) / REGISTRY_CACHE).read_text())) + manifest = _merge_manifest(CARD_MANIFEST, cached) + except (OSError, ValueError, TypeError, KeyError): + return CARD_MANIFEST, _bundled_version() + try: + release = json.loads( + (Path(config_dir) / REGISTRY_RELEASE_CACHE).read_text() + ) + version = _release_version(release["version"], allow_prerelease=True) except (OSError, ValueError, TypeError, KeyError): - return CARD_MANIFEST + version = _bundled_version() + return manifest, version async def async_load_registry(hass): """Load the last valid registry without needing a network connection.""" if REGISTRY_DATA not in hass.data: - manifest = await hass.async_add_executor_job(_load_cached, hass.config.path()) + manifest, version = await hass.async_add_executor_job( + _load_cached, hass.config.path() + ) hass.data.setdefault(REGISTRY_DATA, manifest) + hass.data.setdefault(REGISTRY_VERSION_DATA, version) return get_manifest(hass) -def _store_registry(config_dir, manifest): +def get_registry_version(hass): + """Return the installed registry release version.""" + version = hass.data.get(REGISTRY_VERSION_DATA) + return version if version is not None else _bundled_version() + + +def _store_registry(config_dir, manifest, version): + document = json.dumps( + {"schema_version": REGISTRY_SCHEMA_VERSION, "cards": manifest} + ).encode() + integration = Path(config_dir) / "custom_components/wiser/frontend" + integration.mkdir(parents=True, exist_ok=True) + _atomic_write(integration / "cards.json", document) + _atomic_write( + integration / "panel-config-release.json", + json.dumps( + { + "repository": REGISTRY_REPOSITORY, + "source": "runtime-update", + "asset": "cards.json", + "version": version, + } + ).encode(), + ) path = Path(config_dir) / REGISTRY_CACHE path.parent.mkdir(parents=True, exist_ok=True) - _atomic_write(path, json.dumps(manifest).encode()) - - -async def async_refresh_registry(hass, allow_prerelease=False): - """Check published registry releases, retaining the last good copy on failure.""" + _atomic_write( + path, + document, + ) + _atomic_write( + Path(config_dir) / REGISTRY_RELEASE_CACHE, + json.dumps({"version": version}).encode(), + ) + + +def _release_version(tag, allow_prerelease=False): + """Validate a registry release tag for the selected update channel.""" + if not isinstance(tag, str): + raise ValueError("Invalid frontend registry release version") + value = tag.removeprefix("v") + if not re.fullmatch( + r"\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?", value + ): + raise ValueError("Invalid frontend registry release version") + if "-" in value.split("+", 1)[0] and not allow_prerelease: + raise ValueError("Frontend registry prerelease is not enabled") + return value + + +def _validate_release(metadata, allow_prerelease=False): + """Validate registry release metadata without downloading its asset.""" + if ( + not isinstance(metadata, dict) + or metadata.get("draft") + or not metadata.get("published_at") + or (metadata.get("prerelease") and not allow_prerelease) + ): + raise ValueError("Expected a published frontend registry release") + version = _release_version(metadata["tag_name"], allow_prerelease) + if not isinstance(metadata.get("assets"), list): + raise ValueError("Invalid frontend registry release assets") + assets = [ + asset + for asset in metadata["assets"] + if isinstance(asset, dict) + and asset.get("name") == "cards.json" + and asset.get("state") == "uploaded" + ] + if len(assets) != 1: + raise ValueError("Registry release must contain one cards.json asset") + asset = assets[0] + if ( + not isinstance(asset.get("browser_download_url"), str) + or type(asset.get("size")) is not int + ): + raise ValueError("Invalid frontend registry asset metadata") + url = urlsplit(asset["browser_download_url"]) + if ( + url.scheme != "https" + or url.netloc != "github.com" + or not url.path.startswith(f"/{REGISTRY_REPOSITORY}/releases/download/") + or not 0 < asset["size"] <= _MAX_SIZE + ): + raise ValueError("Invalid frontend registry asset") + return { + "version": version, + "asset": asset, + "release_url": ( + f"https://github.com/{REGISTRY_REPOSITORY}/releases/tag/" + f"{metadata['tag_name']}" + ), + } + + +def _select_release(releases, allow_prerelease): + """Select the highest valid registry release allowed by the channel.""" + selected = None + for metadata in releases: + try: + release = _validate_release(metadata, allow_prerelease) + except (ValueError, KeyError, TypeError): + continue + if selected is None or newer_version(release["version"], selected["version"]): + selected = release + if selected is None: + raise ValueError("No verified frontend registry release is available") + return selected + + +async def async_check_registry_release(hass, allow_prerelease=False): + """Check the latest registry release without changing installed config.""" await async_load_registry(hass) - try: - session = async_get_clientsession(hass) - endpoint = "releases?per_page=100" if allow_prerelease else "releases/latest" - async with session.get( - f"https://api.github.com/repos/{REGISTRY_REPOSITORY}/{endpoint}", - headers={"Accept": "application/vnd.github+json", "User-Agent": "Wiser-Home-Assistant"}, - timeout=aiohttp.ClientTimeout(total=20), - ) as response: - response.raise_for_status() - metadata = await response.json() - releases = metadata if isinstance(metadata, list) else [metadata] - releases = [item for item in releases if isinstance(item, dict) - and not item.get("draft") and item.get("published_at") - and (allow_prerelease or not item.get("prerelease"))] - if not releases: - raise ValueError("No published frontend registry release") - release = max(releases, key=lambda item: item["published_at"]) - if not isinstance(release.get("assets"), list): - raise ValueError("Invalid frontend registry release assets") - assets = [asset for asset in release["assets"] - if isinstance(asset, dict) and asset.get("name") == "cards.json" - and asset.get("state") == "uploaded"] - if len(assets) != 1: - raise ValueError("Registry release must contain one cards.json asset") - asset = assets[0] - if not isinstance(asset.get("browser_download_url"), str) or type(asset.get("size")) is not int: - raise ValueError("Invalid frontend registry asset metadata") - url = urlsplit(asset["browser_download_url"]) - if (url.scheme != "https" or url.netloc != "github.com" - or not url.path.startswith(f"/{REGISTRY_REPOSITORY}/releases/download/") - or not 0 < asset["size"] <= _MAX_SIZE): - raise ValueError("Invalid frontend registry asset") - async with session.get( - asset["browser_download_url"], timeout=aiohttp.ClientTimeout(total=20) - ) as response: - response.raise_for_status() - contents = bytearray() - async for chunk in response.content.iter_chunked(65536): - contents.extend(chunk) - if len(contents) > _MAX_SIZE: - raise ValueError("Frontend registry is too large") - if len(contents) != asset["size"]: - raise ValueError("Frontend registry size mismatch") - if asset.get("digest") and asset["digest"] != "sha256:" + sha256(contents).hexdigest(): - raise ValueError("Frontend registry checksum mismatch") - manifest = _merge_manifest(get_manifest(hass), validate_manifest(json.loads(contents))) - await hass.async_add_executor_job(_store_registry, hass.config.path(), manifest) - hass.data[REGISTRY_DATA] = manifest - except (aiohttp.ClientError, TimeoutError, OSError, ValueError, TypeError, KeyError) as err: - _LOGGER.warning("Unable to refresh Wiser frontend registry; keeping cached cards: %s", err) - return get_manifest(hass) + session = async_get_clientsession(hass) + endpoint = "releases?per_page=100" if allow_prerelease else "releases/latest" + async with session.get( + f"https://api.github.com/repos/{REGISTRY_REPOSITORY}/{endpoint}", + headers={ + "Accept": "application/vnd.github+json", + "User-Agent": "Wiser-Home-Assistant", + }, + timeout=aiohttp.ClientTimeout(total=20), + ) as response: + response.raise_for_status() + metadata = await response.json() + return ( + _select_release(metadata, True) + if allow_prerelease + else _validate_release(metadata) + ) + + +async def async_install_registry_release(hass, release): + """Download, verify, and atomically activate the offered registry release.""" + session = async_get_clientsession(hass) + asset = release["asset"] + async with session.get( + asset["browser_download_url"], timeout=aiohttp.ClientTimeout(total=20) + ) as response: + response.raise_for_status() + contents = bytearray() + async for chunk in response.content.iter_chunked(65536): + contents.extend(chunk) + if len(contents) > _MAX_SIZE: + raise ValueError("Frontend registry is too large") + if len(contents) != asset["size"]: + raise ValueError("Frontend registry size mismatch") + if ( + asset.get("digest") + and asset["digest"] != "sha256:" + sha256(contents).hexdigest() + ): + raise ValueError("Frontend registry checksum mismatch") + manifest = _merge_manifest( + get_manifest(hass), validate_registry(json.loads(contents)) + ) + await hass.async_add_executor_job( + _store_registry, hass.config.path(), manifest, release["version"] + ) + hass.data[REGISTRY_DATA] = manifest + hass.data[REGISTRY_VERSION_DATA] = release["version"] + return manifest diff --git a/custom_components/wiser/update.py b/custom_components/wiser/update.py index de588733..0dd796f7 100644 --- a/custom_components/wiser/update.py +++ b/custom_components/wiser/update.py @@ -1,4 +1,4 @@ -"""Offer independent, manually installed updates for the shared frontend cards.""" +"""Offer independent, manually installed Wiser frontend updates.""" from __future__ import annotations @@ -21,12 +21,19 @@ from .frontend import JSModuleRegistration, async_card_resource from .frontend.card_files import newer_version, prune_card_cache, store_card from .frontend.wiser_sidebar import async_update_wiser_panel -from .frontend.registry import async_refresh_registry, get_manifest +from .frontend.registry import ( + async_check_registry_release, + async_install_registry_release, + async_load_registry, + get_manifest, + get_registry_version, +) _LOGGER = logging.getLogger(__name__) _MANAGER = "wiser_card_updates" _MAX_DOWNLOAD = 20 * 1024 * 1024 _HACS_REPOSITORY_ID = "159080189" +_REGISTRY = "_registry" def _release_version(tag, allow_prerelease=False): @@ -173,11 +180,13 @@ def __init__(self, hass): self.data = {} self.cards = {card["id"]: card for card in get_manifest(hass)} self.added_cards = set() + self.registry_added = False def add_entities(self, entry_id): """Transfer registry ownership before attaching the shared entities.""" self.owner = entry_id self.added_cards = set() + self.registry_added = False self._add_discovered_entities() def _add_discovered_entities(self): @@ -186,26 +195,58 @@ def _add_discovered_entities(self): return registry = er.async_get(self.hass) cards = self.cards.keys() - self.added_cards + entities = [] + if not self.registry_added: + entity_id = registry.async_get_entity_id( + "update", DOMAIN, "wiser_frontend_registry_update" + ) + if entity_id: + registry.async_update_entity(entity_id, config_entry_id=self.owner) + entities.append(WiserFrontendRegistryUpdate(self)) + self.registry_added = True for card in sorted(cards): entity_id = registry.async_get_entity_id("update", DOMAIN, f"wiser_{card}_card_update") if entity_id: registry.async_update_entity(entity_id, config_entry_id=self.owner) - if cards: - self.entries[self.owner]([WiserCardUpdate(self, card) for card in sorted(cards)]) + entities.extend(WiserCardUpdate(self, card) for card in sorted(cards)) + if entities: + self.entries[self.owner](entities) self.added_cards.update(cards) async def _async_update_data(self): async with self.install_lock: - manifest = await async_refresh_registry(self.hass, _prereleases_enabled(self.hass)) + await async_load_registry(self.hass) + registry = await self._check_registry() + manifest = get_manifest(self.hass) self.cards = {card["id"]: card for card in manifest} results = await asyncio.gather(*(self._check_card(card) for card in self.cards)) self._add_discovered_entities() - return dict(zip(self.cards, results)) + return {_REGISTRY: registry, **dict(zip(self.cards, results))} + + async def _check_registry(self): + """Check registry releases without silently installing them.""" + installed = get_registry_version(self.hass) + try: + release = await async_check_registry_release( + self.hass, _prereleases_enabled(self.hass) + ) + return {"installed": installed, "release": release, "error": None} + except (aiohttp.ClientError, TimeoutError, ValueError, KeyError, TypeError) as err: + _LOGGER.warning("Unable to check Wiser frontend registry releases: %s", err) + return {"installed": installed, "release": None, "error": str(err)} async def _check_card(self, card): definition = self.cards[card] repository, filename = definition["repository"], definition["filename"] _, _, installed = await async_card_resource(self.hass, filename) + if installed == "missing": + for legacy_filename in definition.get("legacy_filenames", []): + _, _, legacy_version = await async_card_resource( + self.hass, legacy_filename + ) + if legacy_version != "missing": + installed = legacy_version + break if card in self.pending_refresh: installed = self.pending_refresh[card][0] try: @@ -289,6 +330,89 @@ async def install(self, card): self.installing.discard(card) self.async_update_listeners() + async def install_registry(self): + """Install the offered frontend registry after an explicit update action.""" + async with self.install_lock: + state = self.data.get(_REGISTRY, {}) + release = state.get("release") + if not release: + raise HomeAssistantError( + "No verified frontend registry release is available" + ) + if not newer_version( + release["version"], state.get("installed", "0.0.0") + ): + return + self.installing.add(_REGISTRY) + self.async_update_listeners() + try: + manifest = await async_install_registry_release(self.hass, release) + self.cards = {card["id"]: card for card in manifest} + state["installed"] = release["version"] + results = await asyncio.gather( + *(self._check_card(card) for card in self.cards) + ) + self.data.update(dict(zip(self.cards, results))) + self._add_discovered_entities() + except ( + aiohttp.ClientError, + TimeoutError, + OSError, + ValueError, + RuntimeError, + ) as err: + raise HomeAssistantError( + f"Unable to install frontend registry update: {err}" + ) from err + finally: + self.installing.discard(_REGISTRY) + self.async_update_listeners() + + +class WiserFrontendRegistryUpdate(CoordinatorEntity, UpdateEntity): + """A user-installed update for WiserFrontendPanelConfig.""" + + _attr_supported_features = UpdateEntityFeature.INSTALL + _attr_entity_category = EntityCategory.CONFIG + _attr_has_entity_name = True + _attr_name = "Wiser Frontend Panel Config" + _attr_unique_id = "wiser_frontend_registry_update" + _attr_release_summary = ( + "Updates the card and panel definitions used by the Wiser integration." + ) + + @property + def available(self): + return ( + super().available + and self.coordinator.data.get(_REGISTRY, {}).get("release") is not None + ) + + @property + def installed_version(self): + return self.coordinator.data.get(_REGISTRY, {}).get("installed") + + @property + def latest_version(self): + release = self.coordinator.data.get(_REGISTRY, {}).get("release") + return release["version"] if release else None + + @property + def release_url(self): + release = self.coordinator.data.get(_REGISTRY, {}).get("release") + return release["release_url"] if release else None + + @property + def in_progress(self): + return _REGISTRY in self.coordinator.installing + + def version_is_newer(self, latest_version, installed_version): + return newer_version(latest_version, installed_version) + + async def async_install(self, version, backup, **kwargs): + """Install only after an explicit Home Assistant update action.""" + await self.coordinator.install_registry() + class WiserCardUpdate(CoordinatorEntity, UpdateEntity): """A user-installed frontend card update, separate from hub firmware.""" @@ -302,8 +426,11 @@ def __init__(self, coordinator, card): super().__init__(coordinator) self.card = card self._attr_unique_id = f"wiser_{card}_card_update" - # Registry-defined cards must not require new integration translations. - self._attr_name = coordinator.cards[card]["name"] + + @property + def name(self): + """Follow registry name changes without recreating the update entity.""" + return self.coordinator.cards[self.card]["name"] @property def available(self): diff --git a/scripts/build.py b/scripts/build.py index 267f3bfe..332ee253 100644 --- a/scripts/build.py +++ b/scripts/build.py @@ -45,7 +45,7 @@ def build( repository=panel_config_repository, ) (staging / "frontend/cards.json").write_text( - json.dumps(manifest, indent=2) + "\n" + json.dumps({"schema_version": 1, "cards": manifest}, indent=2) + "\n" ) definitions = {card["id"]: card for card in manifest} selected_repositories = select_repositories(definitions, repositories or {}) diff --git a/scripts/fetch_card_releases.py b/scripts/fetch_card_releases.py index 633783ef..0cb80c33 100644 --- a/scripts/fetch_card_releases.py +++ b/scripts/fetch_card_releases.py @@ -25,6 +25,7 @@ _MANIFEST = importlib.util.module_from_spec(_SPEC) _SPEC.loader.exec_module(_MANIFEST) validate_card_manifest = _MANIFEST.validate_manifest +validate_registry = _MANIFEST.validate_registry def fetch_panel_config( @@ -41,6 +42,10 @@ def fetch_panel_config( ) if local is not None and local.is_file(): contents = local.read_bytes() + build_info = local.with_name("build-info.json") + version = None + if build_info.is_file(): + version = json.loads(build_info.read_text()).get("version") record = { "repository": repository, "source": "local", @@ -48,6 +53,8 @@ def fetch_panel_config( "path": str(local.resolve()), "digest": "sha256:" + sha256(contents).hexdigest(), } + if version: + record["version"] = version else: selected = select_release(list_releases(repository), channel) asset = select_asset(selected, PANEL_CONFIG_FILENAME) @@ -66,7 +73,7 @@ def fetch_panel_config( manifest = json.loads(contents) except (TypeError, json.JSONDecodeError) as error: raise ValueError("Invalid cards.json") from error - return validate_card_manifest(manifest), record + return validate_registry(manifest), record def list_releases(repository): diff --git a/tests/test_build.py b/tests/test_build.py index 08f706ab..8cf3c272 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -41,6 +41,9 @@ def setUp(self): registry.write_text( json.dumps(CARD_MANIFEST), encoding="utf-8" ) + registry.with_name("build-info.json").write_text( + json.dumps({"version": "1.0.1"}), encoding="utf-8" + ) for card, panel in (("schedule", "schedules"), ("zigbee", "zigbee")): (frontend / f"{panel}_sidebar.py").touch() (frontend / f"wiser-{card}-card.js").write_bytes(b"old tracked bundle") @@ -72,6 +75,14 @@ def test_local_bundles_win_without_network_and_tracked_files_are_untouched(self) b"old tracked bundle", ) self.assertEqual(json.loads(archive.read("frontend/card-releases.json")), report) + self.assertEqual( + json.loads(archive.read("frontend/cards.json")), + {"schema_version": 1, "cards": CARD_MANIFEST}, + ) + self.assertEqual( + json.loads(archive.read("frontend/panel-config-release.json"))["version"], + "1.0.1", + ) self.assertFalse(any("__pycache__" in name for name in archive.namelist())) def test_missing_local_bundle_falls_back_independently(self): @@ -116,7 +127,10 @@ def test_external_registry_alone_adds_an_unknown_card_and_repository(self): releases.assert_not_called() self.assertEqual(report[-1]["repository"], "example/monitoring") with ZipFile(self.output) as archive: - self.assertEqual(json.loads(archive.read("frontend/cards.json")), manifest) + self.assertEqual( + json.loads(archive.read("frontend/cards.json")), + {"schema_version": 1, "cards": manifest}, + ) self.assertEqual(archive.read("frontend/wiser-electricity-card.js"), bundle.read_bytes()) def test_build_rejects_bundle_using_removed_settings_endpoint(self): @@ -177,7 +191,7 @@ def test_release_builds_ignore_local_bundles_for_both_channels(self): ) self.assertEqual( json.loads(archive.read("frontend/cards.json")), - CARD_MANIFEST, + {"schema_version": 1, "cards": CARD_MANIFEST}, ) self.assertEqual( json.loads(archive.read("frontend/panel-config-release.json"))["source"], diff --git a/tests/test_card_updates.py b/tests/test_card_updates.py index 51f54ad0..b1b6ca39 100644 --- a/tests/test_card_updates.py +++ b/tests/test_card_updates.py @@ -101,8 +101,16 @@ async def resource(hass, filename): ) self.coordinator = self.updates.CardUpdateCoordinator(self.hass) self.manifest = list(self.coordinator.cards.values()) - self.updates.async_refresh_registry = AsyncMock( - side_effect=lambda hass, _prerelease: self.updates.get_manifest(hass) + self.updates.async_load_registry = AsyncMock( + side_effect=lambda hass: self.updates.get_manifest(hass) + ) + self.updates.get_registry_version = Mock(return_value="1.0.0") + self.updates.async_check_registry_release = AsyncMock( + return_value={ + "version": "1.0.0", + "asset": {}, + "release_url": "https://github.com/andyblac/WiserFrontendPanelConfig/releases/tag/v1.0.0", + } ) def payload(self, card="zigbee", version="2.0.0"): @@ -149,6 +157,7 @@ def registry_response(self, manifest): contents = json.dumps(manifest).encode() registry = sys.modules["card_update_test.frontend.registry"] release = { + "tag_name": "v1.0.0", "published_at": "2026-09-29", "draft": False, "prerelease": False, "assets": [{"name": "cards.json", "state": "uploaded", "size": len(contents), "digest": "sha256:" + sha256(contents).hexdigest(), @@ -159,44 +168,73 @@ def registry_response(self, manifest): async def test_runtime_registry_adds_card_and_survives_restart_offline(self): registry = self.registry_response([*self.manifest, self.extra_card()]) - manifest = await registry.async_refresh_registry(self.hass) + release = await registry.async_check_registry_release(self.hass) + manifest = await registry.async_install_registry_release(self.hass, release) self.assertEqual(manifest[-1], self.extra_card()) + installed = self.directory / "custom_components/wiser/frontend" + self.assertEqual( + json.loads((installed / "cards.json").read_text())["cards"], manifest + ) + self.assertEqual( + json.loads((installed / "panel-config-release.json").read_text())[ + "version" + ], + "1.0.0", + ) self.hass.data.clear() restored = await registry.async_load_registry(self.hass) self.assertEqual(restored, manifest) import aiohttp self.session.get.side_effect = aiohttp.ClientError("offline") - with self.assertLogs(registry.__name__, level="WARNING"): - self.assertEqual(await registry.async_refresh_registry(self.hass), manifest) + with self.assertRaises(aiohttp.ClientError): + await registry.async_check_registry_release(self.hass) + + async def test_loaded_registry_version_does_not_read_bundled_metadata(self): + registry = sys.modules["card_update_test.frontend.registry"] + self.hass.data[registry.REGISTRY_VERSION_DATA] = "1.0.2" + with patch.object( + registry, "_bundled_version", side_effect=AssertionError("file read") + ): + self.assertEqual(registry.get_registry_version(self.hass), "1.0.2") async def test_invalid_registry_does_not_replace_last_good_cache(self): registry = self.registry_response([*self.manifest, self.extra_card()]) - original = await registry.async_refresh_registry(self.hass) + release = await registry.async_check_registry_release(self.hass) + original = await registry.async_install_registry_release(self.hass, release) cache = self.directory / registry.REGISTRY_CACHE previous = cache.read_bytes() self.registry_response([self.extra_card() | {"filename": "../unsafe.js"}]) - with self.assertLogs(registry.__name__, level="WARNING"): - self.assertEqual(await registry.async_refresh_registry(self.hass), original) + release = await registry.async_check_registry_release(self.hass) + with self.assertRaises(ValueError): + await registry.async_install_registry_release(self.hass, release) + self.assertEqual(registry.get_manifest(self.hass), original) self.assertEqual(cache.read_bytes(), previous) async def test_registry_checksum_failure_preserves_bundled_fallback(self): registry = sys.modules["card_update_test.frontend.registry"] contents = json.dumps([self.extra_card()]).encode() - metadata = {"published_at": "2026-09-29", "assets": [{ + metadata = {"tag_name": "v1.0.0", "published_at": "2026-09-29", "assets": [{ "name": "cards.json", "state": "uploaded", "size": len(contents), "digest": "sha256:" + "0" * 64, "browser_download_url": f"https://github.com/{registry.REGISTRY_REPOSITORY}/releases/download/v1/cards.json", }]} self.session.get.side_effect = [self.response(json_data=metadata), self.response(contents=contents)] - with self.assertLogs(registry.__name__, level="WARNING"): - self.assertEqual(await registry.async_refresh_registry(self.hass), self.manifest) + release = await registry.async_check_registry_release(self.hass) + with self.assertRaises(ValueError): + await registry.async_install_registry_release(self.hass, release) + self.assertEqual(registry.get_manifest(self.hass), self.manifest) self.assertFalse((self.directory / registry.REGISTRY_CACHE).exists()) - async def test_registry_rejects_identity_changes_and_duplicate_components(self): + async def test_registry_accepts_identity_changes_and_rejects_duplicates(self): registry = sys.modules["card_update_test.frontend.registry"] - changed = self.manifest[0] | {"repository": "other/repository"} - with self.assertRaises(ValueError): - registry._merge_manifest(self.manifest, [changed]) + changed = self.manifest[0] | { + "filename": "wiser-renamed-card.js", + "legacy_filenames": [self.manifest[0]["filename"]], + "repository": "other/repository", + "component": "wiser-renamed-card", + "panel": "wiser-renamed-panel", + } + self.assertEqual(registry._merge_manifest(self.manifest, [changed])[0], changed) with self.assertRaises(ValueError): registry.validate_manifest([self.extra_card(), self.extra_card() | { "id": "other", "filename": "wiser-other-card.js" @@ -208,11 +246,11 @@ async def test_registry_rejects_foreign_release_asset_without_downloading(self): # Use an explicit release from another host. self.session.get.side_effect = None self.session.get.return_value = self.response(json_data={ - "published_at": "2026-09-29", "assets": [{"name": "cards.json", "state": "uploaded", + "tag_name": "v1.0.0", "published_at": "2026-09-29", "assets": [{"name": "cards.json", "state": "uploaded", "size": 123, "browser_download_url": "https://example.com/cards.json"}], }) - with self.assertLogs(registry.__name__, level="WARNING"): - await registry.async_refresh_registry(self.hass) + with self.assertRaises(ValueError): + await registry.async_check_registry_release(self.hass) self.session.get.assert_called_once() async def test_new_card_entity_is_discovered_once_and_installed_without_bundle(self): @@ -228,7 +266,7 @@ async def test_new_card_entity_is_discovered_once_and_installed_without_bundle(s add.assert_called_once() entities = add.call_args.args[0] self.assertEqual([entity.card for entity in entities], ["energy"]) - self.assertEqual(entities[0]._attr_name, definition["name"]) + self.assertEqual(entities[0].name, definition["name"]) add.reset_mock() await self.coordinator.async_refresh() add.assert_not_called() @@ -483,12 +521,12 @@ async def test_multiple_hubs_share_entities_and_transfer_when_owner_unloads(self await self.updates.async_setup_entry(self.hass, SimpleNamespace(entry_id="first"), first) await self.updates.async_setup_entry(self.hass, SimpleNamespace(entry_id="second"), second) self.coordinator.async_refresh.assert_awaited_once() - self.assertEqual(len(first.call_args.args[0]), 3) + self.assertEqual(len(first.call_args.args[0]), 4) second.assert_not_called() self.registry.async_get_entity_id.side_effect = lambda domain, platform, unique_id: f"update.{unique_id}" await self.updates.async_unload_card_updates(self.hass, SimpleNamespace(entry_id="first")) self.assertEqual(self.coordinator.owner, "second") - self.assertEqual(len(second.call_args.args[0]), 3) + self.assertEqual(len(second.call_args.args[0]), 4) self.assertEqual(self.registry.async_update_entity.call_args.kwargs["config_entry_id"], "second") await self.updates.async_unload_card_updates(self.hass, SimpleNamespace(entry_id="second")) self.coordinator.async_shutdown.assert_awaited_once() @@ -498,6 +536,11 @@ async def test_update_entity_delegates_manual_install_and_exposes_release(self): self.coordinator.data["zigbee"] = {"installed": "1.0.0", "release": self.updates._validate_release(self.coordinator.cards["zigbee"], self.metadata())} entity = self.updates.WiserCardUpdate(self.coordinator, "zigbee") self.assertTrue(entity.available) + self.assertEqual(entity.name, "Wiser Zigbee Card") + self.coordinator.cards["zigbee"] = { + **self.coordinator.cards["zigbee"], "name": "Renamed Zigbee Card" + } + self.assertEqual(entity.name, "Renamed Zigbee Card") self.assertEqual(entity.installed_version, "1.0.0") self.assertEqual(entity.latest_version, "2.0.0") self.assertIn("/releases/tag/v2.0.0", entity.release_url) @@ -505,6 +548,45 @@ async def test_update_entity_delegates_manual_install_and_exposes_release(self): await entity.async_install(None, False) self.coordinator.install.assert_awaited_once_with("zigbee") + async def test_registry_update_entity_installs_only_when_requested(self): + release = { + "version": "1.1.0", + "asset": {}, + "release_url": "https://github.com/andyblac/WiserFrontendPanelConfig/releases/tag/v1.1.0", + } + self.coordinator.data["_registry"] = { + "installed": "1.0.0", "release": release + } + entity = self.updates.WiserFrontendRegistryUpdate(self.coordinator) + self.assertEqual(entity.installed_version, "1.0.0") + self.assertEqual(entity.latest_version, "1.1.0") + self.coordinator.install_registry = AsyncMock() + await entity.async_install(None, False) + self.coordinator.install_registry.assert_awaited_once() + + async def test_registry_install_discovers_new_cards(self): + release = { + "version": "1.1.0", + "asset": {}, + "release_url": "https://github.com/andyblac/WiserFrontendPanelConfig/releases/tag/v1.1.0", + } + manifest = [*self.manifest, self.extra_card()] + self.coordinator.data["_registry"] = { + "installed": "1.0.0", "release": release + } + self.updates.async_install_registry_release = AsyncMock( + return_value=manifest + ) + self.coordinator._check_card = AsyncMock( + return_value={"installed": "0.0.0", "release": None, "error": None} + ) + await self.coordinator.install_registry() + self.updates.async_install_registry_release.assert_awaited_once_with( + self.hass, release + ) + self.assertIn("energy", self.coordinator.cards) + self.assertEqual(self.coordinator.data["_registry"]["installed"], "1.1.0") + async def test_lovelace_resource_moves_to_cached_url_without_duplicate(self): tree = ast.parse((ROOT / "frontend/__init__.py").read_text()) cls = next(node for node in tree.body if isinstance(node, ast.ClassDef) and node.name == "JSModuleRegistration") @@ -516,6 +598,7 @@ async def test_lovelace_resource_moves_to_cached_url_without_duplicate(self): ) self.hass.data["lovelace"] = SimpleNamespace(mode="storage", resources=resources) namespace = { + "asyncio": __import__("asyncio"), "HomeAssistant": object, "LovelaceData": object, "Path": Path, "MAJOR_VERSION": 2025, "MINOR_VERSION": 5, "MODE_STORAGE": "storage", "URL_BASE": "/wiser", @@ -537,6 +620,69 @@ async def test_lovelace_resource_moves_to_cached_url_without_duplicate(self): await registration.async_unregister() resources.async_delete_item.assert_awaited_once_with("card") + async def test_duplicate_lovelace_resources_are_removed(self): + tree = ast.parse((ROOT / "frontend/__init__.py").read_text()) + cls = next(node for node in tree.body if isinstance(node, ast.ClassDef) and node.name == "JSModuleRegistration") + active = "/wiser/cards/wiser-controls-card-abc.js?v=1.0.0" + resources = SimpleNamespace( + async_items=lambda: [ + {"id": "older", "url": active}, + {"id": "newer", "url": active}, + ], + async_update_item=AsyncMock(), async_create_item=AsyncMock(), + async_delete_item=AsyncMock(), + ) + self.hass.data["lovelace"] = SimpleNamespace(mode="storage", resources=resources) + namespace = { + "asyncio": __import__("asyncio"), + "HomeAssistant": object, "LovelaceData": object, "Path": Path, + "MAJOR_VERSION": 2025, "MINOR_VERSION": 5, + "MODE_STORAGE": "storage", "URL_BASE": "/wiser", + "CARD_CACHE_URL": "/wiser/cards", "_LOGGER": Mock(), + "get_manifest": lambda hass: [{ + "filename": "wiser-controls-card.js", "name": "Controls", + }], + "async_card_resource": AsyncMock(return_value=(None, active, "1.0.0")), + } + exec(compile(ast.Module(body=[cls], type_ignores=[]), "frontend/__init__.py", "exec"), namespace) + registration = namespace["JSModuleRegistration"](self.hass) + await registration._async_register_modules() + resources.async_delete_item.assert_awaited_once_with("older") + resources.async_update_item.assert_not_awaited() + resources.async_create_item.assert_not_awaited() + + async def test_renamed_card_reuses_legacy_lovelace_resource(self): + tree = ast.parse((ROOT / "frontend/__init__.py").read_text()) + cls = next(node for node in tree.body if isinstance(node, ast.ClassDef) and node.name == "JSModuleRegistration") + active = "/wiser/cards/wiser-controls-card-abc.js?v=1.0.0" + resource = {"id": "card", "url": "/wiser/cards/wiser-rooms-card-old.js?v=0.9.0"} + resources = SimpleNamespace( + async_items=lambda: [resource], async_update_item=AsyncMock(), + async_create_item=AsyncMock(), async_delete_item=AsyncMock(), + ) + self.hass.data["lovelace"] = SimpleNamespace(mode="storage", resources=resources) + namespace = { + "asyncio": __import__("asyncio"), + "HomeAssistant": object, "LovelaceData": object, "Path": Path, + "MAJOR_VERSION": 2025, "MINOR_VERSION": 5, + "MODE_STORAGE": "storage", "URL_BASE": "/wiser", + "CARD_CACHE_URL": "/wiser/cards", "_LOGGER": Mock(), + "get_manifest": lambda hass: [{ + "filename": "wiser-controls-card.js", + "legacy_filenames": ["wiser-rooms-card.js"], + "name": "Controls", + }], + "async_card_resource": AsyncMock(return_value=(None, active, "1.0.0")), + } + exec(compile(ast.Module(body=[cls], type_ignores=[]), "frontend/__init__.py", "exec"), namespace) + registration = namespace["JSModuleRegistration"](self.hass) + registration.async_remove_gzip_files = AsyncMock() + await registration._async_register_modules() + resources.async_update_item.assert_awaited_once_with( + "card", {"res_type": "module", "url": active} + ) + resources.async_create_item.assert_not_awaited() + async def test_older_stable_release_is_not_installed_over_development_card(self): self.version_reader.return_value = "3.0.0-dev.84" self.coordinator.data["zigbee"] = {"release": self.updates._validate_release(self.coordinator.cards["zigbee"], self.metadata())} From ccf7fec32c4f2e93f3886244d82cacc0037f407c Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Wed, 30 Sep 2026 19:13:26 +0100 Subject: [PATCH 048/154] Restore default titles for renamed panels --- .../wiser/frontend/wiser-panel.js | 6 +-- .../wiser/frontend/wiser_sidebar.py | 21 +++++++-- tests/test_wiser_sidebar.py | 45 +++++++++++++++++++ 3 files changed, 66 insertions(+), 6 deletions(-) diff --git a/custom_components/wiser/frontend/wiser-panel.js b/custom_components/wiser/frontend/wiser-panel.js index bc4982c2..e1892ba5 100644 --- a/custom_components/wiser/frontend/wiser-panel.js +++ b/custom_components/wiser/frontend/wiser-panel.js @@ -1,4 +1,4 @@ -/*! WISER-CARD-VERSION wiser-panel 1.0.4 */ +/*! WISER-CARD-VERSION wiser-panel 1.0.5 */ const WISER_ACTIVE_PANEL_KEY = "wiser-active-panel"; @@ -225,8 +225,8 @@ class WiserPanel extends HTMLElement { const finish = (save) => { if (finished) return; finished = true; - const title = input.value.trim(); - if (!save || !title || title === panel.title) { + const title = input.value.trim() || panel.default_title || panel.title; + if (!save || title === panel.title) { tab.textContent = panel.title; this._syncTabEditing(); return; diff --git a/custom_components/wiser/frontend/wiser_sidebar.py b/custom_components/wiser/frontend/wiser_sidebar.py index b50e17a3..35a803e9 100644 --- a/custom_components/wiser/frontend/wiser_sidebar.py +++ b/custom_components/wiser/frontend/wiser_sidebar.py @@ -49,6 +49,15 @@ def _panel_title(component): return name.replace("-", " ").title() +def _legacy_panel_titles(module): + """Return former default titles derived from renamed card bundles.""" + titles = set() + for filename in module.get("legacy_filenames", []): + name = filename.removeprefix("wiser-").removesuffix("-card.js") + titles.add(name.replace("-", " ").title()) + return titles + + def _stored_config(entry, panel_id): """Return settings from the shared container for any panel.""" generic = entry.options.get(CONF_WISER_PANEL_CONFIG, {}) @@ -61,7 +70,9 @@ async def _discover_panels(hass, entries): """Find installed panel components from the active frontend registry.""" panels = [] hubs = [hub for hub, _ in entries] - for module in get_manifest(hass): + manifest = get_manifest(hass) + definitions = {module["id"]: module for module in manifest} + for module in manifest: component = module.get("panel") if not component: continue @@ -74,10 +85,12 @@ async def _discover_panels(hass, entries): if component not in source: continue panel_id = module["id"] + default_title = _panel_title(component) panels.append( { "id": panel_id, - "title": _panel_title(component), + "title": default_title, + "default_title": default_title, "component": component, "module_url": module_url, "config": { @@ -114,7 +127,9 @@ async def _discover_panels(hass, entries): for panel in panels: title = preferences.get(panel["id"], {}).get("title") if isinstance(title, str) and title.strip(): - panel["title"] = title.strip() + stored_title = title.strip() + if stored_title not in _legacy_panel_titles(definitions[panel["id"]]): + panel["title"] = stored_title order = {item["id"]: index for index, item in enumerate(stored_tabs)} discovered_order = {panel["id"]: index for index, panel in enumerate(panels)} diff --git a/tests/test_wiser_sidebar.py b/tests/test_wiser_sidebar.py index fd2a42d1..b2aa416d 100644 --- a/tests/test_wiser_sidebar.py +++ b/tests/test_wiser_sidebar.py @@ -130,6 +130,8 @@ async def test_single_option_registers_one_panel_with_discovered_panel_cards(sel ["schedule", "zigbee", "rooms"], ) schedule, zigbee, rooms = args["config"]["panels"] + self.assertEqual(schedule["default_title"], "Schedules") + self.assertEqual(rooms["default_title"], "Rooms") self.assertEqual(schedule["config"]["hubs"], ["hub-one", "hub-two"]) self.assertEqual( rooms["config"]["hub_ids"], @@ -184,6 +186,7 @@ async def test_saved_tab_order_and_titles_are_applied_to_discovered_panels(self) await self.sidebar.async_update_wiser_panel(self.hass) panels = self.custom.async_register_panel.call_args.kwargs["config"]["panels"] + self.assertEqual(panels[0]["default_title"], "Rooms") self.assertEqual( [(panel["id"], panel["title"]) for panel in panels], [ @@ -193,6 +196,45 @@ async def test_saved_tab_order_and_titles_are_applied_to_discovered_panels(self) ], ) + async def test_renamed_panel_replaces_stored_legacy_default_title(self): + rooms = next(card for card in self.manifest if card["id"] == "rooms") + rooms.update( + { + "filename": "wiser-controls-card.js", + "component": "wiser-controls-card", + "panel": "wiser-controls-panel", + "legacy_filenames": ["wiser-rooms-card.js"], + } + ) + (Path(self.temporary.name) / "wiser-controls-card.js").write_text( + 'customElements.define("wiser-controls-card", class extends HTMLElement {});' + 'customElements.define("wiser-controls-panel", class extends HTMLElement {})' + ) + self.add_hub( + "hub", + { + "wiser_panel_config": { + "_panel_tabs": [ + {"id": "rooms", "title": "Rooms"}, + {"id": "schedule", "title": "Programmes"}, + ] + } + }, + ) + + await self.sidebar.async_update_wiser_panel(self.hass) + + panels = self.custom.async_register_panel.call_args.kwargs["config"]["panels"] + self.assertEqual(panels[0]["default_title"], "Controls") + self.assertEqual( + [(panel["id"], panel["title"]) for panel in panels], + [ + ("rooms", "Controls"), + ("schedule", "Programmes"), + ("zigbee", "Zigbee"), + ], + ) + async def test_legacy_sidebar_options_do_not_control_unified_panel(self): self.add_hub( "hub", @@ -232,6 +274,9 @@ def test_shell_owns_panel_tabs_and_embeds_each_child_panel(self): self.assertIn('tab.addEventListener("dblclick"', source) self.assertIn('type: "wiser/panel/configure_tabs"', source) self.assertIn("_mergeTabPreferences(panel.config)", source) + self.assertIn( + "input.value.trim() || panel.default_title || panel.title", source + ) def test_new_panel_websocket_commands_are_registered(self): source = (ROOT / "websockets.py").read_text() From bc347f35c05015f253c460093de77f550bb72a5c Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 1 Oct 2026 09:12:40 +0100 Subject: [PATCH 049/154] Update smart plug state immediately --- custom_components/wiser/switch.py | 10 +++- tests/test_switch_hot_water.py | 80 ++++++++++++++++++++++++++++++- 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/custom_components/wiser/switch.py b/custom_components/wiser/switch.py index acb4a75f..1157411c 100755 --- a/custom_components/wiser/switch.py +++ b/custom_components/wiser/switch.py @@ -546,7 +546,7 @@ def extra_state_attributes(self): attrs["manual_state"] = self._device.manual_state attrs["mode"] = self._device.mode attrs["name"] = self._device.name - attrs["output_state"] = "On" if self._device.is_on else "Off" + attrs["output_state"] = "On" if self.is_on else "Off" # Switches could be not allocated to room (issue:209) if self._data.wiserhub.rooms.get_by_id(self._device.room_id) is not None: attrs["room"] = self._data.wiserhub.rooms.get_by_id( @@ -569,6 +569,11 @@ def extra_state_attributes(self): async def async_turn_on(self, **kwargs): """Turn the device on.""" await self._device.turn_on() + # Publish the accepted command immediately. The hub takes a few seconds + # to report the new value, so waiting for the refresh leaves every HA + # dashboard card showing the previous state in the meantime. + self._is_on = True + self.async_write_ha_state() await self.async_force_update(2) return True @@ -576,6 +581,8 @@ async def async_turn_on(self, **kwargs): async def async_turn_off(self, **kwargs): """Turn the device off.""" await self._device.turn_off() + self._is_on = False + self.async_write_ha_state() await self.async_force_update(2) return True @@ -1118,4 +1125,3 @@ async def async_turn_off(self, **kwargs): """Turn hot water off.""" await self._data.wiserhub.hotwater.override_state("Off") await self.async_force_update() - diff --git a/tests/test_switch_hot_water.py b/tests/test_switch_hot_water.py index fbb39641..c177ad26 100644 --- a/tests/test_switch_hot_water.py +++ b/tests/test_switch_hot_water.py @@ -2,6 +2,7 @@ from __future__ import annotations +import __future__ import asyncio import importlib.util from pathlib import Path @@ -95,7 +96,17 @@ class WiserScheduleEntity: assert spec and spec.loader module = importlib.util.module_from_spec(spec) sys.modules[spec.name] = module - spec.loader.exec_module(module) + # The integration targets Home Assistant's newer Python runtime. Compile + # annotations lazily so this lightweight regression test also runs with the + # older system Python available in the local development environment. + source = SOURCE_PATH.read_text(encoding="utf-8") + code = compile( + source, + SOURCE_PATH, + "exec", + flags=__future__.annotations.compiler_flag, + ) + exec(code, module.__dict__) return module @@ -153,5 +164,72 @@ def test_turn_off_overrides_hot_water_state_to_off(self) -> None: self.assertEqual(self._override_calls, ["Off"]) +class _FakeSmartPlug: + def __init__(self, *, is_on: bool) -> None: + self.is_on = is_on + self.schedule = None + self.control_source = "Manual" + self.manual_state = "On" if is_on else "Off" + self.mode = "Manual" + self.name = "Test Plug" + self.room_id = 0 + self.away_mode_action = "Off" + self.scheduled_state = "Off" + self.schedule_id = 0 + self.commands = [] + + async def turn_on(self) -> None: + # The real API object is not updated until the follow-up hub refresh. + self.commands.append("turn_on") + + async def turn_off(self) -> None: + self.commands.append("turn_off") + + +class WiserSmartPlugImmediateStateTest(unittest.TestCase): + """Tests that smart-plug commands update the HA entity before refresh.""" + + @classmethod + def setUpClass(cls) -> None: + cls.switch_module = _load_switch_module() + + def _switch(self, *, is_on: bool): + plug = _FakeSmartPlug(is_on=is_on) + data = SimpleNamespace( + wiserhub=SimpleNamespace( + system=SimpleNamespace(name="WiserHeat045XXX"), + devices=SimpleNamespace(get_by_id=lambda _id: plug), + rooms=SimpleNamespace(get_by_id=lambda _id: None), + ) + ) + switch = self.switch_module.WiserSmartPlugSwitch(data, 1, "Wiser Test Plug") + events = [] + switch.async_write_ha_state = lambda: events.append( + ("write", switch.is_on, switch.extra_state_attributes["output_state"]) + ) + + async def refresh(delay=0): + events.append(("refresh", delay, switch.is_on)) + + switch.async_force_update = refresh + return switch, plug, events + + def test_turn_on_publishes_on_before_delayed_refresh(self) -> None: + switch, plug, events = self._switch(is_on=False) + + asyncio.run(switch.async_turn_on()) + + self.assertEqual(plug.commands, ["turn_on"]) + self.assertEqual(events, [("write", True, "On"), ("refresh", 2, True)]) + + def test_turn_off_publishes_off_before_delayed_refresh(self) -> None: + switch, plug, events = self._switch(is_on=True) + + asyncio.run(switch.async_turn_off()) + + self.assertEqual(plug.commands, ["turn_off"]) + self.assertEqual(events, [("write", False, "Off"), ("refresh", 2, False)]) + + if __name__ == "__main__": unittest.main() From 2363db5f59baa256ee8906847fe020eded97fec0 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 1 Oct 2026 15:06:04 +0100 Subject: [PATCH 050/154] Support independently released panel-only bundles --- custom_components/wiser/frontend/__init__.py | 4 +++ custom_components/wiser/frontend/manifest.py | 7 ++++- tests/test_card_releases.py | 17 ++++++++++++ tests/test_card_updates.py | 28 ++++++++++++++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) diff --git a/custom_components/wiser/frontend/__init__.py b/custom_components/wiser/frontend/__init__.py index f333eb3d..7372a655 100644 --- a/custom_components/wiser/frontend/__init__.py +++ b/custom_components/wiser/frontend/__init__.py @@ -134,6 +134,8 @@ async def _async_register_modules_locked(self): ] for module in get_manifest(self.hass): + if not module.get("card", True): + continue url = f"{URL_BASE}/{module.get('filename')}" filenames = [module["filename"], *module.get("legacy_filenames", [])] @@ -216,6 +218,8 @@ async def async_unregister(self): """Unload lovelace module resource.""" if self.resource_mode == MODE_STORAGE: for module in get_manifest(self.hass): + if not module.get("card", True): + continue filenames = [module["filename"], *module.get("legacy_filenames", [])] wiser_resources = [ resource diff --git a/custom_components/wiser/frontend/manifest.py b/custom_components/wiser/frontend/manifest.py index 093f0654..41112a18 100644 --- a/custom_components/wiser/frontend/manifest.py +++ b/custom_components/wiser/frontend/manifest.py @@ -24,7 +24,7 @@ def validate_manifest(value): seen = {key: set() for key in ("id", "filename", "component", "panel")} patterns = { "id": r"[a-z0-9-]+", - "filename": r"wiser-[a-z0-9-]+-card\.js", + "filename": r"wiser-[a-z0-9-]+-(?:card|panel)\.js", "repository": r"[A-Za-z0-9_-]+/[A-Za-z0-9_.-]+", "component": r"wiser-[a-z0-9-]+", "panel": r"wiser-[a-z0-9-]+-panel", @@ -58,6 +58,11 @@ def validate_manifest(value): raise ValueError("Invalid or duplicate frontend legacy filename") seen["filename"].add(filename) definition = {key: card.get(key) for key in ("name", *patterns)} + is_card = card.get("card", True) + if type(is_card) is not bool: + raise ValueError("Invalid frontend card flag") + if not is_card: + definition["card"] = False if legacy_filenames: definition["legacy_filenames"] = legacy_filenames result.append(definition) diff --git a/tests/test_card_releases.py b/tests/test_card_releases.py index 4ecdaefb..ea05be6c 100644 --- a/tests/test_card_releases.py +++ b/tests/test_card_releases.py @@ -90,6 +90,23 @@ def test_external_panel_config_rejects_invalid_registry(self): with self.assertRaisesRegex(ValueError, "Invalid frontend card"): FETCH.fetch_panel_config("dev", local_root=Path(directory)) + def test_external_registry_accepts_panel_only_bundle_definition(self): + definition = { + "id": "hub", + "name": "Wiser Hub Panel", + "filename": "wiser-hub-panel.js", + "repository": "andyblac/wiser-hub-panel", + "component": "wiser-hub-panel", + "panel": "wiser-hub-panel", + "card": False, + } + self.assertEqual(FETCH.validate_card_manifest([definition]), [definition]) + + def test_external_registry_rejects_invalid_card_flag(self): + definition = CARD_MANIFEST[0] | {"card": "false"} + with self.assertRaisesRegex(ValueError, "card flag"): + FETCH.validate_card_manifest([definition]) + def test_release_build_fetches_published_panel_config(self): published = { "tag_name": "v1.0.0-beta.1", diff --git a/tests/test_card_updates.py b/tests/test_card_updates.py index b1b6ca39..4bfb336d 100644 --- a/tests/test_card_updates.py +++ b/tests/test_card_updates.py @@ -620,6 +620,34 @@ async def test_lovelace_resource_moves_to_cached_url_without_duplicate(self): await registration.async_unregister() resources.async_delete_item.assert_awaited_once_with("card") + async def test_panel_only_bundle_is_not_registered_as_lovelace_card(self): + tree = ast.parse((ROOT / "frontend/__init__.py").read_text()) + cls = next(node for node in tree.body if isinstance(node, ast.ClassDef) and node.name == "JSModuleRegistration") + resources = SimpleNamespace( + async_items=lambda: [], async_update_item=AsyncMock(), + async_create_item=AsyncMock(), async_delete_item=AsyncMock(), + ) + self.hass.data["lovelace"] = SimpleNamespace(mode="storage", resources=resources) + resolve = AsyncMock() + namespace = { + "asyncio": __import__("asyncio"), + "HomeAssistant": object, "LovelaceData": object, "Path": Path, + "MAJOR_VERSION": 2025, "MINOR_VERSION": 5, + "MODE_STORAGE": "storage", "URL_BASE": "/wiser", + "CARD_CACHE_URL": "/wiser/cards", "_LOGGER": Mock(), + "get_manifest": lambda hass: [{ + "filename": "wiser-hub-panel.js", "name": "Hub", "card": False, + }], + "async_card_resource": resolve, + } + exec(compile(ast.Module(body=[cls], type_ignores=[]), "frontend/__init__.py", "exec"), namespace) + registration = namespace["JSModuleRegistration"](self.hass) + await registration._async_register_modules() + resolve.assert_not_awaited() + resources.async_create_item.assert_not_awaited() + await registration.async_unregister() + resources.async_delete_item.assert_not_awaited() + async def test_duplicate_lovelace_resources_are_removed(self): tree = ast.parse((ROOT / "frontend/__init__.py").read_text()) cls = next(node for node in tree.body if isinstance(node, ast.ClassDef) and node.name == "JSModuleRegistration") From 01f6539e101813972a8489ea09da994961896cc0 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 1 Oct 2026 15:16:47 +0100 Subject: [PATCH 051/154] Format installed frontend registry JSON --- custom_components/wiser/frontend/registry.py | 8 ++++++-- tests/test_card_updates.py | 5 ++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/custom_components/wiser/frontend/registry.py b/custom_components/wiser/frontend/registry.py index ec719250..0727cf3b 100644 --- a/custom_components/wiser/frontend/registry.py +++ b/custom_components/wiser/frontend/registry.py @@ -82,8 +82,12 @@ def get_registry_version(hass): def _store_registry(config_dir, manifest, version): - document = json.dumps( - {"schema_version": REGISTRY_SCHEMA_VERSION, "cards": manifest} + document = ( + json.dumps( + {"schema_version": REGISTRY_SCHEMA_VERSION, "cards": manifest}, + indent=2, + ) + + "\n" ).encode() integration = Path(config_dir) / "custom_components/wiser/frontend" integration.mkdir(parents=True, exist_ok=True) diff --git a/tests/test_card_updates.py b/tests/test_card_updates.py index 4bfb336d..73e38f85 100644 --- a/tests/test_card_updates.py +++ b/tests/test_card_updates.py @@ -172,8 +172,11 @@ async def test_runtime_registry_adds_card_and_survives_restart_offline(self): manifest = await registry.async_install_registry_release(self.hass, release) self.assertEqual(manifest[-1], self.extra_card()) installed = self.directory / "custom_components/wiser/frontend" + installed_registry = (installed / "cards.json").read_text() + self.assertTrue(installed_registry.startswith('{\n "schema_version": 1,')) + self.assertTrue(installed_registry.endswith("\n")) self.assertEqual( - json.loads((installed / "cards.json").read_text())["cards"], manifest + json.loads(installed_registry)["cards"], manifest ) self.assertEqual( json.loads((installed / "panel-config-release.json").read_text())[ From 7b861f795e2068a0b5301ca878cb30611b054505 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Fri, 2 Oct 2026 10:37:52 +0100 Subject: [PATCH 052/154] Allow builds with unavailable frontend bundles --- README.md | 5 ++- scripts/build.py | 1 + scripts/fetch_card_releases.py | 79 +++++++++++++++++++++------------- tests/test_build.py | 54 +++++++++++++++++++++-- 4 files changed, 104 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index df76f741..9170b0a7 100755 --- a/README.md +++ b/README.md @@ -78,7 +78,10 @@ workflow and shared panel API. The output is `dist/wiser.zip`. The accompanying `dist/card-releases.json` and `dist/panel-config-release.json` files record the card and registry artifacts -included in the package. Missing or invalid assets fail the build. +included in the package. If an individual published card or panel repository is +temporarily unavailable, its bundle is omitted and the integration still +builds; its Home Assistant update entity can install it later. Invalid local +development bundles and an unavailable registry still fail the build. The **Publish** GitHub Actions workflow runs the same build and attaches `wiser.zip` when an integration release is published. Preview runs provide a downloadable **wiser-package** artifact without publishing a release. diff --git a/scripts/build.py b/scripts/build.py index 332ee253..bd308011 100644 --- a/scripts/build.py +++ b/scripts/build.py @@ -55,6 +55,7 @@ def build( selected_repositories, local_root=local_root, definitions=definitions, + skip_unavailable=True, ) (staging / "frontend/panel-config-release.json").write_text( json.dumps(config_record, indent=2) + "\n" diff --git a/scripts/fetch_card_releases.py b/scripts/fetch_card_releases.py index 0cb80c33..1a825b1f 100644 --- a/scripts/fetch_card_releases.py +++ b/scripts/fetch_card_releases.py @@ -138,9 +138,11 @@ def fetch_cards( definitions, plan=False, local_root=None, + skip_unavailable=False, ): report = [] payloads = {} + omitted = set() # Resolve and validate every source before replacing any staged assets. for card, repository in repositories.items(): definition = definitions[card] @@ -149,39 +151,56 @@ def fetch_cards( Path(local_root) / repository.rsplit("/", 1)[-1] / "dist" / filename if local_root is not None else None ) - if local is not None and local.is_file(): - contents = local.read_bytes() - record = { - "repository": repository, "source": "local", "asset": filename, - "path": str(local.resolve()), - "digest": "sha256:" + sha256(contents).hexdigest(), - } - else: - release = select_release(list_releases(repository), channel) - asset = select_asset(release, filename) - record = { - "repository": repository, "source": "release", - "tag": release["tag_name"], "prerelease": release["prerelease"], - "asset": filename, "asset_id": asset["id"], - "url": asset["browser_download_url"], - } + local_selected = local is not None and local.is_file() + try: + if local_selected: + contents = local.read_bytes() + record = { + "repository": repository, "source": "local", "asset": filename, + "path": str(local.resolve()), + "digest": "sha256:" + sha256(contents).hexdigest(), + } + else: + release = select_release(list_releases(repository), channel) + asset = select_asset(release, filename) + record = { + "repository": repository, "source": "release", + "tag": release["tag_name"], "prerelease": release["prerelease"], + "asset": filename, "asset_id": asset["id"], + "url": asset["browser_download_url"], + } + if not plan: + contents, record["digest"] = download_asset(repository, asset) if not plan: - contents, record["digest"] = download_asset(repository, asset) - if not plan: - if not contents or contents.lstrip().lower().startswith((b" Date: Fri, 2 Oct 2026 12:15:15 +0100 Subject: [PATCH 053/154] Manage frontend registry in integration --- .gitignore | 3 - CHANGELOG.md | 2 +- CONTRIBUTING.md | 4 +- README.md | 42 +-- custom_components/wiser/const.py | 2 +- custom_components/wiser/frontend/cards.json | 41 +++ custom_components/wiser/frontend/registry.py | 235 +---------------- custom_components/wiser/update.py | 135 +--------- docs/frontend-registry.md | 190 +++++++++----- scripts/build.py | 30 +-- scripts/fetch_card_releases.py | 63 +---- tests/test_build.py | 147 +++++++---- tests/test_card_releases.py | 71 +----- tests/test_card_updates.py | 255 ++++--------------- 14 files changed, 396 insertions(+), 824 deletions(-) create mode 100644 custom_components/wiser/frontend/cards.json diff --git a/.gitignore b/.gitignore index 0c3e6d66..2335833c 100755 --- a/.gitignore +++ b/.gitignore @@ -109,6 +109,3 @@ venv.bak/ .mypy_cache/ *.DS_Store .vscode/settings.json - -# Generated from the external frontend registry during packaging -/custom_components/wiser/frontend/cards.json diff --git a/CHANGELOG.md b/CHANGELOG.md index d4a5da5a..4e975af4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ For releases before v3.3.5, see the [Full Change Log](https://github.com/asantag ### Added -- Discover new cards and panels from published WiserFrontendPanelConfig registry releases at runtime, with independent card installation, offline caching, and a generic panel-settings API. +- Manage frontend definitions in the integration's bundled `cards.json`, with independent card and panel installation, offline caching, and a generic panel-settings API. - Added configurable OpenTherm monitoring and controls, including relative modulation, a Delta-T sensor, expanded telemetry, and categorized diagnostics - PR [#697](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/697). - Added a configurable Wiser Schedules sidebar panel - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d521f9e6..99d82a46 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -39,7 +39,7 @@ Please include: | Integration source | `custom_components/wiser/` | | Hub communication | the separate `aioWiserHeatAPI` library, pinned in `manifest.json` | | Frontend panel/card plumbing | `custom_components/wiser/frontend/` | -| Frontend cards and panels | repositories declared in [WiserFrontendPanelConfig](https://github.com/andyblac/WiserFrontendPanelConfig) | +| Frontend cards and panels | repositories declared in `custom_components/wiser/frontend/cards.json` | | Tests | `tests/` | | Packaging scripts | `scripts/` | @@ -50,6 +50,8 @@ Two things that trip people up: - **Card bundles are not committed to this repository.** They are downloaded from the card repositories' GitHub releases at build time. Do not add built `.js` card assets to `custom_components/wiser/frontend/`. +- Follow [Adding Wiser frontend cards and panels](docs/frontend-registry.md) to + register a new frontend repository and test its independent update entity. ## Branching and pull requests diff --git a/README.md b/README.md index 9170b0a7..38290780 100755 --- a/README.md +++ b/README.md @@ -62,26 +62,28 @@ To build a stable release package, run: python3 scripts/build.py --release --channel stable ``` -For a prerelease package, use `--channel dev` instead. The build downloads every card defined by the external frontend registry from GitHub. Stable builds use stable card releases; prerelease builds use the most recently published stable or prerelease card release. In a running installation, card update entities follow the HACS **Pre-release** switch for this integration; without that option they offer stable card releases only. - -The frontend card registry is maintained separately in -[`andyblac/WiserFrontendPanelConfig`](https://github.com/andyblac/WiserFrontendPanelConfig). -Local development builds prefer that sibling repository's validated -`dist/cards.json`; release builds download its published `cards.json` asset. A -snapshot is generated as `frontend/cards.json` in the package; no card list is -maintained in this integration repository. At runtime the integration checks -published registry releases daily and caches the last valid registry. New cards -appear as independent update entities and can be installed without updating the -integration. Installed cards and the cached registry remain available offline. -See [Adding frontend cards and panels](docs/frontend-registry.md) for the release -workflow and shared panel API. - -The output is `dist/wiser.zip`. The accompanying `dist/card-releases.json` and -`dist/panel-config-release.json` files record the card and registry artifacts -included in the package. If an individual published card or panel repository is -temporarily unavailable, its bundle is omitted and the integration still -builds; its Home Assistant update entity can install it later. Invalid local -development bundles and an unavailable registry still fail the build. +For a prerelease package, use `--channel dev` instead. The build downloads every +card and panel declared in `custom_components/wiser/frontend/cards.json` from +its own GitHub repository. Stable builds use stable frontend releases; +prerelease builds use the most recently published stable or prerelease release. +In a running installation, each frontend update entity follows the HACS +**Pre-release** switch for this integration; without that option it offers stable +releases only. See [Adding frontend cards and panels](docs/frontend-registry.md) +for the registry format and shared panel API. + +For an integration-only test package that retains the registry but deliberately +omits every card and panel bundle, run: + +```sh +python3 scripts/build.py --channel dev --without-frontend +``` + +The output is `dist/wiser.zip`. The accompanying `dist/card-releases.json` file +records the frontend artifacts included in the package. If an individual card +or panel repository is temporarily unavailable, its bundle is omitted and the +integration still builds; its Home Assistant update entity can install it later. +Invalid local development bundles and an invalid bundled registry still fail the +build. The **Publish** GitHub Actions workflow runs the same build and attaches `wiser.zip` when an integration release is published. Preview runs provide a downloadable **wiser-package** artifact without publishing a release. diff --git a/custom_components/wiser/const.py b/custom_components/wiser/const.py index 2af6928e..e3f60a44 100755 --- a/custom_components/wiser/const.py +++ b/custom_components/wiser/const.py @@ -26,7 +26,7 @@ def _load_card_manifest(): ) return registry.get("cards", []) if isinstance(registry, dict) else registry except FileNotFoundError: - # Source checkouts have no card definitions; builds inject the registry. + # Keep setup resilient if an incomplete installation omits the registry. return [] diff --git a/custom_components/wiser/frontend/cards.json b/custom_components/wiser/frontend/cards.json new file mode 100644 index 00000000..4a701dca --- /dev/null +++ b/custom_components/wiser/frontend/cards.json @@ -0,0 +1,41 @@ +{ + "schema_version": 1, + "cards": [ + { + "id": "schedule", + "name": "Wiser Schedule Card", + "filename": "wiser-schedule-card.js", + "repository": "andyblac/wiser-schedule-card", + "component": "wiser-schedule-card", + "panel": "wiser-schedules-panel" + }, + { + "id": "zigbee", + "name": "Wiser Zigbee Card", + "filename": "wiser-zigbee-card.js", + "repository": "andyblac/wiser-zigbee-card", + "component": "wiser-zigbee-card", + "panel": "wiser-zigbee-panel" + }, + { + "id": "rooms", + "name": "Wiser Controls Card", + "filename": "wiser-controls-card.js", + "repository": "andyblac/wiser-controls-card", + "component": "wiser-controls-card", + "panel": "wiser-controls-panel", + "legacy_filenames": [ + "wiser-rooms-card.js" + ] + }, + { + "id": "hub", + "name": "Wiser Hub Panel", + "filename": "wiser-hub-panel.js", + "repository": "andyblac/wiser-hub-panel", + "component": "wiser-hub-panel", + "panel": "wiser-hub-panel", + "card": false + } + ] +} diff --git a/custom_components/wiser/frontend/registry.py b/custom_components/wiser/frontend/registry.py index 0727cf3b..02dc9a09 100644 --- a/custom_components/wiser/frontend/registry.py +++ b/custom_components/wiser/frontend/registry.py @@ -1,242 +1,33 @@ -"""Discover frontend cards independently of integration releases.""" +"""Load frontend definitions maintained inside the integration.""" -from hashlib import sha256 import json import logging from pathlib import Path -import re -from urllib.parse import urlsplit - -import aiohttp -from homeassistant.helpers.aiohttp_client import async_get_clientsession from ..const import CARD_MANIFEST -from .card_files import _atomic_write, newer_version -from .manifest import REGISTRY_SCHEMA_VERSION, validate_manifest, validate_registry +from .manifest import validate_registry _LOGGER = logging.getLogger(__name__) -REGISTRY_REPOSITORY = "andyblac/WiserFrontendPanelConfig" -REGISTRY_CACHE = ".storage/wiser_cards/registry.json" -REGISTRY_RELEASE_CACHE = ".storage/wiser_cards/registry-release.json" REGISTRY_DATA = "wiser_frontend_registry" -REGISTRY_VERSION_DATA = "wiser_frontend_registry_version" -_MAX_SIZE = 256 * 1024 +REGISTRY_PATH = Path(__file__).parent / "cards.json" def get_manifest(hass): - """Return the active registry, with bundled definitions as an offline fallback.""" + """Return the last valid local frontend registry.""" return hass.data.get(REGISTRY_DATA, CARD_MANIFEST) -def _merge_manifest(current, incoming): - """Keep omitted cards while allowing the registry to update known cards.""" - merged = {card["id"]: card for card in current} - for card in incoming: - merged[card["id"]] = card - return validate_manifest(list(merged.values())) - - -def _bundled_version(): - """Return the registry release bundled by the integration build.""" - try: - record = json.loads( - (Path(__file__).parent / "panel-config-release.json").read_text() - ) - tag = record.get("tag") or record.get("version") - return _release_version(tag) if tag else "0.0.0" - except (OSError, ValueError, TypeError, KeyError): - return "0.0.0" - - -def _load_cached(config_dir): - try: - cached = validate_registry(json.loads((Path(config_dir) / REGISTRY_CACHE).read_text())) - manifest = _merge_manifest(CARD_MANIFEST, cached) - except (OSError, ValueError, TypeError, KeyError): - return CARD_MANIFEST, _bundled_version() - try: - release = json.loads( - (Path(config_dir) / REGISTRY_RELEASE_CACHE).read_text() - ) - version = _release_version(release["version"], allow_prerelease=True) - except (OSError, ValueError, TypeError, KeyError): - version = _bundled_version() - return manifest, version +def _load_registry(): + """Read and validate the local registry.""" + return validate_registry(json.loads(REGISTRY_PATH.read_text("utf-8"))) async def async_load_registry(hass): - """Load the last valid registry without needing a network connection.""" - if REGISTRY_DATA not in hass.data: - manifest, version = await hass.async_add_executor_job( - _load_cached, hass.config.path() - ) - hass.data.setdefault(REGISTRY_DATA, manifest) - hass.data.setdefault(REGISTRY_VERSION_DATA, version) - return get_manifest(hass) - - -def get_registry_version(hass): - """Return the installed registry release version.""" - version = hass.data.get(REGISTRY_VERSION_DATA) - return version if version is not None else _bundled_version() - - -def _store_registry(config_dir, manifest, version): - document = ( - json.dumps( - {"schema_version": REGISTRY_SCHEMA_VERSION, "cards": manifest}, - indent=2, - ) - + "\n" - ).encode() - integration = Path(config_dir) / "custom_components/wiser/frontend" - integration.mkdir(parents=True, exist_ok=True) - _atomic_write(integration / "cards.json", document) - _atomic_write( - integration / "panel-config-release.json", - json.dumps( - { - "repository": REGISTRY_REPOSITORY, - "source": "runtime-update", - "asset": "cards.json", - "version": version, - } - ).encode(), - ) - path = Path(config_dir) / REGISTRY_CACHE - path.parent.mkdir(parents=True, exist_ok=True) - _atomic_write( - path, - document, - ) - _atomic_write( - Path(config_dir) / REGISTRY_RELEASE_CACHE, - json.dumps({"version": version}).encode(), - ) - - -def _release_version(tag, allow_prerelease=False): - """Validate a registry release tag for the selected update channel.""" - if not isinstance(tag, str): - raise ValueError("Invalid frontend registry release version") - value = tag.removeprefix("v") - if not re.fullmatch( - r"\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?", value - ): - raise ValueError("Invalid frontend registry release version") - if "-" in value.split("+", 1)[0] and not allow_prerelease: - raise ValueError("Frontend registry prerelease is not enabled") - return value - - -def _validate_release(metadata, allow_prerelease=False): - """Validate registry release metadata without downloading its asset.""" - if ( - not isinstance(metadata, dict) - or metadata.get("draft") - or not metadata.get("published_at") - or (metadata.get("prerelease") and not allow_prerelease) - ): - raise ValueError("Expected a published frontend registry release") - version = _release_version(metadata["tag_name"], allow_prerelease) - if not isinstance(metadata.get("assets"), list): - raise ValueError("Invalid frontend registry release assets") - assets = [ - asset - for asset in metadata["assets"] - if isinstance(asset, dict) - and asset.get("name") == "cards.json" - and asset.get("state") == "uploaded" - ] - if len(assets) != 1: - raise ValueError("Registry release must contain one cards.json asset") - asset = assets[0] - if ( - not isinstance(asset.get("browser_download_url"), str) - or type(asset.get("size")) is not int - ): - raise ValueError("Invalid frontend registry asset metadata") - url = urlsplit(asset["browser_download_url"]) - if ( - url.scheme != "https" - or url.netloc != "github.com" - or not url.path.startswith(f"/{REGISTRY_REPOSITORY}/releases/download/") - or not 0 < asset["size"] <= _MAX_SIZE - ): - raise ValueError("Invalid frontend registry asset") - return { - "version": version, - "asset": asset, - "release_url": ( - f"https://github.com/{REGISTRY_REPOSITORY}/releases/tag/" - f"{metadata['tag_name']}" - ), - } - - -def _select_release(releases, allow_prerelease): - """Select the highest valid registry release allowed by the channel.""" - selected = None - for metadata in releases: - try: - release = _validate_release(metadata, allow_prerelease) - except (ValueError, KeyError, TypeError): - continue - if selected is None or newer_version(release["version"], selected["version"]): - selected = release - if selected is None: - raise ValueError("No verified frontend registry release is available") - return selected - - -async def async_check_registry_release(hass, allow_prerelease=False): - """Check the latest registry release without changing installed config.""" - await async_load_registry(hass) - session = async_get_clientsession(hass) - endpoint = "releases?per_page=100" if allow_prerelease else "releases/latest" - async with session.get( - f"https://api.github.com/repos/{REGISTRY_REPOSITORY}/{endpoint}", - headers={ - "Accept": "application/vnd.github+json", - "User-Agent": "Wiser-Home-Assistant", - }, - timeout=aiohttp.ClientTimeout(total=20), - ) as response: - response.raise_for_status() - metadata = await response.json() - return ( - _select_release(metadata, True) - if allow_prerelease - else _validate_release(metadata) - ) - - -async def async_install_registry_release(hass, release): - """Download, verify, and atomically activate the offered registry release.""" - session = async_get_clientsession(hass) - asset = release["asset"] - async with session.get( - asset["browser_download_url"], timeout=aiohttp.ClientTimeout(total=20) - ) as response: - response.raise_for_status() - contents = bytearray() - async for chunk in response.content.iter_chunked(65536): - contents.extend(chunk) - if len(contents) > _MAX_SIZE: - raise ValueError("Frontend registry is too large") - if len(contents) != asset["size"]: - raise ValueError("Frontend registry size mismatch") - if ( - asset.get("digest") - and asset["digest"] != "sha256:" + sha256(contents).hexdigest() - ): - raise ValueError("Frontend registry checksum mismatch") - manifest = _merge_manifest( - get_manifest(hass), validate_registry(json.loads(contents)) - ) - await hass.async_add_executor_job( - _store_registry, hass.config.path(), manifest, release["version"] - ) + """Reload local definitions so a manual update check sees file edits.""" + try: + manifest = await hass.async_add_executor_job(_load_registry) + except (OSError, ValueError, TypeError, KeyError) as error: + _LOGGER.warning("Unable to load Wiser frontend registry: %s", error) + return get_manifest(hass) hass.data[REGISTRY_DATA] = manifest - hass.data[REGISTRY_VERSION_DATA] = release["version"] return manifest diff --git a/custom_components/wiser/update.py b/custom_components/wiser/update.py index 0dd796f7..69425ad4 100644 --- a/custom_components/wiser/update.py +++ b/custom_components/wiser/update.py @@ -17,23 +17,16 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.update_coordinator import CoordinatorEntity, DataUpdateCoordinator -from .const import DOMAIN +from .const import CARD_MANIFEST, DOMAIN from .frontend import JSModuleRegistration, async_card_resource from .frontend.card_files import newer_version, prune_card_cache, store_card +from .frontend.registry import async_load_registry from .frontend.wiser_sidebar import async_update_wiser_panel -from .frontend.registry import ( - async_check_registry_release, - async_install_registry_release, - async_load_registry, - get_manifest, - get_registry_version, -) _LOGGER = logging.getLogger(__name__) _MANAGER = "wiser_card_updates" _MAX_DOWNLOAD = 20 * 1024 * 1024 _HACS_REPOSITORY_ID = "159080189" -_REGISTRY = "_registry" def _release_version(tag, allow_prerelease=False): @@ -178,15 +171,13 @@ def __init__(self, hass): self.installing = set() self.pending_refresh = {} self.data = {} - self.cards = {card["id"]: card for card in get_manifest(hass)} + self.cards = {card["id"]: card for card in CARD_MANIFEST} self.added_cards = set() - self.registry_added = False def add_entities(self, entry_id): - """Transfer registry ownership before attaching the shared entities.""" + """Transfer update-entity ownership to the selected hub.""" self.owner = entry_id self.added_cards = set() - self.registry_added = False self._add_discovered_entities() def _add_discovered_entities(self): @@ -195,45 +186,27 @@ def _add_discovered_entities(self): return registry = er.async_get(self.hass) cards = self.cards.keys() - self.added_cards - entities = [] - if not self.registry_added: - entity_id = registry.async_get_entity_id( - "update", DOMAIN, "wiser_frontend_registry_update" - ) - if entity_id: - registry.async_update_entity(entity_id, config_entry_id=self.owner) - entities.append(WiserFrontendRegistryUpdate(self)) - self.registry_added = True + legacy_registry_entity = registry.async_get_entity_id( + "update", DOMAIN, "wiser_frontend_registry_update" + ) + if legacy_registry_entity: + registry.async_remove(legacy_registry_entity) for card in sorted(cards): entity_id = registry.async_get_entity_id("update", DOMAIN, f"wiser_{card}_card_update") if entity_id: registry.async_update_entity(entity_id, config_entry_id=self.owner) - entities.extend(WiserCardUpdate(self, card) for card in sorted(cards)) + entities = [WiserCardUpdate(self, card) for card in sorted(cards)] if entities: self.entries[self.owner](entities) self.added_cards.update(cards) async def _async_update_data(self): async with self.install_lock: - await async_load_registry(self.hass) - registry = await self._check_registry() - manifest = get_manifest(self.hass) + manifest = await async_load_registry(self.hass) self.cards = {card["id"]: card for card in manifest} results = await asyncio.gather(*(self._check_card(card) for card in self.cards)) self._add_discovered_entities() - return {_REGISTRY: registry, **dict(zip(self.cards, results))} - - async def _check_registry(self): - """Check registry releases without silently installing them.""" - installed = get_registry_version(self.hass) - try: - release = await async_check_registry_release( - self.hass, _prereleases_enabled(self.hass) - ) - return {"installed": installed, "release": release, "error": None} - except (aiohttp.ClientError, TimeoutError, ValueError, KeyError, TypeError) as err: - _LOGGER.warning("Unable to check Wiser frontend registry releases: %s", err) - return {"installed": installed, "release": None, "error": str(err)} + return dict(zip(self.cards, results)) async def _check_card(self, card): definition = self.cards[card] @@ -330,90 +303,6 @@ async def install(self, card): self.installing.discard(card) self.async_update_listeners() - async def install_registry(self): - """Install the offered frontend registry after an explicit update action.""" - async with self.install_lock: - state = self.data.get(_REGISTRY, {}) - release = state.get("release") - if not release: - raise HomeAssistantError( - "No verified frontend registry release is available" - ) - if not newer_version( - release["version"], state.get("installed", "0.0.0") - ): - return - self.installing.add(_REGISTRY) - self.async_update_listeners() - try: - manifest = await async_install_registry_release(self.hass, release) - self.cards = {card["id"]: card for card in manifest} - state["installed"] = release["version"] - results = await asyncio.gather( - *(self._check_card(card) for card in self.cards) - ) - self.data.update(dict(zip(self.cards, results))) - self._add_discovered_entities() - except ( - aiohttp.ClientError, - TimeoutError, - OSError, - ValueError, - RuntimeError, - ) as err: - raise HomeAssistantError( - f"Unable to install frontend registry update: {err}" - ) from err - finally: - self.installing.discard(_REGISTRY) - self.async_update_listeners() - - -class WiserFrontendRegistryUpdate(CoordinatorEntity, UpdateEntity): - """A user-installed update for WiserFrontendPanelConfig.""" - - _attr_supported_features = UpdateEntityFeature.INSTALL - _attr_entity_category = EntityCategory.CONFIG - _attr_has_entity_name = True - _attr_name = "Wiser Frontend Panel Config" - _attr_unique_id = "wiser_frontend_registry_update" - _attr_release_summary = ( - "Updates the card and panel definitions used by the Wiser integration." - ) - - @property - def available(self): - return ( - super().available - and self.coordinator.data.get(_REGISTRY, {}).get("release") is not None - ) - - @property - def installed_version(self): - return self.coordinator.data.get(_REGISTRY, {}).get("installed") - - @property - def latest_version(self): - release = self.coordinator.data.get(_REGISTRY, {}).get("release") - return release["version"] if release else None - - @property - def release_url(self): - release = self.coordinator.data.get(_REGISTRY, {}).get("release") - return release["release_url"] if release else None - - @property - def in_progress(self): - return _REGISTRY in self.coordinator.installing - - def version_is_newer(self, latest_version, installed_version): - return newer_version(latest_version, installed_version) - - async def async_install(self, version, backup, **kwargs): - """Install only after an explicit Home Assistant update action.""" - await self.coordinator.install_registry() - - class WiserCardUpdate(CoordinatorEntity, UpdateEntity): """A user-installed frontend card update, separate from hub firmware.""" diff --git a/docs/frontend-registry.md b/docs/frontend-registry.md index 59dfa6a9..228335d7 100644 --- a/docs/frontend-registry.md +++ b/docs/frontend-registry.md @@ -1,30 +1,42 @@ -# Adding frontend cards and panels - -After installing an integration version with runtime registry support, adding a -card or panel that uses the existing Wiser APIs requires no integration PR. - -1. Publish a release in the card repository with the JavaScript bundle attached. -2. Add its definition to `src/cards.json` in - [WiserFrontendPanelConfig](https://github.com/andyblac/WiserFrontendPanelConfig). -3. Build and publish a registry release with `cards.json` attached. -4. Home Assistant discovers the definition on its next daily card-update check. - To check sooner, run `homeassistant.update_entity` on an existing Wiser card - update entity. The registry and card checks follow the integration's HACS - prerelease switch. -5. Install the new card using its update entity, then refresh the browser. Its - Lovelace resource and any panel tab are registered automatically. A new card - without an installed version is offered with version `0.0.0`. - -Discovery downloads registry metadata only. JavaScript is downloaded when the -user installs the card. The integration retains the last valid registry and -installed bundles under `.storage/wiser_cards` across restarts and upgrades. -A missing or invalid registry release leaves the existing definitions in use. -Omitting a card from a later registry does not uninstall it or erase its settings. -Existing IDs, filenames, repositories and component names are treated as stable -identities; changing them requires an explicit migration rather than silently -redirecting an existing installation. - -## Registry definition +# Adding Wiser frontend cards and panels + +Wiser cards and panels are developed and released from their own repositories. The integration keeps only their definitions in `custom_components/wiser/frontend/cards.json`; compiled JavaScript bundles must not be committed to this repository. + +Adding a new definition requires an integration pull request and release. After that initial registration, new versions of the card or panel are released and updated independently through its Home Assistant update entity. + +## Choose the frontend type + +The registry supports three types of frontend bundle: + +| Type | `component` | `panel` | `card` | +| --- | --- | --- | --- | +| Lovelace card only | Card custom element | `null` | Omit or `true` | +| Sidebar panel only | Panel custom element | Panel custom element | `false` | +| Card and sidebar panel | Card custom element | Panel custom element | Omit or `true` | + +A panel-only bundle is not added to the Lovelace resources list. The integration loads it only for its Wiser sidebar tab. + +## Prepare the frontend repository + +The repository must publish a GitHub release containing one compiled JavaScript asset whose name exactly matches the registry `filename`. The asset must: + +- Be at least 100 bytes and contain JavaScript rather than an HTML error page. +- Define the custom element named by `component`. +- Define the custom element named by `panel` when one is configured. +- Use the shared `wiser/panel/configure` API instead of a panel-specific settings endpoint. +- Begin with a version marker matching the asset filename and release version. + +For `wiser-energy-card.js` version `1.0.0`, the marker is: + +```js +/*! WISER-CARD-VERSION wiser-energy-card 1.0.0 */ +``` + +Use semantic release tags such as `v1.0.0` or `v1.1.0-beta.1`. Stable update checks ignore prereleases. When the HACS **Pre-release** switch is enabled for the integration, update checks consider stable and prerelease versions. + +## Add the registry definition + +Add an entry to the `cards` array in `custom_components/wiser/frontend/cards.json`: ```json { @@ -37,26 +49,93 @@ redirecting an existing installation. } ``` -`cards.json` contains an array of these objects. The `id` is a stable registry -identifier independent of the filename. Use `null` for `panel` for a card with no -sidebar view. IDs, filenames, card components and non-null panel components must -be unique. -The runtime registry accepts up to 100 definitions and a 256 KiB registry asset. +The fields are: -The JavaScript release must include a matching version marker, for example: +| Field | Purpose | +| --- | --- | +| `id` | Stable internal identifier used for settings and the update entity. | +| `name` | Name displayed by the Home Assistant update entity. | +| `filename` | Exact JavaScript filename attached to every GitHub release. | +| `repository` | GitHub repository in `owner/repository` form. | +| `component` | Custom element defined by the JavaScript bundle. | +| `panel` | Sidebar panel custom element, or `null` for a card without a panel. | +| `card` | Set to `false` for a panel-only bundle; otherwise omit it. | +| `legacy_filenames` | Previous filenames retained only when migrating a renamed card. | -```js -/*! WISER-CARD-VERSION wiser-energy-card 1.0.0 */ +A card without a sidebar panel uses `"panel": null`. A panel-only definition uses the panel custom element for both `component` and `panel`: + +```json +{ + "id": "hub", + "name": "Wiser Hub Panel", + "filename": "wiser-hub-panel.js", + "repository": "andyblac/wiser-hub-panel", + "component": "wiser-hub-panel", + "panel": "wiser-hub-panel", + "card": false +} ``` -It must define the declared card and optional panel custom elements. The existing -card repositories demonstrate the panel contract. Each panel receives `hass` and -`panel.config`, including `panel_id`, `hubs`, `hub_ids`, per-hub `card_configs`, -and `card_url`. Always use the supplied `panel_id` when saving settings. +IDs, filenames, component names and non-null panel names must be unique. Treat them as permanent identities after release. Renaming one requires an explicit migration so existing resources, settings and entity history are preserved. The versioned registry document supports up to 100 definitions: -## Shared settings endpoint +```json +{ + "schema_version": 1, + "cards": [] +} +``` + +## Test registration locally + +For the normal development layout, place the frontend repository beside this integration repository and build its `dist/` output. A development integration build automatically prefers that local bundle: + +```text +GitHub/ +├── wiserHomeAssistantPlatform/ +└── wiser-energy-card/ + └── dist/ + └── wiser-energy-card.js +``` + +```sh +python3 scripts/build.py --channel dev +``` + +To test installation through Home Assistant instead, edit the installed `custom_components/wiser/frontend/cards.json` and run **Check for updates** on any Wiser frontend update entity. The shared coordinator reloads and validates the file, creates an update entity for the new definition, and offers it as installed version `0.0.0`. This does not require an integration rebuild or Home Assistant restart. + +To build a package containing the definitions but none of the JavaScript bundles, run: + +```sh +python3 scripts/build.py --channel dev --without-frontend +``` -New panels save preferences using this administrator-only WebSocket command: +This is useful for testing initial installation through all frontend update entities. The build does not contact any card or panel repository. + +You can override a repository during development without changing the registry: + +```sh +python3 scripts/build.py --channel dev \ + --repository energy=example/wiser-energy-card +``` + +## Submit the integration pull request + +The pull request for a new card or panel should contain: + +- Its entry in `custom_components/wiser/frontend/cards.json`. +- Any integration backend, WebSocket or shared-shell changes it requires. +- Tests for new integration behavior. +- A changelog entry when required by the integration contribution guidelines. + +Publish a usable frontend release before the integration release is built. If the frontend repository or release asset is unavailable during packaging, the integration build continues and omits that bundle. Its definition remains in `cards.json`, so Home Assistant can install it later through the update entity. + +After the definition has shipped, normal frontend releases require no further integration pull request. Publish the correctly named and versioned JavaScript asset in the frontend repository; Home Assistant will offer it through the existing update entity. + +## Sidebar panel contract + +Each registered panel receives `hass` and `panel.config`. The configuration includes `panel_id`, `hubs`, `hub_ids`, per-hub `card_configs`, and `card_url`. Use the supplied `panel_id` when saving settings. + +Panel preferences use the administrator-only shared WebSocket command: ```js await hass.callWS({ @@ -68,29 +147,6 @@ await hass.callWS({ }); ``` -The integration stores these settings under -`wiser_panel_config.energy` in each selected hub's options and refreshes the panel -without reloading the hub. All panels, including the existing ones, use this -command. The former per-panel -commands have been removed; deploy the rebuilt card bundles with this integration -bridge. There are no separate per-panel settings options or reload exclusions. -Tab ordering and custom titles continue to use -`wiser/panel/configure_tabs`. - -The shared panel shell and backend APIs still ship with the integration. New -backend commands, new hub data or changes to the shared shell require an -integration release; adding a card or panel using the existing contract does not. - -## Packaging and source ownership - -The integration repository contains no maintained card list. Builds read the -external registry's `dist/cards.json` for local development, or its published -release asset for release builds, and generate the package's offline snapshot. -The build loops over every definition, including new IDs and repositories. -Optional local overrides use `--repository ID=OWNER/REPOSITORY`; there are no -card-specific build flags. Publish the generic-API card bundles before building -an integration release with the bridge. - -Source checkouts without a generated snapshot start with an empty card list and -can discover definitions from the external registry. Normal ZIP installs include -the validated registry snapshot and card bundles for offline setup. +The integration stores this example under `wiser_panel_config.energy` in each selected hub's options and refreshes the panel without reloading the hub. Tab ordering and custom titles continue to use `wiser/panel/configure_tabs`. + +The shared panel shell and backend APIs ship with the integration. A panel that needs new backend commands, hub data or shared-shell behavior must include those changes in its integration pull request. diff --git a/scripts/build.py b/scripts/build.py index bd308011..7668050d 100644 --- a/scripts/build.py +++ b/scripts/build.py @@ -8,11 +8,10 @@ from zipfile import ZIP_DEFLATED, ZipFile from fetch_card_releases import ( - PANEL_CONFIG_REPOSITORY, fetch_cards, - fetch_panel_config, repository_overrides, select_repositories, + validate_registry, ) ROOT = Path(__file__).resolve().parents[1] @@ -25,7 +24,7 @@ def build( channel, repositories=None, release=False, - panel_config_repository=PANEL_CONFIG_REPOSITORY, + without_frontend=False, ): """Stage a fresh integration and replace the ZIP only after a successful build.""" # Stable builds and explicit releases must never package local card builds. @@ -38,14 +37,8 @@ def build( source, staging, ignore=shutil.ignore_patterns("__pycache__", "*.pyc", ".DS_Store"), ) - manifest, config_record = fetch_panel_config( - channel, - local_root=local_root, - release=release, - repository=panel_config_repository, - ) - (staging / "frontend/cards.json").write_text( - json.dumps({"schema_version": 1, "cards": manifest}, indent=2) + "\n" + manifest = validate_registry( + json.loads((staging / "frontend/cards.json").read_text("utf-8")) ) definitions = {card["id"]: card for card in manifest} selected_repositories = select_repositories(definitions, repositories or {}) @@ -56,9 +49,7 @@ def build( local_root=local_root, definitions=definitions, skip_unavailable=True, - ) - (staging / "frontend/panel-config-release.json").write_text( - json.dumps(config_record, indent=2) + "\n" + omit=without_frontend, ) archive_path = Path(temporary) / "wiser.zip" with ZipFile(archive_path, "w", compression=ZIP_DEFLATED) as archive: @@ -73,10 +64,7 @@ def build( staging / "frontend/card-releases.json", output.parent / "card-releases.json", ) - shutil.copyfile( - staging / "frontend/panel-config-release.json", - output.parent / "panel-config-release.json", - ) + (output.parent / "panel-config-release.json").unlink(missing_ok=True) return report @@ -90,7 +78,9 @@ def main(): parser.add_argument("--output", type=Path, default=ROOT / "dist/wiser.zip") parser.add_argument("--repository", action="append", default=[], metavar="ID=OWNER/REPO") parser.add_argument( - "--panel-config-repository", default=PANEL_CONFIG_REPOSITORY + "--without-frontend", + action="store_true", + help="Package cards.json without any card or panel JavaScript bundles", ) args = parser.parse_args() try: @@ -99,7 +89,7 @@ def main(): args.channel, repository_overrides(args.repository), release=args.release, - panel_config_repository=args.panel_config_repository, + without_frontend=args.without_frontend, ) except Exception as error: parser.exit(1, f"Build failed: {error}\n") diff --git a/scripts/fetch_card_releases.py b/scripts/fetch_card_releases.py index 1a825b1f..be259255 100644 --- a/scripts/fetch_card_releases.py +++ b/scripts/fetch_card_releases.py @@ -12,8 +12,7 @@ from urllib.request import Request, urlopen ROOT = Path(__file__).resolve().parents[1] -PANEL_CONFIG_REPOSITORY = "andyblac/WiserFrontendPanelConfig" -PANEL_CONFIG_FILENAME = "cards.json" +REGISTRY_PATH = ROOT / "custom_components/wiser/frontend/cards.json" # Load the dependency-free schema without importing the Home Assistant package. @@ -28,54 +27,6 @@ validate_registry = _MANIFEST.validate_registry -def fetch_panel_config( - channel, - local_root=None, - release=False, - repository=PANEL_CONFIG_REPOSITORY, -): - """Load definitions exclusively from the external registry build or release.""" - local = ( - Path(local_root) / repository.rsplit("/", 1)[-1] / "dist" / PANEL_CONFIG_FILENAME - if local_root is not None and not release - else None - ) - if local is not None and local.is_file(): - contents = local.read_bytes() - build_info = local.with_name("build-info.json") - version = None - if build_info.is_file(): - version = json.loads(build_info.read_text()).get("version") - record = { - "repository": repository, - "source": "local", - "asset": PANEL_CONFIG_FILENAME, - "path": str(local.resolve()), - "digest": "sha256:" + sha256(contents).hexdigest(), - } - if version: - record["version"] = version - else: - selected = select_release(list_releases(repository), channel) - asset = select_asset(selected, PANEL_CONFIG_FILENAME) - contents, digest = download_asset(repository, asset) - record = { - "repository": repository, - "source": "release", - "tag": selected["tag_name"], - "prerelease": selected["prerelease"], - "asset": PANEL_CONFIG_FILENAME, - "asset_id": asset["id"], - "url": asset["browser_download_url"], - "digest": digest, - } - try: - manifest = json.loads(contents) - except (TypeError, json.JSONDecodeError) as error: - raise ValueError("Invalid cards.json") from error - return validate_registry(manifest), record - - def list_releases(repository): if not re.fullmatch(r"[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+", repository): raise ValueError(f"Invalid repository: {repository}") @@ -139,6 +90,7 @@ def fetch_cards( plan=False, local_root=None, skip_unavailable=False, + omit=False, ): report = [] payloads = {} @@ -147,6 +99,14 @@ def fetch_cards( for card, repository in repositories.items(): definition = definitions[card] filename = definition["filename"] + if omit: + omitted.update((filename, *definition.get("legacy_filenames", []))) + report.append({ + "repository": repository, + "source": "omitted", + "asset": filename, + }) + continue local = ( Path(local_root) / repository.rsplit("/", 1)[-1] / "dist" / filename if local_root is not None else None @@ -240,11 +200,10 @@ def main(): parser.add_argument("--output-dir", type=Path, default=Path("dist/wiser/frontend")) parser.add_argument("--card", default="all", help="Registry card ID, or all") parser.add_argument("--repository", action="append", default=[], metavar="ID=OWNER/REPO") - parser.add_argument("--panel-config-repository", default=PANEL_CONFIG_REPOSITORY) parser.add_argument("--plan", action="store_true", help="Resolve registry and releases without downloading card bundles") args = parser.parse_args() try: - manifest, _ = fetch_panel_config(args.channel, release=True, repository=args.panel_config_repository) + manifest = validate_registry(json.loads(REGISTRY_PATH.read_text("utf-8"))) definitions = {card["id"]: card for card in manifest} repositories = select_repositories(definitions, repository_overrides(args.repository)) if args.card != "all": diff --git a/tests/test_build.py b/tests/test_build.py index eb042f72..c8cc5bf8 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -28,31 +28,34 @@ def setUp(self): frontend = self.source / "frontend" frontend.mkdir(parents=True) self.output = self.root / "dist/wiser.zip" + self.output.parent.mkdir() + (self.output.parent / "panel-config-release.json").write_text("obsolete") self.payloads = { "schedule": b'customElements.define("wiser-schedule-card",class{});customElements.define("wiser-schedules-panel",class{})', "zigbee": b'customElements.define("wiser-zigbee-card",class{});customElements.define("wiser-zigbee-panel",class{})', "rooms": ( - b'customElements.define("wiser-rooms-card",class{});' - b'customElements.define("wiser-rooms-panel",class{})' + b'customElements.define("wiser-controls-card",class{});' + b'customElements.define("wiser-controls-panel",class{})' ), + "hub": b'customElements.define("wiser-hub-panel",class{})', } - registry = self.root / "WiserFrontendPanelConfig/dist/cards.json" - registry.parent.mkdir(parents=True) - registry.write_text( - json.dumps(CARD_MANIFEST), encoding="utf-8" - ) - registry.with_name("build-info.json").write_text( - json.dumps({"version": "1.0.1"}), encoding="utf-8" + (frontend / "cards.json").write_text( + json.dumps({"schema_version": 1, "cards": CARD_MANIFEST}), + encoding="utf-8", ) - for card, panel in (("schedule", "schedules"), ("zigbee", "zigbee")): - (frontend / f"{panel}_sidebar.py").touch() - (frontend / f"wiser-{card}-card.js").write_bytes(b"old tracked bundle") - (frontend / "wiser-rooms-card.js").write_bytes(b"old tracked bundle") + for definition in CARD_MANIFEST: + (frontend / definition["filename"]).write_bytes(b"old tracked bundle") (frontend / "__pycache__").mkdir() (frontend / "__pycache__/old.pyc").touch() def local(self, card): - path = self.root / f"wiser-{card}-card/dist/wiser-{card}-card.js" + definition = next(item for item in CARD_MANIFEST if item["id"] == card) + path = ( + self.root + / definition["repository"].rsplit("/", 1)[-1] + / "dist" + / definition["filename"] + ) path.parent.mkdir(parents=True) path.write_bytes(self.payloads[card]) return path @@ -60,18 +63,24 @@ def local(self, card): def build(self): return BUILD.build(self.source, self.output, self.root, "dev", CARD_REPOSITORIES) + def filename(self, card): + return next( + item["filename"] for item in CARD_MANIFEST if item["id"] == card + ) + def test_local_bundles_win_without_network_and_tracked_files_are_untouched(self): for card in self.payloads: self.local(card) with patch.object(FETCH, "list_releases") as releases: report = self.build() releases.assert_not_called() - self.assertEqual([r["source"] for r in report], ["local", "local", "local"]) + self.assertEqual([r["source"] for r in report], ["local"] * 4) with ZipFile(self.output) as archive: for card, payload in self.payloads.items(): - self.assertEqual(archive.read(f"frontend/wiser-{card}-card.js"), payload) + filename = self.filename(card) + self.assertEqual(archive.read(f"frontend/{filename}"), payload) self.assertEqual( - (self.source / f"frontend/wiser-{card}-card.js").read_bytes(), + (self.source / f"frontend/{filename}").read_bytes(), b"old tracked bundle", ) self.assertEqual(json.loads(archive.read("frontend/card-releases.json")), report) @@ -79,37 +88,70 @@ def test_local_bundles_win_without_network_and_tracked_files_are_untouched(self) json.loads(archive.read("frontend/cards.json")), {"schema_version": 1, "cards": CARD_MANIFEST}, ) - self.assertEqual( - json.loads(archive.read("frontend/panel-config-release.json"))["version"], - "1.0.1", - ) self.assertFalse(any("__pycache__" in name for name in archive.namelist())) + self.assertFalse((self.output.parent / "panel-config-release.json").exists()) def test_missing_local_bundle_falls_back_independently(self): self.local("zigbee") self.local("rooms") + self.local("hub") with patch.object(FETCH, "list_releases", return_value=[release("v1", "2026", card="schedule")]) as releases, patch.object(FETCH, "download_asset", return_value=(self.payloads["schedule"], "sha256:test")): report = self.build() releases.assert_called_once_with(CARD_REPOSITORIES["schedule"]) - self.assertEqual([r["source"] for r in report], ["release", "local", "local"]) + self.assertEqual( + [r["source"] for r in report], + ["release", "local", "local", "local"], + ) + + def test_without_frontend_keeps_registry_and_omits_every_bundle(self): + for card in self.payloads: + self.local(card) + (self.source / "frontend/wiser-rooms-card.js").write_bytes( + b"old legacy bundle" + ) + with patch.object(FETCH, "list_releases") as releases: + report = BUILD.build( + self.source, + self.output, + self.root, + "dev", + CARD_REPOSITORIES, + without_frontend=True, + ) + + releases.assert_not_called() + self.assertEqual([item["source"] for item in report], ["omitted"] * 4) + with ZipFile(self.output) as archive: + names = archive.namelist() + for definition in CARD_MANIFEST: + self.assertNotIn(f"frontend/{definition['filename']}", names) + self.assertNotIn("frontend/wiser-rooms-card.js", names) + self.assertEqual( + json.loads(archive.read("frontend/cards.json")), + {"schema_version": 1, "cards": CARD_MANIFEST}, + ) def test_no_local_bundles_downloads_all_releases(self): with patch.object(FETCH, "list_releases", side_effect=[ [release("v1", "2026", card="schedule")], [release("v2", "2026", card="zigbee")], [release("v3", "2026", card="rooms")], + [release("v4", "2026", card="hub")], ]), patch.object(FETCH, "download_asset", side_effect=[ (self.payloads["schedule"], "sha256:schedule"), (self.payloads["zigbee"], "sha256:zigbee"), (self.payloads["rooms"], "sha256:rooms"), + (self.payloads["hub"], "sha256:hub"), ]): report = self.build() - self.assertEqual([r["source"] for r in report], ["release", "release", "release"]) + self.assertEqual([r["source"] for r in report], ["release"] * 4) with ZipFile(self.output) as archive: for card, payload in self.payloads.items(): - self.assertEqual(archive.read(f"frontend/wiser-{card}-card.js"), payload) + self.assertEqual( + archive.read(f"frontend/{self.filename(card)}"), payload + ) - def test_external_registry_alone_adds_an_unknown_card_and_repository(self): + def test_bundled_registry_adds_an_unknown_card_and_repository(self): for card in self.payloads: self.local(card) definition = { @@ -118,7 +160,9 @@ def test_external_registry_alone_adds_an_unknown_card_and_repository(self): "component": "wiser-electricity-card", "panel": "wiser-electricity-panel", } manifest = [*CARD_MANIFEST, definition] - (self.root / "WiserFrontendPanelConfig/dist/cards.json").write_text(json.dumps(manifest)) + (self.source / "frontend/cards.json").write_text( + json.dumps({"schema_version": 1, "cards": manifest}) + ) bundle = self.root / "monitoring/dist/wiser-electricity-card.js" bundle.parent.mkdir(parents=True) bundle.write_bytes(b"customElements.define('wiser-electricity-card',class{});customElements.define('wiser-electricity-panel',class{})") @@ -142,13 +186,13 @@ def test_build_rejects_bundle_using_removed_settings_endpoint(self): def test_failed_fallback_omits_only_the_unavailable_bundle(self): self.local("schedule") self.local("rooms") - self.output.parent.mkdir() + self.local("hub") self.output.write_bytes(b"previous package") with patch.object(FETCH, "list_releases", side_effect=ValueError("unavailable")): report = self.build() self.assertEqual( [record["source"] for record in report], - ["local", "unavailable", "local"], + ["local", "unavailable", "local", "local"], ) self.assertEqual(report[1]["error"], "unavailable") with ZipFile(self.output) as archive: @@ -158,7 +202,7 @@ def test_failed_fallback_omits_only_the_unavailable_bundle(self): self.payloads["schedule"], ) self.assertEqual( - archive.read("frontend/wiser-rooms-card.js"), + archive.read("frontend/wiser-controls-card.js"), self.payloads["rooms"], ) self.assertEqual( @@ -179,28 +223,27 @@ def test_release_builds_ignore_local_bundles_for_both_channels(self): self.local(card) for channel, explicit_release in (("dev", True), ("stable", True), ("stable", False)): with self.subTest(channel=channel, explicit_release=explicit_release): - with patch.object(BUILD, "fetch_panel_config", return_value=( - CARD_MANIFEST, - {"repository": FETCH.PANEL_CONFIG_REPOSITORY, "source": "release"}, - )), patch.object(FETCH, "list_releases", side_effect=[ + with patch.object(FETCH, "list_releases", side_effect=[ [release("v1", "2026", card="schedule")], [release("v2", "2026", card="zigbee")], [release("v3", "2026", card="rooms")], + [release("v4", "2026", card="hub")], ]), patch.object(FETCH, "download_asset", side_effect=[ (self.payloads["schedule"], "sha256:schedule"), (self.payloads["zigbee"], "sha256:zigbee"), ( - b'customElements.define("wiser-rooms-card",class{});' - b'customElements.define("wiser-rooms-panel",class{})', + b'customElements.define("wiser-controls-card",class{});' + b'customElements.define("wiser-controls-panel",class{})', "sha256:rooms", ), + (self.payloads["hub"], "sha256:hub"), ]) as download: report = BUILD.build( self.source, self.output, self.root, channel, CARD_REPOSITORIES, release=explicit_release, ) - self.assertEqual(download.call_count, 3) - self.assertEqual([r["source"] for r in report], ["release", "release", "release"]) + self.assertEqual(download.call_count, 4) + self.assertEqual([r["source"] for r in report], ["release"] * 4) with ZipFile(self.output) as archive: self.assertEqual( archive.read("frontend/wiser-zigbee-card.js"), @@ -211,21 +254,20 @@ def test_release_builds_ignore_local_bundles_for_both_channels(self): {"schema_version": 1, "cards": CARD_MANIFEST}, ) self.assertEqual( - json.loads(archive.read("frontend/panel-config-release.json"))["source"], - "release", + archive.read("frontend/wiser-controls-card.js"), + self.payloads["rooms"], ) def test_stable_build_omits_an_unavailable_published_bundle(self): - with patch.object(BUILD, "fetch_panel_config", return_value=( - CARD_MANIFEST, - {"repository": FETCH.PANEL_CONFIG_REPOSITORY, "source": "release"}, - )), patch.object(FETCH, "list_releases", side_effect=[ + with patch.object(FETCH, "list_releases", side_effect=[ [release("v1", "2026", card="schedule")], ValueError("repository unavailable"), [release("v3", "2026", card="rooms")], + [release("v4", "2026", card="hub")], ]), patch.object(FETCH, "download_asset", side_effect=[ (self.payloads["schedule"], "sha256:schedule"), (self.payloads["rooms"], "sha256:rooms"), + (self.payloads["hub"], "sha256:hub"), ]): report = BUILD.build( self.source, self.output, self.root, "stable", CARD_REPOSITORIES, @@ -233,24 +275,25 @@ def test_stable_build_omits_an_unavailable_published_bundle(self): self.assertEqual( [record["source"] for record in report], - ["release", "unavailable", "release"], + ["release", "unavailable", "release", "release"], ) with ZipFile(self.output) as archive: self.assertIn("frontend/wiser-schedule-card.js", archive.namelist()) self.assertNotIn("frontend/wiser-zigbee-card.js", archive.namelist()) - self.assertIn("frontend/wiser-rooms-card.js", archive.namelist()) + self.assertIn("frontend/wiser-controls-card.js", archive.namelist()) + self.assertIn("frontend/wiser-hub-panel.js", archive.namelist()) self.assertEqual( json.loads(archive.read("frontend/cards.json")), {"schema_version": 1, "cards": CARD_MANIFEST}, ) - def test_release_failure_does_not_fall_back_to_local_bundles(self): + def test_release_failure_omits_bundles_without_falling_back_to_local(self): for card in self.payloads: self.local(card) with patch.object(FETCH, "list_releases", side_effect=ValueError("unavailable")): - with self.assertRaisesRegex(ValueError, "unavailable"): - BUILD.build( - self.source, self.output, self.root, "dev", - CARD_REPOSITORIES, release=True, - ) - self.assertFalse(self.output.exists()) + report = BUILD.build( + self.source, self.output, self.root, "dev", + CARD_REPOSITORIES, release=True, + ) + self.assertTrue(self.output.exists()) + self.assertTrue(all(item["source"] == "unavailable" for item in report)) diff --git a/tests/test_card_releases.py b/tests/test_card_releases.py index ea05be6c..d6d25043 100644 --- a/tests/test_card_releases.py +++ b/tests/test_card_releases.py @@ -11,16 +11,24 @@ SPEC.loader.exec_module(FETCH) -CARD_MANIFEST = json.loads((Path(__file__).parent / "fixtures/frontend_cards.json").read_text()) +CARD_MANIFEST = json.loads( + ( + Path(__file__).resolve().parents[1] + / "custom_components/wiser/frontend/cards.json" + ).read_text() +)["cards"] CARD_REPOSITORIES = {card["id"]: card["repository"] for card in CARD_MANIFEST} CARD_DEFINITIONS = {card["id"]: card for card in CARD_MANIFEST} def release(tag, date, prerelease=False, card="zigbee", draft=False, asset=True): + definition = CARD_DEFINITIONS[card] + filename = definition["filename"] + repository = definition["repository"] return { "tag_name": tag, "published_at": date, "prerelease": prerelease, "draft": draft, - "assets": [{"id": 1, "name": f"wiser-{card}-card.js", "state": "uploaded", "size": 200, - "browser_download_url": f"https://github.com/andyblac/wiser-{card}-card/releases/download/{tag}/wiser-{card}-card.js"}] if asset else [], + "assets": [{"id": 1, "name": filename, "state": "uploaded", "size": 200, + "browser_download_url": f"https://github.com/{repository}/releases/download/{tag}/{filename}"}] if asset else [], } @@ -68,29 +76,7 @@ def test_missing_release_or_asset_fails(self): with self.assertRaisesRegex(ValueError, "must have one"): FETCH.select_asset(release("missing", "2026", asset=False), "wiser-zigbee-card.js") - def test_external_panel_config_prefers_local_build(self): - with TemporaryDirectory() as directory: - root = Path(directory) - built = root / "WiserFrontendPanelConfig/dist/cards.json" - built.parent.mkdir(parents=True) - built.write_text(json.dumps(CARD_MANIFEST)) - with patch.object(FETCH, "list_releases") as releases: - manifest, record = FETCH.fetch_panel_config( - "dev", local_root=root - ) - releases.assert_not_called() - self.assertEqual(manifest, CARD_MANIFEST) - self.assertEqual(record["source"], "local") - - def test_external_panel_config_rejects_invalid_registry(self): - with TemporaryDirectory() as directory: - packaged = Path(directory) / "WiserFrontendPanelConfig/dist/cards.json" - packaged.parent.mkdir(parents=True) - packaged.write_text('[{"id":"bad"}]') - with self.assertRaisesRegex(ValueError, "Invalid frontend card"): - FETCH.fetch_panel_config("dev", local_root=Path(directory)) - - def test_external_registry_accepts_panel_only_bundle_definition(self): + def test_registry_accepts_panel_only_bundle_definition(self): definition = { "id": "hub", "name": "Wiser Hub Panel", @@ -102,42 +88,11 @@ def test_external_registry_accepts_panel_only_bundle_definition(self): } self.assertEqual(FETCH.validate_card_manifest([definition]), [definition]) - def test_external_registry_rejects_invalid_card_flag(self): + def test_registry_rejects_invalid_card_flag(self): definition = CARD_MANIFEST[0] | {"card": "false"} with self.assertRaisesRegex(ValueError, "card flag"): FETCH.validate_card_manifest([definition]) - def test_release_build_fetches_published_panel_config(self): - published = { - "tag_name": "v1.0.0-beta.1", - "published_at": "2026-09-29T00:00:00Z", - "prerelease": True, - "draft": False, - "assets": [{ - "id": 42, - "name": "cards.json", - "state": "uploaded", - "size": 661, - "browser_download_url": ( - "https://github.com/andyblac/WiserFrontendPanelConfig/" - "releases/download/v1.0.0-beta.1/cards.json" - ), - }], - } - payload = json.dumps(CARD_MANIFEST).encode() - with patch.object(FETCH, "list_releases", return_value=[published]), patch.object( - FETCH, "download_asset", return_value=(payload, "sha256:registry") - ) as download: - manifest, record = FETCH.fetch_panel_config( - "dev", release=True - ) - download.assert_called_once_with( - FETCH.PANEL_CONFIG_REPOSITORY, published["assets"][0] - ) - self.assertEqual(manifest, CARD_MANIFEST) - self.assertEqual(record["tag"], "v1.0.0-beta.1") - self.assertEqual(record["digest"], "sha256:registry") - def test_plan_does_not_download_or_write(self): with TemporaryDirectory() as directory: out = Path(directory) / "not-created" diff --git a/tests/test_card_updates.py b/tests/test_card_updates.py index 73e38f85..a6eb2698 100644 --- a/tests/test_card_updates.py +++ b/tests/test_card_updates.py @@ -57,7 +57,9 @@ def setUp(self): self.addCleanup(self.temporary.cleanup) self.directory = Path(self.temporary.name) self.registry = SimpleNamespace( - async_get_entity_id=Mock(return_value=None), async_update_entity=Mock() + async_get_entity_id=Mock(return_value=None), + async_update_entity=Mock(), + async_remove=Mock(), ) self.session = Mock() self.registration = SimpleNamespace(async_register=AsyncMock()) @@ -66,9 +68,9 @@ def setUp(self): "card_update_test": module("card_update_test", __path__=[str(ROOT)]), "card_update_test.const": module( "card_update_test.const", URL_BASE="/wiser", DOMAIN="wiser", - CARD_MANIFEST=json.loads( - (Path(__file__).parent / "fixtures/frontend_cards.json").read_text() - ), + CARD_MANIFEST=json.loads((ROOT / "frontend/cards.json").read_text())[ + "cards" + ], ), "card_update_test.frontend": frontend, "homeassistant": module("homeassistant"), @@ -100,18 +102,6 @@ async def resource(hass, filename): states=SimpleNamespace(is_state=Mock(return_value=False)), ) self.coordinator = self.updates.CardUpdateCoordinator(self.hass) - self.manifest = list(self.coordinator.cards.values()) - self.updates.async_load_registry = AsyncMock( - side_effect=lambda hass: self.updates.get_manifest(hass) - ) - self.updates.get_registry_version = Mock(return_value="1.0.0") - self.updates.async_check_registry_release = AsyncMock( - return_value={ - "version": "1.0.0", - "asset": {}, - "release_url": "https://github.com/andyblac/WiserFrontendPanelConfig/releases/tag/v1.0.0", - } - ) def payload(self, card="zigbee", version="2.0.0"): definition = self.coordinator.cards[card] @@ -146,160 +136,51 @@ async def chunks(size): })() return context - def extra_card(self): - return { - "id": "energy", "name": "Wiser Energy Card", - "filename": "wiser-energy-card.js", "repository": "andyblac/wiser-energy-card", - "component": "wiser-energy-card", "panel": "wiser-energy-panel", + async def test_update_check_reloads_local_registry_and_discovers_new_card(self): + definition = { + "id": "energy", + "name": "Wiser Energy Card", + "filename": "wiser-energy-card.js", + "repository": "andyblac/wiser-energy-card", + "component": "wiser-energy-card", + "panel": "wiser-energy-panel", } - - def registry_response(self, manifest): - contents = json.dumps(manifest).encode() registry = sys.modules["card_update_test.frontend.registry"] - release = { - "tag_name": "v1.0.0", - "published_at": "2026-09-29", "draft": False, "prerelease": False, - "assets": [{"name": "cards.json", "state": "uploaded", "size": len(contents), - "digest": "sha256:" + sha256(contents).hexdigest(), - "browser_download_url": f"https://github.com/{registry.REGISTRY_REPOSITORY}/releases/download/v1/cards.json"}], - } - self.session.get.side_effect = [self.response(json_data=release), self.response(contents=contents)] - return registry - - async def test_runtime_registry_adds_card_and_survives_restart_offline(self): - registry = self.registry_response([*self.manifest, self.extra_card()]) - release = await registry.async_check_registry_release(self.hass) - manifest = await registry.async_install_registry_release(self.hass, release) - self.assertEqual(manifest[-1], self.extra_card()) - installed = self.directory / "custom_components/wiser/frontend" - installed_registry = (installed / "cards.json").read_text() - self.assertTrue(installed_registry.startswith('{\n "schema_version": 1,')) - self.assertTrue(installed_registry.endswith("\n")) - self.assertEqual( - json.loads(installed_registry)["cards"], manifest + registry_path = self.directory / "cards.json" + registry_path.write_text( + json.dumps( + { + "schema_version": 1, + "cards": [*self.coordinator.cards.values(), definition], + } + ) ) - self.assertEqual( - json.loads((installed / "panel-config-release.json").read_text())[ - "version" - ], - "1.0.0", + self.coordinator._check_card = AsyncMock( + return_value={"installed": "0.0.0", "release": None, "error": None} ) - self.hass.data.clear() - restored = await registry.async_load_registry(self.hass) - self.assertEqual(restored, manifest) - import aiohttp - self.session.get.side_effect = aiohttp.ClientError("offline") - with self.assertRaises(aiohttp.ClientError): - await registry.async_check_registry_release(self.hass) + add = Mock() + self.coordinator.entries["hub"] = add + self.coordinator.add_entities("hub") + add.reset_mock() - async def test_loaded_registry_version_does_not_read_bundled_metadata(self): - registry = sys.modules["card_update_test.frontend.registry"] - self.hass.data[registry.REGISTRY_VERSION_DATA] = "1.0.2" - with patch.object( - registry, "_bundled_version", side_effect=AssertionError("file read") - ): - self.assertEqual(registry.get_registry_version(self.hass), "1.0.2") - - async def test_invalid_registry_does_not_replace_last_good_cache(self): - registry = self.registry_response([*self.manifest, self.extra_card()]) - release = await registry.async_check_registry_release(self.hass) - original = await registry.async_install_registry_release(self.hass, release) - cache = self.directory / registry.REGISTRY_CACHE - previous = cache.read_bytes() - self.registry_response([self.extra_card() | {"filename": "../unsafe.js"}]) - release = await registry.async_check_registry_release(self.hass) - with self.assertRaises(ValueError): - await registry.async_install_registry_release(self.hass, release) - self.assertEqual(registry.get_manifest(self.hass), original) - self.assertEqual(cache.read_bytes(), previous) + with patch.object(registry, "REGISTRY_PATH", registry_path): + await self.coordinator.async_refresh() - async def test_registry_checksum_failure_preserves_bundled_fallback(self): - registry = sys.modules["card_update_test.frontend.registry"] - contents = json.dumps([self.extra_card()]).encode() - metadata = {"tag_name": "v1.0.0", "published_at": "2026-09-29", "assets": [{ - "name": "cards.json", "state": "uploaded", "size": len(contents), - "digest": "sha256:" + "0" * 64, - "browser_download_url": f"https://github.com/{registry.REGISTRY_REPOSITORY}/releases/download/v1/cards.json", - }]} - self.session.get.side_effect = [self.response(json_data=metadata), self.response(contents=contents)] - release = await registry.async_check_registry_release(self.hass) - with self.assertRaises(ValueError): - await registry.async_install_registry_release(self.hass, release) - self.assertEqual(registry.get_manifest(self.hass), self.manifest) - self.assertFalse((self.directory / registry.REGISTRY_CACHE).exists()) + self.assertIn("energy", self.coordinator.cards) + self.assertEqual([entity.card for entity in add.call_args.args[0]], ["energy"]) - async def test_registry_accepts_identity_changes_and_rejects_duplicates(self): + async def test_invalid_local_registry_keeps_last_valid_definitions(self): registry = sys.modules["card_update_test.frontend.registry"] - changed = self.manifest[0] | { - "filename": "wiser-renamed-card.js", - "legacy_filenames": [self.manifest[0]["filename"]], - "repository": "other/repository", - "component": "wiser-renamed-card", - "panel": "wiser-renamed-panel", - } - self.assertEqual(registry._merge_manifest(self.manifest, [changed])[0], changed) - with self.assertRaises(ValueError): - registry.validate_manifest([self.extra_card(), self.extra_card() | { - "id": "other", "filename": "wiser-other-card.js" - }]) - self.assertEqual(registry._merge_manifest(self.manifest, []), self.manifest) - - async def test_registry_rejects_foreign_release_asset_without_downloading(self): - registry = self.registry_response([self.extra_card()]) - # Use an explicit release from another host. - self.session.get.side_effect = None - self.session.get.return_value = self.response(json_data={ - "tag_name": "v1.0.0", "published_at": "2026-09-29", "assets": [{"name": "cards.json", "state": "uploaded", - "size": 123, "browser_download_url": "https://example.com/cards.json"}], - }) - with self.assertRaises(ValueError): - await registry.async_check_registry_release(self.hass) - self.session.get.assert_called_once() + self.hass.data[registry.REGISTRY_DATA] = list(self.coordinator.cards.values()) + registry_path = self.directory / "cards.json" + registry_path.write_text('{"schema_version": 1, "cards": [{"id": "bad"}]}') - async def test_new_card_entity_is_discovered_once_and_installed_without_bundle(self): - definition = self.extra_card() - registry = sys.modules["card_update_test.frontend.registry"] - self.hass.data[registry.REGISTRY_DATA] = [*self.manifest, definition] - self.coordinator._check_card = AsyncMock(return_value={"installed": "0.0.0", "release": None}) - add = Mock() - self.coordinator.entries["hub"] = add - self.coordinator.add_entities("hub") - add.reset_mock() - await self.coordinator.async_refresh() - add.assert_called_once() - entities = add.call_args.args[0] - self.assertEqual([entity.card for entity in entities], ["energy"]) - self.assertEqual(entities[0].name, definition["name"]) - add.reset_mock() - await self.coordinator.async_refresh() - add.assert_not_called() - self.assertNotIn("energy", {card["id"] for card in self.manifest}) - - contents = ( - "/*! WISER-CARD-VERSION wiser-energy-card 1.0.0 */\n" - "customElements.define('wiser-energy-card', class extends HTMLElement {});" - "customElements.define('wiser-energy-panel', class extends HTMLElement {});" - ).encode() - metadata = {"tag_name": "v1.0.0", "published_at": "2026-09-29", "assets": [{ - "name": definition["filename"], "state": "uploaded", "size": len(contents), - "browser_download_url": "https://github.com/andyblac/wiser-energy-card/releases/download/v1.0.0/wiser-energy-card.js", - "digest": "sha256:" + sha256(contents).hexdigest(), - }]} - self.version_reader.return_value = "missing" - self.session.get.return_value = self.response(json_data=metadata) - state = await self.updates.CardUpdateCoordinator._check_card(self.coordinator, "energy") - self.assertEqual(state["installed"], "0.0.0") - self.coordinator.data["energy"] = state - self.session.get.return_value = self.response(contents=contents) - await self.coordinator.install("energy") - self.assertEqual(self.coordinator.data["energy"]["installed"], "1.0.0") - self.registration.async_register.assert_awaited_once() - self.updates.async_update_wiser_panel.assert_awaited_once() - # A fresh resolver still finds the downloaded card without any bundled copy. - path, url, version = self.files.resolve_card(self.directory, definition["filename"], self.version_reader) - self.assertEqual(path.read_bytes(), contents) - self.assertEqual(version, "1.0.0") - self.assertIn("/wiser/cards/", url) + with patch.object(registry, "REGISTRY_PATH", registry_path), self.assertLogs( + "card_update_test.frontend.registry", level="WARNING" + ): + manifest = await registry.async_load_registry(self.hass) + + self.assertEqual(manifest, list(self.coordinator.cards.values())) def test_rejects_bundle_using_removed_panel_specific_settings_api(self): definition = self.coordinator.cards["zigbee"] @@ -314,8 +195,8 @@ def test_rooms_release_is_validated_and_cached_independently(self): release = self.updates._validate_release(self.coordinator.cards["rooms"], self.metadata("rooms")) contents = self.payload("rooms") self.updates._validate_download(self.coordinator.cards["rooms"], release, contents) - self.files.store_card(self.directory, "wiser-rooms-card.js", "2.0.0", contents) - path, _, version = self.files.resolve_card(self.directory, "wiser-rooms-card.js", self.version_reader) + self.files.store_card(self.directory, "wiser-controls-card.js", "2.0.0", contents) + path, _, version = self.files.resolve_card(self.directory, "wiser-controls-card.js", self.version_reader) self.assertEqual(path.read_bytes(), contents) self.assertEqual(version, "2.0.0") @@ -415,13 +296,15 @@ async def test_network_failure_does_not_block_other_card_or_hub_setup(self): self.session.get.side_effect = [ self.response(error=aiohttp.ClientError("offline")), self.response(json_data=self.metadata()), - self.response(error=aiohttp.ClientError("offline")), + self.response(json_data=self.metadata("rooms")), + self.response(json_data=self.metadata("hub")), ] with self.assertLogs("card_update_test.update", level="WARNING"): await self.coordinator.async_refresh() self.assertIsNone(self.coordinator.data["schedule"]["release"]) self.assertEqual(self.coordinator.data["zigbee"]["release"]["version"], "2.0.0") - self.assertIsNone(self.coordinator.data["rooms"]["release"]) + self.assertEqual(self.coordinator.data["rooms"]["release"]["version"], "2.0.0") + self.assertEqual(self.coordinator.data["hub"]["release"]["version"], "2.0.0") self.assertEqual(self.coordinator.options["update_interval"], timedelta(hours=24)) async def test_check_does_not_install_until_user_requests_it(self): @@ -530,6 +413,9 @@ async def test_multiple_hubs_share_entities_and_transfer_when_owner_unloads(self await self.updates.async_unload_card_updates(self.hass, SimpleNamespace(entry_id="first")) self.assertEqual(self.coordinator.owner, "second") self.assertEqual(len(second.call_args.args[0]), 4) + self.registry.async_remove.assert_called_with( + "update.wiser_frontend_registry_update" + ) self.assertEqual(self.registry.async_update_entity.call_args.kwargs["config_entry_id"], "second") await self.updates.async_unload_card_updates(self.hass, SimpleNamespace(entry_id="second")) self.coordinator.async_shutdown.assert_awaited_once() @@ -551,45 +437,6 @@ async def test_update_entity_delegates_manual_install_and_exposes_release(self): await entity.async_install(None, False) self.coordinator.install.assert_awaited_once_with("zigbee") - async def test_registry_update_entity_installs_only_when_requested(self): - release = { - "version": "1.1.0", - "asset": {}, - "release_url": "https://github.com/andyblac/WiserFrontendPanelConfig/releases/tag/v1.1.0", - } - self.coordinator.data["_registry"] = { - "installed": "1.0.0", "release": release - } - entity = self.updates.WiserFrontendRegistryUpdate(self.coordinator) - self.assertEqual(entity.installed_version, "1.0.0") - self.assertEqual(entity.latest_version, "1.1.0") - self.coordinator.install_registry = AsyncMock() - await entity.async_install(None, False) - self.coordinator.install_registry.assert_awaited_once() - - async def test_registry_install_discovers_new_cards(self): - release = { - "version": "1.1.0", - "asset": {}, - "release_url": "https://github.com/andyblac/WiserFrontendPanelConfig/releases/tag/v1.1.0", - } - manifest = [*self.manifest, self.extra_card()] - self.coordinator.data["_registry"] = { - "installed": "1.0.0", "release": release - } - self.updates.async_install_registry_release = AsyncMock( - return_value=manifest - ) - self.coordinator._check_card = AsyncMock( - return_value={"installed": "0.0.0", "release": None, "error": None} - ) - await self.coordinator.install_registry() - self.updates.async_install_registry_release.assert_awaited_once_with( - self.hass, release - ) - self.assertIn("energy", self.coordinator.cards) - self.assertEqual(self.coordinator.data["_registry"]["installed"], "1.1.0") - async def test_lovelace_resource_moves_to_cached_url_without_duplicate(self): tree = ast.parse((ROOT / "frontend/__init__.py").read_text()) cls = next(node for node in tree.body if isinstance(node, ast.ClassDef) and node.name == "JSModuleRegistration") From b3d426e4f1890c529bdb94d5712bcd03332a2e02 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Sat, 3 Oct 2026 12:19:26 +0100 Subject: [PATCH 054/154] Handle current API OpenTherm demand attributes --- custom_components/wiser/climate.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/custom_components/wiser/climate.py b/custom_components/wiser/climate.py index c6414153..5571c3b3 100755 --- a/custom_components/wiser/climate.py +++ b/custom_components/wiser/climate.py @@ -513,7 +513,10 @@ def extra_state_attributes(self): if opentherm is not None and opentherm.enabled: attrs["demand_type"] = self._room.demand_type attrs["percentage_demand"] = self._room.percentage_demand - attrs["is_calling_for_heat"] = self._room.is_calling_for_heat + if hasattr(self._room, "is_calling_for_heat"): + attrs["is_calling_for_heat"] = self._room.is_calling_for_heat + else: + attrs["is_calling_for_heat"] = self._room.percentage_demand > 0 # If boosted show boost end time if self._room.is_boosted: From 67388c10c0dfd13024282a728df98788c198821e Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Mon, 5 Oct 2026 21:45:42 +0100 Subject: [PATCH 055/154] fix: hide V2 system sensors on V1 hubs --- custom_components/wiser/binary_sensor.py | 37 +++++++++++++++++--- tests/test_sensor.py | 44 ++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 5 deletions(-) diff --git a/custom_components/wiser/binary_sensor.py b/custom_components/wiser/binary_sensor.py index c05d8469..c903a81b 100644 --- a/custom_components/wiser/binary_sensor.py +++ b/custom_components/wiser/binary_sensor.py @@ -8,6 +8,7 @@ ) from homeassistant.const import EntityCategory from homeassistant.core import HomeAssistant, callback +from homeassistant.helpers import entity_registry as er from homeassistant.helpers.update_coordinator import CoordinatorEntity from .const import CONF_OPENTHERM_SENSORS, DATA, DOMAIN, ENTITY_PREFIX, MANUFACTURER @@ -31,12 +32,34 @@ _LOGGER = logging.getLogger(__name__) +V2_SYSTEM_BINARY_SENSOR_TYPES = ( + "Summer Discomfort Prevention", + "Summer Comfort Available", + "PCM Device Limit Reached", +) + def _entity_translation_key(name: str) -> str: """Return the stable translation key for a fixed Wiser entity label.""" return name.lower().replace(" ", "_") +def _remove_unsupported_v2_entities(hass: HomeAssistant, data) -> None: + """Remove V2-only registry entries previously created for a V1 hub.""" + registry = er.async_get(hass) + legacy_hub_name = data.wiserhub.system.name.replace("WiserHeat", "HeatHub") + for sensor_type in V2_SYSTEM_BINARY_SENSOR_TYPES: + unique_id = get_unique_id( + data, + "sensor", + sensor_type, + f"{legacy_hub_name} {sensor_type}", + ) + entity_id = registry.async_get_entity_id("binary_sensor", DOMAIN, unique_id) + if entity_id is not None: + registry.async_remove(entity_id) + + async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entities): """Set up Wiser climate device.""" data = hass.data[DOMAIN][config_entry.entry_id][DATA] # Get Handler @@ -61,15 +84,19 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie ) ) - # System sensors - if data.wiserhub.system: + # Summer comfort and PCM are available only on second-generation hubs. + if data.hub_version == 2: binary_sensors.extend( [ - WiserSummerDiscomfortPrevention(data, 0, "Summer Discomfort Prevention"), + WiserSummerDiscomfortPrevention( + data, 0, "Summer Discomfort Prevention" + ), WiserSummerComfortAvailable(data, 0, "Summer Comfort Available"), - WiserPCMDeviceLimitReached(data, 0, "PCM Device Limit Reached") + WiserPCMDeviceLimitReached(data, 0, "PCM Device Limit Reached"), ] - ) + ) + else: + _remove_unsupported_v2_entities(hass, data) # Smoke alarm sensors for device in data.wiserhub.devices.smokealarms.all: diff --git a/tests/test_sensor.py b/tests/test_sensor.py index c9102fcb..728dc18f 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -292,6 +292,50 @@ class BinarySensorEntity: return module +class WiserSummerComfortSetupTest(unittest.TestCase): + """Tests for second-generation hub system sensor setup.""" + + def test_summer_comfort_sensors_are_guarded_by_hub_version(self) -> None: + setup_source = BINARY_SENSOR_SOURCE_PATH.read_text().split( + "class BaseBinarySensor", 1 + )[0] + tree = ast.parse(setup_source) + setup = next( + node + for node in tree.body + if isinstance(node, ast.AsyncFunctionDef) + and node.name == "async_setup_entry" + ) + v2_guard = next( + node + for node in ast.walk(setup) + if isinstance(node, ast.If) + and ast.unparse(node.test) == "data.hub_version == 2" + ) + guarded_calls = { + node.func.id + for node in ast.walk(v2_guard) + if isinstance(node, ast.Call) and isinstance(node.func, ast.Name) + } + + self.assertTrue( + { + "WiserSummerDiscomfortPrevention", + "WiserSummerComfortAvailable", + "WiserPCMDeviceLimitReached", + }.issubset(guarded_calls) + ) + + cleanup_call = next( + node + for node in ast.walk(setup) + if isinstance(node, ast.Call) + and isinstance(node.func, ast.Name) + and node.func.id == "_remove_unsupported_v2_entities" + ) + self.assertIsNotNone(cleanup_call) + + class WiserDeviceSignalSensorNameTest(unittest.TestCase): """Tests for controller and device signal sensor names.""" From 9864276a6e6e5e3ec359cbe78dd91697e9df0736 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Mon, 5 Oct 2026 21:55:21 +0100 Subject: [PATCH 056/154] fix: detect V2 system sensor support --- custom_components/wiser/binary_sensor.py | 45 ++++++++++++++++----- tests/test_sensor.py | 50 ++++++++++++++++++++++-- 2 files changed, 82 insertions(+), 13 deletions(-) diff --git a/custom_components/wiser/binary_sensor.py b/custom_components/wiser/binary_sensor.py index c903a81b..9b69726b 100644 --- a/custom_components/wiser/binary_sensor.py +++ b/custom_components/wiser/binary_sensor.py @@ -18,8 +18,10 @@ get_hub_device_info, get_hub_via_device_info, get_identifier, + get_legacy_unique_id, get_light_binary_sensor_unique_id, get_unique_id, + get_uuid_unique_id, ) from .opentherm import ( OPENTHERM_BINARY_SENSOR_KEYS, @@ -44,20 +46,45 @@ def _entity_translation_key(name: str) -> str: return name.lower().replace(" ", "_") -def _remove_unsupported_v2_entities(hass: HomeAssistant, data) -> None: - """Remove V2-only registry entries previously created for a V1 hub.""" +def _supports_v2_system_binary_sensors(data) -> bool: + """Return whether the hub supplies second-generation system data.""" + if data.hub_version != 2: + return False + system = data.wiserhub.system + return any( + getattr(system, attribute, None) is not None + for attribute in ( + "summer_comfort_available", + "summer_discomfort_prevention", + ) + ) + + +def _remove_unsupported_v2_entities( + hass: HomeAssistant, config_entry_id: str, data +) -> None: + """Remove V2-only registry entries from an unsupported hub.""" registry = er.async_get(hass) legacy_hub_name = data.wiserhub.system.name.replace("WiserHeat", "HeatHub") for sensor_type in V2_SYSTEM_BINARY_SENSOR_TYPES: - unique_id = get_unique_id( + legacy_unique_id = get_legacy_unique_id( data, "sensor", sensor_type, f"{legacy_hub_name} {sensor_type}", ) - entity_id = registry.async_get_entity_id("binary_sensor", DOMAIN, unique_id) - if entity_id is not None: - registry.async_remove(entity_id) + unique_ids = { + legacy_unique_id, + get_uuid_unique_id(legacy_unique_id), + } + for unique_id in unique_ids: + entity_id = registry.async_get_entity_id( + "binary_sensor", DOMAIN, unique_id + ) + if entity_id is not None: + entry = registry.async_get(entity_id) + if entry and entry.config_entry_id == config_entry_id: + registry.async_remove(entity_id) async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entities): @@ -84,8 +111,8 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie ) ) - # Summer comfort and PCM are available only on second-generation hubs. - if data.hub_version == 2: + # Summer comfort and PCM require second-generation system data. + if _supports_v2_system_binary_sensors(data): binary_sensors.extend( [ WiserSummerDiscomfortPrevention( @@ -96,7 +123,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie ] ) else: - _remove_unsupported_v2_entities(hass, data) + _remove_unsupported_v2_entities(hass, config_entry.entry_id, data) # Smoke alarm sensors for device in data.wiserhub.devices.smokealarms.all: diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 728dc18f..54e92f2d 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -295,14 +295,55 @@ class BinarySensorEntity: class WiserSummerComfortSetupTest(unittest.TestCase): """Tests for second-generation hub system sensor setup.""" - def test_summer_comfort_sensors_are_guarded_by_hub_version(self) -> None: + @classmethod + def setUpClass(cls) -> None: setup_source = BINARY_SENSOR_SOURCE_PATH.read_text().split( "class BaseBinarySensor", 1 )[0] - tree = ast.parse(setup_source) + cls.tree = ast.parse(setup_source) + support_function = next( + node + for node in cls.tree.body + if isinstance(node, ast.FunctionDef) + and node.name == "_supports_v2_system_binary_sensors" + ) + namespace = {} + exec( + compile( + ast.Module(body=[support_function], type_ignores=[]), + BINARY_SENSOR_SOURCE_PATH.name, + "exec", + ), + namespace, + ) + cls.supports_v2_sensors = staticmethod( + namespace["_supports_v2_system_binary_sensors"] + ) + + def test_v1_does_not_support_v2_system_sensors(self) -> None: + data = SimpleNamespace(hub_version=1) + self.assertFalse(self.supports_v2_sensors(data)) + + def test_v2_without_summer_comfort_data_is_not_supported(self) -> None: + data = SimpleNamespace( + hub_version=2, + wiserhub=SimpleNamespace(system=SimpleNamespace()), + ) + self.assertFalse(self.supports_v2_sensors(data)) + + def test_v2_with_summer_comfort_data_is_supported(self) -> None: + data = SimpleNamespace( + hub_version=2, + wiserhub=SimpleNamespace( + system=SimpleNamespace(summer_comfort_available=False) + ), + ) + self.assertTrue(self.supports_v2_sensors(data)) + + def test_summer_comfort_sensors_use_capability_guard(self) -> None: setup = next( node - for node in tree.body + for node in self.tree.body if isinstance(node, ast.AsyncFunctionDef) and node.name == "async_setup_entry" ) @@ -310,7 +351,8 @@ def test_summer_comfort_sensors_are_guarded_by_hub_version(self) -> None: node for node in ast.walk(setup) if isinstance(node, ast.If) - and ast.unparse(node.test) == "data.hub_version == 2" + and ast.unparse(node.test) + == "_supports_v2_system_binary_sensors(data)" ) guarded_calls = { node.func.id From a63559b331833a04f0c0266e31267303256429c6 Mon Sep 17 00:00:00 2001 From: LGO44 <95585425+LGO44@users.noreply.github.com> Date: Tue, 29 Sep 2026 10:12:03 +0200 Subject: [PATCH 057/154] re introduice equipment --- custom_components/wiser/sensor.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index 55fa4366..44d58c88 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -275,6 +275,9 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie for smartplug in data.wiserhub.devices.smartplugs.all: # Hub V2 equipment telemetry if smartplug.equipment_id > 0: + wiser_sensors.append( + WiserEquipmentSensor(data, smartplug.id, ) + ) wiser_sensors.extend( [ WiserLTSPowerSensor( @@ -338,6 +341,11 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie ), ] ) + # Add a sensor equipment for powertags + if hasattr(power_tag, "equipment"): + wiser_sensors.append( + WiserEquipmentSensor(data, power_tag.id, ) + ) # Add LTS sensors - for room temp and target temp _LOGGER.debug("Setting up LTS sensors") @@ -384,6 +392,10 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie for heating_actuator in data.wiserhub.devices.heating_actuators.all: # Hub V2 equipment telemetry if heating_actuator.equipment_id > 0: + wiser_sensors.append( + WiserEquipmentSensor(data, heating_actuator.id, ) + ) + wiser_sensors.extend( [ WiserLTSPowerSensor( @@ -2084,6 +2096,11 @@ async def async_update(self) -> None: """Fetch new state data for the sensor.""" await super().async_update() + @property + def name(self): + """Return the name of the sensor.""" + return f"{self._sensor_type} Equipment" + @property def icon(self): """Return icon.""" From cef31ec4b95a8e63f22629497146dc40ad439886 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Fri, 2 Oct 2026 14:54:45 +0100 Subject: [PATCH 058/154] Make equipment sensors optional --- custom_components/wiser/config_flow.py | 51 +++++++++ custom_components/wiser/const.py | 1 + custom_components/wiser/sensor.py | 24 +++-- custom_components/wiser/strings.json | 14 ++- custom_components/wiser/translations/de.json | 14 ++- .../wiser/translations/en-GB.json | 14 ++- custom_components/wiser/translations/en.json | 14 ++- custom_components/wiser/translations/fr.json | 14 ++- tests/test_sensor.py | 10 +- tests/test_ui_options.py | 101 +++++++++++++++++- 10 files changed, 238 insertions(+), 19 deletions(-) diff --git a/custom_components/wiser/config_flow.py b/custom_components/wiser/config_flow.py index f8ecd960..9834eada 100755 --- a/custom_components/wiser/config_flow.py +++ b/custom_components/wiser/config_flow.py @@ -47,6 +47,7 @@ CONF_AUTOMATIONS_HW_SENSOR_ENTITY_ID, CONF_AUTOMATIONS_PASSIVE, CONF_AUTOMATIONS_PASSIVE_TEMP_INCREMENT, + CONF_EQUIPMENT_SENSORS, CONF_HEATING_BOOST_TEMP, CONF_HEATING_BOOST_TIME, CONF_HOSTNAME, @@ -265,16 +266,66 @@ def _opentherm(self): return None return getattr(entry_data[DATA].wiserhub.system, "opentherm", None) + def _equipment_available(self): + """Return whether the loaded entry has equipment data available.""" + entry_data = self.hass.data.get(DOMAIN, {}).get(self.config_entry.entry_id) + if not entry_data: + return False + devices = entry_data[DATA].wiserhub.devices + + def all_devices(collection_name): + collection = getattr(devices, collection_name, None) + return getattr(collection, "all", ()) + + return ( + any( + getattr(device, "equipment_id", 0) > 0 + for device in all_devices("smartplugs") + ) + or any( + device.equipment is not None + for device in all_devices("power_tags") + ) + or any( + getattr(device, "equipment_id", 0) > 0 + for device in all_devices("heating_actuators") + ) + ) + async def async_step_init(self, user_input=None): """Handle options flow.""" menu_options = ["main_params", "automation_params", "ui_options"] if self._opentherm() is not None: menu_options.append("opentherm_sensors") + if self._equipment_available(): + menu_options.append("equipment_sensors") return self.async_show_menu( step_id="init", menu_options=menu_options, ) + async def async_step_equipment_sensors(self, user_input=None): + """Configure detailed equipment data sensors.""" + if not self._equipment_available(): + return self.async_abort(reason="equipment_not_available") + if user_input is not None: + return self.async_create_entry( + data=self.config_entry.options | user_input + ) + return self.async_show_form( + step_id="equipment_sensors", + data_schema=vol.Schema( + { + vol.Optional( + CONF_EQUIPMENT_SENSORS, + default=self.config_entry.options.get( + CONF_EQUIPMENT_SENSORS, False + ), + ): BooleanSelector(), + } + ), + ) + async def async_step_ui_options(self, user_input=None): """Configure Wiser UI options, including legacy naming and sidebar panels.""" if user_input is not None: diff --git a/custom_components/wiser/const.py b/custom_components/wiser/const.py index e3f60a44..302f547b 100755 --- a/custom_components/wiser/const.py +++ b/custom_components/wiser/const.py @@ -104,6 +104,7 @@ class HWCycleModes(StrEnum): CONF_AUTOMATIONS_HW_SENSOR_ENTITY_ID = "hotwater_sensor_entity_id" CONF_DEPRECATED_HW_TARGET_TEMP = "hotwater_target_temperature" CONF_OPENTHERM_SENSORS = "opentherm_sensors" +CONF_EQUIPMENT_SENSORS = "equipment_sensors" # Custom Attributes ATTR_OPENTHERM_ENDPOINT = "endpoint" diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index 44d58c88..388d1d61 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -42,6 +42,7 @@ from aioWiserHeatAPI.wiserhub import TEMP_MINIMUM, TEMP_OFF from .const import ( + CONF_EQUIPMENT_SENSORS, CONF_OPENTHERM_SENSORS, DATA, DOMAIN, @@ -117,6 +118,9 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie """Initialize the entry.""" data = hass.data[DOMAIN][config_entry.entry_id][DATA] # Get Handler wiser_sensors = [] + equipment_sensors_enabled = config_entry.options.get( + CONF_EQUIPMENT_SENSORS, False + ) # Add signal sensors for all devices _LOGGER.debug("Setting up Device sensors") @@ -275,9 +279,8 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie for smartplug in data.wiserhub.devices.smartplugs.all: # Hub V2 equipment telemetry if smartplug.equipment_id > 0: - wiser_sensors.append( - WiserEquipmentSensor(data, smartplug.id, ) - ) + if equipment_sensors_enabled: + wiser_sensors.append(WiserEquipmentSensor(data, smartplug.id)) wiser_sensors.extend( [ WiserLTSPowerSensor( @@ -341,11 +344,9 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie ), ] ) - # Add a sensor equipment for powertags - if hasattr(power_tag, "equipment"): - wiser_sensors.append( - WiserEquipmentSensor(data, power_tag.id, ) - ) + # Add an equipment sensor for PowerTags + if equipment_sensors_enabled and power_tag.equipment is not None: + wiser_sensors.append(WiserEquipmentSensor(data, power_tag.id)) # Add LTS sensors - for room temp and target temp _LOGGER.debug("Setting up LTS sensors") @@ -392,9 +393,10 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie for heating_actuator in data.wiserhub.devices.heating_actuators.all: # Hub V2 equipment telemetry if heating_actuator.equipment_id > 0: - wiser_sensors.append( - WiserEquipmentSensor(data, heating_actuator.id, ) - ) + if equipment_sensors_enabled: + wiser_sensors.append( + WiserEquipmentSensor(data, heating_actuator.id) + ) wiser_sensors.extend( [ diff --git a/custom_components/wiser/strings.json b/custom_components/wiser/strings.json index 8f0a9f34..d848ae1b 100755 --- a/custom_components/wiser/strings.json +++ b/custom_components/wiser/strings.json @@ -42,6 +42,7 @@ "main_params": "Main Parameters", "automation_params": "Automation Parameters", "opentherm_sensors": "OpenTherm sensors", + "equipment_sensors": "Equipment sensors", "ui_options": "UI options" } }, @@ -95,6 +96,16 @@ } } }, + "equipment_sensors": { + "title": "Equipment sensors", + "description": "Configure detailed equipment data entities for compatible devices.", + "data": { + "equipment_sensors": "Enable equipment data sensors" + }, + "data_description": { + "equipment_sensors": "Expose an additional sensor containing detailed equipment attributes for each compatible smart plug, PowerTag, and heating actuator." + } + }, "opentherm_sensors": { "title": "OpenTherm sensors", "description": "Choose a category of detected OpenTherm attributes.", @@ -176,7 +187,8 @@ } }, "abort": { - "opentherm_not_available": "OpenTherm data is not available for this Wiser hub." + "opentherm_not_available": "OpenTherm data is not available for this Wiser hub.", + "equipment_not_available": "Equipment data is not available for this Wiser hub." } }, "services": { diff --git a/custom_components/wiser/translations/de.json b/custom_components/wiser/translations/de.json index a62ede5b..b312ea99 100644 --- a/custom_components/wiser/translations/de.json +++ b/custom_components/wiser/translations/de.json @@ -42,6 +42,7 @@ "main_params": "Hauptparameter", "automation_params": "Automatisierungsparameter", "opentherm_sensors": "OpenTherm-Sensoren", + "equipment_sensors": "Gerätesensoren", "ui_options": "UI-Optionen" } }, @@ -95,6 +96,16 @@ } } }, + "equipment_sensors": { + "title": "Gerätesensoren", + "description": "Detaillierte Gerätedatenentitäten für kompatible Geräte konfigurieren.", + "data": { + "equipment_sensors": "Gerätedatensensoren aktivieren" + }, + "data_description": { + "equipment_sensors": "Stellt für jede kompatible intelligente Steckdose, jedes PowerTag und jeden Heizungsaktor einen zusätzlichen Sensor mit detaillierten Geräteattributen bereit." + } + }, "opentherm_sensors": { "title": "OpenTherm-Sensoren", "description": "Wählen Sie eine Kategorie erkannter OpenTherm-Attribute.", @@ -176,7 +187,8 @@ } }, "abort": { - "opentherm_not_available": "Für diesen Wiser Heat Hub sind keine OpenTherm-Daten verfügbar." + "opentherm_not_available": "Für diesen Wiser Heat Hub sind keine OpenTherm-Daten verfügbar.", + "equipment_not_available": "Für diesen Wiser Heat Hub sind keine Gerätedaten verfügbar." } }, "services": { diff --git a/custom_components/wiser/translations/en-GB.json b/custom_components/wiser/translations/en-GB.json index 0100e815..1bb4b954 100644 --- a/custom_components/wiser/translations/en-GB.json +++ b/custom_components/wiser/translations/en-GB.json @@ -42,6 +42,7 @@ "main_params": "Main Parameters", "automation_params": "Automation Parameters", "opentherm_sensors": "OpenTherm sensors", + "equipment_sensors": "Equipment sensors", "ui_options": "UI options" } }, @@ -95,6 +96,16 @@ } } }, + "equipment_sensors": { + "title": "Equipment sensors", + "description": "Configure detailed equipment data entities for compatible devices.", + "data": { + "equipment_sensors": "Enable equipment data sensors" + }, + "data_description": { + "equipment_sensors": "Expose an additional sensor containing detailed equipment attributes for each compatible smart plug, PowerTag, and heating actuator." + } + }, "opentherm_sensors": { "title": "OpenTherm sensors", "description": "Choose a category of detected OpenTherm attributes.", @@ -176,7 +187,8 @@ } }, "abort": { - "opentherm_not_available": "OpenTherm data is not available for this Wiser hub." + "opentherm_not_available": "OpenTherm data is not available for this Wiser hub.", + "equipment_not_available": "Equipment data is not available for this Wiser hub." } }, "services": { diff --git a/custom_components/wiser/translations/en.json b/custom_components/wiser/translations/en.json index 3964ffe2..872918e1 100755 --- a/custom_components/wiser/translations/en.json +++ b/custom_components/wiser/translations/en.json @@ -42,6 +42,7 @@ "main_params": "Main Parameters", "automation_params": "Automation Parameters", "opentherm_sensors": "OpenTherm sensors", + "equipment_sensors": "Equipment sensors", "ui_options": "UI options" } }, @@ -95,6 +96,16 @@ } } }, + "equipment_sensors": { + "title": "Equipment sensors", + "description": "Configure detailed equipment data entities for compatible devices.", + "data": { + "equipment_sensors": "Enable equipment data sensors" + }, + "data_description": { + "equipment_sensors": "Expose an additional sensor containing detailed equipment attributes for each compatible smart plug, PowerTag, and heating actuator." + } + }, "opentherm_sensors": { "title": "OpenTherm sensors", "description": "Choose a category of detected OpenTherm attributes.", @@ -176,7 +187,8 @@ } }, "abort": { - "opentherm_not_available": "OpenTherm data is not available for this Wiser hub." + "opentherm_not_available": "OpenTherm data is not available for this Wiser hub.", + "equipment_not_available": "Equipment data is not available for this Wiser hub." } }, "services": { diff --git a/custom_components/wiser/translations/fr.json b/custom_components/wiser/translations/fr.json index a634518c..1a47645e 100644 --- a/custom_components/wiser/translations/fr.json +++ b/custom_components/wiser/translations/fr.json @@ -42,6 +42,7 @@ "main_params": "Paramètres principaux", "automation_params": "Paramètres d'automatisation", "opentherm_sensors": "Capteurs OpenTherm", + "equipment_sensors": "Capteurs d’équipement", "ui_options": "Options de l’interface" } }, @@ -95,6 +96,16 @@ } } }, + "equipment_sensors": { + "title": "Capteurs d’équipement", + "description": "Configurez les entités de données détaillées des équipements compatibles.", + "data": { + "equipment_sensors": "Activer les capteurs de données des équipements" + }, + "data_description": { + "equipment_sensors": "Expose un capteur supplémentaire contenant les attributs détaillés de l’équipement pour chaque prise intelligente, PowerTag et actionneur de chauffage compatible." + } + }, "opentherm_sensors": { "title": "Capteurs OpenTherm", "description": "Choisissez une catégorie d’attributs OpenTherm détectés.", @@ -176,7 +187,8 @@ } }, "abort": { - "opentherm_not_available": "Les données OpenTherm ne sont pas disponibles pour cette passerelle Wiser." + "opentherm_not_available": "Les données OpenTherm ne sont pas disponibles pour cette passerelle Wiser.", + "equipment_not_available": "Les données des équipements ne sont pas disponibles pour cette passerelle Wiser." } }, "services": { diff --git a/tests/test_sensor.py b/tests/test_sensor.py index c9102fcb..43d4a0de 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -91,6 +91,7 @@ def available(self): _module( "wiser.const", DATA="data", + CONF_EQUIPMENT_SENSORS="equipment_sensors", CONF_OPENTHERM_SENSORS="opentherm_sensors", DOMAIN="wiser", ENTITY_PREFIX="Wiser", @@ -371,9 +372,14 @@ def test_controller_signal_belongs_to_physical_hub(self) -> None: self.assertEqual(sensor.device_info, {"identifiers": {("wiser", "hub")}}) - def test_hub_v2_setup_does_not_create_duplicate_equipment_readings(self) -> None: + def test_detailed_equipment_readings_are_opt_in(self) -> None: setup_source = SOURCE_PATH.read_text().split("class WiserSensor", 1)[0] - self.assertNotIn("WiserEquipmentSensor(", setup_source) + self.assertIn( + 'config_entry.options.get(\n CONF_EQUIPMENT_SENSORS, False', + setup_source, + ) + self.assertEqual(setup_source.count("WiserEquipmentSensor("), 3) + self.assertEqual(setup_source.count("if equipment_sensors_enabled"), 3) self.assertNotIn('legacy_name="Equipment Energy Delivered"', setup_source) def test_power_display_name_does_not_change_historical_unique_id_input( diff --git a/tests/test_ui_options.py b/tests/test_ui_options.py index 0ae7b666..6ea55fc0 100644 --- a/tests/test_ui_options.py +++ b/tests/test_ui_options.py @@ -42,8 +42,11 @@ class UIOptionsTest(unittest.IsolatedAsyncioTestCase): def setUp(self): self.namespace = { "CONF_LEGACY_NAMING": "legacy_naming", + "CONF_EQUIPMENT_SENSORS": "equipment_sensors", "CONF_SHOW_WISER_SIDEBAR": "show_wiser_sidebar", "CONF_NAME": "name", + "DATA": "data", + "DOMAIN": "wiser", "HomeAssistant": object, "ConfigEntry": object, "FlowResult": dict, @@ -87,9 +90,105 @@ async def test_migration_enables_legacy_and_preserves_other_options(self): async def test_menu_available_without_opentherm(self): functions = load_functions("config_flow.py", {"async_step_init"}, self.namespace) - flow = SimpleNamespace(_opentherm=lambda: None, async_show_menu=lambda **kw: kw) + flow = SimpleNamespace( + _opentherm=lambda: None, + _equipment_available=lambda: False, + async_show_menu=lambda **kw: kw, + ) result = await functions.async_step_init(flow) self.assertIn("ui_options", result["menu_options"]) + self.assertNotIn("equipment_sensors", result["menu_options"]) + + async def test_equipment_menu_is_below_opentherm(self): + functions = load_functions( + "config_flow.py", {"async_step_init"}, self.namespace + ) + flow = SimpleNamespace( + _opentherm=lambda: object(), + _equipment_available=lambda: True, + async_show_menu=lambda **kw: kw, + ) + result = await functions.async_step_init(flow) + self.assertLess( + result["menu_options"].index("opentherm_sensors"), + result["menu_options"].index("equipment_sensors"), + ) + + async def test_equipment_menu_does_not_require_opentherm(self): + functions = load_functions( + "config_flow.py", {"async_step_init"}, self.namespace + ) + flow = SimpleNamespace( + _opentherm=lambda: None, + _equipment_available=lambda: True, + async_show_menu=lambda **kw: kw, + ) + result = await functions.async_step_init(flow) + self.assertIn("equipment_sensors", result["menu_options"]) + self.assertNotIn("opentherm_sensors", result["menu_options"]) + + def test_equipment_menu_requires_a_compatible_device(self): + functions = load_functions( + "config_flow.py", {"_equipment_available"}, self.namespace + ) + + def flow_with_devices(*, smartplugs=(), power_tags=(), actuators=()): + devices = SimpleNamespace( + smartplugs=SimpleNamespace(all=smartplugs), + power_tags=SimpleNamespace(all=power_tags), + heating_actuators=SimpleNamespace(all=actuators), + ) + return SimpleNamespace( + config_entry=SimpleNamespace(entry_id="entry"), + hass=SimpleNamespace( + data={ + "wiser": { + "entry": { + "data": SimpleNamespace( + wiserhub=SimpleNamespace(devices=devices) + ) + } + } + } + ), + ) + + self.assertFalse(functions._equipment_available(flow_with_devices())) + self.assertTrue( + functions._equipment_available( + flow_with_devices( + power_tags=(SimpleNamespace(equipment=object()),) + ) + ) + ) + + async def test_equipment_option_defaults_off_and_preserves_options(self): + self.namespace.update( + vol=SimpleNamespace( + Optional=lambda key, default: (key, default), + Schema=lambda data: data, + ), + BooleanSelector=lambda: bool, + ) + functions = load_functions( + "config_flow.py", {"async_step_equipment_sensors"}, self.namespace + ) + flow = SimpleNamespace( + _equipment_available=lambda: True, + config_entry=SimpleNamespace(options={"scan_interval": 30}), + async_show_form=lambda **kwargs: kwargs, + async_create_entry=lambda **kwargs: kwargs, + ) + form = await functions.async_step_equipment_sensors(flow) + self.assertIn(("equipment_sensors", False), form["data_schema"]) + + saved = await functions.async_step_equipment_sensors( + flow, {"equipment_sensors": True} + ) + self.assertEqual( + saved["data"], + {"scan_interval": 30, "equipment_sensors": True}, + ) async def test_saving_ui_options_preserves_other_options(self): functions = load_functions("config_flow.py", {"async_step_ui_options"}, self.namespace) From 6fadb0846aefc3ee3ef834e8789cb16c536911c3 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 08:22:50 +0100 Subject: [PATCH 059/154] fix: detect equipment data safely --- custom_components/wiser/config_flow.py | 19 +++++++------------ custom_components/wiser/sensor.py | 4 ++-- tests/test_sensor.py | 1 + tests/test_ui_options.py | 8 ++++++++ 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/custom_components/wiser/config_flow.py b/custom_components/wiser/config_flow.py index 9834eada..db2c5700 100755 --- a/custom_components/wiser/config_flow.py +++ b/custom_components/wiser/config_flow.py @@ -277,19 +277,14 @@ def all_devices(collection_name): collection = getattr(devices, collection_name, None) return getattr(collection, "all", ()) - return ( - any( - getattr(device, "equipment_id", 0) > 0 - for device in all_devices("smartplugs") - ) - or any( - device.equipment is not None - for device in all_devices("power_tags") - ) - or any( - getattr(device, "equipment_id", 0) > 0 - for device in all_devices("heating_actuators") + return any( + getattr(device, "equipment", None) is not None + for collection_name in ( + "smartplugs", + "power_tags", + "heating_actuators", ) + for device in all_devices(collection_name) ) async def async_step_init(self, user_input=None): diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index 388d1d61..058372cd 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -278,7 +278,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie _LOGGER.debug("Setting up Smart Plug power sensors") for smartplug in data.wiserhub.devices.smartplugs.all: # Hub V2 equipment telemetry - if smartplug.equipment_id > 0: + if smartplug.equipment is not None: if equipment_sensors_enabled: wiser_sensors.append(WiserEquipmentSensor(data, smartplug.id)) wiser_sensors.extend( @@ -392,7 +392,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie _LOGGER.debug("Setting up Heating Actuator LTS sensors") for heating_actuator in data.wiserhub.devices.heating_actuators.all: # Hub V2 equipment telemetry - if heating_actuator.equipment_id > 0: + if heating_actuator.equipment is not None: if equipment_sensors_enabled: wiser_sensors.append( WiserEquipmentSensor(data, heating_actuator.id) diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 43d4a0de..3aaadc1b 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -380,6 +380,7 @@ def test_detailed_equipment_readings_are_opt_in(self) -> None: ) self.assertEqual(setup_source.count("WiserEquipmentSensor("), 3) self.assertEqual(setup_source.count("if equipment_sensors_enabled"), 3) + self.assertNotIn("equipment_id > 0", setup_source) self.assertNotIn('legacy_name="Equipment Energy Delivered"', setup_source) def test_power_display_name_does_not_change_historical_unique_id_input( diff --git a/tests/test_ui_options.py b/tests/test_ui_options.py index 6ea55fc0..a1264430 100644 --- a/tests/test_ui_options.py +++ b/tests/test_ui_options.py @@ -161,6 +161,14 @@ def flow_with_devices(*, smartplugs=(), power_tags=(), actuators=()): ) ) ) + self.assertFalse( + functions._equipment_available( + flow_with_devices( + smartplugs=(SimpleNamespace(equipment=None),), + actuators=(SimpleNamespace(equipment=None),), + ) + ) + ) async def test_equipment_option_defaults_off_and_preserves_options(self): self.namespace.update( From 4353115ed5aca1231bc29622524f4a1d4796a1ef Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 08:24:02 +0100 Subject: [PATCH 060/154] fix: handle missing equipment energy --- custom_components/wiser/sensor.py | 7 ++++--- tests/test_sensor.py | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index 058372cd..e919b571 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -2176,10 +2176,11 @@ def extra_state_attributes(self): attrs["active_power"] = self._device.equipment.power.active_power attrs["total_active_power"] = self._device.equipment.power.total_active_power - attrs["energy"] = round( - self._device.equipment.power.current_summation_delivered / 1000, - 2, + delivered_energy = ( + self._device.equipment.power.current_summation_delivered ) + if delivered_energy is not None: + attrs["energy"] = round(delivered_energy / 1000, 2) # PowerTagE attributes if self._device.equipment.device_type in ["PTE","PowerTagE",]: diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 3aaadc1b..15d69399 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -419,6 +419,28 @@ def test_power_display_name_does_not_change_historical_unique_id_input( self.assertEqual(energy._attr_translation_key, "total_energy") self.assertEqual(energy._sensor_type, "Equipment Total Energy ") + def test_equipment_attributes_handle_missing_delivered_energy(self) -> None: + class OptionalAttributes(SimpleNamespace): + def __getattr__(self, _name): + return None + + power = OptionalAttributes( + active_power=10, + total_active_power=20, + current_summation_delivered=None, + ) + equipment = OptionalAttributes(device_type="Other", power=power) + sensor = object.__new__(self.sensor_module.WiserEquipmentSensor) + sensor._device = OptionalAttributes( + product_identifier="product", + equipment=equipment, + ) + + self.assertNotIn("energy", sensor.extra_state_attributes) + + power.current_summation_delivered = 0 + self.assertEqual(sensor.extra_state_attributes["energy"], 0) + class WiserSystemCircuitStateTest(unittest.TestCase): """Tests for normalized heating and hot-water circuit states.""" From 133f177901244e7c1404997f568fd08648c3d317 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 08:26:17 +0100 Subject: [PATCH 061/154] fix: translate equipment sensor names --- custom_components/wiser/sensor.py | 5 ----- custom_components/wiser/strings.json | 2 +- custom_components/wiser/translations/de.json | 2 +- custom_components/wiser/translations/en-GB.json | 2 +- custom_components/wiser/translations/en.json | 2 +- custom_components/wiser/translations/fr.json | 2 +- tests/test_sensor.py | 16 ++++++++++++++++ 7 files changed, 21 insertions(+), 10 deletions(-) diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index e919b571..b7bcc4df 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -2098,11 +2098,6 @@ async def async_update(self) -> None: """Fetch new state data for the sensor.""" await super().async_update() - @property - def name(self): - """Return the name of the sensor.""" - return f"{self._sensor_type} Equipment" - @property def icon(self): """Return icon.""" diff --git a/custom_components/wiser/strings.json b/custom_components/wiser/strings.json index d848ae1b..30cfdd5a 100755 --- a/custom_components/wiser/strings.json +++ b/custom_components/wiser/strings.json @@ -388,7 +388,7 @@ "total_energy": { "name": "Total energy" }, "energy_delivered": { "name": "Energy delivered" }, "energy_received": { "name": "Energy received" }, - "equipment_power": { "name": "Equipment power" } + "equipment_power": { "name": "Equipment" } } }, "device_automation": { diff --git a/custom_components/wiser/translations/de.json b/custom_components/wiser/translations/de.json index b312ea99..a4d801c2 100644 --- a/custom_components/wiser/translations/de.json +++ b/custom_components/wiser/translations/de.json @@ -386,7 +386,7 @@ "total_energy": { "name": "Gesamtenergie" }, "energy_delivered": { "name": "Gelieferte Energie" }, "energy_received": { "name": "Empfangene Energie" }, - "equipment_power": { "name": "Geräteleistung" } + "equipment_power": { "name": "Gerät" } } }, "device_automation": { diff --git a/custom_components/wiser/translations/en-GB.json b/custom_components/wiser/translations/en-GB.json index 1bb4b954..d2000cb9 100644 --- a/custom_components/wiser/translations/en-GB.json +++ b/custom_components/wiser/translations/en-GB.json @@ -386,7 +386,7 @@ "total_energy": { "name": "Total energy" }, "energy_delivered": { "name": "Energy delivered" }, "energy_received": { "name": "Energy received" }, - "equipment_power": { "name": "Equipment power" } + "equipment_power": { "name": "Equipment" } } }, "device_automation": { diff --git a/custom_components/wiser/translations/en.json b/custom_components/wiser/translations/en.json index 872918e1..a6dc522e 100755 --- a/custom_components/wiser/translations/en.json +++ b/custom_components/wiser/translations/en.json @@ -386,7 +386,7 @@ "total_energy": { "name": "Total energy" }, "energy_delivered": { "name": "Energy delivered" }, "energy_received": { "name": "Energy received" }, - "equipment_power": { "name": "Equipment power" } + "equipment_power": { "name": "Equipment" } } }, "device_automation": { diff --git a/custom_components/wiser/translations/fr.json b/custom_components/wiser/translations/fr.json index 1a47645e..c9624c73 100644 --- a/custom_components/wiser/translations/fr.json +++ b/custom_components/wiser/translations/fr.json @@ -386,7 +386,7 @@ "total_energy": { "name": "Énergie totale" }, "energy_delivered": { "name": "Énergie fournie" }, "energy_received": { "name": "Énergie reçue" }, - "equipment_power": { "name": "Puissance de l’équipement" } + "equipment_power": { "name": "Équipement" } } }, "device_automation": { diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 15d69399..a8aafbd6 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -441,6 +441,22 @@ def __getattr__(self, _name): power.current_summation_delivered = 0 self.assertEqual(sensor.extra_state_attributes["energy"], 0) + def test_equipment_name_uses_translation_without_changing_unique_id(self) -> None: + device = SimpleNamespace(id=9) + data = SimpleNamespace( + wiserhub=SimpleNamespace( + devices=SimpleNamespace(get_by_id=lambda _device_id: device), + rooms=SimpleNamespace(get_by_device_id=lambda _device_id: None), + system=SimpleNamespace(name="WiserHeat123456"), + ) + ) + + sensor = self.sensor_module.WiserEquipmentSensor(data, 9) + + self.assertEqual(sensor._sensor_type, "") + self.assertEqual(sensor._attr_translation_key, "equipment_power") + self.assertNotIn("name", self.sensor_module.WiserEquipmentSensor.__dict__) + class WiserSystemCircuitStateTest(unittest.TestCase): """Tests for normalized heating and hot-water circuit states.""" From 8c01c4a7613b4d540132b79a37175ba56759257d Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 08:27:22 +0100 Subject: [PATCH 062/154] fix: classify equipment power sensors --- custom_components/wiser/sensor.py | 9 ++++++--- tests/test_sensor.py | 26 +++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index b7bcc4df..aff165b1 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -2073,6 +2073,10 @@ def native_unit_of_measurement(self) -> str: class WiserEquipmentSensor(WiserSensor): """Definition of Wiser Equipment Sensor.""" + _attr_device_class = SensorDeviceClass.POWER + _attr_entity_category = EntityCategory.DIAGNOSTIC + _attr_state_class = SensorStateClass.MEASUREMENT + def __init__(self, data, device_id=0, sensor_type="") -> None: """Initialise the device sensor.""" super().__init__( @@ -2091,7 +2095,6 @@ def _handle_coordinator_update(self) -> None: self._device = self._data.wiserhub.system else: self._device = self._data.wiserhub.devices.get_by_id(self._device_id) - self._state = self._device.equipment.power.total_active_power self.async_write_ha_state() async def async_update(self) -> None: @@ -2104,8 +2107,8 @@ def icon(self): return "mdi:home-lightning-bolt" @property - def state(self) -> float: - """Return the state of the entity.""" + def native_value(self) -> float | None: + """Return the native power value.""" return self._device.equipment.power.total_active_power @property diff --git a/tests/test_sensor.py b/tests/test_sensor.py index a8aafbd6..bdddf98c 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -66,7 +66,7 @@ class SensorEntity: UnitOfElectricCurrent=SimpleNamespace(), UnitOfElectricPotential=SimpleNamespace(), PERCENTAGE="%", - UnitOfPower=SimpleNamespace(KILO_WATT="kW"), + UnitOfPower=SimpleNamespace(KILO_WATT="kW", WATT="W"), UnitOfEnergy=SimpleNamespace(), UnitOfPressure=SimpleNamespace(BAR="bar"), UnitOfVolumeFlowRate=SimpleNamespace(LITERS_PER_MINUTE="L/min"), @@ -457,6 +457,30 @@ def test_equipment_name_uses_translation_without_changing_unique_id(self) -> Non self.assertEqual(sensor._attr_translation_key, "equipment_power") self.assertNotIn("name", self.sensor_module.WiserEquipmentSensor.__dict__) + def test_equipment_power_uses_native_measurement_metadata(self) -> None: + device = SimpleNamespace( + id=9, + equipment=SimpleNamespace( + power=SimpleNamespace(total_active_power=123.4) + ), + ) + data = SimpleNamespace( + wiserhub=SimpleNamespace( + devices=SimpleNamespace(get_by_id=lambda _device_id: device), + rooms=SimpleNamespace(get_by_device_id=lambda _device_id: None), + system=SimpleNamespace(name="WiserHeat123456"), + ) + ) + + sensor = self.sensor_module.WiserEquipmentSensor(data, 9) + + self.assertEqual(sensor.native_value, 123.4) + self.assertEqual(sensor.native_unit_of_measurement, "W") + self.assertEqual(sensor._attr_device_class, "power") + self.assertEqual(sensor._attr_state_class, "measurement") + self.assertEqual(sensor._attr_entity_category, "diagnostic") + self.assertNotIn("state", self.sensor_module.WiserEquipmentSensor.__dict__) + class WiserSystemCircuitStateTest(unittest.TestCase): """Tests for normalized heating and hot-water circuit states.""" From de32c0896a17822110f4bfec3dd09fb87426d352 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 08:28:27 +0100 Subject: [PATCH 063/154] fix: exclude live equipment attributes from recorder --- custom_components/wiser/sensor.py | 11 +++++++++++ tests/test_sensor.py | 14 ++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index aff165b1..45873b2e 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -2076,6 +2076,17 @@ class WiserEquipmentSensor(WiserSensor): _attr_device_class = SensorDeviceClass.POWER _attr_entity_category = EntityCategory.DIAGNOSTIC _attr_state_class = SensorStateClass.MEASUREMENT + _unrecorded_attributes = frozenset( + { + "active_power", + "energy", + "energy_delivered", + "energy_received", + "rms_current", + "rms_voltage", + "total_active_power", + } + ) def __init__(self, data, device_id=0, sensor_type="") -> None: """Initialise the device sensor.""" diff --git a/tests/test_sensor.py b/tests/test_sensor.py index bdddf98c..d76962bf 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -481,6 +481,20 @@ def test_equipment_power_uses_native_measurement_metadata(self) -> None: self.assertEqual(sensor._attr_entity_category, "diagnostic") self.assertNotIn("state", self.sensor_module.WiserEquipmentSensor.__dict__) + def test_live_equipment_attributes_are_excluded_from_recorder(self) -> None: + self.assertEqual( + self.sensor_module.WiserEquipmentSensor._unrecorded_attributes, + { + "active_power", + "energy", + "energy_delivered", + "energy_received", + "rms_current", + "rms_voltage", + "total_active_power", + }, + ) + class WiserSystemCircuitStateTest(unittest.TestCase): """Tests for normalized heating and hot-water circuit states.""" From 225af7b8db86a652269095875d082f5addc14435 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 08:29:59 +0100 Subject: [PATCH 064/154] feat: support PowerTag Control equipment sensors --- custom_components/wiser/config_flow.py | 1 + custom_components/wiser/sensor.py | 8 ++++++++ tests/test_sensor.py | 5 +++-- tests/test_ui_options.py | 12 +++++++++++- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/custom_components/wiser/config_flow.py b/custom_components/wiser/config_flow.py index db2c5700..c5bd2bb1 100755 --- a/custom_components/wiser/config_flow.py +++ b/custom_components/wiser/config_flow.py @@ -282,6 +282,7 @@ def all_devices(collection_name): for collection_name in ( "smartplugs", "power_tags", + "power_tags_c", "heating_actuators", ) for device in all_devices(collection_name) diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index 45873b2e..4a1a42c4 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -348,6 +348,14 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie if equipment_sensors_enabled and power_tag.equipment is not None: wiser_sensors.append(WiserEquipmentSensor(data, power_tag.id)) + # Add equipment sensors for PowerTag Control devices + if equipment_sensors_enabled and data.wiserhub.devices.power_tags_c: + for power_tag_control in data.wiserhub.devices.power_tags_c.all: + if power_tag_control.equipment is not None: + wiser_sensors.append( + WiserEquipmentSensor(data, power_tag_control.id) + ) + # Add LTS sensors - for room temp and target temp _LOGGER.debug("Setting up LTS sensors") for room in data.wiserhub.rooms.all: diff --git a/tests/test_sensor.py b/tests/test_sensor.py index d76962bf..ad7ade04 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -378,9 +378,10 @@ def test_detailed_equipment_readings_are_opt_in(self) -> None: 'config_entry.options.get(\n CONF_EQUIPMENT_SENSORS, False', setup_source, ) - self.assertEqual(setup_source.count("WiserEquipmentSensor("), 3) - self.assertEqual(setup_source.count("if equipment_sensors_enabled"), 3) + self.assertEqual(setup_source.count("WiserEquipmentSensor("), 4) + self.assertEqual(setup_source.count("if equipment_sensors_enabled"), 4) self.assertNotIn("equipment_id > 0", setup_source) + self.assertIn("power_tags_c", setup_source) self.assertNotIn('legacy_name="Equipment Energy Delivered"', setup_source) def test_power_display_name_does_not_change_historical_unique_id_input( diff --git a/tests/test_ui_options.py b/tests/test_ui_options.py index a1264430..fb0c2e08 100644 --- a/tests/test_ui_options.py +++ b/tests/test_ui_options.py @@ -132,10 +132,13 @@ def test_equipment_menu_requires_a_compatible_device(self): "config_flow.py", {"_equipment_available"}, self.namespace ) - def flow_with_devices(*, smartplugs=(), power_tags=(), actuators=()): + def flow_with_devices( + *, smartplugs=(), power_tags=(), power_tags_c=(), actuators=() + ): devices = SimpleNamespace( smartplugs=SimpleNamespace(all=smartplugs), power_tags=SimpleNamespace(all=power_tags), + power_tags_c=SimpleNamespace(all=power_tags_c), heating_actuators=SimpleNamespace(all=actuators), ) return SimpleNamespace( @@ -169,6 +172,13 @@ def flow_with_devices(*, smartplugs=(), power_tags=(), actuators=()): ) ) ) + self.assertTrue( + functions._equipment_available( + flow_with_devices( + power_tags_c=(SimpleNamespace(equipment=object()),) + ) + ) + ) async def test_equipment_option_defaults_off_and_preserves_options(self): self.namespace.update( From f03633db431070583588dce71080716b9e92fc7c Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 08:31:06 +0100 Subject: [PATCH 065/154] fix: clarify equipment name attribute --- custom_components/wiser/sensor.py | 2 +- tests/test_sensor.py | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index 4a1a42c4..3fc419eb 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -2154,7 +2154,7 @@ def extra_state_attributes(self): # common attributes attrs["product_identifier"] = self._device.product_identifier - attrs["name"] = self._device.equipment.equipment_name + attrs["equipment_name"] = self._device.equipment.equipment_name attrs["device_type"] = self._device.equipment.device_type attrs["family"] = self._device.equipment.equipment_family attrs["installation_type"] = self._device.equipment.installation_type diff --git a/tests/test_sensor.py b/tests/test_sensor.py index ad7ade04..f13dd9dc 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -430,14 +430,21 @@ def __getattr__(self, _name): total_active_power=20, current_summation_delivered=None, ) - equipment = OptionalAttributes(device_type="Other", power=power) + equipment = OptionalAttributes( + device_type="Other", + equipment_name="Test equipment", + power=power, + ) sensor = object.__new__(self.sensor_module.WiserEquipmentSensor) sensor._device = OptionalAttributes( product_identifier="product", equipment=equipment, ) - self.assertNotIn("energy", sensor.extra_state_attributes) + attributes = sensor.extra_state_attributes + self.assertEqual(attributes["equipment_name"], "Test equipment") + self.assertNotIn("name", attributes) + self.assertNotIn("energy", attributes) power.current_summation_delivered = 0 self.assertEqual(sensor.extra_state_attributes["energy"], 0) From 477d7e3e47191eca43362dee4591b74e6bf2ccd9 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 08:34:56 +0100 Subject: [PATCH 066/154] fix: handle temporary equipment data loss --- custom_components/wiser/sensor.py | 15 +++++++++++++- tests/test_sensor.py | 33 +++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index 3fc419eb..ddf790e1 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -2125,10 +2125,20 @@ def icon(self): """Return icon.""" return "mdi:home-lightning-bolt" + @property + def available(self) -> bool: + """Return whether equipment data is currently available.""" + return ( + super().available + and self._device is not None + and getattr(self._device, "equipment", None) is not None + ) + @property def native_value(self) -> float | None: """Return the native power value.""" - return self._device.equipment.power.total_active_power + equipment = getattr(self._device, "equipment", None) + return equipment.power.total_active_power if equipment is not None else None @property def native_unit_of_measurement(self) -> str: @@ -2149,6 +2159,9 @@ def device_info(self): @property def extra_state_attributes(self): """Return device state attributes.""" + if self._device is None or self._device.equipment is None: + return {} + attrs = {} # common attributes diff --git a/tests/test_sensor.py b/tests/test_sensor.py index f13dd9dc..eb627fdd 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -489,6 +489,39 @@ def test_equipment_power_uses_native_measurement_metadata(self) -> None: self.assertEqual(sensor._attr_entity_category, "diagnostic") self.assertNotIn("state", self.sensor_module.WiserEquipmentSensor.__dict__) + def test_equipment_sensor_recovers_from_missing_runtime_data(self) -> None: + equipment = SimpleNamespace( + power=SimpleNamespace(total_active_power=123.4) + ) + device = SimpleNamespace(id=9, equipment=equipment) + data = SimpleNamespace( + last_update_success=True, + wiserhub=SimpleNamespace( + devices=SimpleNamespace(get_by_id=lambda _device_id: device), + rooms=SimpleNamespace(get_by_device_id=lambda _device_id: None), + system=SimpleNamespace(name="WiserHeat123456"), + ), + ) + sensor = self.sensor_module.WiserEquipmentSensor(data, 9) + + self.assertTrue(sensor.available) + self.assertEqual(sensor.native_value, 123.4) + + device.equipment = None + self.assertFalse(sensor.available) + self.assertIsNone(sensor.native_value) + self.assertEqual(sensor.extra_state_attributes, {}) + + sensor._device = None + self.assertFalse(sensor.available) + self.assertIsNone(sensor.native_value) + self.assertEqual(sensor.extra_state_attributes, {}) + + sensor._device = device + device.equipment = equipment + self.assertTrue(sensor.available) + self.assertEqual(sensor.native_value, 123.4) + def test_live_equipment_attributes_are_excluded_from_recorder(self) -> None: self.assertEqual( self.sensor_module.WiserEquipmentSensor._unrecorded_attributes, From 938d6647c11c1afed03847b9eca36db9f073e229 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 08:36:13 +0100 Subject: [PATCH 067/154] fix: retain enabled equipment option during data gaps --- custom_components/wiser/config_flow.py | 8 +++-- tests/test_ui_options.py | 49 ++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/custom_components/wiser/config_flow.py b/custom_components/wiser/config_flow.py index c5bd2bb1..5b7d6822 100755 --- a/custom_components/wiser/config_flow.py +++ b/custom_components/wiser/config_flow.py @@ -293,7 +293,9 @@ async def async_step_init(self, user_input=None): menu_options = ["main_params", "automation_params", "ui_options"] if self._opentherm() is not None: menu_options.append("opentherm_sensors") - if self._equipment_available(): + if self._equipment_available() or self.config_entry.options.get( + CONF_EQUIPMENT_SENSORS, False + ): menu_options.append("equipment_sensors") return self.async_show_menu( step_id="init", @@ -302,7 +304,9 @@ async def async_step_init(self, user_input=None): async def async_step_equipment_sensors(self, user_input=None): """Configure detailed equipment data sensors.""" - if not self._equipment_available(): + if not self._equipment_available() and not self.config_entry.options.get( + CONF_EQUIPMENT_SENSORS, False + ): return self.async_abort(reason="equipment_not_available") if user_input is not None: return self.async_create_entry( diff --git a/tests/test_ui_options.py b/tests/test_ui_options.py index fb0c2e08..df7e4f40 100644 --- a/tests/test_ui_options.py +++ b/tests/test_ui_options.py @@ -93,6 +93,7 @@ async def test_menu_available_without_opentherm(self): flow = SimpleNamespace( _opentherm=lambda: None, _equipment_available=lambda: False, + config_entry=SimpleNamespace(options={}), async_show_menu=lambda **kw: kw, ) result = await functions.async_step_init(flow) @@ -106,6 +107,7 @@ async def test_equipment_menu_is_below_opentherm(self): flow = SimpleNamespace( _opentherm=lambda: object(), _equipment_available=lambda: True, + config_entry=SimpleNamespace(options={}), async_show_menu=lambda **kw: kw, ) result = await functions.async_step_init(flow) @@ -121,12 +123,59 @@ async def test_equipment_menu_does_not_require_opentherm(self): flow = SimpleNamespace( _opentherm=lambda: None, _equipment_available=lambda: True, + config_entry=SimpleNamespace(options={}), async_show_menu=lambda **kw: kw, ) result = await functions.async_step_init(flow) self.assertIn("equipment_sensors", result["menu_options"]) self.assertNotIn("opentherm_sensors", result["menu_options"]) + async def test_enabled_equipment_option_remains_available_during_data_gap(self): + self.namespace.update( + vol=SimpleNamespace( + Optional=lambda key, default: (key, default), + Schema=lambda data: data, + ), + BooleanSelector=lambda: bool, + ) + functions = load_functions( + "config_flow.py", + {"async_step_init", "async_step_equipment_sensors"}, + self.namespace, + ) + flow = SimpleNamespace( + _opentherm=lambda: None, + _equipment_available=lambda: False, + config_entry=SimpleNamespace(options={"equipment_sensors": True}), + async_show_menu=lambda **kwargs: kwargs, + async_show_form=lambda **kwargs: kwargs, + async_create_entry=lambda **kwargs: kwargs, + ) + + menu = await functions.async_step_init(flow) + self.assertIn("equipment_sensors", menu["menu_options"]) + + form = await functions.async_step_equipment_sensors(flow) + self.assertIn(("equipment_sensors", True), form["data_schema"]) + + saved = await functions.async_step_equipment_sensors( + flow, {"equipment_sensors": False} + ) + self.assertEqual(saved["data"], {"equipment_sensors": False}) + + async def test_unconfigured_equipment_option_aborts_without_data(self): + functions = load_functions( + "config_flow.py", {"async_step_equipment_sensors"}, self.namespace + ) + flow = SimpleNamespace( + _equipment_available=lambda: False, + config_entry=SimpleNamespace(options={}), + async_abort=lambda **kwargs: kwargs, + ) + + result = await functions.async_step_equipment_sensors(flow) + self.assertEqual(result["reason"], "equipment_not_available") + def test_equipment_menu_requires_a_compatible_device(self): functions = load_functions( "config_flow.py", {"_equipment_available"}, self.namespace From 5ab4540a65e45b6a2ca5e1beb3755b1b9ff1f02a Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 08:37:56 +0100 Subject: [PATCH 068/154] refactor: clean up equipment attributes --- custom_components/wiser/sensor.py | 111 ++++++++++++++---------------- 1 file changed, 50 insertions(+), 61 deletions(-) diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index ddf790e1..ebe3e152 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -2159,78 +2159,67 @@ def device_info(self): @property def extra_state_attributes(self): """Return device state attributes.""" - if self._device is None or self._device.equipment is None: + equipment = getattr(self._device, "equipment", None) + if equipment is None: return {} - attrs = {} - - # common attributes - attrs["product_identifier"] = self._device.product_identifier - - attrs["equipment_name"] = self._device.equipment.equipment_name - attrs["device_type"] = self._device.equipment.device_type - attrs["family"] = self._device.equipment.equipment_family - attrs["installation_type"] = self._device.equipment.installation_type - - attrs["equipment_id"] = self._device.equipment.id - attrs["equipment_device_id"] = self._device.equipment.device_id - attrs["equipment_UUID"] = self._device.equipment.uuid - # more info 2024 06 - attrs["controllable"] = self._device.equipment.controllable - attrs["cloud_managed"] = self._device.equipment.cloud_managed - attrs["monitored"] = self._device.equipment.monitored - attrs["smart_compatible"] = self._device.equipment.smart_compatible - attrs["smart_supported"] = self._device.equipment.smart_supported - attrs["can_be_scheduled"] = self._device.equipment.can_be_scheduled - attrs["onoff_green_schedule_supported"] = self._device.equipment.onoff_green_schedule_supported - attrs["onoff_cost_schedule_supported"] = self._device.equipment.onoff_cost_schedule_supported - attrs["controllable"] = self._device.equipment.controllable - - attrs["functional_control_mode"] = self._device.equipment.functional_control_mode - attrs["current_control_mode"] = self._device.equipment.current_control_mode - #PCM - attrs["pcm_mode"] = self._device.equipment.pcm_mode - attrs["pcm_supported"] = self._device.equipment.pcm_supported - attrs["pcm_priority"] = self._device.equipment.pcm_priority - - attrs["number_of_phases"] = self._device.equipment.number_of_phases - attrs["direction"] = self._device.equipment.direction - attrs["operating_status"] = self._device.equipment.operating_status - attrs["fault_status"] = self._device.equipment.fault_status - #Load - attrs["load_state_status"] = self._device.equipment.load_state_status - attrs["load_state_command_optimized"] = self._device.equipment.load_state_command_optimized - attrs["load_shedding_status"] = self._device.equipment.load_shedding_status - attrs["load_state_command_prio"] = self._device.equipment.load_state_command_prio - attrs["load_setpoint_command_prio"] = self._device.equipment.load_setpoint_command_prio - - attrs["active_power"] = self._device.equipment.power.active_power - attrs["total_active_power"] = self._device.equipment.power.total_active_power - delivered_energy = ( - self._device.equipment.power.current_summation_delivered - ) + power = equipment.power + attrs = { + "product_identifier": self._device.product_identifier, + "equipment_name": equipment.equipment_name, + "device_type": equipment.device_type, + "family": equipment.equipment_family, + "installation_type": equipment.installation_type, + "equipment_id": equipment.id, + "equipment_device_id": equipment.device_id, + # Retain the existing key spelling for attribute compatibility. + "equipment_UUID": equipment.uuid, + "controllable": equipment.controllable, + "cloud_managed": equipment.cloud_managed, + "monitored": equipment.monitored, + "smart_compatible": equipment.smart_compatible, + "smart_supported": equipment.smart_supported, + "can_be_scheduled": equipment.can_be_scheduled, + "onoff_green_schedule_supported": ( + equipment.onoff_green_schedule_supported + ), + "onoff_cost_schedule_supported": equipment.onoff_cost_schedule_supported, + "functional_control_mode": equipment.functional_control_mode, + "current_control_mode": equipment.current_control_mode, + "pcm_mode": equipment.pcm_mode, + "pcm_supported": equipment.pcm_supported, + "pcm_priority": equipment.pcm_priority, + "number_of_phases": equipment.number_of_phases, + "direction": equipment.direction, + "operating_status": equipment.operating_status, + "fault_status": equipment.fault_status, + "load_state_status": equipment.load_state_status, + "load_state_command_optimized": equipment.load_state_command_optimized, + "load_shedding_status": equipment.load_shedding_status, + "load_state_command_prio": equipment.load_state_command_prio, + "load_setpoint_command_prio": equipment.load_setpoint_command_prio, + "active_power": power.active_power, + "total_active_power": power.total_active_power, + } + + delivered_energy = power.current_summation_delivered if delivered_energy is not None: attrs["energy"] = round(delivered_energy / 1000, 2) # PowerTagE attributes - if self._device.equipment.device_type in ["PTE","PowerTagE",]: + if equipment.device_type in ("PTE", "PowerTagE"): attrs["grid_limit"] = self._device.grid_limit + # Retain the existing key spelling for attribute compatibility. attrs["grid_limit_Uom"] = self._device.grid_limit_uom attrs["energy_export"] = self._device.energy_export attrs["self_consumption"] = self._device.self_consumption - - attrs["rms_current"] = self._device.equipment.power.rms_current - attrs["rms_voltage"] = self._device.equipment.power.rms_voltage - attrs["energy_received"] = self._device.equipment.power.current_summation_received - # SmartPlug attributes - if self._device.equipment.device_type in ["SmartPlug"]: - attrs["functional_control_mode"] = self._device.equipment.functional_control_mode + attrs["rms_current"] = power.rms_current + attrs["rms_voltage"] = power.rms_voltage + attrs["energy_received"] = power.current_summation_received # PowerTagE and SmartPlug attributes - if self._device.equipment.device_type in ["PTE","PowerTagE","SmartPlug"]: - attrs["energy_delivered"] = self._device.equipment.power.current_summation_delivered - attrs["pcm_mode"] = self._device.equipment.pcm_mode + if equipment.device_type in ("PTE", "PowerTagE", "SmartPlug"): + attrs["energy_delivered"] = power.current_summation_delivered - - return attrs + return attrs From 3beb8c20b5d38545e81e7a00280f242a13cfe152 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 08:40:12 +0100 Subject: [PATCH 069/154] fix: handle missing binary equipment data --- custom_components/wiser/binary_sensor.py | 23 ++++++++++- tests/test_sensor.py | 51 ++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/custom_components/wiser/binary_sensor.py b/custom_components/wiser/binary_sensor.py index c05d8469..96ff4da3 100644 --- a/custom_components/wiser/binary_sensor.py +++ b/custom_components/wiser/binary_sensor.py @@ -441,7 +441,28 @@ class WiserRemoteAlarm(BaseBinarySensor): class WiserEquipment(BaseBinarySensor): - """Base binary sensor class.""" + """Binary sensor backed by optional equipment data.""" + + @property + def available(self) -> bool: + """Return whether equipment data is currently available.""" + return ( + super().available + and self._device is not None + and getattr(self._device, "equipment", None) is not None + ) + + @callback + def _handle_coordinator_update(self) -> None: + """Refresh state without failing when equipment data is missing.""" + self._device = self._data.wiserhub.devices.get_by_id(self._device_id) + equipment = getattr(self._device, "equipment", None) + self._state = ( + getattr(equipment, self._sensor_type.replace(" ", "_").lower()) + if equipment is not None + else None + ) + self.async_write_ha_state() ## binary sensor of System diff --git a/tests/test_sensor.py b/tests/test_sensor.py index eb627fdd..11e7c444 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -1019,3 +1019,54 @@ def test_capability_flag_is_a_diagnostic_entity(self): ) self.assertEqual(sensor._attr_entity_category, "diagnostic") + + +class WiserEquipmentBinarySensorTest(unittest.TestCase): + """Tests for binary sensors backed by optional equipment data.""" + + @classmethod + def setUpClass(cls): + cls.binary_sensor_module = _load_binary_sensor_module() + + def setUp(self): + self.equipment = SimpleNamespace(controllable=True, pcm_mode=False) + self.device = SimpleNamespace( + id=9, + equipment=self.equipment, + product_type="SmartPlug", + firmware_version="1.0", + ) + self.data = SimpleNamespace( + last_update_success=True, + wiserhub=SimpleNamespace( + devices=SimpleNamespace(get_by_id=lambda _device_id: self.device), + rooms=SimpleNamespace(get_by_device_id=lambda _device_id: None), + system=SimpleNamespace(name="WiserHeat123456"), + ), + ) + self.sensor = self.binary_sensor_module.WiserEquipment( + self.data, 9, "Controllable", "equipment" + ) + self.sensor.async_write_ha_state = Mock() + + def test_becomes_unavailable_and_recovers_with_equipment_data(self): + self.assertTrue(self.sensor.available) + self.assertTrue(self.sensor.is_on) + + self.device.equipment = None + self.sensor._handle_coordinator_update() + self.assertFalse(self.sensor.available) + self.assertIsNone(self.sensor.is_on) + + self.device.equipment = self.equipment + self.sensor._handle_coordinator_update() + self.assertTrue(self.sensor.available) + self.assertTrue(self.sensor.is_on) + + def test_handles_device_temporarily_disappearing(self): + self.device = None + + self.sensor._handle_coordinator_update() + + self.assertFalse(self.sensor.available) + self.assertIsNone(self.sensor.is_on) From 717652e41f5b51d42e0f70e673e210333993b1b4 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 08:52:10 +0100 Subject: [PATCH 070/154] fix: fall back to available equipment power --- custom_components/wiser/sensor.py | 14 +++++++++++++- tests/test_sensor.py | 12 +++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index ebe3e152..94b3eac6 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -2138,7 +2138,19 @@ def available(self) -> bool: def native_value(self) -> float | None: """Return the native power value.""" equipment = getattr(self._device, "equipment", None) - return equipment.power.total_active_power if equipment is not None else None + if equipment is None: + return None + + power = equipment.power + for value in ( + getattr(power, "total_active_power", None), + getattr(power, "active_power", None), + getattr(self._device, "instantaneous_power", None), + ): + if value is not None: + return value + + return None @property def native_unit_of_measurement(self) -> str: diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 11e7c444..791233d0 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -468,8 +468,9 @@ def test_equipment_name_uses_translation_without_changing_unique_id(self) -> Non def test_equipment_power_uses_native_measurement_metadata(self) -> None: device = SimpleNamespace( id=9, + instantaneous_power=45.6, equipment=SimpleNamespace( - power=SimpleNamespace(total_active_power=123.4) + power=SimpleNamespace(total_active_power=123.4, active_power=78.9) ), ) data = SimpleNamespace( @@ -489,6 +490,15 @@ def test_equipment_power_uses_native_measurement_metadata(self) -> None: self.assertEqual(sensor._attr_entity_category, "diagnostic") self.assertNotIn("state", self.sensor_module.WiserEquipmentSensor.__dict__) + device.equipment.power.total_active_power = None + self.assertEqual(sensor.native_value, 78.9) + + device.equipment.power.active_power = None + self.assertEqual(sensor.native_value, 45.6) + + device.instantaneous_power = 0 + self.assertEqual(sensor.native_value, 0) + def test_equipment_sensor_recovers_from_missing_runtime_data(self) -> None: equipment = SimpleNamespace( power=SimpleNamespace(total_active_power=123.4) From 76d27826f37a0476ac5c722f641a26610aec3ea2 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 08:55:43 +0100 Subject: [PATCH 071/154] fix: refresh cached equipment power state --- custom_components/wiser/sensor.py | 2 ++ tests/test_sensor.py | 11 ++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index 94b3eac6..c1cca2da 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -2105,6 +2105,7 @@ def __init__(self, data, device_id=0, sensor_type="") -> None: self._device = self._data.wiserhub.system else: self._device = self._data.wiserhub.devices.get_by_id(self._device_id) + self._state = self.native_value @callback def _handle_coordinator_update(self) -> None: @@ -2114,6 +2115,7 @@ def _handle_coordinator_update(self) -> None: self._device = self._data.wiserhub.system else: self._device = self._data.wiserhub.devices.get_by_id(self._device_id) + self._state = self.native_value self.async_write_ha_state() async def async_update(self) -> None: diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 791233d0..cf424d2d 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -482,8 +482,10 @@ def test_equipment_power_uses_native_measurement_metadata(self) -> None: ) sensor = self.sensor_module.WiserEquipmentSensor(data, 9) + sensor.async_write_ha_state = Mock() self.assertEqual(sensor.native_value, 123.4) + self.assertEqual(sensor.state, 123.4) self.assertEqual(sensor.native_unit_of_measurement, "W") self.assertEqual(sensor._attr_device_class, "power") self.assertEqual(sensor._attr_state_class, "measurement") @@ -491,13 +493,16 @@ def test_equipment_power_uses_native_measurement_metadata(self) -> None: self.assertNotIn("state", self.sensor_module.WiserEquipmentSensor.__dict__) device.equipment.power.total_active_power = None - self.assertEqual(sensor.native_value, 78.9) + sensor._handle_coordinator_update() + self.assertEqual(sensor.state, 78.9) device.equipment.power.active_power = None - self.assertEqual(sensor.native_value, 45.6) + sensor._handle_coordinator_update() + self.assertEqual(sensor.state, 45.6) device.instantaneous_power = 0 - self.assertEqual(sensor.native_value, 0) + sensor._handle_coordinator_update() + self.assertEqual(sensor.state, 0) def test_equipment_sensor_recovers_from_missing_runtime_data(self) -> None: equipment = SimpleNamespace( From 010c24cc0ca06a25e003e3b248990bcc25b1597b Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Mon, 5 Oct 2026 12:40:24 +0100 Subject: [PATCH 072/154] fix: detect active OpenTherm installations --- custom_components/wiser/__init__.py | 37 +++++++ custom_components/wiser/binary_sensor.py | 3 +- custom_components/wiser/config_flow.py | 8 +- custom_components/wiser/const.py | 1 + .../wiser/opentherm_detection.py | 14 +++ custom_components/wiser/sensor.py | 6 +- tests/test_ui_options.py | 99 +++++++++++++++++++ 7 files changed, 162 insertions(+), 6 deletions(-) create mode 100644 custom_components/wiser/opentherm_detection.py diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index 7b83e933..4c47997d 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -5,6 +5,7 @@ """ import asyncio +from functools import partial import logging from homeassistant.config_entries import ConfigEntry @@ -27,6 +28,7 @@ CONF_AUTOMATIONS_PASSIVE_TEMP_INCREMENT, CONF_DEPRECATED_HW_TARGET_TEMP, CONF_LEGACY_NAMING, + CONF_OPENTHERM_EVER_CONNECTED, DATA, DOMAIN, MANUFACTURER, @@ -207,6 +209,11 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): if not coordinator.last_update_status == "Success": raise ConfigEntryNotReady + # Remember a confirmed connection before platform setup. This prevents a + # standard boiler's dormant OpenTherm endpoint from creating entities, + # while allowing a real OpenTherm installation to survive later outages. + _remember_opentherm_connection(hass, config_entry, coordinator) + # Update listener for config option changes update_listener = config_entry.add_update_listener(_async_update_listener) @@ -216,6 +223,20 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): "reload_settings": integration_reload_settings(config_entry), } + # If OpenTherm connects for the first time after startup, saving the flag + # causes one integration reload so its entities are added. Future outages + # retain those entities and their registry/history records. + config_entry.async_on_unload( + coordinator.async_add_listener( + partial( + _remember_opentherm_connection, + hass, + config_entry, + coordinator, + ) + ) + ) + update_hub_device_names(hass) # Register the physical hub before its entities and connected devices. @@ -257,6 +278,22 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): return True +@callback +def _remember_opentherm_connection(hass, config_entry, coordinator) -> None: + """Persist the first confirmed OpenTherm connection.""" + if config_entry.data.get(CONF_OPENTHERM_EVER_CONNECTED, False): + return + + opentherm = getattr(coordinator.wiserhub.system, "opentherm", None) + if getattr(opentherm, "connection_status", None) != "Connected": + return + + hass.config_entries.async_update_entry( + config_entry, + data={**config_entry.data, CONF_OPENTHERM_EVER_CONNECTED: True}, + ) + + async def async_update_device_registry(hass: HomeAssistant, config_entry): """Update device registry.""" data = hass.data[DOMAIN][config_entry.entry_id][DATA] diff --git a/custom_components/wiser/binary_sensor.py b/custom_components/wiser/binary_sensor.py index 96ff4da3..1b1778ed 100644 --- a/custom_components/wiser/binary_sensor.py +++ b/custom_components/wiser/binary_sensor.py @@ -28,6 +28,7 @@ opentherm_sensor_value, opentherm_sensor_is_enabled, ) +from .opentherm_detection import opentherm_is_detected _LOGGER = logging.getLogger(__name__) @@ -44,7 +45,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie binary_sensors = [] opentherm = getattr(data.wiserhub.system, "opentherm", None) - if opentherm is not None and opentherm.enabled: + if opentherm_is_detected(config_entry, opentherm): configured_sensors = config_entry.options.get(CONF_OPENTHERM_SENSORS) binary_sensors.extend( WiserOpenThermAttributeBinarySensor(data, key) diff --git a/custom_components/wiser/config_flow.py b/custom_components/wiser/config_flow.py index 5b7d6822..fed0d4b5 100755 --- a/custom_components/wiser/config_flow.py +++ b/custom_components/wiser/config_flow.py @@ -75,6 +75,7 @@ detected_opentherm_sensor_keys, opentherm_sensor_is_enabled, ) +from .opentherm_detection import opentherm_is_detected _LOGGER = logging.getLogger(__name__) @@ -264,7 +265,12 @@ def _opentherm(self): entry_data = self.hass.data.get(DOMAIN, {}).get(self.config_entry.entry_id) if not entry_data: return None - return getattr(entry_data[DATA].wiserhub.system, "opentherm", None) + opentherm = getattr(entry_data[DATA].wiserhub.system, "opentherm", None) + return ( + opentherm + if opentherm_is_detected(self.config_entry, opentherm) + else None + ) def _equipment_available(self): """Return whether the loaded entry has equipment data available.""" diff --git a/custom_components/wiser/const.py b/custom_components/wiser/const.py index 302f547b..689c66dd 100755 --- a/custom_components/wiser/const.py +++ b/custom_components/wiser/const.py @@ -103,6 +103,7 @@ class HWCycleModes(StrEnum): CONF_AUTOMATIONS_HW_BOOST_MODE = "hotwater_boost_mode" CONF_AUTOMATIONS_HW_SENSOR_ENTITY_ID = "hotwater_sensor_entity_id" CONF_DEPRECATED_HW_TARGET_TEMP = "hotwater_target_temperature" +CONF_OPENTHERM_EVER_CONNECTED = "opentherm_ever_connected" CONF_OPENTHERM_SENSORS = "opentherm_sensors" CONF_EQUIPMENT_SENSORS = "equipment_sensors" diff --git a/custom_components/wiser/opentherm_detection.py b/custom_components/wiser/opentherm_detection.py new file mode 100644 index 00000000..bbd41322 --- /dev/null +++ b/custom_components/wiser/opentherm_detection.py @@ -0,0 +1,14 @@ +"""Track whether a Wiser hub has a confirmed OpenTherm connection.""" + +from .const import CONF_OPENTHERM_EVER_CONNECTED + + +def opentherm_is_detected(config_entry, opentherm) -> bool: + """Return whether OpenTherm is connected now or has connected before.""" + return bool( + opentherm + and ( + config_entry.data.get(CONF_OPENTHERM_EVER_CONNECTED, False) + or getattr(opentherm, "connection_status", None) == "Connected" + ) + ) diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index c1cca2da..7acc210e 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -72,6 +72,7 @@ opentherm_sensor_is_enabled, relative_modulation_level as _relative_modulation_level, ) +from .opentherm_detection import opentherm_is_detected from .temperature import room_target_temperature _LOGGER = logging.getLogger(__name__) @@ -202,10 +203,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie # Add enabled OpenTherm sensors. Flow and return temperatures retain their # historical default; every additional attribute is opt-in. - if ( - data.wiserhub.system.opentherm is not None - and data.wiserhub.system.opentherm.enabled - ): + if opentherm_is_detected(config_entry, data.wiserhub.system.opentherm): _LOGGER.debug("Setting up Opentherm sensors") opentherm = data.wiserhub.system.opentherm configured_sensors = config_entry.options.get(CONF_OPENTHERM_SENSORS) diff --git a/tests/test_ui_options.py b/tests/test_ui_options.py index df7e4f40..b4dc33a4 100644 --- a/tests/test_ui_options.py +++ b/tests/test_ui_options.py @@ -43,6 +43,7 @@ def setUp(self): self.namespace = { "CONF_LEGACY_NAMING": "legacy_naming", "CONF_EQUIPMENT_SENSORS": "equipment_sensors", + "CONF_OPENTHERM_EVER_CONNECTED": "opentherm_ever_connected", "CONF_SHOW_WISER_SIDEBAR": "show_wiser_sidebar", "CONF_NAME": "name", "DATA": "data", @@ -57,6 +58,104 @@ def setUp(self): "MINOR_VERSION": 8, } + def test_opentherm_detection_uses_live_or_remembered_connection(self): + functions = load_functions( + "opentherm_detection.py", {"opentherm_is_detected"}, self.namespace + ) + disconnected = SimpleNamespace( + enabled=True, connection_status="Disconnected" + ) + connected = SimpleNamespace(enabled=True, connection_status="Connected") + + self.assertFalse( + functions.opentherm_is_detected( + SimpleNamespace(data={}), disconnected + ) + ) + self.assertTrue( + functions.opentherm_is_detected(SimpleNamespace(data={}), connected) + ) + self.assertTrue( + functions.opentherm_is_detected( + SimpleNamespace(data={"opentherm_ever_connected": True}), + disconnected, + ) + ) + self.assertFalse( + functions.opentherm_is_detected(SimpleNamespace(data={}), None) + ) + + def test_first_opentherm_connection_is_remembered_once(self): + functions = load_functions( + "__init__.py", {"_remember_opentherm_connection"}, self.namespace + ) + update = Mock() + hass = SimpleNamespace( + config_entries=SimpleNamespace(async_update_entry=update) + ) + entry = SimpleNamespace(data={"host": "wiser.local"}) + opentherm = SimpleNamespace(connection_status="Disconnected") + coordinator = SimpleNamespace( + wiserhub=SimpleNamespace( + system=SimpleNamespace(opentherm=opentherm) + ) + ) + + functions._remember_opentherm_connection(hass, entry, coordinator) + update.assert_not_called() + + opentherm.connection_status = "Connected" + functions._remember_opentherm_connection(hass, entry, coordinator) + update.assert_called_once_with( + entry, + data={"host": "wiser.local", "opentherm_ever_connected": True}, + ) + + update.reset_mock() + entry.data = {"host": "wiser.local", "opentherm_ever_connected": True} + opentherm.connection_status = "Disconnected" + functions._remember_opentherm_connection(hass, entry, coordinator) + update.assert_not_called() + + def test_options_hide_opentherm_until_detected(self): + detection = load_functions( + "opentherm_detection.py", {"opentherm_is_detected"}, self.namespace + ) + self.namespace["opentherm_is_detected"] = detection.opentherm_is_detected + self.namespace.update(DATA="data", DOMAIN="wiser") + functions = load_functions("config_flow.py", {"_opentherm"}, self.namespace) + opentherm = SimpleNamespace( + enabled=True, connection_status="Disconnected" + ) + coordinator = SimpleNamespace( + wiserhub=SimpleNamespace(system=SimpleNamespace(opentherm=opentherm)) + ) + flow = SimpleNamespace( + config_entry=SimpleNamespace(entry_id="entry", data={}), + hass=SimpleNamespace(data={"wiser": {"entry": {"data": coordinator}}}), + ) + + self.assertIsNone(functions._opentherm(flow)) + flow.config_entry.data["opentherm_ever_connected"] = True + self.assertIs(functions._opentherm(flow), opentherm) + + def test_sensor_setup_requires_detected_opentherm(self): + for filename, marker in ( + ( + "sensor.py", + "opentherm_is_detected(config_entry, data.wiserhub.system.opentherm)", + ), + ( + "binary_sensor.py", + "opentherm_is_detected(config_entry, opentherm)", + ), + ): + with self.subTest(filename=filename): + setup = (COMPONENT / filename).read_text().split( + "class Wiser", 1 + )[0] + self.assertIn(marker, setup) + async def test_new_manual_and_discovered_install_defaults(self): for method in ("async_step_user", "async_step_zeroconf_confirm"): for version, expected in (((2025, 12), True), ((2026, 7), True), From f97357b00e76e996de875dc6f8ebe7b44fbd4b3e Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Mon, 5 Oct 2026 12:47:12 +0100 Subject: [PATCH 073/154] fix: hide inactive OpenTherm entities --- custom_components/wiser/__init__.py | 26 +++++++ .../wiser/opentherm_detection.py | 41 +++++++++++ tests/test_ui_options.py | 73 +++++++++++++++++++ 3 files changed, 140 insertions(+) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index 4c47997d..6267b677 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -57,6 +57,10 @@ get_instance_count, get_legacy_room_identifier, ) +from .opentherm_detection import ( + opentherm_entity_unique_ids, + opentherm_is_detected, +) from .services import async_setup_services from .websockets import async_register_websockets from .update import async_unload_card_updates @@ -281,6 +285,8 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): @callback def _remember_opentherm_connection(hass, config_entry, coordinator) -> None: """Persist the first confirmed OpenTherm connection.""" + _sync_opentherm_entity_registry(hass, config_entry, coordinator) + if config_entry.data.get(CONF_OPENTHERM_EVER_CONNECTED, False): return @@ -294,6 +300,26 @@ def _remember_opentherm_connection(hass, config_entry, coordinator) -> None: ) +@callback +def _sync_opentherm_entity_registry(hass, config_entry, coordinator) -> None: + """Hide false OpenTherm entities while preserving their registry data.""" + opentherm = getattr(coordinator.wiserhub.system, "opentherm", None) + detected = opentherm_is_detected(config_entry, opentherm) + unique_ids = opentherm_entity_unique_ids(coordinator) + registry = er.async_get(hass) + + for entry in er.async_entries_for_config_entry(registry, config_entry.entry_id): + if (entry.domain, entry.unique_id) not in unique_ids: + continue + if not detected and entry.disabled_by is None: + registry.async_update_entity( + entry.entity_id, + disabled_by=er.RegistryEntryDisabler.INTEGRATION, + ) + elif detected and entry.disabled_by == er.RegistryEntryDisabler.INTEGRATION: + registry.async_update_entity(entry.entity_id, disabled_by=None) + + async def async_update_device_registry(hass: HomeAssistant, config_entry): """Update device registry.""" data = hass.data[DOMAIN][config_entry.entry_id][DATA] diff --git a/custom_components/wiser/opentherm_detection.py b/custom_components/wiser/opentherm_detection.py index bbd41322..c5f6f1c0 100644 --- a/custom_components/wiser/opentherm_detection.py +++ b/custom_components/wiser/opentherm_detection.py @@ -1,6 +1,11 @@ """Track whether a Wiser hub has a confirmed OpenTherm connection.""" from .const import CONF_OPENTHERM_EVER_CONNECTED +from .helpers import get_unique_id +from .opentherm import ( + OPENTHERM_BINARY_SENSOR_KEYS, + OPENTHERM_SENSOR_NAMES, +) def opentherm_is_detected(config_entry, opentherm) -> bool: @@ -12,3 +17,39 @@ def opentherm_is_detected(config_entry, opentherm) -> bool: or getattr(opentherm, "connection_status", None) == "Connected" ) ) + + +def opentherm_entity_unique_ids(data): + """Return the entity-registry IDs reserved for OpenTherm entities.""" + sensor_types = { + "LTS Boiler Flow Temperature", + "LTS Boiler Return Temperature", + } + binary_sensor_types = { + f"opentherm_{key}" for key in OPENTHERM_BINARY_SENSOR_KEYS + } + + for key in OPENTHERM_SENSOR_NAMES: + if key in OPENTHERM_BINARY_SENSOR_KEYS or key in { + "ch_flow_temperature", + "ch_return_temperature", + }: + continue + sensor_types.add( + "relative_modulation_level" + if key == "relative_modulation_level" + else f"opentherm_{key}" + ) + + unique_ids = { + ("sensor", get_unique_id(data, "sensor", sensor_type, 0)) + for sensor_type in sensor_types + } + unique_ids.update( + ( + "binary_sensor", + get_unique_id(data, "binary_sensor", sensor_type, 0), + ) + for sensor_type in binary_sensor_types + ) + return unique_ids diff --git a/tests/test_ui_options.py b/tests/test_ui_options.py index b4dc33a4..c7674e03 100644 --- a/tests/test_ui_options.py +++ b/tests/test_ui_options.py @@ -86,6 +86,8 @@ def test_opentherm_detection_uses_live_or_remembered_connection(self): ) def test_first_opentherm_connection_is_remembered_once(self): + sync_registry = Mock() + self.namespace["_sync_opentherm_entity_registry"] = sync_registry functions = load_functions( "__init__.py", {"_remember_opentherm_connection"}, self.namespace ) @@ -103,6 +105,7 @@ def test_first_opentherm_connection_is_remembered_once(self): functions._remember_opentherm_connection(hass, entry, coordinator) update.assert_not_called() + sync_registry.assert_called_once_with(hass, entry, coordinator) opentherm.connection_status = "Connected" functions._remember_opentherm_connection(hass, entry, coordinator) @@ -112,10 +115,80 @@ def test_first_opentherm_connection_is_remembered_once(self): ) update.reset_mock() + sync_registry.reset_mock() entry.data = {"host": "wiser.local", "opentherm_ever_connected": True} opentherm.connection_status = "Disconnected" functions._remember_opentherm_connection(hass, entry, coordinator) update.assert_not_called() + sync_registry.assert_called_once_with(hass, entry, coordinator) + + def test_opentherm_registry_entries_are_disabled_without_detection(self): + integration = "integration" + registry = SimpleNamespace(async_update_entity=Mock()) + entries = [ + SimpleNamespace( + domain="sensor", + unique_id="flow", + entity_id="sensor.boiler_flow_temperature", + disabled_by=None, + ), + SimpleNamespace( + domain="sensor", + unique_id="return", + entity_id="sensor.boiler_return_temperature", + disabled_by="user", + ), + SimpleNamespace( + domain="sensor", + unique_id="cloud", + entity_id="sensor.cloud", + disabled_by=None, + ), + ] + fake_er = SimpleNamespace( + RegistryEntryDisabler=SimpleNamespace(INTEGRATION=integration), + async_get=lambda _hass: registry, + async_entries_for_config_entry=lambda _registry, _entry_id: entries, + ) + self.namespace.update( + er=fake_er, + opentherm_entity_unique_ids=lambda _data: { + ("sensor", "flow"), + ("sensor", "return"), + }, + opentherm_is_detected=lambda entry, opentherm: bool( + entry.data.get("opentherm_ever_connected") + or opentherm.connection_status == "Connected" + ), + ) + functions = load_functions( + "__init__.py", {"_sync_opentherm_entity_registry"}, self.namespace + ) + config_entry = SimpleNamespace(entry_id="entry", data={}) + coordinator = SimpleNamespace( + wiserhub=SimpleNamespace( + system=SimpleNamespace( + opentherm=SimpleNamespace(connection_status="Disconnected") + ) + ) + ) + + functions._sync_opentherm_entity_registry( + object(), config_entry, coordinator + ) + registry.async_update_entity.assert_called_once_with( + "sensor.boiler_flow_temperature", disabled_by=integration + ) + + registry.async_update_entity.reset_mock() + entries[0].disabled_by = integration + config_entry.data["opentherm_ever_connected"] = True + functions._sync_opentherm_entity_registry( + object(), config_entry, coordinator + ) + registry.async_update_entity.assert_called_once_with( + "sensor.boiler_flow_temperature", disabled_by=None + ) def test_options_hide_opentherm_until_detected(self): detection = load_functions( From 385f302c88f8b7deb181370702fcefb91a4c2f83 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 15:04:29 +0100 Subject: [PATCH 074/154] fix: clear remembered OpenTherm state when disabled --- custom_components/wiser/__init__.py | 16 +++++++++--- tests/test_ui_options.py | 39 ++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index 6267b677..5ca1d361 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -284,13 +284,23 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): @callback def _remember_opentherm_connection(hass, config_entry, coordinator) -> None: - """Persist the first confirmed OpenTherm connection.""" + """Persist a confirmed OpenTherm connection until it is disabled.""" + opentherm = getattr(coordinator.wiserhub.system, "opentherm", None) + remembered = config_entry.data.get(CONF_OPENTHERM_EVER_CONNECTED, False) + + if getattr(opentherm, "enabled", None) is False: + if remembered: + entry_data = dict(config_entry.data) + entry_data.pop(CONF_OPENTHERM_EVER_CONNECTED, None) + hass.config_entries.async_update_entry(config_entry, data=entry_data) + _sync_opentherm_entity_registry(hass, config_entry, coordinator) + return + _sync_opentherm_entity_registry(hass, config_entry, coordinator) - if config_entry.data.get(CONF_OPENTHERM_EVER_CONNECTED, False): + if remembered: return - opentherm = getattr(coordinator.wiserhub.system, "opentherm", None) if getattr(opentherm, "connection_status", None) != "Connected": return diff --git a/tests/test_ui_options.py b/tests/test_ui_options.py index c7674e03..d8bd07ad 100644 --- a/tests/test_ui_options.py +++ b/tests/test_ui_options.py @@ -96,7 +96,9 @@ def test_first_opentherm_connection_is_remembered_once(self): config_entries=SimpleNamespace(async_update_entry=update) ) entry = SimpleNamespace(data={"host": "wiser.local"}) - opentherm = SimpleNamespace(connection_status="Disconnected") + opentherm = SimpleNamespace( + enabled=True, connection_status="Disconnected" + ) coordinator = SimpleNamespace( wiserhub=SimpleNamespace( system=SimpleNamespace(opentherm=opentherm) @@ -122,6 +124,41 @@ def test_first_opentherm_connection_is_remembered_once(self): update.assert_not_called() sync_registry.assert_called_once_with(hass, entry, coordinator) + def test_disabling_opentherm_clears_remembered_connection(self): + sync_registry = Mock() + self.namespace["_sync_opentherm_entity_registry"] = sync_registry + functions = load_functions( + "__init__.py", {"_remember_opentherm_connection"}, self.namespace + ) + update = Mock() + hass = SimpleNamespace( + config_entries=SimpleNamespace(async_update_entry=update) + ) + entry = SimpleNamespace( + data={ + "host": "wiser.local", + "opentherm_ever_connected": True, + } + ) + coordinator = SimpleNamespace( + wiserhub=SimpleNamespace( + system=SimpleNamespace( + opentherm=SimpleNamespace( + enabled=False, + connection_status="Disconnected", + ) + ) + ) + ) + + functions._remember_opentherm_connection(hass, entry, coordinator) + + update.assert_called_once_with( + entry, + data={"host": "wiser.local"}, + ) + sync_registry.assert_called_once_with(hass, entry, coordinator) + def test_opentherm_registry_entries_are_disabled_without_detection(self): integration = "integration" registry = SimpleNamespace(async_update_entity=Mock()) From 4121d8aa6d22118142b87cd597c6f603dd8b8107 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 15:05:40 +0100 Subject: [PATCH 075/154] docs: explain OpenTherm availability behaviour --- custom_components/wiser/binary_sensor.py | 1 + custom_components/wiser/opentherm_detection.py | 7 ++++++- custom_components/wiser/sensor.py | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/custom_components/wiser/binary_sensor.py b/custom_components/wiser/binary_sensor.py index 1b1778ed..303cbfbf 100644 --- a/custom_components/wiser/binary_sensor.py +++ b/custom_components/wiser/binary_sensor.py @@ -255,6 +255,7 @@ def __init__(self, coordinator, sensor_key) -> None: @property def available(self): + # Keep the entity during outages without exposing stale boiler state. opentherm = self._data.wiserhub.system.opentherm return ( super().available diff --git a/custom_components/wiser/opentherm_detection.py b/custom_components/wiser/opentherm_detection.py index c5f6f1c0..560cd293 100644 --- a/custom_components/wiser/opentherm_detection.py +++ b/custom_components/wiser/opentherm_detection.py @@ -9,7 +9,12 @@ def opentherm_is_detected(config_entry, opentherm) -> bool: - """Return whether OpenTherm is connected now or has connected before.""" + """Return whether OpenTherm is connected now or has connected before. + + This sticky predicate controls entity creation and registry visibility so a + temporary outage does not discard entities or history. Entity availability + deliberately continues to require live OpenTherm data. + """ return bool( opentherm and ( diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index 7acc210e..c2666965 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -1352,6 +1352,8 @@ def __init__(self, data, sensor_key) -> None: @property def available(self): + # Detection is sticky for registry continuity, but values are available + # only while the hub reports usable live OpenTherm data. opentherm = self._data.wiserhub.system.opentherm return ( super().available @@ -1565,6 +1567,7 @@ def __init__(self, data, device_id, sensor_type="") -> None: @property def available(self): + # Keep the entity during outages without exposing a stale temperature. opentherm = self._data.wiserhub.system.opentherm return ( super().available From 6f613626453ff0f69cc33798c660693af1b24435 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 15:06:31 +0100 Subject: [PATCH 076/154] perf: sync OpenTherm registry on detection changes --- custom_components/wiser/__init__.py | 34 +++++++++++++++++++---------- tests/test_ui_options.py | 18 ++++++++++++--- 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index 5ca1d361..8179112f 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -293,28 +293,38 @@ def _remember_opentherm_connection(hass, config_entry, coordinator) -> None: entry_data = dict(config_entry.data) entry_data.pop(CONF_OPENTHERM_EVER_CONNECTED, None) hass.config_entries.async_update_entry(config_entry, data=entry_data) - _sync_opentherm_entity_registry(hass, config_entry, coordinator) - return - - _sync_opentherm_entity_registry(hass, config_entry, coordinator) - - if remembered: - return + remembered = False + elif ( + not remembered + and getattr(opentherm, "connection_status", None) == "Connected" + ): + hass.config_entries.async_update_entry( + config_entry, + data={**config_entry.data, CONF_OPENTHERM_EVER_CONNECTED: True}, + ) + remembered = True - if getattr(opentherm, "connection_status", None) != "Connected": + detected = bool(opentherm and remembered) + if getattr(coordinator, "_wiser_opentherm_detected", None) is detected: return - hass.config_entries.async_update_entry( + coordinator._wiser_opentherm_detected = detected + _sync_opentherm_entity_registry( + hass, config_entry, - data={**config_entry.data, CONF_OPENTHERM_EVER_CONNECTED: True}, + coordinator, + detected=detected, ) @callback -def _sync_opentherm_entity_registry(hass, config_entry, coordinator) -> None: +def _sync_opentherm_entity_registry( + hass, config_entry, coordinator, detected=None +) -> None: """Hide false OpenTherm entities while preserving their registry data.""" opentherm = getattr(coordinator.wiserhub.system, "opentherm", None) - detected = opentherm_is_detected(config_entry, opentherm) + if detected is None: + detected = opentherm_is_detected(config_entry, opentherm) unique_ids = opentherm_entity_unique_ids(coordinator) registry = er.async_get(hass) diff --git a/tests/test_ui_options.py b/tests/test_ui_options.py index d8bd07ad..54d7fd79 100644 --- a/tests/test_ui_options.py +++ b/tests/test_ui_options.py @@ -107,7 +107,14 @@ def test_first_opentherm_connection_is_remembered_once(self): functions._remember_opentherm_connection(hass, entry, coordinator) update.assert_not_called() - sync_registry.assert_called_once_with(hass, entry, coordinator) + sync_registry.assert_called_once_with( + hass, entry, coordinator, detected=False + ) + + sync_registry.reset_mock() + functions._remember_opentherm_connection(hass, entry, coordinator) + update.assert_not_called() + sync_registry.assert_not_called() opentherm.connection_status = "Connected" functions._remember_opentherm_connection(hass, entry, coordinator) @@ -115,6 +122,9 @@ def test_first_opentherm_connection_is_remembered_once(self): entry, data={"host": "wiser.local", "opentherm_ever_connected": True}, ) + sync_registry.assert_called_once_with( + hass, entry, coordinator, detected=True + ) update.reset_mock() sync_registry.reset_mock() @@ -122,7 +132,7 @@ def test_first_opentherm_connection_is_remembered_once(self): opentherm.connection_status = "Disconnected" functions._remember_opentherm_connection(hass, entry, coordinator) update.assert_not_called() - sync_registry.assert_called_once_with(hass, entry, coordinator) + sync_registry.assert_not_called() def test_disabling_opentherm_clears_remembered_connection(self): sync_registry = Mock() @@ -157,7 +167,9 @@ def test_disabling_opentherm_clears_remembered_connection(self): entry, data={"host": "wiser.local"}, ) - sync_registry.assert_called_once_with(hass, entry, coordinator) + sync_registry.assert_called_once_with( + hass, entry, coordinator, detected=False + ) def test_opentherm_registry_entries_are_disabled_without_detection(self): integration = "integration" From 6c9dfb4c955195534f24e4231a70dd9240cb403b Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 15:07:13 +0100 Subject: [PATCH 077/154] docs: explain OpenTherm detection persistence --- custom_components/wiser/__init__.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index 8179112f..55485ddd 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -213,9 +213,11 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): if not coordinator.last_update_status == "Success": raise ConfigEntryNotReady - # Remember a confirmed connection before platform setup. This prevents a - # standard boiler's dormant OpenTherm endpoint from creating entities, - # while allowing a real OpenTherm installation to survive later outages. + # This must run before both the update listener and reload-settings snapshot. + # A setup-time flag change is then included in the initial snapshot without + # scheduling a reload; a later change is observed and reloads exactly once. + # This prevents a standard boiler's dormant OpenTherm endpoint from creating + # entities while allowing a real installation to survive temporary outages. _remember_opentherm_connection(hass, config_entry, coordinator) # Update listener for config option changes @@ -284,7 +286,12 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): @callback def _remember_opentherm_connection(hass, config_entry, coordinator) -> None: - """Persist a confirmed OpenTherm connection until it is disabled.""" + """Persist a confirmed OpenTherm connection until it is disabled. + + The flag intentionally lives in config-entry data so the existing entry + update listener reloads platforms when runtime detection changes. A Store + would persist the state but would not trigger that reload. + """ opentherm = getattr(coordinator.wiserhub.system, "opentherm", None) remembered = config_entry.data.get(CONF_OPENTHERM_EVER_CONNECTED, False) From dfc9d3ad420b4e9fe4ce0b4c0248f39a942b9977 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 15:08:10 +0100 Subject: [PATCH 078/154] test: cover OpenTherm reload lifecycle --- tests/test_ui_options.py | 57 ++++++++++++++++++++++++++++--------- tests/test_wiser_sidebar.py | 20 +++++++++++++ 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/tests/test_ui_options.py b/tests/test_ui_options.py index 54d7fd79..e07ceb53 100644 --- a/tests/test_ui_options.py +++ b/tests/test_ui_options.py @@ -38,6 +38,33 @@ def load_functions(filename, names, namespace): return SimpleNamespace(**namespace) +def function_call_lines(filename, function_name): + """Return call names and line numbers from a function's syntax tree.""" + source = (COMPONENT / filename).read_text() + try: + tree = ast.parse(source) + except SyntaxError: + # The local test runner can be older than the integration's supported + # Python version. Platform setup precedes the entity classes, so parse + # only that section when later syntax is unsupported by the runner. + tree = ast.parse(source.partition("\nclass ")[0]) + function = next( + node + for node in ast.walk(tree) + if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)) + and node.name == function_name + ) + calls = [] + for node in ast.walk(function): + if not isinstance(node, ast.Call): + continue + if isinstance(node.func, ast.Name): + calls.append((node.func.id, node.lineno)) + elif isinstance(node.func, ast.Attribute): + calls.append((node.func.attr, node.lineno)) + return calls + + class UIOptionsTest(unittest.IsolatedAsyncioTestCase): def setUp(self): self.namespace = { @@ -262,21 +289,23 @@ def test_options_hide_opentherm_until_detected(self): self.assertIs(functions._opentherm(flow), opentherm) def test_sensor_setup_requires_detected_opentherm(self): - for filename, marker in ( - ( - "sensor.py", - "opentherm_is_detected(config_entry, data.wiserhub.system.opentherm)", - ), - ( - "binary_sensor.py", - "opentherm_is_detected(config_entry, opentherm)", - ), - ): + for filename in ("sensor.py", "binary_sensor.py"): with self.subTest(filename=filename): - setup = (COMPONENT / filename).read_text().split( - "class Wiser", 1 - )[0] - self.assertIn(marker, setup) + calls = function_call_lines(filename, "async_setup_entry") + self.assertIn("opentherm_is_detected", {name for name, _ in calls}) + + def test_detection_precedes_listener_and_reload_snapshot(self): + calls = function_call_lines("__init__.py", "async_setup_entry") + call_lines = {name: line for name, line in calls} + + self.assertLess( + call_lines["_remember_opentherm_connection"], + call_lines["add_update_listener"], + ) + self.assertLess( + call_lines["add_update_listener"], + call_lines["integration_reload_settings"], + ) async def test_new_manual_and_discovered_install_defaults(self): for method in ("async_step_user", "async_step_zeroconf_confirm"): diff --git a/tests/test_wiser_sidebar.py b/tests/test_wiser_sidebar.py index b2aa416d..2db8926b 100644 --- a/tests/test_wiser_sidebar.py +++ b/tests/test_wiser_sidebar.py @@ -350,6 +350,26 @@ async def test_all_panel_settings_apply_without_reloading_integration(self): await self.entry_updates.async_handle_entry_update(self.hass, entry) self.hass.config_entries.async_reload.assert_awaited_once_with(entry.entry_id) + async def test_opentherm_detection_change_reloads_once(self): + entry = self.add_hub("hub", {}) + entry.data = {"host": "wiser.local"} + loaded = self.hass.data["wiser"][entry.entry_id] + loaded["reload_settings"] = self.entry_updates.integration_reload_settings(entry) + self.hass.config_entries.async_reload = AsyncMock() + + entry.data["opentherm_ever_connected"] = True + await self.entry_updates.async_handle_entry_update(self.hass, entry) + self.hass.config_entries.async_reload.assert_awaited_once_with(entry.entry_id) + + self.hass.config_entries.async_reload.reset_mock() + loaded["reload_settings"] = self.entry_updates.integration_reload_settings(entry) + with patch.object( + self.entry_updates, "async_update_wiser_panel", AsyncMock() + ) as refresh: + await self.entry_updates.async_handle_entry_update(self.hass, entry) + self.hass.config_entries.async_reload.assert_not_awaited() + refresh.assert_awaited_once_with(self.hass) + def test_invalid_panel_settings_do_not_partially_save(self): self.add_hub("first", {}) self.add_hub("second", {}) From bd7c2e8e652ddcc864df4e4216b1a3dc669fd419 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 15:08:56 +0100 Subject: [PATCH 079/154] fix: guard missing OpenTherm system data --- custom_components/wiser/__init__.py | 12 +++++++++-- tests/test_ui_options.py | 31 +++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index 55485ddd..c1649ee8 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -292,7 +292,11 @@ def _remember_opentherm_connection(hass, config_entry, coordinator) -> None: update listener reloads platforms when runtime detection changes. A Store would persist the state but would not trigger that reload. """ - opentherm = getattr(coordinator.wiserhub.system, "opentherm", None) + system = getattr(coordinator.wiserhub, "system", None) + if system is None: + return + + opentherm = getattr(system, "opentherm", None) remembered = config_entry.data.get(CONF_OPENTHERM_EVER_CONNECTED, False) if getattr(opentherm, "enabled", None) is False: @@ -329,7 +333,11 @@ def _sync_opentherm_entity_registry( hass, config_entry, coordinator, detected=None ) -> None: """Hide false OpenTherm entities while preserving their registry data.""" - opentherm = getattr(coordinator.wiserhub.system, "opentherm", None) + system = getattr(coordinator.wiserhub, "system", None) + if system is None: + return + + opentherm = getattr(system, "opentherm", None) if detected is None: detected = opentherm_is_detected(config_entry, opentherm) unique_ids = opentherm_entity_unique_ids(coordinator) diff --git a/tests/test_ui_options.py b/tests/test_ui_options.py index e07ceb53..3202fe2d 100644 --- a/tests/test_ui_options.py +++ b/tests/test_ui_options.py @@ -198,6 +198,29 @@ def test_disabling_opentherm_clears_remembered_connection(self): hass, entry, coordinator, detected=False ) + def test_missing_system_preserves_remembered_connection(self): + sync_registry = Mock() + self.namespace["_sync_opentherm_entity_registry"] = sync_registry + functions = load_functions( + "__init__.py", {"_remember_opentherm_connection"}, self.namespace + ) + update = Mock() + hass = SimpleNamespace( + config_entries=SimpleNamespace(async_update_entry=update) + ) + entry = SimpleNamespace( + data={ + "host": "wiser.local", + "opentherm_ever_connected": True, + } + ) + coordinator = SimpleNamespace(wiserhub=SimpleNamespace(system=None)) + + functions._remember_opentherm_connection(hass, entry, coordinator) + + update.assert_not_called() + sync_registry.assert_not_called() + def test_opentherm_registry_entries_are_disabled_without_detection(self): integration = "integration" registry = SimpleNamespace(async_update_entity=Mock()) @@ -241,6 +264,14 @@ def test_opentherm_registry_entries_are_disabled_without_detection(self): "__init__.py", {"_sync_opentherm_entity_registry"}, self.namespace ) config_entry = SimpleNamespace(entry_id="entry", data={}) + + functions._sync_opentherm_entity_registry( + object(), + config_entry, + SimpleNamespace(wiserhub=SimpleNamespace(system=None)), + ) + registry.async_update_entity.assert_not_called() + coordinator = SimpleNamespace( wiserhub=SimpleNamespace( system=SimpleNamespace( From 839ff0f8e6db900cd56263ed464f3462ad37af91 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 15:12:14 +0100 Subject: [PATCH 080/154] fix: guard missing OpenTherm circuit data --- custom_components/wiser/sensor.py | 21 +++++++++++------ tests/test_sensor.py | 39 +++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index c2666965..23cd51a6 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -920,15 +920,22 @@ def extra_state_attributes(self): attrs[f"is_smartvalve_preventing_demand_{heating_channel.name}"] = ( heating_channel.is_smart_valve_preventing_demand ) - if self._data.wiserhub.system.opentherm.connection_status == "Connected": - opentherm = self._data.wiserhub.system.opentherm.operational_data - attrs["ch_flow_temperature"] = opentherm.ch_flow_temperature - attrs["ch_pressure_bar"] = opentherm.ch_pressure_bar - attrs["ch_return_temperature"] = opentherm.ch_return_temperature + system = getattr(self._data.wiserhub, "system", None) + opentherm = getattr(system, "opentherm", None) + operational_data = getattr(opentherm, "operational_data", None) + if ( + getattr(opentherm, "connection_status", None) == "Connected" + and operational_data is not None + ): + attrs["ch_flow_temperature"] = operational_data.ch_flow_temperature + attrs["ch_pressure_bar"] = operational_data.ch_pressure_bar + attrs["ch_return_temperature"] = ( + operational_data.ch_return_temperature + ) attrs["relative_modulation_level"] = _relative_modulation_level( - self._data.wiserhub.system.opentherm + opentherm ) - attrs["hw_temperature"] = opentherm.hw_temperature + attrs["hw_temperature"] = operational_data.hw_temperature else: hw = self._data.wiserhub.hotwater # If boosted show boost end time diff --git a/tests/test_sensor.py b/tests/test_sensor.py index cf424d2d..811e63f6 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -243,6 +243,16 @@ def opentherm_sensor_value(opentherm, key): ), relative_modulation_level=relative_modulation_level, ) + _module( + "wiser.opentherm_detection", + opentherm_is_detected=lambda config_entry, opentherm: bool( + opentherm + and ( + config_entry.data.get("opentherm_ever_connected", False) + or getattr(opentherm, "connection_status", None) == "Connected" + ) + ), + ) _module( "wiser.temperature", room_target_temperature=lambda room, frost_temp, off_temp: ( @@ -566,8 +576,13 @@ def _sensor( heating_state="Off", demand_state="Off", hot_water_state="Off", + system=None, ): heating_channel = SimpleNamespace( + name="Channel 1", + percentage_demand=0, + room_ids=[], + is_smart_valve_preventing_demand=False, heating_relay_status=heating_state, demand_on_off_output=demand_state, ) @@ -580,6 +595,7 @@ def _sensor( get_by_id=lambda _device_id: heating_channel ), hotwater=SimpleNamespace(current_state=hot_water_state), + system=system, ) ) sensor.async_write_ha_state = Mock() @@ -615,6 +631,29 @@ def test_unknown_or_unexpected_state_is_not_reported_as_off(self) -> None: self.assertIsNone(sensor.native_value) + def test_heating_attributes_handle_missing_opentherm_data(self) -> None: + for system in ( + None, + SimpleNamespace(opentherm=None), + SimpleNamespace( + opentherm=SimpleNamespace( + connection_status="Connected", + operational_data=None, + ) + ), + ): + with self.subTest(system=system): + sensor = self._sensor("Heating", system=system) + + self.assertEqual( + sensor.extra_state_attributes, + { + "percentage_demand_Channel 1": 0, + "room_ids_Channel 1": [], + "is_smartvalve_preventing_demand_Channel 1": False, + }, + ) + def test_circuit_states_have_translations(self) -> None: files = [ SOURCE_PATH.parent / "strings.json", From 94c0e476c8644f75a5088c179d2d86d02c1a108c Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 16:11:28 +0100 Subject: [PATCH 081/154] test: complete binary sensor import stubs --- tests/test_sensor.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 54e92f2d..14942cda 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -72,7 +72,8 @@ class SensorEntity: UnitOfVolumeFlowRate=SimpleNamespace(LITERS_PER_MINUTE="L/min"), ) _module("homeassistant.core", HomeAssistant=object, callback=lambda func: func) - _module("homeassistant.helpers") + entity_registry = _module("homeassistant.helpers.entity_registry") + _module("homeassistant.helpers", entity_registry=entity_registry) class CoordinatorEntity: def __init__(self, coordinator, *args: object) -> None: @@ -111,7 +112,9 @@ def available(self): get_identifier=lambda *_args: "identifier", get_hub_device_info=lambda _data: {"identifiers": {("wiser", "hub")}}, get_hub_via_device_info=lambda _data: {}, + get_legacy_unique_id=lambda *_args: "legacy-unique-id", get_unique_id=lambda *_args: "unique-id", + get_uuid_unique_id=lambda unique_id: f"uuid-{unique_id}", ) class WiserEntityMixin: pass From 63b7480824038458fe3dc9ad4b418ed8e3c4dd23 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 16:12:22 +0100 Subject: [PATCH 082/154] fix: detect PCM support independently --- custom_components/wiser/binary_sensor.py | 47 ++++++++++++---- tests/test_sensor.py | 68 ++++++++++++++++++------ 2 files changed, 89 insertions(+), 26 deletions(-) diff --git a/custom_components/wiser/binary_sensor.py b/custom_components/wiser/binary_sensor.py index 9b69726b..0aa4596e 100644 --- a/custom_components/wiser/binary_sensor.py +++ b/custom_components/wiser/binary_sensor.py @@ -2,6 +2,8 @@ import logging +from aioWiserHeatAPI.const import TEXT_UNKNOWN + from homeassistant.components.binary_sensor import ( BinarySensorDeviceClass, BinarySensorEntity, @@ -34,9 +36,11 @@ _LOGGER = logging.getLogger(__name__) -V2_SYSTEM_BINARY_SENSOR_TYPES = ( +SUMMER_COMFORT_BINARY_SENSOR_TYPES = ( "Summer Discomfort Prevention", "Summer Comfort Available", +) +PCM_BINARY_SENSOR_TYPES = ( "PCM Device Limit Reached", ) @@ -46,8 +50,8 @@ def _entity_translation_key(name: str) -> str: return name.lower().replace(" ", "_") -def _supports_v2_system_binary_sensors(data) -> bool: - """Return whether the hub supplies second-generation system data.""" +def _supports_summer_comfort_binary_sensors(data) -> bool: + """Return whether the hub supplies summer-comfort system data.""" if data.hub_version != 2: return False system = data.wiserhub.system @@ -60,13 +64,23 @@ def _supports_v2_system_binary_sensors(data) -> bool: ) +def _supports_pcm_binary_sensor(data) -> bool: + """Return whether the hub supplies PCM system data.""" + if data.hub_version != 2: + return False + return getattr(data.wiserhub.system, "pcm_version", TEXT_UNKNOWN) not in ( + None, + TEXT_UNKNOWN, + ) + + def _remove_unsupported_v2_entities( - hass: HomeAssistant, config_entry_id: str, data + hass: HomeAssistant, config_entry_id: str, data, sensor_types ) -> None: """Remove V2-only registry entries from an unsupported hub.""" registry = er.async_get(hass) legacy_hub_name = data.wiserhub.system.name.replace("WiserHeat", "HeatHub") - for sensor_type in V2_SYSTEM_BINARY_SENSOR_TYPES: + for sensor_type in sensor_types: legacy_unique_id = get_legacy_unique_id( data, "sensor", @@ -111,19 +125,34 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie ) ) - # Summer comfort and PCM require second-generation system data. - if _supports_v2_system_binary_sensors(data): + if _supports_summer_comfort_binary_sensors(data): binary_sensors.extend( [ WiserSummerDiscomfortPrevention( data, 0, "Summer Discomfort Prevention" ), WiserSummerComfortAvailable(data, 0, "Summer Comfort Available"), - WiserPCMDeviceLimitReached(data, 0, "PCM Device Limit Reached"), ] ) else: - _remove_unsupported_v2_entities(hass, config_entry.entry_id, data) + _remove_unsupported_v2_entities( + hass, + config_entry.entry_id, + data, + SUMMER_COMFORT_BINARY_SENSOR_TYPES, + ) + + if _supports_pcm_binary_sensor(data): + binary_sensors.append( + WiserPCMDeviceLimitReached(data, 0, "PCM Device Limit Reached") + ) + else: + _remove_unsupported_v2_entities( + hass, + config_entry.entry_id, + data, + PCM_BINARY_SENSOR_TYPES, + ) # Smoke alarm sensors for device in data.wiserhub.devices.smokealarms.all: diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 14942cda..3e4d9dbf 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -304,35 +304,41 @@ def setUpClass(cls) -> None: "class BaseBinarySensor", 1 )[0] cls.tree = ast.parse(setup_source) - support_function = next( + support_functions = [ node for node in cls.tree.body if isinstance(node, ast.FunctionDef) - and node.name == "_supports_v2_system_binary_sensors" - ) - namespace = {} + and node.name + in { + "_supports_summer_comfort_binary_sensors", + "_supports_pcm_binary_sensor", + } + ] + namespace = {"TEXT_UNKNOWN": "Unknown"} exec( compile( - ast.Module(body=[support_function], type_ignores=[]), + ast.Module(body=support_functions, type_ignores=[]), BINARY_SENSOR_SOURCE_PATH.name, "exec", ), namespace, ) - cls.supports_v2_sensors = staticmethod( - namespace["_supports_v2_system_binary_sensors"] + cls.supports_summer_comfort = staticmethod( + namespace["_supports_summer_comfort_binary_sensors"] ) + cls.supports_pcm = staticmethod(namespace["_supports_pcm_binary_sensor"]) def test_v1_does_not_support_v2_system_sensors(self) -> None: data = SimpleNamespace(hub_version=1) - self.assertFalse(self.supports_v2_sensors(data)) + self.assertFalse(self.supports_summer_comfort(data)) + self.assertFalse(self.supports_pcm(data)) def test_v2_without_summer_comfort_data_is_not_supported(self) -> None: data = SimpleNamespace( hub_version=2, wiserhub=SimpleNamespace(system=SimpleNamespace()), ) - self.assertFalse(self.supports_v2_sensors(data)) + self.assertFalse(self.supports_summer_comfort(data)) def test_v2_with_summer_comfort_data_is_supported(self) -> None: data = SimpleNamespace( @@ -341,7 +347,21 @@ def test_v2_with_summer_comfort_data_is_supported(self) -> None: system=SimpleNamespace(summer_comfort_available=False) ), ) - self.assertTrue(self.supports_v2_sensors(data)) + self.assertTrue(self.supports_summer_comfort(data)) + + def test_v2_without_pcm_data_is_not_supported(self) -> None: + data = SimpleNamespace( + hub_version=2, + wiserhub=SimpleNamespace(system=SimpleNamespace()), + ) + self.assertFalse(self.supports_pcm(data)) + + def test_v2_with_pcm_data_is_supported(self) -> None: + data = SimpleNamespace( + hub_version=2, + wiserhub=SimpleNamespace(system=SimpleNamespace(pcm_version="1.0")), + ) + self.assertTrue(self.supports_pcm(data)) def test_summer_comfort_sensors_use_capability_guard(self) -> None: setup = next( @@ -350,25 +370,39 @@ def test_summer_comfort_sensors_use_capability_guard(self) -> None: if isinstance(node, ast.AsyncFunctionDef) and node.name == "async_setup_entry" ) - v2_guard = next( + summer_guard = next( node for node in ast.walk(setup) if isinstance(node, ast.If) and ast.unparse(node.test) - == "_supports_v2_system_binary_sensors(data)" + == "_supports_summer_comfort_binary_sensors(data)" ) - guarded_calls = { + summer_calls = { node.func.id - for node in ast.walk(v2_guard) + for node in ast.walk(summer_guard) if isinstance(node, ast.Call) and isinstance(node.func, ast.Name) } - self.assertTrue( { "WiserSummerDiscomfortPrevention", "WiserSummerComfortAvailable", - "WiserPCMDeviceLimitReached", - }.issubset(guarded_calls) + }.issubset(summer_calls) + ) + + pcm_guard = next( + node + for node in ast.walk(setup) + if isinstance(node, ast.If) + and ast.unparse(node.test) == "_supports_pcm_binary_sensor(data)" + ) + pcm_calls = { + node.func.id + for node in ast.walk(pcm_guard) + if isinstance(node, ast.Call) and isinstance(node.func, ast.Name) + } + self.assertIn( + "WiserPCMDeviceLimitReached", + pcm_calls, ) cleanup_call = next( From 16ae1a87e4084fee291d9309a1f20e3d6f0f0dc5 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 16:16:15 +0100 Subject: [PATCH 083/154] fix: limit V2 entity cleanup to V1 hubs --- custom_components/wiser/binary_sensor.py | 16 +++++++--------- tests/test_sensor.py | 9 +++++++++ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/custom_components/wiser/binary_sensor.py b/custom_components/wiser/binary_sensor.py index 0aa4596e..eeaa10ee 100644 --- a/custom_components/wiser/binary_sensor.py +++ b/custom_components/wiser/binary_sensor.py @@ -74,6 +74,11 @@ def _supports_pcm_binary_sensor(data) -> bool: ) +def _requires_v2_entity_cleanup(data) -> bool: + """Return whether the hub is definitively unable to support V2 entities.""" + return data.hub_version < 2 + + def _remove_unsupported_v2_entities( hass: HomeAssistant, config_entry_id: str, data, sensor_types ) -> None: @@ -134,24 +139,17 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie WiserSummerComfortAvailable(data, 0, "Summer Comfort Available"), ] ) - else: - _remove_unsupported_v2_entities( - hass, - config_entry.entry_id, - data, - SUMMER_COMFORT_BINARY_SENSOR_TYPES, - ) if _supports_pcm_binary_sensor(data): binary_sensors.append( WiserPCMDeviceLimitReached(data, 0, "PCM Device Limit Reached") ) - else: + if _requires_v2_entity_cleanup(data): _remove_unsupported_v2_entities( hass, config_entry.entry_id, data, - PCM_BINARY_SENSOR_TYPES, + SUMMER_COMFORT_BINARY_SENSOR_TYPES + PCM_BINARY_SENSOR_TYPES, ) # Smoke alarm sensors diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 3e4d9dbf..873b20e0 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -312,6 +312,7 @@ def setUpClass(cls) -> None: in { "_supports_summer_comfort_binary_sensors", "_supports_pcm_binary_sensor", + "_requires_v2_entity_cleanup", } ] namespace = {"TEXT_UNKNOWN": "Unknown"} @@ -327,6 +328,9 @@ def setUpClass(cls) -> None: namespace["_supports_summer_comfort_binary_sensors"] ) cls.supports_pcm = staticmethod(namespace["_supports_pcm_binary_sensor"]) + cls.requires_cleanup = staticmethod( + namespace["_requires_v2_entity_cleanup"] + ) def test_v1_does_not_support_v2_system_sensors(self) -> None: data = SimpleNamespace(hub_version=1) @@ -363,6 +367,11 @@ def test_v2_with_pcm_data_is_supported(self) -> None: ) self.assertTrue(self.supports_pcm(data)) + def test_cleanup_is_limited_to_v1_hubs(self) -> None: + self.assertTrue(self.requires_cleanup(SimpleNamespace(hub_version=1))) + self.assertFalse(self.requires_cleanup(SimpleNamespace(hub_version=2))) + self.assertFalse(self.requires_cleanup(SimpleNamespace(hub_version=3))) + def test_summer_comfort_sensors_use_capability_guard(self) -> None: setup = next( node From 245060dfa00d1db9082aaf6a483a9e9c7d2043a1 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 16:16:55 +0100 Subject: [PATCH 084/154] fix: support future hub generations --- custom_components/wiser/binary_sensor.py | 4 ++-- tests/test_sensor.py | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/custom_components/wiser/binary_sensor.py b/custom_components/wiser/binary_sensor.py index eeaa10ee..1b871876 100644 --- a/custom_components/wiser/binary_sensor.py +++ b/custom_components/wiser/binary_sensor.py @@ -52,7 +52,7 @@ def _entity_translation_key(name: str) -> str: def _supports_summer_comfort_binary_sensors(data) -> bool: """Return whether the hub supplies summer-comfort system data.""" - if data.hub_version != 2: + if data.hub_version < 2: return False system = data.wiserhub.system return any( @@ -66,7 +66,7 @@ def _supports_summer_comfort_binary_sensors(data) -> bool: def _supports_pcm_binary_sensor(data) -> bool: """Return whether the hub supplies PCM system data.""" - if data.hub_version != 2: + if data.hub_version < 2: return False return getattr(data.wiserhub.system, "pcm_version", TEXT_UNKNOWN) not in ( None, diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 873b20e0..10983d6f 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -367,6 +367,19 @@ def test_v2_with_pcm_data_is_supported(self) -> None: ) self.assertTrue(self.supports_pcm(data)) + def test_future_hub_versions_can_support_v2_system_sensors(self) -> None: + data = SimpleNamespace( + hub_version=3, + wiserhub=SimpleNamespace( + system=SimpleNamespace( + summer_comfort_available=False, + pcm_version="1.0", + ) + ), + ) + self.assertTrue(self.supports_summer_comfort(data)) + self.assertTrue(self.supports_pcm(data)) + def test_cleanup_is_limited_to_v1_hubs(self) -> None: self.assertTrue(self.requires_cleanup(SimpleNamespace(hub_version=1))) self.assertFalse(self.requires_cleanup(SimpleNamespace(hub_version=2))) From 694cabdad51f8d578c888f16333e269e83ecaef4 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 16:18:25 +0100 Subject: [PATCH 085/154] refactor: clean migrated V2 entity IDs --- custom_components/wiser/binary_sensor.py | 29 ++++++++++-------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/custom_components/wiser/binary_sensor.py b/custom_components/wiser/binary_sensor.py index 1b871876..1a2bfaae 100644 --- a/custom_components/wiser/binary_sensor.py +++ b/custom_components/wiser/binary_sensor.py @@ -86,24 +86,19 @@ def _remove_unsupported_v2_entities( registry = er.async_get(hass) legacy_hub_name = data.wiserhub.system.name.replace("WiserHeat", "HeatHub") for sensor_type in sensor_types: - legacy_unique_id = get_legacy_unique_id( - data, - "sensor", - sensor_type, - f"{legacy_hub_name} {sensor_type}", - ) - unique_ids = { - legacy_unique_id, - get_uuid_unique_id(legacy_unique_id), - } - for unique_id in unique_ids: - entity_id = registry.async_get_entity_id( - "binary_sensor", DOMAIN, unique_id + unique_id = get_uuid_unique_id( + get_legacy_unique_id( + data, + "sensor", + sensor_type, + f"{legacy_hub_name} {sensor_type}", ) - if entity_id is not None: - entry = registry.async_get(entity_id) - if entry and entry.config_entry_id == config_entry_id: - registry.async_remove(entity_id) + ) + entity_id = registry.async_get_entity_id("binary_sensor", DOMAIN, unique_id) + if entity_id is not None: + entry = registry.async_get(entity_id) + if entry and entry.config_entry_id == config_entry_id: + registry.async_remove(entity_id) async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entities): From 71dd088493dcf61198dc9a20b68bd6a06e4fea81 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 16:19:43 +0100 Subject: [PATCH 086/154] refactor: share V2 sensor names --- custom_components/wiser/binary_sensor.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/custom_components/wiser/binary_sensor.py b/custom_components/wiser/binary_sensor.py index 1a2bfaae..e58078a5 100644 --- a/custom_components/wiser/binary_sensor.py +++ b/custom_components/wiser/binary_sensor.py @@ -36,13 +36,14 @@ _LOGGER = logging.getLogger(__name__) +SUMMER_DISCOMFORT_PREVENTION = "Summer Discomfort Prevention" +SUMMER_COMFORT_AVAILABLE = "Summer Comfort Available" +PCM_DEVICE_LIMIT_REACHED = "PCM Device Limit Reached" SUMMER_COMFORT_BINARY_SENSOR_TYPES = ( - "Summer Discomfort Prevention", - "Summer Comfort Available", -) -PCM_BINARY_SENSOR_TYPES = ( - "PCM Device Limit Reached", + SUMMER_DISCOMFORT_PREVENTION, + SUMMER_COMFORT_AVAILABLE, ) +PCM_BINARY_SENSOR_TYPES = (PCM_DEVICE_LIMIT_REACHED,) def _entity_translation_key(name: str) -> str: @@ -129,15 +130,15 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie binary_sensors.extend( [ WiserSummerDiscomfortPrevention( - data, 0, "Summer Discomfort Prevention" + data, 0, SUMMER_DISCOMFORT_PREVENTION ), - WiserSummerComfortAvailable(data, 0, "Summer Comfort Available"), + WiserSummerComfortAvailable(data, 0, SUMMER_COMFORT_AVAILABLE), ] ) if _supports_pcm_binary_sensor(data): binary_sensors.append( - WiserPCMDeviceLimitReached(data, 0, "PCM Device Limit Reached") + WiserPCMDeviceLimitReached(data, 0, PCM_DEVICE_LIMIT_REACHED) ) if _requires_v2_entity_cleanup(data): _remove_unsupported_v2_entities( From f6455da5719a684a3851f3c3d950ccdba734dd73 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 16:20:43 +0100 Subject: [PATCH 087/154] test: cover V2 entity cleanup --- tests/test_sensor.py | 69 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 10983d6f..e5ce0c4b 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -304,7 +304,7 @@ def setUpClass(cls) -> None: "class BaseBinarySensor", 1 )[0] cls.tree = ast.parse(setup_source) - support_functions = [ + tested_functions = [ node for node in cls.tree.body if isinstance(node, ast.FunctionDef) @@ -313,12 +313,23 @@ def setUpClass(cls) -> None: "_supports_summer_comfort_binary_sensors", "_supports_pcm_binary_sensor", "_requires_v2_entity_cleanup", + "_remove_unsupported_v2_entities", } ] - namespace = {"TEXT_UNKNOWN": "Unknown"} + cls.registry = Mock() + cls.get_legacy_unique_id = Mock(return_value="legacy-unique-id") + cls.get_uuid_unique_id = Mock(return_value="uuid-unique-id") + namespace = { + "DOMAIN": "wiser", + "HomeAssistant": object, + "TEXT_UNKNOWN": "Unknown", + "er": SimpleNamespace(async_get=lambda _hass: cls.registry), + "get_legacy_unique_id": cls.get_legacy_unique_id, + "get_uuid_unique_id": cls.get_uuid_unique_id, + } exec( compile( - ast.Module(body=support_functions, type_ignores=[]), + ast.Module(body=tested_functions, type_ignores=[]), BINARY_SENSOR_SOURCE_PATH.name, "exec", ), @@ -331,6 +342,16 @@ def setUpClass(cls) -> None: cls.requires_cleanup = staticmethod( namespace["_requires_v2_entity_cleanup"] ) + cls.remove_unsupported_entities = staticmethod( + namespace["_remove_unsupported_v2_entities"] + ) + + def setUp(self) -> None: + self.registry.reset_mock() + self.get_legacy_unique_id.reset_mock() + self.get_uuid_unique_id.reset_mock() + self.get_legacy_unique_id.return_value = "legacy-unique-id" + self.get_uuid_unique_id.return_value = "uuid-unique-id" def test_v1_does_not_support_v2_system_sensors(self) -> None: data = SimpleNamespace(hub_version=1) @@ -385,6 +406,48 @@ def test_cleanup_is_limited_to_v1_hubs(self) -> None: self.assertFalse(self.requires_cleanup(SimpleNamespace(hub_version=2))) self.assertFalse(self.requires_cleanup(SimpleNamespace(hub_version=3))) + def test_cleanup_removes_owned_migrated_entity(self) -> None: + self.registry.async_get_entity_id.return_value = "binary_sensor.pcm_limit" + self.registry.async_get.return_value = SimpleNamespace( + config_entry_id="entry-id" + ) + data = SimpleNamespace( + wiserhub=SimpleNamespace(system=SimpleNamespace(name="WiserHeat123456")) + ) + + self.remove_unsupported_entities( + object(), "entry-id", data, ("PCM Device Limit Reached",) + ) + + self.get_legacy_unique_id.assert_called_once_with( + data, + "sensor", + "PCM Device Limit Reached", + "HeatHub123456 PCM Device Limit Reached", + ) + self.get_uuid_unique_id.assert_called_once_with("legacy-unique-id") + self.registry.async_get_entity_id.assert_called_once_with( + "binary_sensor", "wiser", "uuid-unique-id" + ) + self.registry.async_remove.assert_called_once_with( + "binary_sensor.pcm_limit" + ) + + def test_cleanup_keeps_entity_owned_by_another_entry(self) -> None: + self.registry.async_get_entity_id.return_value = "binary_sensor.pcm_limit" + self.registry.async_get.return_value = SimpleNamespace( + config_entry_id="other-entry" + ) + data = SimpleNamespace( + wiserhub=SimpleNamespace(system=SimpleNamespace(name="WiserHeat123456")) + ) + + self.remove_unsupported_entities( + object(), "entry-id", data, ("PCM Device Limit Reached",) + ) + + self.registry.async_remove.assert_not_called() + def test_summer_comfort_sensors_use_capability_guard(self) -> None: setup = next( node From 7c6fa972fa297fabe08e4e24eb22f47c10b45156 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 16:21:33 +0100 Subject: [PATCH 088/154] test: inspect V2 guards structurally --- tests/test_sensor.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/test_sensor.py b/tests/test_sensor.py index e5ce0c4b..f11604fc 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -455,13 +455,18 @@ def test_summer_comfort_sensors_use_capability_guard(self) -> None: if isinstance(node, ast.AsyncFunctionDef) and node.name == "async_setup_entry" ) - summer_guard = next( - node - for node in ast.walk(setup) - if isinstance(node, ast.If) - and ast.unparse(node.test) - == "_supports_summer_comfort_binary_sensors(data)" - ) + + def guard_for(function_name: str) -> ast.If: + return next( + node + for node in ast.walk(setup) + if isinstance(node, ast.If) + and isinstance(node.test, ast.Call) + and isinstance(node.test.func, ast.Name) + and node.test.func.id == function_name + ) + + summer_guard = guard_for("_supports_summer_comfort_binary_sensors") summer_calls = { node.func.id for node in ast.walk(summer_guard) @@ -474,12 +479,7 @@ def test_summer_comfort_sensors_use_capability_guard(self) -> None: }.issubset(summer_calls) ) - pcm_guard = next( - node - for node in ast.walk(setup) - if isinstance(node, ast.If) - and ast.unparse(node.test) == "_supports_pcm_binary_sensor(data)" - ) + pcm_guard = guard_for("_supports_pcm_binary_sensor") pcm_calls = { node.func.id for node in ast.walk(pcm_guard) From 73785c8a00185d97f0b4ead3f8e7828b62f01484 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 16:23:53 +0100 Subject: [PATCH 089/154] fix: detect summer sensor support independently --- custom_components/wiser/binary_sensor.py | 43 +++++++++++++--------- tests/test_sensor.py | 47 ++++++++++++++++++------ 2 files changed, 62 insertions(+), 28 deletions(-) diff --git a/custom_components/wiser/binary_sensor.py b/custom_components/wiser/binary_sensor.py index e58078a5..0cd17b00 100644 --- a/custom_components/wiser/binary_sensor.py +++ b/custom_components/wiser/binary_sensor.py @@ -51,17 +51,24 @@ def _entity_translation_key(name: str) -> str: return name.lower().replace(" ", "_") -def _supports_summer_comfort_binary_sensors(data) -> bool: - """Return whether the hub supplies summer-comfort system data.""" +def _supports_v2_system_property(data, property_name: str) -> bool: + """Return whether the hub supplies a second-generation system property.""" if data.hub_version < 2: return False - system = data.wiserhub.system - return any( - getattr(system, attribute, None) is not None - for attribute in ( - "summer_comfort_available", - "summer_discomfort_prevention", - ) + return getattr(data.wiserhub.system, property_name, None) is not None + + +def _supports_summer_discomfort_prevention(data) -> bool: + """Return whether the hub supplies summer-discomfort data.""" + return _supports_v2_system_property( + data, "summer_discomfort_prevention" + ) + + +def _supports_summer_comfort_available(data) -> bool: + """Return whether the hub supplies summer-comfort availability data.""" + return _supports_v2_system_property( + data, "summer_comfort_available" ) @@ -126,14 +133,16 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie ) ) - if _supports_summer_comfort_binary_sensors(data): - binary_sensors.extend( - [ - WiserSummerDiscomfortPrevention( - data, 0, SUMMER_DISCOMFORT_PREVENTION - ), - WiserSummerComfortAvailable(data, 0, SUMMER_COMFORT_AVAILABLE), - ] + if _supports_summer_discomfort_prevention(data): + binary_sensors.append( + WiserSummerDiscomfortPrevention( + data, 0, SUMMER_DISCOMFORT_PREVENTION + ) + ) + + if _supports_summer_comfort_available(data): + binary_sensors.append( + WiserSummerComfortAvailable(data, 0, SUMMER_COMFORT_AVAILABLE) ) if _supports_pcm_binary_sensor(data): diff --git a/tests/test_sensor.py b/tests/test_sensor.py index f11604fc..a3dd9c6f 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -310,7 +310,9 @@ def setUpClass(cls) -> None: if isinstance(node, ast.FunctionDef) and node.name in { - "_supports_summer_comfort_binary_sensors", + "_supports_v2_system_property", + "_supports_summer_discomfort_prevention", + "_supports_summer_comfort_available", "_supports_pcm_binary_sensor", "_requires_v2_entity_cleanup", "_remove_unsupported_v2_entities", @@ -335,8 +337,11 @@ def setUpClass(cls) -> None: ), namespace, ) + cls.supports_summer_discomfort = staticmethod( + namespace["_supports_summer_discomfort_prevention"] + ) cls.supports_summer_comfort = staticmethod( - namespace["_supports_summer_comfort_binary_sensors"] + namespace["_supports_summer_comfort_available"] ) cls.supports_pcm = staticmethod(namespace["_supports_pcm_binary_sensor"]) cls.requires_cleanup = staticmethod( @@ -355,6 +360,7 @@ def setUp(self) -> None: def test_v1_does_not_support_v2_system_sensors(self) -> None: data = SimpleNamespace(hub_version=1) + self.assertFalse(self.supports_summer_discomfort(data)) self.assertFalse(self.supports_summer_comfort(data)) self.assertFalse(self.supports_pcm(data)) @@ -363,9 +369,10 @@ def test_v2_without_summer_comfort_data_is_not_supported(self) -> None: hub_version=2, wiserhub=SimpleNamespace(system=SimpleNamespace()), ) + self.assertFalse(self.supports_summer_discomfort(data)) self.assertFalse(self.supports_summer_comfort(data)) - def test_v2_with_summer_comfort_data_is_supported(self) -> None: + def test_v2_summer_properties_are_detected_independently(self) -> None: data = SimpleNamespace( hub_version=2, wiserhub=SimpleNamespace( @@ -373,6 +380,13 @@ def test_v2_with_summer_comfort_data_is_supported(self) -> None: ), ) self.assertTrue(self.supports_summer_comfort(data)) + self.assertFalse(self.supports_summer_discomfort(data)) + + data.wiserhub.system = SimpleNamespace( + summer_discomfort_prevention=False + ) + self.assertTrue(self.supports_summer_discomfort(data)) + self.assertFalse(self.supports_summer_comfort(data)) def test_v2_without_pcm_data_is_not_supported(self) -> None: data = SimpleNamespace( @@ -394,10 +408,12 @@ def test_future_hub_versions_can_support_v2_system_sensors(self) -> None: wiserhub=SimpleNamespace( system=SimpleNamespace( summer_comfort_available=False, + summer_discomfort_prevention=False, pcm_version="1.0", ) ), ) + self.assertTrue(self.supports_summer_discomfort(data)) self.assertTrue(self.supports_summer_comfort(data)) self.assertTrue(self.supports_pcm(data)) @@ -466,17 +482,26 @@ def guard_for(function_name: str) -> ast.If: and node.test.func.id == function_name ) - summer_guard = guard_for("_supports_summer_comfort_binary_sensors") - summer_calls = { + discomfort_guard = guard_for("_supports_summer_discomfort_prevention") + discomfort_calls = { node.func.id - for node in ast.walk(summer_guard) + for node in ast.walk(discomfort_guard) if isinstance(node, ast.Call) and isinstance(node.func, ast.Name) } - self.assertTrue( - { - "WiserSummerDiscomfortPrevention", - "WiserSummerComfortAvailable", - }.issubset(summer_calls) + self.assertIn( + "WiserSummerDiscomfortPrevention", + discomfort_calls, + ) + + comfort_guard = guard_for("_supports_summer_comfort_available") + comfort_calls = { + node.func.id + for node in ast.walk(comfort_guard) + if isinstance(node, ast.Call) and isinstance(node.func, ast.Name) + } + self.assertIn( + "WiserSummerComfortAvailable", + comfort_calls, ) pcm_guard = guard_for("_supports_pcm_binary_sensor") From 3453bc079d4b057d646f09edb9ad470ac3b383bc Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 16:24:52 +0100 Subject: [PATCH 090/154] docs: correct PCM sensor description --- custom_components/wiser/binary_sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/wiser/binary_sensor.py b/custom_components/wiser/binary_sensor.py index 0cd17b00..1a3f9b58 100644 --- a/custom_components/wiser/binary_sensor.py +++ b/custom_components/wiser/binary_sensor.py @@ -550,7 +550,7 @@ class WiserSummerComfortAvailable(SystemBinarySensor): _attr_device_class = BinarySensorDeviceClass.HEAT class WiserPCMDeviceLimitReached(SystemBinarySensor): - """Summer Comfort Available sensor.""" + """PCM device limit reached sensor.""" _attr_device_class = BinarySensorDeviceClass.POWER From 3b972ea874e43c93d421a5468f98bf273b1ef186 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Mon, 5 Oct 2026 17:24:13 +0100 Subject: [PATCH 091/154] fix: preserve devices across room renames --- custom_components/wiser/__init__.py | 260 +++++++++++++++++++++++++++- custom_components/wiser/climate.py | 9 +- custom_components/wiser/const.py | 1 + custom_components/wiser/device.py | 169 ++++++++++++++++++ custom_components/wiser/helpers.py | 54 ++++-- custom_components/wiser/sensor.py | 22 +++ custom_components/wiser/switch.py | 21 +-- tests/test_device.py | 186 +++++++++++++++++++- tests/test_hub_naming.py | 71 ++++++++ tests/test_sensor.py | 6 + tests/test_switch_hot_water.py | 1 + 11 files changed, 762 insertions(+), 38 deletions(-) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index c1649ee8..a0ddb87f 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -7,6 +7,7 @@ import asyncio from functools import partial import logging +import re from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_NAME @@ -29,8 +30,10 @@ CONF_DEPRECATED_HW_TARGET_TEMP, CONF_LEGACY_NAMING, CONF_OPENTHERM_EVER_CONNECTED, + CONF_WISER_ROOM_NAMES, DATA, DOMAIN, + ENTITY_PREFIX, MANUFACTURER, UPDATE_LISTENER, WISER_PLATFORMS, @@ -41,7 +44,11 @@ from .device import ( assign_device_area_if_unset, merge_legacy_hub_device, + migrate_entity_unique_id_duplicates, + migrate_physical_device, + migrate_room_entities, migrate_room_device, + move_devices_from_managed_area, register_hub_device, register_room_assigned_device, ) @@ -55,7 +62,11 @@ get_hub_device_name, get_identifier, get_instance_count, + get_itrv_temperature_unique_id, + get_legacy_device_identifier, get_legacy_room_identifier, + get_room_entity_unique_id, + get_unique_id, ) from .opentherm_detection import ( opentherm_entity_unique_ids, @@ -219,14 +230,8 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): # This prevents a standard boiler's dormant OpenTherm endpoint from creating # entities while allowing a real installation to survive temporary outages. _remember_opentherm_connection(hass, config_entry, coordinator) - - # Update listener for config option changes - update_listener = config_entry.add_update_listener(_async_update_listener) - hass.data[DOMAIN][config_entry.entry_id] = { DATA: coordinator, - UPDATE_LISTENER: update_listener, - "reload_settings": integration_reload_settings(config_entry), } # If OpenTherm connects for the first time after startup, saving the flag @@ -249,8 +254,12 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): hub_device = await async_update_device_registry(hass, config_entry) coordinator.hub_device_id = hub_device.id - # Create physical devices with their Wiser room as Home Assistant's initial - # area. The registry keeps any area the user chooses later. + # Physical device identifiers used to contain mutable room or device names. + # Migrate them before platform setup so renames cannot duplicate devices. + migrate_physical_device_registry(hass, config_entry, hub_device.id) + + # Create physical devices in their Wiser room's Home Assistant area. Later + # room renames move devices only while they remain in that managed area. register_room_assigned_devices(hass, config_entry, hub_device.id) # Move existing hub entities off the old virtual Controller record. @@ -259,6 +268,29 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): # Give logical room devices stable IDs and concise device names. migrate_room_device_registry(hass, config_entry) + previous_room_names = config_entry.data.get(CONF_WISER_ROOM_NAMES, {}) + sync_wiser_room_areas(hass, config_entry, previous_room_names) + _store_wiser_room_names(hass, config_entry, coordinator) + + # Register listeners only after setup-time registry and config migrations. + update_listener = config_entry.add_update_listener(_async_update_listener) + hass.data[DOMAIN][config_entry.entry_id].update( + { + UPDATE_LISTENER: update_listener, + "reload_settings": integration_reload_settings(config_entry), + } + ) + config_entry.async_on_unload( + coordinator.async_add_listener( + partial( + _sync_wiser_room_names, + hass, + config_entry, + coordinator, + ) + ) + ) + # Remap light entity unique_ids from the pre-#683 scheme before the # platforms create entities, so existing light entities are preserved # instead of orphaned (see async_migrate_light_unique_ids). @@ -412,6 +444,127 @@ def register_room_assigned_devices( ) +def migrate_physical_device_registry( + hass: HomeAssistant, config_entry, hub_device_id: str +): + """Migrate physical devices from name-derived to stable identifiers.""" + data = hass.data[DOMAIN][config_entry.entry_id][DATA] + device_registry = dr.async_get(hass) + entity_registry = er.async_get(hass) + registry_devices = list( + dr.async_entries_for_config_entry( + device_registry, config_entry.entry_id + ) + ) + registry_entities = list( + er.async_entries_for_config_entry( + entity_registry, config_entry.entry_id + ) + ) + itrv_identifier_prefix = ( + f"{data.wiserhub.system.name} {ENTITY_PREFIX} iTRV " + ) + for device in data.wiserhub.devices.all: + stable_identifier = (DOMAIN, get_identifier(data, device.id)) + legacy_identifier = ( + DOMAIN, + get_legacy_device_identifier(data, device.id), + ) + possible_devices = [ + entry + for entry in registry_devices + if stable_identifier in entry.identifiers + or legacy_identifier in entry.identifiers + ] + room = data.wiserhub.rooms.get_by_device_id(device.id) + + if device.product_type == "iTRV": + possible_room_names = set() + if room is not None: + possible_room_names.add(room.name) + for entry in registry_devices: + if entry.model != "iTRV": + continue + for domain, value in entry.identifiers: + if domain != DOMAIN or not value.startswith( + itrv_identifier_prefix + ): + continue + suffix = value[len(itrv_identifier_prefix):] + possible_room_names.add(suffix) + possible_room_names.add(re.sub(r"-\d+$", "", suffix)) + + old_temperature_ids = { + get_unique_id( + data, + "sensor", + f"LTS Temperature iTRV {room_name}", + device.id, + ) + for room_name in possible_room_names + } + stable_temperature_id = get_itrv_temperature_unique_id( + data, device.id + ) + matching_temperature_entries = [ + entry + for entry in registry_entities + if entry.domain == "sensor" + and entry.platform == DOMAIN + and entry.unique_id + in old_temperature_ids | {stable_temperature_id} + ] + matching_device_ids = { + entry.device_id + for entry in matching_temperature_entries + if entry.device_id is not None + } + + # Signal and battery IDs have always used the immutable device ID, + # so they locate the record if temperature is disabled or removed. + stable_entity_ids = { + get_unique_id(data, "sensor", device.product_type, device.id), + get_unique_id(data, "sensor", "Battery", device.id), + } + matching_device_ids.update( + entry.device_id + for entry in registry_entities + if entry.unique_id in stable_entity_ids + and entry.device_id is not None + ) + possible_devices.extend( + entry + for entry in registry_devices + if entry.id in matching_device_ids + ) + + migrate_entity_unique_id_duplicates( + entity_registry, + matching_temperature_entries, + stable_temperature_id, + ) + + device_entry = migrate_physical_device( + device_registry, + entity_registry, + config_entry.entry_id, + stable_identifier, + possible_devices, + get_device_name(data, device.id), + manufacturer=MANUFACTURER, + model=device.product_type, + sw_version=device.firmware_version, + via_device_id=hub_device_id, + ) + if room is not None: + assign_device_area_if_unset( + device_registry, + ar.async_get(hass), + device_entry, + room.name, + ) + + def migrate_room_device_registry(hass: HomeAssistant, config_entry): """Migrate all logical room devices away from name-derived identifiers.""" data = hass.data[DOMAIN][config_entry.entry_id][DATA] @@ -431,6 +584,97 @@ def migrate_room_device_registry(hass: HomeAssistant, config_entry): assign_device_area_if_unset( device_registry, area_registry, device_entry, room.name ) + migrate_room_entities( + entity_registry, + device_entry.id, + lambda entity_type: get_room_entity_unique_id( + data, room.id, entity_type + ), + ) + + +def _current_wiser_room_names(coordinator): + """Return Wiser room names keyed by their stable room IDs.""" + return { + str(room.id): room.name for room in coordinator.wiserhub.rooms.all + } + + +def _store_wiser_room_names(hass, config_entry, coordinator) -> None: + """Persist room names before the config-entry update listener is registered.""" + current = _current_wiser_room_names(coordinator) + if config_entry.data.get(CONF_WISER_ROOM_NAMES, {}) == current: + return + hass.config_entries.async_update_entry( + config_entry, + data={**config_entry.data, CONF_WISER_ROOM_NAMES: current}, + ) + + +def _device_by_identifier(device_registry, config_entry_id, identifier): + """Return a device registry entry using current and older HA APIs.""" + get_by_identifier = getattr( + device_registry, "async_get_device_by_identifier", None + ) + if get_by_identifier: + return get_by_identifier(identifier, config_entry_id) + return device_registry.async_get_device(identifiers={identifier}) + + +def sync_wiser_room_areas(hass, config_entry, previous_room_names) -> int: + """Move Wiser devices when their integration-managed room is renamed.""" + data = hass.data[DOMAIN][config_entry.entry_id][DATA] + device_registry = dr.async_get(hass) + area_registry = ar.async_get(hass) + moved = 0 + + for room in data.wiserhub.rooms.all: + room_device = _device_by_identifier( + device_registry, + config_entry.entry_id, + (DOMAIN, get_identifier(data, room.id, "room")), + ) + previous_name = previous_room_names.get(str(room.id)) + if previous_name is None and room_device and room_device.area_id: + previous_area = area_registry.async_get_area(room_device.area_id) + if previous_area is not None: + previous_name = previous_area.name + + room_devices = [room_device] + for device in data.wiserhub.devices.all: + device_room = data.wiserhub.rooms.get_by_device_id(device.id) + if device_room is None or device_room.id != room.id: + continue + room_devices.append( + _device_by_identifier( + device_registry, + config_entry.entry_id, + (DOMAIN, get_identifier(data, device.id)), + ) + ) + + moved += move_devices_from_managed_area( + device_registry, + area_registry, + room_devices, + previous_name, + room.name, + ) + + return moved + + +def _sync_wiser_room_names(hass, config_entry, coordinator) -> None: + """Apply Wiser room renames after a coordinator refresh.""" + previous = config_entry.data.get(CONF_WISER_ROOM_NAMES, {}) + current = _current_wiser_room_names(coordinator) + if previous == current: + return + sync_wiser_room_areas(hass, config_entry, previous) + hass.config_entries.async_update_entry( + config_entry, + data={**config_entry.data, CONF_WISER_ROOM_NAMES: current}, + ) def update_hub_device_names(hass: HomeAssistant): diff --git a/custom_components/wiser/climate.py b/custom_components/wiser/climate.py index 5571c3b3..3c347151 100755 --- a/custom_components/wiser/climate.py +++ b/custom_components/wiser/climate.py @@ -54,7 +54,7 @@ get_device_name, get_hub_via_device_info, get_identifier, - get_room_name, + get_room_entity_unique_id, get_uuid_unique_id, hub_error_handler, ) @@ -707,12 +707,7 @@ def temperature_unit(self): @property def unique_id(self): """Return unique Id.""" - legacy_name = get_room_name(self._data, self._room_id) - legacy_unique_id = ( - f"{self._data.wiserhub.system.name}-WiserRoom-" - f"{self._room_id}-{legacy_name}" - ) - return get_uuid_unique_id(legacy_unique_id) + return get_room_entity_unique_id(self._data, self._room_id, "climate") @hub_error_handler async def async_boost_heating( diff --git a/custom_components/wiser/const.py b/custom_components/wiser/const.py index 689c66dd..353b51f0 100755 --- a/custom_components/wiser/const.py +++ b/custom_components/wiser/const.py @@ -16,6 +16,7 @@ URL_BASE = "/wiser" CONF_SHOW_WISER_SIDEBAR = "show_wiser_sidebar" CONF_WISER_PANEL_CONFIG = "wiser_panel_config" +CONF_WISER_ROOM_NAMES = "wiser_room_names" def _load_card_manifest(): diff --git a/custom_components/wiser/device.py b/custom_components/wiser/device.py index d47e2283..d25eceda 100644 --- a/custom_components/wiser/device.py +++ b/custom_components/wiser/device.py @@ -12,6 +12,31 @@ def assign_device_area_if_unset( return device_registry.async_update_device(device.id, area_id=area.id) +def move_devices_from_managed_area( + device_registry, + area_registry, + devices, + previous_area_name, + new_area_name, +): + """Move Wiser devices that remain in their previous managed area.""" + if not previous_area_name or previous_area_name == new_area_name: + return 0 + + previous_area = area_registry.async_get_area_by_name(previous_area_name) + if previous_area is None: + return 0 + + new_area = area_registry.async_get_or_create(new_area_name) + moved = 0 + for device in {device.id: device for device in devices if device}.values(): + if device.area_id != previous_area.id: + continue + device_registry.async_update_device(device.id, area_id=new_area.id) + moved += 1 + return moved + + def register_room_assigned_device( device_registry, config_entry_id, @@ -30,6 +55,150 @@ def register_room_assigned_device( ) +def migrate_physical_device( + device_registry, + entity_registry, + config_entry_id, + identifier, + candidates, + name, + **device_info, +): + """Give a physical device a stable ID and merge duplicate registry rows.""" + get_by_identifier = getattr( + device_registry, "async_get_device_by_identifier", None + ) + stable_device = ( + get_by_identifier(identifier, config_entry_id) + if get_by_identifier + else device_registry.async_get_device(identifiers={identifier}) + ) + + candidates = list({device.id: device for device in candidates}.values()) + if stable_device is not None and all( + device.id != stable_device.id for device in candidates + ): + candidates.append(stable_device) + if candidates: + canonical = min( + candidates, + key=lambda device: ( + getattr(device, "created_at", None) is None, + getattr(device, "created_at", None), + device.id, + ), + ) + else: + canonical = None + + if canonical is None: + return device_registry.async_get_or_create( + config_entry_id=config_entry_id, + identifiers={identifier}, + name=name, + **device_info, + ) + + for duplicate in candidates: + if duplicate.id == canonical.id: + continue + for entity in list(entity_registry.entities.values()): + if entity.device_id == duplicate.id: + entity_registry.async_update_entity( + entity.entity_id, device_id=canonical.id + ) + device_registry.async_remove_device(duplicate.id) + return device_registry.async_update_device( + canonical.id, + new_identifiers={identifier}, + name=name, + **device_info, + ) + + +def migrate_entity_unique_id_duplicates( + entity_registry, + entries, + new_unique_id, +): + """Keep the oldest entity while replacing duplicate historical IDs.""" + entries = list({entry.entity_id: entry for entry in entries}.values()) + if not entries: + return None + + existing_entity_id = entity_registry.async_get_entity_id( + entries[0].domain, entries[0].platform, new_unique_id + ) + existing = ( + entity_registry.async_get(existing_entity_id) + if existing_entity_id is not None + else None + ) + if existing is not None and all( + entry.entity_id != existing.entity_id for entry in entries + ): + entries.append(existing) + canonical = min( + entries, + key=lambda entry: ( + getattr(entry, "created_at", None) is None, + getattr(entry, "created_at", None), + entry.entity_id, + ), + ) + for duplicate in entries: + if duplicate.entity_id != canonical.entity_id: + entity_registry.async_remove(duplicate.entity_id) + if canonical.unique_id != new_unique_id: + entity_registry.async_update_entity( + canonical.entity_id, new_unique_id=new_unique_id + ) + return canonical + + +def migrate_room_entities( + entity_registry, + room_device_id, + unique_id_for_type, +): + """Migrate room-name-derived entities and remove their duplicates.""" + groups = {} + for entry in list(entity_registry.entities.values()): + if entry.device_id != room_device_id or entry.platform != "wiser": + continue + + entity_type = None + translation_key = getattr(entry, "translation_key", None) + if entry.domain == "climate": + entity_type = "climate" + elif entry.domain == "switch" and translation_key: + entity_type = f"switch_{translation_key}" + elif entry.domain == "sensor": + if translation_key == "heating_demand": + entity_type = "heating_demand" + elif translation_key == "target_temperature": + entity_type = "current_target_temp" + elif ( + translation_key is None + and "temperature" + in { + str(getattr(entry, "device_class", None)), + str(getattr(entry, "original_device_class", None)), + } + ): + entity_type = "current_temp" + + if entity_type is not None: + groups.setdefault(entity_type, []).append(entry) + + for entity_type, entries in groups.items(): + migrate_entity_unique_id_duplicates( + entity_registry, + entries, + unique_id_for_type(entity_type), + ) + + def register_hub_device( device_registry, config_entry_id, diff --git a/custom_components/wiser/helpers.py b/custom_components/wiser/helpers.py index 7b38c94b..92d5687d 100644 --- a/custom_components/wiser/helpers.py +++ b/custom_components/wiser/helpers.py @@ -76,6 +76,8 @@ def get_device_name(data, device_id, device_type="device"): return get_hub_device_name(data) if device.product_type == "iTRV": + if not legacy_naming: + return f"{ENTITY_PREFIX} {device.product_type}" device_room = data.wiserhub.rooms.get_by_device_id(device_id) # If device not allocated to a room return type and id only if device_room: @@ -183,25 +185,43 @@ def get_identifier(data, device_id, device_type="device"): if device_id == 0 and device_type == "device": # Preserve the historical Controller identifier for registry migration. device_name = f"{ENTITY_PREFIX} HeatHub ({data.wiserhub.system.name})" - elif device_type == "device" and ( - device := data.wiserhub.devices.get_by_id(device_id) - ).product_type == "RoomStat": - # Preserve the existing name-derived identifier while modernising the - # RoomStat's display name. + elif device_type == "device": + # A physical device can move between rooms or be renamed without + # becoming a new Home Assistant device. + return f"{data.wiserhub.system.name} device {device_id}" + else: + device_name = get_device_name(data, device_id, device_type) + return f"{data.wiserhub.system.name} {device_name}" + + +def get_legacy_device_identifier(data, device_id): + """Return the former name-derived identifier for a physical device.""" + device = data.wiserhub.devices.get_by_id(device_id) + if device.product_type == "RoomStat": device_room = data.wiserhub.rooms.get_by_device_id(device_id) if device_room: device_name = f"{ENTITY_PREFIX} RoomStat {device_room.name}" else: device_name = f"{ENTITY_PREFIX} RoomStat {device.id}" - elif ( - device_type == "device" - and device.product_type == "TemperatureHumiditySensor" - ): - # Preserve the former name-derived identifier while modernising the - # physical sensor's display name. + elif device.product_type == "TemperatureHumiditySensor": device_name = get_legacy_device_name(data, device_id) + elif device.product_type == "iTRV": + device_room = data.wiserhub.rooms.get_by_device_id(device_id) + if device_room: + if device_room.number_of_smartvalves > 1: + index = device_room.smartvalve_ids.index(device.id) + 1 + device_name = ( + f"{ENTITY_PREFIX} {device.product_type} " + f"{device_room.name}-{index}" + ) + else: + device_name = ( + f"{ENTITY_PREFIX} {device.product_type} {device_room.name}" + ) + else: + device_name = f"{ENTITY_PREFIX} {device.product_type} {device.id}" else: - device_name = get_device_name(data, device_id, device_type) + device_name = get_device_name(data, device_id) return f"{data.wiserhub.system.name} {device_name}" @@ -255,6 +275,16 @@ def get_unique_id(data, device_type, entity_type, device_id): ) +def get_itrv_temperature_unique_id(data, device_id): + """Return the room-independent unique ID for an iTRV temperature.""" + return get_unique_id(data, "sensor", "smartvalve_temp", device_id) + + +def get_room_entity_unique_id(data, room_id, entity_type): + """Return a room-name-independent unique ID for a room entity.""" + return get_unique_id(data, "room", entity_type, room_id) + + def get_light_binary_sensor_unique_id(data, light, sensor_type): """Return the per-channel unique ID for a light capability sensor.""" light_name = f"{ENTITY_PREFIX} {light.name}" diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index 23cd51a6..93b9d6c7 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -58,7 +58,9 @@ get_device_name, get_hub_device_info, get_hub_via_device_info, + get_itrv_temperature_unique_id, get_identifier, + get_room_entity_unique_id, get_unique_id, ) from .opentherm import ( @@ -1239,6 +1241,17 @@ def __init__( translation_key="target_temperature", ) + @property + def unique_id(self): + """Return a stable ID when an iTRV is moved or its room is renamed.""" + if self._lts_sensor_type == "smartvalve_temp": + return get_itrv_temperature_unique_id(self._data, self._device_id) + if self._lts_sensor_type in {"current_temp", "current_target_temp"}: + return get_room_entity_unique_id( + self._data, self._device_id, self._lts_sensor_type + ) + return super().unique_id + @callback def _handle_coordinator_update(self) -> None: """Fetch new state data for the sensor.""" @@ -1753,6 +1766,15 @@ def __init__(self, data, device_id, sensor_type="") -> None: translation_key="heating_demand", ) + @property + def unique_id(self): + """Return a stable ID for room demand across room renames.""" + if self._lts_sensor_type == "room": + return get_room_entity_unique_id( + self._data, self._device_id, "heating_demand" + ) + return super().unique_id + @callback def _handle_coordinator_update(self) -> None: """Fetch new state data for the sensor.""" diff --git a/custom_components/wiser/switch.py b/custom_components/wiser/switch.py index 1157411c..84386545 100755 --- a/custom_components/wiser/switch.py +++ b/custom_components/wiser/switch.py @@ -25,7 +25,7 @@ get_identifier, get_legacy_device_name, get_legacy_unique_id, - get_room_name, + get_room_entity_unique_id, get_unique_id, get_uuid_unique_id, hub_error_handler, @@ -300,11 +300,13 @@ def icon(self): @property def unique_id(self): if self._type == "room": - legacy_name = ( - f"{get_room_name(self._data, self._room_id)} {self._name}" + entity_key = self._attr_translation_key or self._key + return get_room_entity_unique_id( + self._data, + self._room_id, + f"switch_{entity_key}", ) - else: - legacy_name = get_device_name(self._data, 0, self._name) + legacy_name = get_device_name(self._data, 0, self._name) return get_unique_id(self._data, self._type, "switch", legacy_name) @property @@ -799,11 +801,10 @@ def _handle_coordinator_update(self) -> None: @property def unique_id(self): """Return unique Id.""" - legacy_name = ( - f"{get_room_name(self._data, self._room_id)} Passive Mode" - ) - return get_unique_id( - self._data, "passive-mode-switch", legacy_name, self._room_id + return get_room_entity_unique_id( + self._data, + self._room_id, + "switch_passive_mode", ) @property diff --git a/tests/test_device.py b/tests/test_device.py index 367a2c4f..0002c753 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -3,6 +3,7 @@ from __future__ import annotations from dataclasses import dataclass, field +from datetime import datetime, timezone from importlib.util import module_from_spec, spec_from_file_location from pathlib import Path import unittest @@ -23,6 +24,7 @@ class DeviceEntry: area_id: str | None = None labels: set = field(default_factory=set) name_by_user: str | None = None + created_at: datetime | None = None @dataclass @@ -31,6 +33,13 @@ class EntityEntry: entity_id: str device_id: str | None + domain: str = "sensor" + platform: str = "wiser" + unique_id: str = "" + created_at: datetime | None = None + translation_key: str | None = None + device_class: str | None = None + original_device_class: str | None = None @dataclass @@ -38,6 +47,7 @@ class AreaEntry: """Minimal area-registry entry used by the tests.""" id: str + name: str = "" class AreaRegistry: @@ -45,10 +55,24 @@ class AreaRegistry: def __init__(self) -> None: self.requested = [] + self.areas = {} def async_get_or_create(self, name): self.requested.append(name) - return AreaEntry(name.lower().replace(" ", "_")) + area = self.async_get_area_by_name(name) + if area is None: + area = AreaEntry(name.lower().replace(" ", "_"), name) + self.areas[area.id] = area + return area + + def async_get_area_by_name(self, name): + return next( + (area for area in self.areas.values() if area.name == name), + None, + ) + + def async_get_area(self, area_id): + return self.areas.get(area_id) class EntityRegistry: @@ -57,10 +81,29 @@ class EntityRegistry: def __init__(self, entities=None) -> None: self.entities = entities or {} self.updated = [] + self.removed = [] + + def async_get_entity_id(self, domain, platform, unique_id): + return next( + ( + entry.entity_id + for entry in self.entities.values() + if entry.domain == domain + and entry.platform == platform + and entry.unique_id == unique_id + ), + None, + ) + + def async_get(self, entity_id): + return self.entities.get(entity_id) def async_update_entity(self, entity_id, **kwargs) -> None: self.updated.append((entity_id, kwargs)) + def async_remove(self, entity_id) -> None: + self.removed.append(entity_id) + class DeviceRegistry: """Minimal current Home Assistant device registry.""" @@ -297,6 +340,33 @@ def test_preserves_existing_user_area(self) -> None: self.assertEqual(area_registry.requested, []) self.assertEqual(device_registry.updated, []) + def test_moves_only_devices_still_in_previous_managed_area(self) -> None: + device_registry = DeviceRegistry() + area_registry = AreaRegistry() + area_registry.areas["test"] = AreaEntry("test", "Test") + devices = [ + DeviceEntry("room-device", area_id="test"), + DeviceEntry("itrv", area_id="test"), + DeviceEntry("manually-moved", area_id="upstairs"), + ] + + moved = DEVICE.move_devices_from_managed_area( + device_registry, + area_registry, + devices, + "Test", + "Test2", + ) + + self.assertEqual(moved, 2) + self.assertEqual( + device_registry.updated, + [ + ("room-device", {"area_id": "test2"}), + ("itrv", {"area_id": "test2"}), + ], + ) + class MigrateRoomDeviceTest(unittest.TestCase): """Test migration of logical Wiser room devices.""" @@ -386,3 +456,117 @@ def test_preserves_legacy_area_when_merging_duplicate_room(self) -> None: self.assertEqual(registry.updated[0][0], "stable-room") self.assertEqual(registry.updated[0][1]["area_id"], "custom_area") + + +class MigratePhysicalDeviceTest(unittest.TestCase): + """Test migration of room-derived physical device records.""" + + def test_keeps_oldest_device_and_merges_renamed_duplicate(self) -> None: + old = DeviceEntry( + "old-device", + created_at=datetime(2026, 1, 1, tzinfo=timezone.utc), + ) + renamed = DeviceEntry( + "renamed-device", + created_at=datetime(2026, 10, 1, tzinfo=timezone.utc), + ) + registry = DeviceRegistry() + entities = EntityRegistry( + { + "sensor.old_temperature": EntityEntry( + "sensor.old_temperature", "old-device" + ), + "sensor.signal": EntityEntry("sensor.signal", "renamed-device"), + } + ) + + result = DEVICE.migrate_physical_device( + registry, + entities, + "entry-id", + ("wiser", "WiserHeat123456 device 31"), + [renamed, old], + "Wiser iTRV", + model="iTRV", + ) + + self.assertEqual(result.id, "old-device") + self.assertEqual(registry.updated[0][0], "old-device") + self.assertEqual( + registry.updated[0][1]["new_identifiers"], + {("wiser", "WiserHeat123456 device 31")}, + ) + self.assertEqual( + entities.updated, + [("sensor.signal", {"device_id": "old-device"})], + ) + self.assertEqual(registry.removed, ["renamed-device"]) + + def test_keeps_oldest_temperature_entity_and_removes_duplicate(self) -> None: + old = EntityEntry( + "sensor.room_temperature", + "old-device", + unique_id="old-room-id", + created_at=datetime(2026, 1, 1, tzinfo=timezone.utc), + ) + renamed = EntityEntry( + "sensor.test_temperature", + "renamed-device", + unique_id="renamed-room-id", + created_at=datetime(2026, 10, 1, tzinfo=timezone.utc), + ) + entities = EntityRegistry( + {old.entity_id: old, renamed.entity_id: renamed} + ) + + result = DEVICE.migrate_entity_unique_id_duplicates( + entities, + [renamed, old], + "stable-id", + ) + + self.assertEqual(result.entity_id, "sensor.room_temperature") + self.assertEqual( + entities.updated, + [("sensor.room_temperature", {"new_unique_id": "stable-id"})], + ) + self.assertEqual(entities.removed, ["sensor.test_temperature"]) + + def test_migrates_all_room_name_derived_entity_types(self) -> None: + entities = {} + definitions = ( + ("climate", None, None, "climate"), + ("switch", "window_detection", None, "switch_window_detection"), + ("sensor", "heating_demand", None, "heating_demand"), + ("sensor", "target_temperature", "temperature", "current_target_temp"), + ("sensor", None, "temperature", "current_temp"), + ) + for domain, translation_key, device_class, expected_type in definitions: + for suffix, created_at in ( + ("old", datetime(2026, 1, 1, tzinfo=timezone.utc)), + ("new", datetime(2026, 10, 1, tzinfo=timezone.utc)), + ): + entity_id = f"{domain}.{expected_type}_{suffix}" + entities[entity_id] = EntityEntry( + entity_id, + "room-device", + domain=domain, + unique_id=f"{expected_type}-{suffix}", + created_at=created_at, + translation_key=translation_key, + device_class=device_class, + ) + registry = EntityRegistry(entities) + + DEVICE.migrate_room_entities( + registry, + "room-device", + lambda entity_type: f"stable-{entity_type}", + ) + + self.assertEqual(len(registry.updated), len(definitions)) + self.assertEqual(len(registry.removed), len(definitions)) + self.assertEqual( + {update[1]["new_unique_id"] for update in registry.updated}, + {f"stable-{definition[3]}" for definition in definitions}, + ) diff --git a/tests/test_hub_naming.py b/tests/test_hub_naming.py index 9a57f2e3..df58ff30 100644 --- a/tests/test_hub_naming.py +++ b/tests/test_hub_naming.py @@ -191,6 +191,10 @@ def test_roomstat_name_uses_area_for_room_context(self) -> None: ) self.assertEqual( self.helpers.get_identifier(self.data, 21), + "WiserHeatNOTUSED device 21", + ) + self.assertEqual( + self.helpers.get_legacy_device_identifier(self.data, 21), "WiserHeatNOTUSED Wiser RoomStat Andys Bedroom", ) @@ -259,6 +263,10 @@ def test_temperature_sensor_has_concise_name_and_stable_identifier(self) -> None ) self.assertEqual( self.helpers.get_identifier(self.data, 31), + "WiserHeatNOTUSED device 31", + ) + self.assertEqual( + self.helpers.get_legacy_device_identifier(self.data, 31), "WiserHeatNOTUSED Wiser TemperatureHumiditySensor " "Andys Bedroom Kitchen Temperature Sensor", ) @@ -268,6 +276,69 @@ def test_temperature_sensor_has_concise_name_and_stable_identifier(self) -> None "Andys Bedroom Kitchen Temperature Sensor", ) + def test_itrv_name_respects_legacy_option_without_changing_identity(self): + self.data.wiserhub.devices.get_by_id = lambda device_id: SimpleNamespace( + id=device_id, + product_type="iTRV", + ) + self.data.wiserhub.rooms.get_by_device_id = lambda _device_id: SimpleNamespace( + id=7, + name="Andys Bedroom", + number_of_smartvalves=1, + smartvalve_ids=[31], + ) + + self.data.legacy_naming = False + self.assertEqual(self.helpers.get_device_name(self.data, 31), "Wiser iTRV") + identifier = self.helpers.get_identifier(self.data, 31) + self.assertEqual(identifier, "WiserHeatNOTUSED device 31") + + self.data.legacy_naming = True + self.assertEqual( + self.helpers.get_device_name(self.data, 31), + "Wiser iTRV Andys Bedroom", + ) + self.assertEqual(self.helpers.get_identifier(self.data, 31), identifier) + + def test_itrv_temperature_unique_id_does_not_use_room_name(self): + before = self.helpers.get_itrv_temperature_unique_id(self.data, 31) + self.data.wiserhub.rooms.get_by_device_id = lambda _device_id: SimpleNamespace( + id=7, + name="Renamed Room", + ) + self.assertEqual( + self.helpers.get_itrv_temperature_unique_id(self.data, 31), before + ) + + def test_all_physical_device_identifiers_use_immutable_device_id(self): + self.data.wiserhub.devices.get_by_id = lambda _device_id: ( + _ for _ in () + ).throw( + AssertionError( + "physical identifiers must not inspect mutable device data" + ) + ) + + self.assertEqual( + self.helpers.get_identifier(self.data, 42), + "WiserHeatNOTUSED device 42", + ) + + def test_room_entity_unique_id_does_not_use_room_name(self): + before = self.helpers.get_room_entity_unique_id( + self.data, 7, "current_temp" + ) + self.data.wiserhub.rooms.get_by_id = lambda room_id: SimpleNamespace( + id=room_id, + name="Renamed Room", + ) + self.assertEqual( + self.helpers.get_room_entity_unique_id( + self.data, 7, "current_temp" + ), + before, + ) + if __name__ == "__main__": unittest.main() diff --git a/tests/test_sensor.py b/tests/test_sensor.py index f46320db..697eab23 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -114,6 +114,8 @@ def available(self): get_hub_device_info=lambda _data: {"identifiers": {("wiser", "hub")}}, get_hub_via_device_info=lambda _data: {}, get_legacy_unique_id=lambda *_args: "legacy-unique-id", + get_itrv_temperature_unique_id=lambda *_args: "itrv-temperature-id", + get_room_entity_unique_id=lambda *_args: "room-entity-id", get_unique_id=lambda *_args: "unique-id", get_uuid_unique_id=lambda unique_id: f"uuid-{unique_id}", ) @@ -121,6 +123,10 @@ class WiserEntityMixin: pass _module("wiser.entity", WiserEntityMixin=WiserEntityMixin) + _module( + "wiser.opentherm_detection", + opentherm_is_detected=lambda *_args: True, + ) def relative_modulation_level(opentherm): raw = opentherm.operational_data.json_data.get("RelativeModulationLevel") if isinstance(raw, bool) or not isinstance(raw, (int, float)): diff --git a/tests/test_switch_hot_water.py b/tests/test_switch_hot_water.py index c177ad26..d072fe07 100644 --- a/tests/test_switch_hot_water.py +++ b/tests/test_switch_hot_water.py @@ -75,6 +75,7 @@ def hub_error_handler(func): get_identifier=lambda *_args: "identifier", get_legacy_device_name=lambda *_args, **_kwargs: "Wiser HeatHub", get_legacy_unique_id=lambda *_args: "legacy-unique-id", + get_room_entity_unique_id=lambda *_args: "room-entity-id", get_unique_id=lambda *_args: "unique-id", get_uuid_unique_id=lambda *_args: "uuid-unique-id", hub_error_handler=hub_error_handler, From 2b9110e1c3586ee337dacc8918d3afac32de2ac4 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Mon, 5 Oct 2026 18:37:58 +0100 Subject: [PATCH 092/154] fix: stabilize physical entity identities --- custom_components/wiser/__init__.py | 103 ++++++++++------ custom_components/wiser/binary_sensor.py | 10 +- custom_components/wiser/cover.py | 11 +- custom_components/wiser/helpers.py | 145 +++++++++++++++++++++-- custom_components/wiser/number.py | 9 +- custom_components/wiser/sensor.py | 18 ++- custom_components/wiser/switch.py | 71 +++++------ tests/test_hub_naming.py | 36 +++++- tests/test_light_unique_id_migration.py | 12 +- tests/test_sensor.py | 1 + tests/test_switch_hot_water.py | 1 + 11 files changed, 299 insertions(+), 118 deletions(-) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index a0ddb87f..4555ac6b 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -58,13 +58,14 @@ from .frontend.wiser_sidebar import async_update_wiser_panel from .helpers import ( build_light_unique_id_migration, + build_physical_entity_unique_id_migration, get_device_name, get_hub_device_name, get_identifier, get_instance_count, - get_itrv_temperature_unique_id, get_legacy_device_identifier, get_legacy_room_identifier, + get_physical_entity_unique_id, get_room_entity_unique_id, get_unique_id, ) @@ -155,18 +156,20 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> return True -async def async_migrate_light_unique_ids(hass: HomeAssistant, config_entry, data) -> None: - """Preserve light entities across the multi-gang dimmer fix (#681/#683). +async def async_migrate_physical_entity_unique_ids( + hass: HomeAssistant, config_entry, data +) -> None: + """Preserve physical entities while adopting stable unique IDs. - The fix keys every light-derived entity on the per-channel ``light_id`` - instead of the physical device ``id`` (see build_light_unique_id_migration), - which changes the unique_ids of the light, its mode/LED/power-on selects, - its away-mode switch and its four capability binary_sensors. Without this - the pre-fix entities orphan on update, losing their history and dashboard - references. This renames the matching registry entries to the new scheme so - their entity_ids survive the update untouched. + This includes the multi-gang light migration and physical entities whose + historical unique IDs included mutable device or room names. """ - mapping = build_light_unique_id_migration(data) + mapping = { + **build_physical_entity_unique_id_migration(data), + # Light channels need the more specific per-channel migration when a + # physical device exposes more than one light. + **build_light_unique_id_migration(data), + } if not mapping: return @@ -204,7 +207,7 @@ def _migrate(entry: er.RegistryEntry) -> dict | None: ) return None _LOGGER.info( - "Wiser: migrating light unique_id %s -> %s", + "Wiser: migrating entity unique_id %s -> %s", entry.unique_id, new_unique_id, ) @@ -291,10 +294,11 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): ) ) - # Remap light entity unique_ids from the pre-#683 scheme before the - # platforms create entities, so existing light entities are preserved - # instead of orphaned (see async_migrate_light_unique_ids). - await async_migrate_light_unique_ids(hass, config_entry, coordinator) + # Remap historical name-based entity IDs before platform setup so existing + # entities, history, and dashboard references are retained. + await async_migrate_physical_entity_unique_ids( + hass, config_entry, coordinator + ) # Setup platforms await hass.config_entries.async_forward_entry_setups(config_entry, WISER_PLATFORMS) @@ -477,8 +481,11 @@ def migrate_physical_device_registry( or legacy_identifier in entry.identifiers ] room = data.wiserhub.rooms.get_by_device_id(device.id) + temperature_type = None + old_temperature_names = set() if device.product_type == "iTRV": + temperature_type = "smartvalve_temp" possible_room_names = set() if room is not None: possible_room_names.add(room.name) @@ -493,18 +500,39 @@ def migrate_physical_device_registry( suffix = value[len(itrv_identifier_prefix):] possible_room_names.add(suffix) possible_room_names.add(re.sub(r"-\d+$", "", suffix)) + old_temperature_names.update( + f"LTS Temperature iTRV {room_name}" + for room_name in possible_room_names + ) + elif device.product_type == "SmokeAlarmDevice": + temperature_type = "smokealarm_temp" + if room is not None: + old_temperature_names.add( + f"{room.name} {device.name} Temperature" + ) + else: + old_temperature_names.add( + f"{device.name} {device.id} Temperature" + ) + elif device.product_type == "UnderFloorHeating": + temperature_type = "ufh_measured_temp" + old_temperature_names.add(f"{device.name} Measured Temperature") + elif device.product_type in {"HeatingActuator", "CFMT"} and getattr( + device, "floor_temperature_sensor", None + ): + temperature_type = "floor_current_temp" + old_temperature_names.add( + f"LTS Floor Temperature " + f"{room.name if room is not None else device.name}" + ) + if temperature_type is not None: old_temperature_ids = { - get_unique_id( - data, - "sensor", - f"LTS Temperature iTRV {room_name}", - device.id, - ) - for room_name in possible_room_names + get_unique_id(data, "sensor", name, device.id) + for name in old_temperature_names } - stable_temperature_id = get_itrv_temperature_unique_id( - data, device.id + stable_temperature_id = get_physical_entity_unique_id( + data, "sensor", device.id, temperature_type ) matching_temperature_entries = [ entry @@ -520,18 +548,19 @@ def migrate_physical_device_registry( if entry.device_id is not None } - # Signal and battery IDs have always used the immutable device ID, - # so they locate the record if temperature is disabled or removed. - stable_entity_ids = { - get_unique_id(data, "sensor", device.product_type, device.id), - get_unique_id(data, "sensor", "Battery", device.id), - } - matching_device_ids.update( - entry.device_id - for entry in registry_entities - if entry.unique_id in stable_entity_ids - and entry.device_id is not None - ) + if device.product_type == "iTRV": + # Signal and battery IDs have always used the immutable device + # ID, so they locate an iTRV whose temperature was removed. + stable_entity_ids = { + get_unique_id(data, "sensor", device.product_type, device.id), + get_unique_id(data, "sensor", "Battery", device.id), + } + matching_device_ids.update( + entry.device_id + for entry in registry_entities + if entry.unique_id in stable_entity_ids + and entry.device_id is not None + ) possible_devices.extend( entry for entry in registry_devices diff --git a/custom_components/wiser/binary_sensor.py b/custom_components/wiser/binary_sensor.py index 1bf87af9..2242f4ec 100644 --- a/custom_components/wiser/binary_sensor.py +++ b/custom_components/wiser/binary_sensor.py @@ -22,6 +22,7 @@ get_identifier, get_legacy_unique_id, get_light_binary_sensor_unique_id, + get_physical_entity_unique_id, get_unique_id, get_uuid_unique_id, ) @@ -289,12 +290,9 @@ def is_on(self): @property def unique_id(self): - """Return uniqueid.""" - legacy_name = ( - f"{get_device_name(self._data, self._device_id)} {self._sensor_type}" - ) - return get_unique_id( - self._data, "binary_sensor", self._sensor_type, legacy_name + """Return a name-independent unique ID.""" + return get_physical_entity_unique_id( + self._data, "binary_sensor", self._device_id, self._sensor_type ) @property diff --git a/custom_components/wiser/cover.py b/custom_components/wiser/cover.py index 6727c989..b990fa3b 100644 --- a/custom_components/wiser/cover.py +++ b/custom_components/wiser/cover.py @@ -25,7 +25,7 @@ get_device_name, get_hub_via_device_info, get_identifier, - get_uuid_unique_id, + get_physical_entity_unique_id, hub_error_handler, ) from .schedules import WiserScheduleEntity @@ -147,13 +147,10 @@ def is_closing(self): @property def unique_id(self): - """Return unique Id.""" - legacy_name = f"{get_device_name(self._data, self._device_id)} Control" - legacy_unique_id = ( - f"{self._data.wiserhub.system.name}-Wisershutter-" - f"{self._device_id}-{legacy_name}" + """Return a name-independent unique ID.""" + return get_physical_entity_unique_id( + self._data, "cover", self._device_id, "control" ) - return get_uuid_unique_id(legacy_unique_id) @property def extra_state_attributes(self): diff --git a/custom_components/wiser/helpers.py b/custom_components/wiser/helpers.py index 92d5687d..f198d755 100644 --- a/custom_components/wiser/helpers.py +++ b/custom_components/wiser/helpers.py @@ -275,9 +275,9 @@ def get_unique_id(data, device_type, entity_type, device_id): ) -def get_itrv_temperature_unique_id(data, device_id): - """Return the room-independent unique ID for an iTRV temperature.""" - return get_unique_id(data, "sensor", "smartvalve_temp", device_id) +def get_physical_entity_unique_id(data, domain, device_id, entity_type): + """Return a name-independent unique ID for a physical-device entity.""" + return get_unique_id(data, domain, entity_type, device_id) def get_room_entity_unique_id(data, room_id, entity_type): @@ -286,16 +286,140 @@ def get_room_entity_unique_id(data, room_id, entity_type): def get_light_binary_sensor_unique_id(data, light, sensor_type): - """Return the per-channel unique ID for a light capability sensor.""" - light_name = f"{ENTITY_PREFIX} {light.name}" + """Return the stable per-channel ID for a light capability sensor.""" return get_unique_id( data, "binary_sensor", sensor_type, - f"{light_name} {sensor_type}", + light.light_id, ) +def build_physical_entity_unique_id_migration(data) -> dict: + """Map mutable-name physical entity IDs to immutable device-based IDs.""" + mapping = {} + binary_sensor_types = ( + "Smoke Alarm", + "Heat Alarm", + "Tamper Alarm", + "Fault Warning", + "Remote Alarm", + "Battery Defect", + "Controllable", + "PCM Mode", + "Is Tilt Supported", + "Is Open", + "Is Closed", + "Active", + ) + + for device in data.wiserhub.devices.all: + device_name = get_device_name(data, device.id) + product_type = device.product_type + + # Light capability sensors are keyed by channel ``light_id`` and have + # their own migration below. A multi-gang dimmer shares one physical + # device ID, so treating these as ordinary physical-device sensors + # would merge distinct channels. + if product_type not in {"DimmableLight", "OnOffLight"}: + for sensor_type in binary_sensor_types: + old_name = f"{device_name} {sensor_type}" + mapping[ + get_unique_id(data, "binary_sensor", sensor_type, old_name) + ] = get_physical_entity_unique_id( + data, "binary_sensor", device.id, sensor_type + ) + + if product_type == "Shutter": + old_cover_id = get_uuid_unique_id( + f"{data.wiserhub.system.name}-Wisershutter-" + f"{device.id}-{device_name} Control" + ) + mapping[old_cover_id] = get_physical_entity_unique_id( + data, "cover", device.id, "control" + ) + for label, entity_type in ( + ("Away Mode Closes", "away_mode_closes"), + ("Respect Summer Comfort", "respect_summer_comfort"), + ): + mapping[ + get_unique_id( + data, + product_type, + f"{device_name} {label}", + device.id, + ) + ] = get_physical_entity_unique_id( + data, "switch", device.id, entity_type + ) + + if product_type in {"HeatingActuator", "CFMT"}: + mapping[ + get_unique_id( + data, + "system", + "number", + f"{device_name} Floor Temp Offset", + ) + ] = get_physical_entity_unique_id( + data, "number", device.id, "floor_temperature_offset" + ) + + if product_type in {"SmartPlug", "PowerTagC"}: + mapping[ + get_unique_id( + data, + product_type, + f"{device_name} Switch", + device.id, + ) + ] = get_physical_entity_unique_id( + data, "switch", device.id, "outlet" + ) + mapping[ + get_unique_id( + data, + product_type, + f"{device_name} Away Mode Turns Off", + device.id, + ) + ] = get_physical_entity_unique_id( + data, "switch", device.id, "away_mode_turns_off" + ) + + if hasattr(device, "interacts_with_room_climate"): + suffix = "Interacts With Room Climate" + old_id = get_legacy_unique_id( + data, + product_type, + f"{get_legacy_device_name(data, device.id)} {suffix}", + device.id, + ) + mapping[get_uuid_unique_id(old_id)] = get_physical_entity_unique_id( + data, "switch", device.id, "interacts_with_room_climate" + ) + + for ancillary in getattr(device, "threshold_sensors", ()): + suffix = f"{ancillary.quantity} Interacts With Room Climate" + old_id = get_legacy_unique_id( + data, + product_type, + f"{get_legacy_device_name(data, device.id)} {suffix}", + device.id, + ) + mapping[get_uuid_unique_id(f"{old_id}_{ancillary.id}")] = ( + get_physical_entity_unique_id( + data, + "switch", + device.id, + f"{ancillary.quantity.lower()}_interacts_with_room_climate_" + f"{ancillary.id}", + ) + ) + + return mapping + + def build_light_unique_id_migration(data) -> dict: """Map pre-#683 light unique_ids to the new per-channel light_id scheme. @@ -343,7 +467,14 @@ def build_light_unique_id_migration(data) -> dict: # away-mode switch (both name and id embedded in the unique_id) mapping[ get_unique_id(data, ptype, f"{old_name} Away Mode Turns Off", old_id) - ] = get_unique_id(data, ptype, f"{new_name} Away Mode Turns Off", new_id) + ] = get_physical_entity_unique_id( + data, "switch", new_id, "away_mode_turns_off" + ) + mapping[ + get_unique_id(data, ptype, f"{new_name} Away Mode Turns Off", new_id) + ] = get_physical_entity_unique_id( + data, "switch", new_id, "away_mode_turns_off" + ) # capability binary_sensors (name-based) for stype in LIGHT_BINARY_SENSOR_TYPES: diff --git a/custom_components/wiser/number.py b/custom_components/wiser/number.py index 0aaa8f30..12fda50a 100644 --- a/custom_components/wiser/number.py +++ b/custom_components/wiser/number.py @@ -8,6 +8,7 @@ get_hub_device_info, get_hub_via_device_info, get_identifier, + get_physical_entity_unique_id, get_unique_id, hub_error_handler, ) @@ -213,10 +214,12 @@ def icon(self): @property def unique_id(self): - legacy_name = ( - f"{get_device_name(self._data, self._actuator.id)} Floor Temp Offset" + return get_physical_entity_unique_id( + self._data, + "number", + self._actuator.id, + "floor_temperature_offset", ) - return get_unique_id(self._data, "system", "number", legacy_name) @property def device_info(self): diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index 93b9d6c7..e5600acc 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -58,7 +58,7 @@ get_device_name, get_hub_device_info, get_hub_via_device_info, - get_itrv_temperature_unique_id, + get_physical_entity_unique_id, get_identifier, get_room_entity_unique_id, get_unique_id, @@ -1243,9 +1243,19 @@ def __init__( @property def unique_id(self): - """Return a stable ID when an iTRV is moved or its room is renamed.""" - if self._lts_sensor_type == "smartvalve_temp": - return get_itrv_temperature_unique_id(self._data, self._device_id) + """Return a stable ID when a device or room is renamed.""" + if self._lts_sensor_type in { + "floor_current_temp", + "smokealarm_temp", + "smartvalve_temp", + "ufh_measured_temp", + }: + return get_physical_entity_unique_id( + self._data, + "sensor", + self._device_id, + self._lts_sensor_type, + ) if self._lts_sensor_type in {"current_temp", "current_target_temp"}: return get_room_entity_unique_id( self._data, self._device_id, self._lts_sensor_type diff --git a/custom_components/wiser/switch.py b/custom_components/wiser/switch.py index 84386545..b84958b0 100755 --- a/custom_components/wiser/switch.py +++ b/custom_components/wiser/switch.py @@ -23,11 +23,9 @@ get_hub_device_info, get_hub_via_device_info, get_identifier, - get_legacy_device_name, - get_legacy_unique_id, + get_physical_entity_unique_id, get_room_entity_unique_id, get_unique_id, - get_uuid_unique_id, hub_error_handler, ) from custom_components.wiser.schedules import WiserScheduleEntity @@ -522,10 +520,9 @@ def _handle_coordinator_update(self) -> None: @property def unique_id(self): - """Return unique Id.""" - legacy_name = f"{get_device_name(self._data, self._device_id)} Switch" - return get_unique_id( - self._data, self._device.product_type, legacy_name, self._device_id + """Return a name-independent unique ID.""" + return get_physical_entity_unique_id( + self._data, "switch", self._device_id, "outlet" ) @property @@ -611,15 +608,12 @@ def _handle_coordinator_update(self) -> None: @property def unique_id(self): - """Return unique Id.""" - legacy_name = ( - f"{get_device_name(self._data, self._smart_plug_id)} Away Mode Turns Off" - ) - return get_unique_id( + """Return a name-independent unique ID.""" + return get_physical_entity_unique_id( self._data, - self._smartplug.product_type, - legacy_name, + "switch", self._smart_plug_id, + "away_mode_turns_off", ) @property @@ -683,12 +677,9 @@ def name(self): @property def unique_id(self): - """Return unique Id.""" - legacy_name = ( - f"{get_device_name(self._data, self._light_id)} Away Mode Turns Off" - ) - return get_unique_id( - self._data, self._light.product_type, legacy_name, self._light_id + """Return a name-independent per-channel unique ID.""" + return get_physical_entity_unique_id( + self._data, "switch", self._light_id, "away_mode_turns_off" ) @property @@ -740,12 +731,9 @@ def _handle_coordinator_update(self) -> None: @property def unique_id(self): - """Return unique Id.""" - legacy_name = ( - f"{get_device_name(self._data, self._shutter_id)} Away Mode Closes" - ) - return get_unique_id( - self._data, self._shutter.product_type, legacy_name, self._shutter_id + """Return a name-independent unique ID.""" + return get_physical_entity_unique_id( + self._data, "switch", self._shutter_id, "away_mode_closes" ) @property @@ -866,12 +854,12 @@ def _handle_coordinator_update(self) -> None: @property def unique_id(self): - """Return unique Id.""" - legacy_name = ( - f"{get_device_name(self._data, self._shutter_id)} Respect Summer Comfort" - ) - return get_unique_id( - self._data, self._shutter.product_type, legacy_name, self._shutter_id + """Return a name-independent unique ID.""" + return get_physical_entity_unique_id( + self._data, + "switch", + self._shutter_id, + "respect_summer_comfort", ) @property @@ -952,19 +940,16 @@ def _handle_coordinator_update(self) -> None: @property def unique_id(self): - """Return unique Id.""" - suffix = "Interacts With Room Climate" + """Return a name-independent unique ID.""" + entity_type = "interacts_with_room_climate" if self._ancillary_sensor_type: - suffix = f"{self._ancillary_sensor_type} {suffix}" - legacy_name = ( - f"{get_legacy_device_name(self._data, self._device_id)} {suffix}" - ) - legacy_unique_id = get_legacy_unique_id( - self._data, self._device.product_type, legacy_name, self._device_id + entity_type = ( + f"{self._ancillary_sensor_type.lower()}_" + f"interacts_with_room_climate_{self._ancillary_sensor_id}" + ) + return get_physical_entity_unique_id( + self._data, "switch", self._device_id, entity_type ) - if self._ancillary_sensor_id: - legacy_unique_id = f"{legacy_unique_id}_{self._ancillary_sensor_id}" - return get_uuid_unique_id(legacy_unique_id) @property def is_on(self) -> bool: diff --git a/tests/test_hub_naming.py b/tests/test_hub_naming.py index df58ff30..5e7148cd 100644 --- a/tests/test_hub_naming.py +++ b/tests/test_hub_naming.py @@ -300,14 +300,19 @@ def test_itrv_name_respects_legacy_option_without_changing_identity(self): ) self.assertEqual(self.helpers.get_identifier(self.data, 31), identifier) - def test_itrv_temperature_unique_id_does_not_use_room_name(self): - before = self.helpers.get_itrv_temperature_unique_id(self.data, 31) + def test_physical_entity_unique_id_does_not_use_room_name(self): + before = self.helpers.get_physical_entity_unique_id( + self.data, "sensor", 31, "smartvalve_temp" + ) self.data.wiserhub.rooms.get_by_device_id = lambda _device_id: SimpleNamespace( id=7, name="Renamed Room", ) self.assertEqual( - self.helpers.get_itrv_temperature_unique_id(self.data, 31), before + self.helpers.get_physical_entity_unique_id( + self.data, "sensor", 31, "smartvalve_temp" + ), + before, ) def test_all_physical_device_identifiers_use_immutable_device_id(self): @@ -324,6 +329,31 @@ def test_all_physical_device_identifiers_use_immutable_device_id(self): "WiserHeatNOTUSED device 42", ) + def test_physical_entity_migration_replaces_name_based_ids(self): + device = SimpleNamespace( + id=42, + name="Bedroom Blind", + product_type="Shutter", + ) + self.data.wiserhub.devices = SimpleNamespace( + all=[device], + get_by_id=lambda _device_id: device, + ) + + mapping = self.helpers.build_physical_entity_unique_id_migration( + self.data + ) + old_cover_id = self.helpers.get_uuid_unique_id( + "WiserHeatNOTUSED-Wisershutter-42-" + "Wiser Shutter Andys Bedroom Bedroom Blind Control" + ) + self.assertEqual( + mapping[old_cover_id], + self.helpers.get_physical_entity_unique_id( + self.data, "cover", 42, "control" + ), + ) + def test_room_entity_unique_id_does_not_use_room_name(self): before = self.helpers.get_room_entity_unique_id( self.data, 7, "current_temp" diff --git a/tests/test_light_unique_id_migration.py b/tests/test_light_unique_id_migration.py index 253faed8..d30d35de 100644 --- a/tests/test_light_unique_id_migration.py +++ b/tests/test_light_unique_id_migration.py @@ -136,9 +136,7 @@ def test_away_switch_maps_name_and_id(self) -> None: "Wiser DimmableLight Diele Diele Away Mode Turns Off", 101, ) - new = self._unique_id( - "DimmableLight", "Wiser Diele Away Mode Turns Off", 1 - ) + new = self._unique_id("switch", "away_mode_turns_off", 1) self.assertEqual(mapping[old], new) def test_capability_binary_sensors_map_name(self) -> None: @@ -150,9 +148,7 @@ def test_capability_binary_sensors_map_name(self) -> None: "Is Dimmable", "Wiser DimmableLight Diele Diele Is Dimmable", ) - new = self._unique_id( - "binary_sensor", "Is Dimmable", "Wiser Diele Is Dimmable" - ) + new = self._unique_id("binary_sensor", "Is Dimmable", 1) self.assertEqual(mapping[old], new) self.assertEqual( self.helpers.get_light_binary_sensor_unique_id( @@ -181,8 +177,8 @@ def test_no_noop_entries_and_exact_count(self) -> None: mapping = self._mapping() # Every entry is a real rename. self.assertTrue(all(old != new for old, new in mapping.items())) - # 2 single-gang lights x (1 light + 3 selects + 1 away + 4 binary) = 18. - self.assertEqual(len(mapping), 18) + # 2 lights x (1 light + 3 selects + 2 away aliases + 4 binary) = 20. + self.assertEqual(len(mapping), 20) if __name__ == "__main__": diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 697eab23..6675619b 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -115,6 +115,7 @@ def available(self): get_hub_via_device_info=lambda _data: {}, get_legacy_unique_id=lambda *_args: "legacy-unique-id", get_itrv_temperature_unique_id=lambda *_args: "itrv-temperature-id", + get_physical_entity_unique_id=lambda *_args: "physical-entity-id", get_room_entity_unique_id=lambda *_args: "room-entity-id", get_unique_id=lambda *_args: "unique-id", get_uuid_unique_id=lambda unique_id: f"uuid-{unique_id}", diff --git a/tests/test_switch_hot_water.py b/tests/test_switch_hot_water.py index d072fe07..56ece42d 100644 --- a/tests/test_switch_hot_water.py +++ b/tests/test_switch_hot_water.py @@ -75,6 +75,7 @@ def hub_error_handler(func): get_identifier=lambda *_args: "identifier", get_legacy_device_name=lambda *_args, **_kwargs: "Wiser HeatHub", get_legacy_unique_id=lambda *_args: "legacy-unique-id", + get_physical_entity_unique_id=lambda *_args: "physical-entity-id", get_room_entity_unique_id=lambda *_args: "room-entity-id", get_unique_id=lambda *_args: "unique-id", get_uuid_unique_id=lambda *_args: "uuid-unique-id", From 14dfc851bdc70df42a79b7228eaeba5bc222a6b3 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Wed, 7 Oct 2026 09:57:33 +0100 Subject: [PATCH 093/154] fix: remove deleted Wiser rooms --- custom_components/wiser/__init__.py | 48 ++++++++++++++++++++++++---- custom_components/wiser/device.py | 31 ++++++++++++++++++ tests/test_device.py | 49 +++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+), 6 deletions(-) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index 4555ac6b..c21c3d05 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -51,6 +51,7 @@ move_devices_from_managed_area, register_hub_device, register_room_assigned_device, + remove_room_devices, ) from .entity_migration import migrate_entity_unique_ids from .frontend import JSModuleRegistration @@ -272,6 +273,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): migrate_room_device_registry(hass, config_entry) previous_room_names = config_entry.data.get(CONF_WISER_ROOM_NAMES, {}) + remove_deleted_room_devices(hass, config_entry, previous_room_names) sync_wiser_room_areas(hass, config_entry, previous_room_names) _store_wiser_room_names(hass, config_entry, coordinator) @@ -650,6 +652,36 @@ def _device_by_identifier(device_registry, config_entry_id, identifier): return device_registry.async_get_device(identifiers={identifier}) +def remove_deleted_room_devices(hass, config_entry, previous_room_names) -> int: + """Remove registry records for rooms deleted from the Wiser system.""" + data = hass.data[DOMAIN][config_entry.entry_id][DATA] + current_room_ids = {str(room.id) for room in data.wiserhub.rooms.all} + deleted_room_ids = set(previous_room_names) - current_room_ids + identifiers = [] + + for room_id in deleted_room_ids: + identifiers.extend( + ( + (DOMAIN, get_identifier(data, room_id, "room")), + ( + DOMAIN, + f"{data.wiserhub.system.name} {ENTITY_PREFIX} " + f"{previous_room_names[room_id]}", + ), + ) + ) + + removed = remove_room_devices( + dr.async_get(hass), + er.async_get(hass), + config_entry.entry_id, + identifiers, + ) + if removed: + _LOGGER.info("Removed %s deleted Wiser room device(s)", removed) + return removed + + def sync_wiser_room_areas(hass, config_entry, previous_room_names) -> int: """Move Wiser devices when their integration-managed room is renamed.""" data = hass.data[DOMAIN][config_entry.entry_id][DATA] @@ -699,6 +731,7 @@ def _sync_wiser_room_names(hass, config_entry, coordinator) -> None: current = _current_wiser_room_names(coordinator) if previous == current: return + remove_deleted_room_devices(hass, config_entry, previous) sync_wiser_room_areas(hass, config_entry, previous) hass.config_entries.async_update_entry( config_entry, @@ -732,13 +765,16 @@ async def _async_update_listener(hass: HomeAssistant, config_entry): async def async_remove_config_entry_device( hass: HomeAssistant, config_entry, device_entry ) -> bool: - """Delete device if not entities.""" - if device_entry.model == "Controller" or ( - DOMAIN, - config_entry.data.get(CONF_NAME), - ) in device_entry.identifiers: + """Allow device removal while protecting the physical HeatHub.""" + data = hass.data.get(DOMAIN, {}).get(config_entry.entry_id, {}).get(DATA) + hub_name = ( + data.wiserhub.system.name + if data is not None + else config_entry.data.get(CONF_NAME) + ) + if (DOMAIN, hub_name) in device_entry.identifiers: _LOGGER.error( - "You cannot delete the Wiser HeatHub using device delete. Please remove the integration instead" + "You cannot delete the Wiser HeatHub using device delete. Please remove the integration instead" ) return False return True diff --git a/custom_components/wiser/device.py b/custom_components/wiser/device.py index d25eceda..c18c71ff 100644 --- a/custom_components/wiser/device.py +++ b/custom_components/wiser/device.py @@ -327,3 +327,34 @@ def migrate_room_device( ) return None + + +def remove_room_devices( + device_registry, + entity_registry, + config_entry_id, + identifiers, +): + """Remove deleted logical room devices and their registry entities.""" + get_by_identifier = getattr( + device_registry, "async_get_device_by_identifier", None + ) + removed_device_ids = set() + + for identifier in identifiers: + device = ( + get_by_identifier(identifier, config_entry_id) + if get_by_identifier + else device_registry.async_get_device(identifiers={identifier}) + ) + if device is None or device.id in removed_device_ids: + continue + + for entity in list(entity_registry.entities.values()): + if entity.device_id == device.id: + entity_registry.async_remove(entity.entity_id) + + device_registry.async_remove_device(device.id) + removed_device_ids.add(device.id) + + return len(removed_device_ids) diff --git a/tests/test_device.py b/tests/test_device.py index 0002c753..8ad142f6 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -458,6 +458,55 @@ def test_preserves_legacy_area_when_merging_duplicate_room(self) -> None: self.assertEqual(registry.updated[0][1]["area_id"], "custom_area") +class RemoveRoomDevicesTest(unittest.TestCase): + """Test cleanup of rooms removed from the Wiser system.""" + + config_entry_id = "entry-id" + stable_identifier = ("wiser", "WiserHeat123456 room 7") + legacy_identifier = ("wiser", "WiserHeat123456 Wiser Test") + + def test_removes_room_device_and_its_entities(self) -> None: + room = DeviceEntry("room-device") + registry = DeviceRegistry( + { + (self.stable_identifier, self.config_entry_id): room, + (self.legacy_identifier, self.config_entry_id): room, + } + ) + entities = EntityRegistry( + { + "climate.test": EntityEntry("climate.test", "room-device"), + "sensor.other": EntityEntry("sensor.other", "other-device"), + } + ) + + removed = DEVICE.remove_room_devices( + registry, + entities, + self.config_entry_id, + (self.stable_identifier, self.legacy_identifier), + ) + + self.assertEqual(removed, 1) + self.assertEqual(entities.removed, ["climate.test"]) + self.assertEqual(registry.removed, ["room-device"]) + + def test_ignores_unknown_room_identifiers(self) -> None: + registry = DeviceRegistry() + entities = EntityRegistry() + + removed = DEVICE.remove_room_devices( + registry, + entities, + self.config_entry_id, + (self.stable_identifier,), + ) + + self.assertEqual(removed, 0) + self.assertEqual(entities.removed, []) + self.assertEqual(registry.removed, []) + + class MigratePhysicalDeviceTest(unittest.TestCase): """Test migration of room-derived physical device records.""" From c743a975c8c330a617aac40cb90a7a21256e5eb6 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Sun, 4 Oct 2026 14:27:00 +0100 Subject: [PATCH 094/154] Assign new Wiser rooms to Home Assistant areas --- CHANGELOG.md | 1 + custom_components/wiser/__init__.py | 1 + custom_components/wiser/device.py | 13 +++++++++-- tests/test_device.py | 35 +++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e975af4..26aa5194 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ For releases before v3.3.5, see the [Full Change Log](https://github.com/asantag ### Fixed +- Fixed newly added or previously removed Wiser rooms retaining an orphaned Home Assistant device without an area assignment. - Reintroduced the previous Power and Energy entities, corrected equipment data naming on v2 hubs, and added an active state for the window/door sensor - issue [#677](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/677), PR [#690](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/690). - Fixed multi-gang dimmer lights breaking select, binary_sensor, switch, and sensor entities - issue [#681](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/681), PR [#683](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/683). - Preserved light entities across the multi-gang unique_id migration - issue [#681](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/681), PR [#683](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/683). diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index c21c3d05..cf122287 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -611,6 +611,7 @@ def migrate_room_device_registry(hass: HomeAssistant, config_entry): (DOMAIN, get_identifier(data, room.id, "room")), (DOMAIN, get_legacy_room_identifier(data, room.id)), get_device_name(data, room.id, "room"), + via_device=(DOMAIN, data.wiserhub.system.name), ) assign_device_area_if_unset( device_registry, area_registry, device_entry, room.name diff --git a/custom_components/wiser/device.py b/custom_components/wiser/device.py index c18c71ff..d3b191cc 100644 --- a/custom_components/wiser/device.py +++ b/custom_components/wiser/device.py @@ -287,8 +287,9 @@ def migrate_room_device( identifier, legacy_identifier, name, + via_device=None, ): - """Migrate a name-derived Wiser room device to its stable identifier.""" + """Migrate or create a Wiser room device with its stable identifier.""" get_by_identifier = getattr( device_registry, "async_get_device_by_identifier", None ) @@ -326,7 +327,15 @@ def migrate_room_device( name=name, ) - return None + create_info = {} + if via_device is not None: + create_info["via_device"] = via_device + return device_registry.async_get_or_create( + config_entry_id=config_entry_id, + identifiers={identifier}, + name=name, + **create_info, + ) def remove_room_devices( diff --git a/tests/test_device.py b/tests/test_device.py index 8ad142f6..5e444849 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -375,6 +375,41 @@ class MigrateRoomDeviceTest(unittest.TestCase): legacy_identifier = ("wiser", "WiserHeat123456 Wiser Andys Bedroom") config_entry_id = "entry-id" + def test_creates_missing_room_device_before_entity_setup(self) -> None: + device_registry = DeviceRegistry() + area_registry = AreaRegistry() + + result = DEVICE.migrate_room_device( + device_registry, + EntityRegistry(), + self.config_entry_id, + self.identifier, + self.legacy_identifier, + "Wiser Room", + via_device=("wiser", "WiserHeat123456"), + ) + result = DEVICE.assign_device_area_if_unset( + device_registry, area_registry, result, "Test" + ) + + self.assertEqual(result.id, "new-hub") + self.assertEqual( + device_registry.created, + [ + { + "config_entry_id": self.config_entry_id, + "identifiers": {self.identifier}, + "name": "Wiser Room", + "via_device": ("wiser", "WiserHeat123456"), + } + ], + ) + self.assertEqual(area_registry.requested, ["Test"]) + self.assertEqual( + device_registry.updated, + [("new-hub", {"area_id": "test"})], + ) + def test_migrates_legacy_room_identifier_and_name(self) -> None: registry = DeviceRegistry( { From 3bfc3221eeaab0bd8c77df9891b9f3a63e8326b0 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 12:32:52 +0100 Subject: [PATCH 095/154] fix: use compatible parent identifier during migration --- custom_components/wiser/__init__.py | 1 + custom_components/wiser/device.py | 10 +++++++- tests/test_device.py | 37 +++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index cf122287..8f400774 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -585,6 +585,7 @@ def migrate_physical_device_registry( manufacturer=MANUFACTURER, model=device.product_type, sw_version=device.firmware_version, + via_device=(DOMAIN, data.wiserhub.system.name), via_device_id=hub_device_id, ) if room is not None: diff --git a/custom_components/wiser/device.py b/custom_components/wiser/device.py index d3b191cc..df198887 100644 --- a/custom_components/wiser/device.py +++ b/custom_components/wiser/device.py @@ -62,6 +62,7 @@ def migrate_physical_device( identifier, candidates, name, + via_device=None, **device_info, ): """Give a physical device a stable ID and merge duplicate registry rows.""" @@ -92,11 +93,18 @@ def migrate_physical_device( canonical = None if canonical is None: + create_info = { + key: value + for key, value in device_info.items() + if key != "via_device_id" + } + if via_device is not None: + create_info["via_device"] = via_device return device_registry.async_get_or_create( config_entry_id=config_entry_id, identifiers={identifier}, name=name, - **device_info, + **create_info, ) for duplicate in candidates: diff --git a/tests/test_device.py b/tests/test_device.py index 5e444849..f11d0d76 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -545,6 +545,37 @@ def test_ignores_unknown_room_identifiers(self) -> None: class MigratePhysicalDeviceTest(unittest.TestCase): """Test migration of room-derived physical device records.""" + def test_uses_identifier_parent_only_when_creating_device(self) -> None: + registry = DeviceRegistry() + + result = DEVICE.migrate_physical_device( + registry, + EntityRegistry(), + "entry-id", + ("wiser", "WiserHeat123456 device 31"), + [], + "Wiser iTRV", + via_device=("wiser", "WiserHeat123456"), + via_device_id="physical-hub-id", + model="iTRV", + ) + + self.assertEqual(result.id, "new-hub") + self.assertEqual( + registry.created, + [ + { + "config_entry_id": "entry-id", + "identifiers": { + ("wiser", "WiserHeat123456 device 31") + }, + "name": "Wiser iTRV", + "via_device": ("wiser", "WiserHeat123456"), + "model": "iTRV", + } + ], + ) + def test_keeps_oldest_device_and_merges_renamed_duplicate(self) -> None: old = DeviceEntry( "old-device", @@ -571,6 +602,8 @@ def test_keeps_oldest_device_and_merges_renamed_duplicate(self) -> None: ("wiser", "WiserHeat123456 device 31"), [renamed, old], "Wiser iTRV", + via_device=("wiser", "WiserHeat123456"), + via_device_id="physical-hub-id", model="iTRV", ) @@ -580,6 +613,10 @@ def test_keeps_oldest_device_and_merges_renamed_duplicate(self) -> None: registry.updated[0][1]["new_identifiers"], {("wiser", "WiserHeat123456 device 31")}, ) + self.assertEqual( + registry.updated[0][1]["via_device_id"], "physical-hub-id" + ) + self.assertNotIn("via_device", registry.updated[0][1]) self.assertEqual( entities.updated, [("sensor.signal", {"device_id": "old-device"})], From ed8ef84b8921d9dfbafb1f5b5b9da41a60bf49a3 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 12:50:06 +0100 Subject: [PATCH 096/154] fix: find renamed physical devices by stable entities --- custom_components/wiser/__init__.py | 30 ++++++++-------------- custom_components/wiser/device.py | 22 ++++++++++++++++ tests/test_device.py | 39 +++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 19 deletions(-) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index 8f400774..7b52d441 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -43,6 +43,7 @@ from .coordinator import WiserUpdateCoordinator from .device import ( assign_device_area_if_unset, + find_physical_device_candidates, merge_legacy_hub_device, migrate_entity_unique_id_duplicates, migrate_physical_device, @@ -476,12 +477,16 @@ def migrate_physical_device_registry( DOMAIN, get_legacy_device_identifier(data, device.id), ) - possible_devices = [ - entry - for entry in registry_devices - if stable_identifier in entry.identifiers - or legacy_identifier in entry.identifiers - ] + stable_entity_ids = { + get_unique_id(data, "sensor", device.product_type, device.id), + get_unique_id(data, "sensor", "Battery", device.id), + } + possible_devices = find_physical_device_candidates( + registry_devices, + registry_entities, + {stable_identifier, legacy_identifier}, + stable_entity_ids, + ) room = data.wiserhub.rooms.get_by_device_id(device.id) temperature_type = None old_temperature_names = set() @@ -550,19 +555,6 @@ def migrate_physical_device_registry( if entry.device_id is not None } - if device.product_type == "iTRV": - # Signal and battery IDs have always used the immutable device - # ID, so they locate an iTRV whose temperature was removed. - stable_entity_ids = { - get_unique_id(data, "sensor", device.product_type, device.id), - get_unique_id(data, "sensor", "Battery", device.id), - } - matching_device_ids.update( - entry.device_id - for entry in registry_entities - if entry.unique_id in stable_entity_ids - and entry.device_id is not None - ) possible_devices.extend( entry for entry in registry_devices diff --git a/custom_components/wiser/device.py b/custom_components/wiser/device.py index df198887..25d9e5c3 100644 --- a/custom_components/wiser/device.py +++ b/custom_components/wiser/device.py @@ -55,6 +55,28 @@ def register_room_assigned_device( ) +def find_physical_device_candidates( + registry_devices, + registry_entities, + identifiers, + stable_entity_ids, +): + """Find physical devices by identifier or immutable entity identity.""" + entity_device_ids = { + entry.device_id + for entry in registry_entities + if entry.platform == "wiser" + and entry.unique_id in stable_entity_ids + and entry.device_id is not None + } + return [ + entry + for entry in registry_devices + if identifiers.intersection(entry.identifiers) + or entry.id in entity_device_ids + ] + + def migrate_physical_device( device_registry, entity_registry, diff --git a/tests/test_device.py b/tests/test_device.py index f11d0d76..b49703d3 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -25,6 +25,7 @@ class DeviceEntry: labels: set = field(default_factory=set) name_by_user: str | None = None created_at: datetime | None = None + identifiers: set = field(default_factory=set) @dataclass @@ -545,6 +546,44 @@ def test_ignores_unknown_room_identifiers(self) -> None: class MigratePhysicalDeviceTest(unittest.TestCase): """Test migration of room-derived physical device records.""" + def test_finds_previously_renamed_non_itrv_by_stable_entity(self) -> None: + old_device = DeviceEntry( + "old-roomstat", + identifiers={ + ("wiser", "WiserHeat123456 Wiser RoomStat Old Room") + }, + ) + unrelated_device = DeviceEntry( + "unrelated", + identifiers={ + ("wiser", "WiserHeat123456 Wiser RoomStat Other Room") + }, + ) + entities = [ + EntityEntry( + "sensor.roomstat_signal", + "old-roomstat", + unique_id="stable-signal-id", + ), + EntityEntry( + "sensor.unrelated_signal", + "unrelated", + unique_id="other-signal-id", + ), + ] + + candidates = DEVICE.find_physical_device_candidates( + [old_device, unrelated_device], + entities, + { + ("wiser", "WiserHeat123456 device 21"), + ("wiser", "WiserHeat123456 Wiser RoomStat New Room"), + }, + {"stable-signal-id", "stable-battery-id"}, + ) + + self.assertEqual(candidates, [old_device]) + def test_uses_identifier_parent_only_when_creating_device(self) -> None: registry = DeviceRegistry() From 26db842c99440aef6d2819c6bab21737cf961223 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 12:57:03 +0100 Subject: [PATCH 097/154] fix: separate light away switch identities --- custom_components/wiser/helpers.py | 4 ++-- custom_components/wiser/switch.py | 5 ++++- tests/test_light_unique_id_migration.py | 12 +++++++++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/custom_components/wiser/helpers.py b/custom_components/wiser/helpers.py index f198d755..a1cccac3 100644 --- a/custom_components/wiser/helpers.py +++ b/custom_components/wiser/helpers.py @@ -468,12 +468,12 @@ def build_light_unique_id_migration(data) -> dict: mapping[ get_unique_id(data, ptype, f"{old_name} Away Mode Turns Off", old_id) ] = get_physical_entity_unique_id( - data, "switch", new_id, "away_mode_turns_off" + data, "switch", new_id, "light_away_mode_turns_off" ) mapping[ get_unique_id(data, ptype, f"{new_name} Away Mode Turns Off", new_id) ] = get_physical_entity_unique_id( - data, "switch", new_id, "away_mode_turns_off" + data, "switch", new_id, "light_away_mode_turns_off" ) # capability binary_sensors (name-based) diff --git a/custom_components/wiser/switch.py b/custom_components/wiser/switch.py index b84958b0..ad21b371 100755 --- a/custom_components/wiser/switch.py +++ b/custom_components/wiser/switch.py @@ -679,7 +679,10 @@ def name(self): def unique_id(self): """Return a name-independent per-channel unique ID.""" return get_physical_entity_unique_id( - self._data, "switch", self._light_id, "away_mode_turns_off" + self._data, + "switch", + self._light_id, + "light_away_mode_turns_off", ) @property diff --git a/tests/test_light_unique_id_migration.py b/tests/test_light_unique_id_migration.py index d30d35de..8ebf30d1 100644 --- a/tests/test_light_unique_id_migration.py +++ b/tests/test_light_unique_id_migration.py @@ -136,9 +136,19 @@ def test_away_switch_maps_name_and_id(self) -> None: "Wiser DimmableLight Diele Diele Away Mode Turns Off", 101, ) - new = self._unique_id("switch", "away_mode_turns_off", 1) + new = self._unique_id("switch", "light_away_mode_turns_off", 1) self.assertEqual(mapping[old], new) + def test_light_and_smart_plug_away_switch_ids_cannot_collide(self) -> None: + light_id = self._unique_id( + "switch", "light_away_mode_turns_off", 2 + ) + smart_plug_id = self._unique_id( + "switch", "away_mode_turns_off", 2 + ) + + self.assertNotEqual(light_id, smart_plug_id) + def test_capability_binary_sensors_map_name(self) -> None: mapping = self._mapping() data = _hub_data() From db094e2bed0d6a69159cf3dab6ce98ef41fa930c Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 13:00:51 +0100 Subject: [PATCH 098/154] fix: confirm room deletion before registry cleanup --- custom_components/wiser/__init__.py | 84 +++++++++++++++++++++++++---- custom_components/wiser/device.py | 40 ++++++++++++++ tests/test_device.py | 51 ++++++++++++++++++ 3 files changed, 164 insertions(+), 11 deletions(-) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index 7b52d441..5631b767 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -43,6 +43,7 @@ from .coordinator import WiserUpdateCoordinator from .device import ( assign_device_area_if_unset, + confirmed_deleted_room_ids, find_physical_device_candidates, merge_legacy_hub_device, migrate_entity_unique_id_duplicates, @@ -53,6 +54,7 @@ register_hub_device, register_room_assigned_device, remove_room_devices, + room_names_with_pending_deletions, ) from .entity_migration import migrate_entity_unique_ids from .frontend import JSModuleRegistration @@ -274,9 +276,29 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): migrate_room_device_registry(hass, config_entry) previous_room_names = config_entry.data.get(CONF_WISER_ROOM_NAMES, {}) - remove_deleted_room_devices(hass, config_entry, previous_room_names) + current_room_names = _current_wiser_room_names(coordinator) + confirmed_deleted_ids = _confirmed_deleted_room_ids( + hass, + config_entry, + previous_room_names, + current_room_names, + ) + remove_deleted_room_devices( + hass, + config_entry, + previous_room_names, + confirmed_deleted_ids, + ) sync_wiser_room_areas(hass, config_entry, previous_room_names) - _store_wiser_room_names(hass, config_entry, coordinator) + _store_wiser_room_names( + hass, + config_entry, + room_names_with_pending_deletions( + previous_room_names, + current_room_names, + confirmed_deleted_ids, + ), + ) # Register listeners only after setup-time registry and config migrations. update_listener = config_entry.add_update_listener(_async_update_listener) @@ -625,14 +647,30 @@ def _current_wiser_room_names(coordinator): } -def _store_wiser_room_names(hass, config_entry, coordinator) -> None: +def _store_wiser_room_names(hass, config_entry, room_names) -> None: """Persist room names before the config-entry update listener is registered.""" - current = _current_wiser_room_names(coordinator) - if config_entry.data.get(CONF_WISER_ROOM_NAMES, {}) == current: + if config_entry.data.get(CONF_WISER_ROOM_NAMES, {}) == room_names: return hass.config_entries.async_update_entry( config_entry, - data={**config_entry.data, CONF_WISER_ROOM_NAMES: current}, + data={**config_entry.data, CONF_WISER_ROOM_NAMES: room_names}, + ) + + +def _confirmed_deleted_room_ids( + hass, + config_entry, + previous_room_names, + current_room_names, +): + """Track missing rooms across successful coordinator refreshes.""" + missing_counts = hass.data[DOMAIN][config_entry.entry_id].setdefault( + "missing_room_counts", {} + ) + return confirmed_deleted_room_ids( + previous_room_names, + current_room_names, + missing_counts, ) @@ -646,11 +684,14 @@ def _device_by_identifier(device_registry, config_entry_id, identifier): return device_registry.async_get_device(identifiers={identifier}) -def remove_deleted_room_devices(hass, config_entry, previous_room_names) -> int: +def remove_deleted_room_devices( + hass, + config_entry, + previous_room_names, + deleted_room_ids, +) -> int: """Remove registry records for rooms deleted from the Wiser system.""" data = hass.data[DOMAIN][config_entry.entry_id][DATA] - current_room_ids = {str(room.id) for room in data.wiserhub.rooms.all} - deleted_room_ids = set(previous_room_names) - current_room_ids identifiers = [] for room_id in deleted_room_ids: @@ -724,12 +765,33 @@ def _sync_wiser_room_names(hass, config_entry, coordinator) -> None: previous = config_entry.data.get(CONF_WISER_ROOM_NAMES, {}) current = _current_wiser_room_names(coordinator) if previous == current: + hass.data[DOMAIN][config_entry.entry_id].setdefault( + "missing_room_counts", {} + ).clear() return - remove_deleted_room_devices(hass, config_entry, previous) + confirmed_deleted_ids = _confirmed_deleted_room_ids( + hass, + config_entry, + previous, + current, + ) + remove_deleted_room_devices( + hass, + config_entry, + previous, + confirmed_deleted_ids, + ) sync_wiser_room_areas(hass, config_entry, previous) + stored_room_names = room_names_with_pending_deletions( + previous, + current, + confirmed_deleted_ids, + ) + if stored_room_names == previous: + return hass.config_entries.async_update_entry( config_entry, - data={**config_entry.data, CONF_WISER_ROOM_NAMES: current}, + data={**config_entry.data, CONF_WISER_ROOM_NAMES: stored_room_names}, ) diff --git a/custom_components/wiser/device.py b/custom_components/wiser/device.py index 25d9e5c3..5d6b3993 100644 --- a/custom_components/wiser/device.py +++ b/custom_components/wiser/device.py @@ -37,6 +37,46 @@ def move_devices_from_managed_area( return moved +def confirmed_deleted_room_ids( + previous_room_ids, + current_room_ids, + missing_counts, + required_observations=2, +): + """Return rooms absent from consecutive non-empty hub responses.""" + if not current_room_ids: + missing_counts.clear() + return set() + + missing_room_ids = set(previous_room_ids) - set(current_room_ids) + for room_id in list(missing_counts): + if room_id not in missing_room_ids: + missing_counts.pop(room_id) + for room_id in missing_room_ids: + missing_counts[room_id] = missing_counts.get(room_id, 0) + 1 + + return { + room_id + for room_id in missing_room_ids + if missing_counts[room_id] >= required_observations + } + + +def room_names_with_pending_deletions( + previous_room_names, + current_room_names, + confirmed_deleted_ids, +): + """Retain missing room names until their deletion is confirmed.""" + retained = { + room_id: name + for room_id, name in previous_room_names.items() + if room_id not in confirmed_deleted_ids + } + retained.update(current_room_names) + return retained + + def register_room_assigned_device( device_registry, config_entry_id, diff --git a/tests/test_device.py b/tests/test_device.py index b49703d3..91ad5673 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -307,6 +307,57 @@ def test_registers_device_with_area_and_physical_hub_parent(self) -> None: ) +class ConfirmedDeletedRoomIdsTest(unittest.TestCase): + """Test protection against transient room-list data gaps.""" + + def test_requires_two_consecutive_missing_observations(self) -> None: + missing_counts = {} + + first = DEVICE.confirmed_deleted_room_ids( + {"7", "8"}, {"8"}, missing_counts + ) + second = DEVICE.confirmed_deleted_room_ids( + {"7", "8"}, {"8"}, missing_counts + ) + + self.assertEqual(first, set()) + self.assertEqual(second, {"7"}) + + def test_empty_room_response_never_confirms_deletion(self) -> None: + missing_counts = {"7": 1} + + confirmed = DEVICE.confirmed_deleted_room_ids( + {"7"}, set(), missing_counts + ) + + self.assertEqual(confirmed, set()) + self.assertEqual(missing_counts, {}) + + def test_room_reappearing_clears_its_missing_count(self) -> None: + missing_counts = {"7": 1} + + confirmed = DEVICE.confirmed_deleted_room_ids( + {"7"}, {"7"}, missing_counts + ) + + self.assertEqual(confirmed, set()) + self.assertEqual(missing_counts, {}) + + def test_pending_room_name_is_retained_until_confirmed(self) -> None: + previous = {"7": "Test", "8": "Kitchen"} + current = {"8": "Kitchen"} + + pending = DEVICE.room_names_with_pending_deletions( + previous, current, set() + ) + confirmed = DEVICE.room_names_with_pending_deletions( + previous, current, {"7"} + ) + + self.assertEqual(pending, previous) + self.assertEqual(confirmed, current) + + class AssignDeviceAreaIfUnsetTest(unittest.TestCase): """Test conservative assignment of Wiser devices to areas.""" From d77dd9c25811461cc70d7a5f6d8809bcaf673e09 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 13:02:04 +0100 Subject: [PATCH 099/154] fix: preserve user-selected areas during migration --- custom_components/wiser/__init__.py | 12 +++++++++--- custom_components/wiser/device.py | 11 +++++++++++ tests/test_device.py | 26 ++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index 5631b767..84e0042d 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -45,6 +45,7 @@ assign_device_area_if_unset, confirmed_deleted_room_ids, find_physical_device_candidates, + known_wiser_room_area_name, merge_legacy_hub_device, migrate_entity_unique_id_duplicates, migrate_physical_device, @@ -722,6 +723,9 @@ def sync_wiser_room_areas(hass, config_entry, previous_room_names) -> int: data = hass.data[DOMAIN][config_entry.entry_id][DATA] device_registry = dr.async_get(hass) area_registry = ar.async_get(hass) + current_room_names = { + room.name for room in data.wiserhub.rooms.all + } moved = 0 for room in data.wiserhub.rooms.all: @@ -732,9 +736,11 @@ def sync_wiser_room_areas(hass, config_entry, previous_room_names) -> int: ) previous_name = previous_room_names.get(str(room.id)) if previous_name is None and room_device and room_device.area_id: - previous_area = area_registry.async_get_area(room_device.area_id) - if previous_area is not None: - previous_name = previous_area.name + previous_name = known_wiser_room_area_name( + area_registry, + room_device.area_id, + current_room_names, + ) room_devices = [room_device] for device in data.wiserhub.devices.all: diff --git a/custom_components/wiser/device.py b/custom_components/wiser/device.py index 5d6b3993..b0dc7db0 100644 --- a/custom_components/wiser/device.py +++ b/custom_components/wiser/device.py @@ -37,6 +37,17 @@ def move_devices_from_managed_area( return moved +def known_wiser_room_area_name(area_registry, area_id, room_names): + """Return an area's name only when it matches a current Wiser room.""" + if not area_id: + return None + + area = area_registry.async_get_area(area_id) + if area is None or area.name not in set(room_names): + return None + return area.name + + def confirmed_deleted_room_ids( previous_room_ids, current_room_ids, diff --git a/tests/test_device.py b/tests/test_device.py index 91ad5673..b037b24c 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -419,6 +419,32 @@ def test_moves_only_devices_still_in_previous_managed_area(self) -> None: ], ) + def test_recognises_area_matching_a_current_wiser_room(self) -> None: + area_registry = AreaRegistry() + area_registry.areas["test"] = AreaEntry("test", "Test") + + result = DEVICE.known_wiser_room_area_name( + area_registry, + "test", + {"Kitchen", "Test"}, + ) + + self.assertEqual(result, "Test") + + def test_rejects_user_selected_area_on_first_upgrade(self) -> None: + area_registry = AreaRegistry() + area_registry.areas["living_room"] = AreaEntry( + "living_room", "Living Room" + ) + + result = DEVICE.known_wiser_room_area_name( + area_registry, + "living_room", + {"Kitchen", "Lounge"}, + ) + + self.assertIsNone(result) + class MigrateRoomDeviceTest(unittest.TestCase): """Test migration of logical Wiser room devices.""" From 09c110c9885d7961432ad1535437fb17cb900cc0 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 13:03:38 +0100 Subject: [PATCH 100/154] fix: persist room names without reloading --- custom_components/wiser/__init__.py | 47 +++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index 84e0042d..dc08f4f5 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -19,6 +19,7 @@ entity_registry as er, ) from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC +from homeassistant.helpers.storage import Store from .const import ( CONF_AUTOMATIONS_HW_AUTO_MODE, @@ -79,8 +80,12 @@ opentherm_is_detected, ) from .services import async_setup_services -from .websockets import async_register_websockets from .update import async_unload_card_updates +from .websockets import async_register_websockets + +ROOM_NAMES_STORAGE_VERSION = 1 +ROOM_NAMES_STORAGE_KEY = f"{DOMAIN}.{{}}.room_names" +ROOM_NAMES_STORE = "room_names_store" _LOGGER = logging.getLogger(__name__) @@ -232,14 +237,31 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): if not coordinator.last_update_status == "Success": raise ConfigEntryNotReady + room_names_store = Store( + hass, + ROOM_NAMES_STORAGE_VERSION, + ROOM_NAMES_STORAGE_KEY.format(config_entry.entry_id), + ) + stored_room_names = await room_names_store.async_load() + previous_room_names = ( + stored_room_names + if isinstance(stored_room_names, dict) + else config_entry.data.get(CONF_WISER_ROOM_NAMES, {}) + ) + # This must run before both the update listener and reload-settings snapshot. # A setup-time flag change is then included in the initial snapshot without # scheduling a reload; a later change is observed and reloads exactly once. # This prevents a standard boiler's dormant OpenTherm endpoint from creating # entities while allowing a real installation to survive temporary outages. _remember_opentherm_connection(hass, config_entry, coordinator) + hass.data[DOMAIN][config_entry.entry_id] = { DATA: coordinator, + CONF_WISER_ROOM_NAMES: ( + previous_room_names if stored_room_names is not None else None + ), + ROOM_NAMES_STORE: room_names_store, } # If OpenTherm connects for the first time after startup, saving the flag @@ -276,7 +298,6 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): # Give logical room devices stable IDs and concise device names. migrate_room_device_registry(hass, config_entry) - previous_room_names = config_entry.data.get(CONF_WISER_ROOM_NAMES, {}) current_room_names = _current_wiser_room_names(coordinator) confirmed_deleted_ids = _confirmed_deleted_room_ids( hass, @@ -649,12 +670,15 @@ def _current_wiser_room_names(coordinator): def _store_wiser_room_names(hass, config_entry, room_names) -> None: - """Persist room names before the config-entry update listener is registered.""" - if config_entry.data.get(CONF_WISER_ROOM_NAMES, {}) == room_names: + """Persist room names without triggering a config-entry reload.""" + entry_data = hass.data[DOMAIN][config_entry.entry_id] + if entry_data.get(CONF_WISER_ROOM_NAMES) == room_names: return - hass.config_entries.async_update_entry( - config_entry, - data={**config_entry.data, CONF_WISER_ROOM_NAMES: room_names}, + room_names = dict(room_names) + entry_data[CONF_WISER_ROOM_NAMES] = room_names + entry_data[ROOM_NAMES_STORE].async_delay_save( + lambda: room_names, + 1, ) @@ -768,7 +792,9 @@ def sync_wiser_room_areas(hass, config_entry, previous_room_names) -> int: def _sync_wiser_room_names(hass, config_entry, coordinator) -> None: """Apply Wiser room renames after a coordinator refresh.""" - previous = config_entry.data.get(CONF_WISER_ROOM_NAMES, {}) + previous = hass.data[DOMAIN][config_entry.entry_id].get( + CONF_WISER_ROOM_NAMES, {} + ) current = _current_wiser_room_names(coordinator) if previous == current: hass.data[DOMAIN][config_entry.entry_id].setdefault( @@ -795,10 +821,7 @@ def _sync_wiser_room_names(hass, config_entry, coordinator) -> None: ) if stored_room_names == previous: return - hass.config_entries.async_update_entry( - config_entry, - data={**config_entry.data, CONF_WISER_ROOM_NAMES: stored_room_names}, - ) + _store_wiser_room_names(hass, config_entry, stored_room_names) def update_hub_device_names(hass: HomeAssistant): From 4693a440299b53aa3e8a2419f1befdcfcdbefd10 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 13:11:45 +0100 Subject: [PATCH 101/154] fix: stabilize humidity and power sensor identities --- custom_components/wiser/__init__.py | 107 ++++++++++++++++++++++------ custom_components/wiser/helpers.py | 50 ++++++++++++- custom_components/wiser/sensor.py | 27 +++++++ tests/test_hub_naming.py | 77 ++++++++++++++++++++ tests/test_sensor.py | 54 +++++++++++++- 5 files changed, 292 insertions(+), 23 deletions(-) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index dc08f4f5..7fd8d5be 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -167,7 +167,10 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> async def async_migrate_physical_entity_unique_ids( - hass: HomeAssistant, config_entry, data + hass: HomeAssistant, + config_entry, + data, + previous_room_names=None, ) -> None: """Preserve physical entities while adopting stable unique IDs. @@ -175,7 +178,9 @@ async def async_migrate_physical_entity_unique_ids( historical unique IDs included mutable device or room names. """ mapping = { - **build_physical_entity_unique_id_migration(data), + **build_physical_entity_unique_id_migration( + data, previous_room_names + ), # Light channels need the more specific per-channel migration when a # physical device exposes more than one light. **build_light_unique_id_migration(data), @@ -286,7 +291,12 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): # Physical device identifiers used to contain mutable room or device names. # Migrate them before platform setup so renames cannot duplicate devices. - migrate_physical_device_registry(hass, config_entry, hub_device.id) + migrate_physical_device_registry( + hass, + config_entry, + hub_device.id, + previous_room_names, + ) # Create physical devices in their Wiser room's Home Assistant area. Later # room renames move devices only while they remain in that managed area. @@ -344,7 +354,10 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): # Remap historical name-based entity IDs before platform setup so existing # entities, history, and dashboard references are retained. await async_migrate_physical_entity_unique_ids( - hass, config_entry, coordinator + hass, + config_entry, + coordinator, + previous_room_names, ) # Setup platforms @@ -496,7 +509,10 @@ def register_room_assigned_devices( def migrate_physical_device_registry( - hass: HomeAssistant, config_entry, hub_device_id: str + hass: HomeAssistant, + config_entry, + hub_device_id: str, + previous_room_names=None, ): """Migrate physical devices from name-derived to stable identifiers.""" data = hass.data[DOMAIN][config_entry.entry_id][DATA] @@ -515,6 +531,15 @@ def migrate_physical_device_registry( itrv_identifier_prefix = ( f"{data.wiserhub.system.name} {ENTITY_PREFIX} iTRV " ) + previous_room_names = previous_room_names or {} + physical_entity_migration = build_physical_entity_unique_id_migration( + data, previous_room_names + ) + physical_entity_ids_by_target = {} + for old_unique_id, new_unique_id in physical_entity_migration.items(): + physical_entity_ids_by_target.setdefault(new_unique_id, set()).add( + old_unique_id + ) for device in data.wiserhub.devices.all: stable_identifier = (DOMAIN, get_identifier(data, device.id)) legacy_identifier = ( @@ -525,6 +550,18 @@ def migrate_physical_device_registry( get_unique_id(data, "sensor", device.product_type, device.id), get_unique_id(data, "sensor", "Battery", device.id), } + stable_entity_ids.update( + { + get_physical_entity_unique_id( + data, "sensor", device.id, entity_type + ) + for entity_type in ( + "power", + "energy", + "energy_received", + ) + } + ) possible_devices = find_physical_device_candidates( registry_devices, registry_entities, @@ -534,12 +571,14 @@ def migrate_physical_device_registry( room = data.wiserhub.rooms.get_by_device_id(device.id) temperature_type = None old_temperature_names = set() + possible_room_names = set() + if room is not None: + possible_room_names.add(room.name) + if previous_name := previous_room_names.get(str(room.id)): + possible_room_names.add(previous_name) if device.product_type == "iTRV": temperature_type = "smartvalve_temp" - possible_room_names = set() - if room is not None: - possible_room_names.add(room.name) for entry in registry_devices: if entry.model != "iTRV": continue @@ -577,38 +616,64 @@ def migrate_physical_device_registry( f"{room.name if room is not None else device.name}" ) + sensor_id_migrations = {} if temperature_type is not None: - old_temperature_ids = { + sensor_id_migrations[ + get_physical_entity_unique_id( + data, "sensor", device.id, temperature_type + ) + ] = { get_unique_id(data, "sensor", name, device.id) for name in old_temperature_names } - stable_temperature_id = get_physical_entity_unique_id( - data, "sensor", device.id, temperature_type + + room_attached_sensor_ids = set() + for entity_type in ( + "humidity", + "power", + "energy", + "energy_received", + ): + stable_sensor_id = get_physical_entity_unique_id( + data, "sensor", device.id, entity_type + ) + old_sensor_ids = physical_entity_ids_by_target.get( + stable_sensor_id, set() ) - matching_temperature_entries = [ + if old_sensor_ids: + sensor_id_migrations[stable_sensor_id] = old_sensor_ids + if entity_type == "humidity": + # Room-stat humidity is displayed on the logical room device. + # Its entity must not make that room device a physical-device + # migration candidate. + room_attached_sensor_ids.add(stable_sensor_id) + + for stable_sensor_id, old_sensor_ids in sensor_id_migrations.items(): + matching_sensor_entries = [ entry for entry in registry_entities if entry.domain == "sensor" and entry.platform == DOMAIN and entry.unique_id - in old_temperature_ids | {stable_temperature_id} + in old_sensor_ids | {stable_sensor_id} ] matching_device_ids = { entry.device_id - for entry in matching_temperature_entries + for entry in matching_sensor_entries if entry.device_id is not None } - possible_devices.extend( - entry - for entry in registry_devices - if entry.id in matching_device_ids - ) + if stable_sensor_id not in room_attached_sensor_ids: + possible_devices.extend( + entry + for entry in registry_devices + if entry.id in matching_device_ids + ) migrate_entity_unique_id_duplicates( entity_registry, - matching_temperature_entries, - stable_temperature_id, + matching_sensor_entries, + stable_sensor_id, ) device_entry = migrate_physical_device( diff --git a/custom_components/wiser/helpers.py b/custom_components/wiser/helpers.py index a1cccac3..28cf4067 100644 --- a/custom_components/wiser/helpers.py +++ b/custom_components/wiser/helpers.py @@ -295,9 +295,12 @@ def get_light_binary_sensor_unique_id(data, light, sensor_type): ) -def build_physical_entity_unique_id_migration(data) -> dict: +def build_physical_entity_unique_id_migration( + data, previous_room_names=None +) -> dict: """Map mutable-name physical entity IDs to immutable device-based IDs.""" mapping = {} + previous_room_names = previous_room_names or {} binary_sensor_types = ( "Smoke Alarm", "Heat Alarm", @@ -316,6 +319,51 @@ def build_physical_entity_unique_id_migration(data) -> dict: for device in data.wiserhub.devices.all: device_name = get_device_name(data, device.id) product_type = device.product_type + room = data.wiserhub.rooms.get_by_device_id(device.id) + possible_room_names = {room.name} if room is not None else set() + if room is not None and ( + previous_name := previous_room_names.get(str(room.id)) + ): + possible_room_names.add(previous_name) + + if product_type == "RoomStat": + for room_name in possible_room_names: + mapping[ + get_unique_id( + data, + "sensor", + f"LTS Humidity {room_name}", + device.id, + ) + ] = get_physical_entity_unique_id( + data, "sensor", device.id, "humidity" + ) + + power_device_names = possible_room_names or { + f"{product_type} {device.id}" + } + historical_power_types = { + "Power": "power", + "Total Power": "energy", + "Equipment Power ": "power", + "Equipment Total Energy ": "energy", + "Power ": "power", + "Energy Delivered ": "energy", + "Energy Received ": "energy_received", + } + for power_device_name in power_device_names: + historical_power_types.update( + { + f"LTS Power {power_device_name}": "power", + f"LTS Energy {power_device_name}": "energy", + } + ) + for old_entity_type, new_entity_type in historical_power_types.items(): + mapping[ + get_unique_id(data, "sensor", old_entity_type, device.id) + ] = get_physical_entity_unique_id( + data, "sensor", device.id, new_entity_type + ) # Light capability sensors are keyed by channel ``light_id`` and have # their own migration below. A multi-gang dimmer shares one physical diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index e5600acc..34687611 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -1097,6 +1097,14 @@ def __init__(self, data, device_id, sensor_type="") -> None: self._device = data.wiserhub.devices.smartplugs.get_by_id(device_id) self._last_delivered_power = 0 + @property + def unique_id(self): + """Return a stable ID across device and room renames.""" + entity_type = "power" if self._sensor_type == "Power" else "energy" + return get_physical_entity_unique_id( + self._data, "sensor", self._device_id, entity_type + ) + @callback def _handle_coordinator_update(self) -> None: """Fetch new state data for the sensor.""" @@ -1682,6 +1690,13 @@ def __init__( use_device_class_name=True, ) + @property + def unique_id(self): + """Return a room-name-independent humidity sensor ID.""" + return get_physical_entity_unique_id( + self._data, "sensor", self._device_id, "humidity" + ) + @callback def _handle_coordinator_update(self) -> None: """Fetch new state data for the sensor.""" @@ -1918,6 +1933,18 @@ def __init__( ), ) + @property + def unique_id(self): + """Return a room-name-independent power or energy sensor ID.""" + entity_type = { + "Power": "power", + "Energy": "energy", + "EnergyReceived": "energy_received", + }[self._lts_sensor_type] + return get_physical_entity_unique_id( + self._data, "sensor", self._device_id, entity_type + ) + @callback def _handle_coordinator_update(self) -> None: """Fetch new state data for the sensor.""" diff --git a/tests/test_hub_naming.py b/tests/test_hub_naming.py index 5e7148cd..ef118c35 100644 --- a/tests/test_hub_naming.py +++ b/tests/test_hub_naming.py @@ -354,6 +354,83 @@ def test_physical_entity_migration_replaces_name_based_ids(self): ), ) + def test_physical_sensor_migration_covers_humidity_power_and_energy(self): + room = SimpleNamespace( + id=7, + name="Andys Bedroom", + number_of_heating_actuators=1, + heating_actuator_ids=[42], + ) + devices = [ + SimpleNamespace( + id=41, + name="Roomstat", + product_type="RoomStat", + ), + SimpleNamespace( + id=42, + name="Actuator", + product_type="HeatingActuator", + ), + ] + self.data.wiserhub.devices = SimpleNamespace( + all=devices, + get_by_id=lambda device_id: next( + device for device in devices if device.id == device_id + ), + ) + self.data.wiserhub.rooms.get_by_device_id = lambda _device_id: room + + mapping = self.helpers.build_physical_entity_unique_id_migration( + self.data, + {"7": "Previous Bedroom"}, + ) + + expected = { + self.helpers.get_unique_id( + self.data, + "sensor", + "LTS Humidity Andys Bedroom", + 41, + ): self.helpers.get_physical_entity_unique_id( + self.data, "sensor", 41, "humidity" + ), + self.helpers.get_unique_id( + self.data, + "sensor", + "LTS Power Andys Bedroom", + 42, + ): self.helpers.get_physical_entity_unique_id( + self.data, "sensor", 42, "power" + ), + self.helpers.get_unique_id( + self.data, + "sensor", + "LTS Energy Andys Bedroom", + 42, + ): self.helpers.get_physical_entity_unique_id( + self.data, "sensor", 42, "energy" + ), + self.helpers.get_unique_id( + self.data, + "sensor", + "LTS Humidity Previous Bedroom", + 41, + ): self.helpers.get_physical_entity_unique_id( + self.data, "sensor", 41, "humidity" + ), + self.helpers.get_unique_id( + self.data, + "sensor", + "LTS Power Previous Bedroom", + 42, + ): self.helpers.get_physical_entity_unique_id( + self.data, "sensor", 42, "power" + ), + } + for old_unique_id, new_unique_id in expected.items(): + self.assertEqual(mapping[old_unique_id], new_unique_id) + def test_room_entity_unique_id_does_not_use_room_name(self): before = self.helpers.get_room_entity_unique_id( self.data, 7, "current_temp" diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 6675619b..d8599c39 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -115,7 +115,9 @@ def available(self): get_hub_via_device_info=lambda _data: {}, get_legacy_unique_id=lambda *_args: "legacy-unique-id", get_itrv_temperature_unique_id=lambda *_args: "itrv-temperature-id", - get_physical_entity_unique_id=lambda *_args: "physical-entity-id", + get_physical_entity_unique_id=lambda _data, domain, device_id, entity_type: ( + f"physical-{domain}-{device_id}-{entity_type}" + ), get_room_entity_unique_id=lambda *_args: "room-entity-id", get_unique_id=lambda *_args: "unique-id", get_uuid_unique_id=lambda unique_id: f"uuid-{unique_id}", @@ -602,6 +604,56 @@ def test_room_measurements_do_not_expose_lts_implementation_detail(self) -> None self.assertIsNone(getattr(humidity, "_attr_translation_key", None)) self.assertEqual(demand._attr_translation_key, "heating_demand") + def test_humidity_uses_physical_device_unique_id(self) -> None: + room = SimpleNamespace(id=1, name="Kitchen") + roomstat = SimpleNamespace(id=2, room_id=1) + data = SimpleNamespace( + wiserhub=SimpleNamespace( + devices=SimpleNamespace(get_by_id=lambda _device_id: roomstat), + rooms=SimpleNamespace( + get_by_id=lambda _room_id: room, + get_by_device_id=lambda _device_id: room, + ), + system=SimpleNamespace(name="WiserHeat123456"), + ) + ) + + sensor = self.sensor_module.WiserLTSHumiditySensor(data, 2) + + self.assertEqual(sensor.unique_id, "physical-sensor-2-humidity") + + def test_power_sensors_use_physical_device_unique_ids(self) -> None: + room = SimpleNamespace(id=1, name="Kitchen") + device = SimpleNamespace( + id=9, + room_id=1, + product_type="HeatingActuator", + ) + devices = SimpleNamespace( + get_by_id=lambda _device_id: device, + smartplugs=SimpleNamespace(get_by_id=lambda _device_id: device), + ) + data = SimpleNamespace( + wiserhub=SimpleNamespace( + devices=devices, + rooms=SimpleNamespace( + get_by_id=lambda _room_id: room, + get_by_device_id=lambda _device_id: room, + ), + system=SimpleNamespace(name="WiserHeat123456"), + ) + ) + + smartplug = self.sensor_module.WiserSmartplugPower( + data, 9, sensor_type="Total Power" + ) + actuator = self.sensor_module.WiserLTSPowerSensor( + data, 9, sensor_type="Power" + ) + + self.assertEqual(smartplug.unique_id, "physical-sensor-9-energy") + self.assertEqual(actuator.unique_id, "physical-sensor-9-power") + def test_heating_demand_is_not_classified_as_power_factor(self) -> None: """A percentage heating demand is not an electrical power factor.""" demand_class = next( From 87f5529b3bba2ecd7c43e20fc32a07a7343f530a Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 13:13:00 +0100 Subject: [PATCH 102/154] test: recognise stable unique ID helpers --- tests/test_entity_naming.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/test_entity_naming.py b/tests/test_entity_naming.py index 4d27a533..12a8c935 100644 --- a/tests/test_entity_naming.py +++ b/tests/test_entity_naming.py @@ -181,7 +181,12 @@ def test_unique_ids_do_not_depend_on_new_entity_names(self) -> None: ) def test_all_entity_unique_ids_are_uuid_backed(self) -> None: - uuid_helpers = {"get_unique_id", "get_uuid_unique_id"} + uuid_helpers = { + "get_physical_entity_unique_id", + "get_room_entity_unique_id", + "get_unique_id", + "get_uuid_unique_id", + } for filename in ENTITY_BASE_CLASSES: tree = ast.parse((COMPONENT_PATH / filename).read_text()) for node in ast.walk(tree): From 982518aaa9beedd8a2bcbd18d4bc3eb7e992cf32 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 13:14:44 +0100 Subject: [PATCH 103/154] fix: retain duplicate migration records --- custom_components/wiser/__init__.py | 9 ++++---- custom_components/wiser/device.py | 7 ++---- tests/test_device.py | 33 ++++++++++++++++++++++++++--- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index 7fd8d5be..c7666c70 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -197,8 +197,8 @@ def _migrate(entry: er.RegistryEntry) -> dict | None: return None # The original migration could create the target entry while the # capability binary sensors continued to register with their old - # unique_id. Keep the canonical target (which retains the original - # entity_id and history) and remove the later legacy-ID duplicate. + # unique_id. Keep both registry records so history is recoverable; + # the legacy-ID entry becomes unavailable after platform setup. target_entity_id = ent_reg.async_get_entity_id( entry.domain, entry.platform, new_unique_id ) @@ -208,12 +208,11 @@ def _migrate(entry: er.RegistryEntry) -> dict | None: target_entry and target_entry.config_entry_id == config_entry.entry_id ): - _LOGGER.info( - "Wiser: removing duplicate legacy entity %s; target is %s", + _LOGGER.warning( + "Wiser: retaining duplicate legacy entity %s; target is %s", entry.entity_id, target_entity_id, ) - ent_reg.async_remove(entry.entity_id) return None _LOGGER.warning( "Wiser: not migrating unique_id %s -> %s, target already exists", diff --git a/custom_components/wiser/device.py b/custom_components/wiser/device.py index b0dc7db0..c9060945 100644 --- a/custom_components/wiser/device.py +++ b/custom_components/wiser/device.py @@ -202,7 +202,7 @@ def migrate_entity_unique_id_duplicates( entries, new_unique_id, ): - """Keep the oldest entity while replacing duplicate historical IDs.""" + """Migrate one entity while retaining historical duplicates.""" entries = list({entry.entity_id: entry for entry in entries}.values()) if not entries: return None @@ -219,7 +219,7 @@ def migrate_entity_unique_id_duplicates( entry.entity_id != existing.entity_id for entry in entries ): entries.append(existing) - canonical = min( + canonical = existing or min( entries, key=lambda entry: ( getattr(entry, "created_at", None) is None, @@ -227,9 +227,6 @@ def migrate_entity_unique_id_duplicates( entry.entity_id, ), ) - for duplicate in entries: - if duplicate.entity_id != canonical.entity_id: - entity_registry.async_remove(duplicate.entity_id) if canonical.unique_id != new_unique_id: entity_registry.async_update_entity( canonical.entity_id, new_unique_id=new_unique_id diff --git a/tests/test_device.py b/tests/test_device.py index b037b24c..5b3a3e53 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -739,7 +739,7 @@ def test_keeps_oldest_device_and_merges_renamed_duplicate(self) -> None: ) self.assertEqual(registry.removed, ["renamed-device"]) - def test_keeps_oldest_temperature_entity_and_removes_duplicate(self) -> None: + def test_keeps_oldest_temperature_entity_and_retains_duplicate(self) -> None: old = EntityEntry( "sensor.room_temperature", "old-device", @@ -767,7 +767,34 @@ def test_keeps_oldest_temperature_entity_and_removes_duplicate(self) -> None: entities.updated, [("sensor.room_temperature", {"new_unique_id": "stable-id"})], ) - self.assertEqual(entities.removed, ["sensor.test_temperature"]) + self.assertEqual(entities.removed, []) + + def test_keeps_existing_stable_target_and_retains_older_duplicate(self) -> None: + old = EntityEntry( + "sensor.room_temperature", + "old-device", + unique_id="old-room-id", + created_at=datetime(2026, 1, 1, tzinfo=timezone.utc), + ) + target = EntityEntry( + "sensor.test_temperature", + "renamed-device", + unique_id="stable-id", + created_at=datetime(2026, 10, 1, tzinfo=timezone.utc), + ) + entities = EntityRegistry( + {old.entity_id: old, target.entity_id: target} + ) + + result = DEVICE.migrate_entity_unique_id_duplicates( + entities, + [old], + "stable-id", + ) + + self.assertIs(result, target) + self.assertEqual(entities.updated, []) + self.assertEqual(entities.removed, []) def test_migrates_all_room_name_derived_entity_types(self) -> None: entities = {} @@ -802,7 +829,7 @@ def test_migrates_all_room_name_derived_entity_types(self) -> None: ) self.assertEqual(len(registry.updated), len(definitions)) - self.assertEqual(len(registry.removed), len(definitions)) + self.assertEqual(registry.removed, []) self.assertEqual( {update[1]["new_unique_id"] for update in registry.updated}, {f"stable-{definition[3]}" for definition in definitions}, From 8a92f61c1b12bd89c3340029e2a69f3b97aee199 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 13:16:19 +0100 Subject: [PATCH 104/154] fix: preserve additional device identifiers --- custom_components/wiser/device.py | 8 +++++++- tests/test_device.py | 14 +++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/custom_components/wiser/device.py b/custom_components/wiser/device.py index c9060945..d500aee8 100644 --- a/custom_components/wiser/device.py +++ b/custom_components/wiser/device.py @@ -189,9 +189,15 @@ def migrate_physical_device( entity.entity_id, device_id=canonical.id ) device_registry.async_remove_device(duplicate.id) + preserved_identifiers = { + candidate_identifier + for candidate in candidates + for candidate_identifier in candidate.identifiers + if candidate_identifier[0] != identifier[0] + } return device_registry.async_update_device( canonical.id, - new_identifiers={identifier}, + new_identifiers=preserved_identifiers | {identifier}, name=name, **device_info, ) diff --git a/tests/test_device.py b/tests/test_device.py index 5b3a3e53..7f6cc26b 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -696,10 +696,18 @@ def test_keeps_oldest_device_and_merges_renamed_duplicate(self) -> None: old = DeviceEntry( "old-device", created_at=datetime(2026, 1, 1, tzinfo=timezone.utc), + identifiers={ + ("wiser", "WiserHeat123456 Wiser iTRV Bedroom"), + ("matter", "matter-device-31"), + }, ) renamed = DeviceEntry( "renamed-device", created_at=datetime(2026, 10, 1, tzinfo=timezone.utc), + identifiers={ + ("wiser", "WiserHeat123456 Wiser iTRV Lounge"), + ("zigbee", "zigbee-device-31"), + }, ) registry = DeviceRegistry() entities = EntityRegistry( @@ -727,7 +735,11 @@ def test_keeps_oldest_device_and_merges_renamed_duplicate(self) -> None: self.assertEqual(registry.updated[0][0], "old-device") self.assertEqual( registry.updated[0][1]["new_identifiers"], - {("wiser", "WiserHeat123456 device 31")}, + { + ("wiser", "WiserHeat123456 device 31"), + ("matter", "matter-device-31"), + ("zigbee", "zigbee-device-31"), + }, ) self.assertEqual( registry.updated[0][1]["via_device_id"], "physical-hub-id" From 3eaed59167f44056d1680805bd6be5ee1ff571a9 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 13:17:03 +0100 Subject: [PATCH 105/154] fix: avoid empty areas during room migration --- custom_components/wiser/device.py | 16 ++++++++++------ tests/test_device.py | 17 +++++++++++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/custom_components/wiser/device.py b/custom_components/wiser/device.py index d500aee8..733aef41 100644 --- a/custom_components/wiser/device.py +++ b/custom_components/wiser/device.py @@ -27,14 +27,18 @@ def move_devices_from_managed_area( if previous_area is None: return 0 + devices_to_move = [ + device + for device in {device.id: device for device in devices if device}.values() + if device.area_id == previous_area.id + ] + if not devices_to_move: + return 0 + new_area = area_registry.async_get_or_create(new_area_name) - moved = 0 - for device in {device.id: device for device in devices if device}.values(): - if device.area_id != previous_area.id: - continue + for device in devices_to_move: device_registry.async_update_device(device.id, area_id=new_area.id) - moved += 1 - return moved + return len(devices_to_move) def known_wiser_room_area_name(area_registry, area_id, room_names): diff --git a/tests/test_device.py b/tests/test_device.py index 7f6cc26b..dfce6427 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -419,6 +419,23 @@ def test_moves_only_devices_still_in_previous_managed_area(self) -> None: ], ) + def test_does_not_create_area_when_no_device_qualifies(self) -> None: + device_registry = DeviceRegistry() + area_registry = AreaRegistry() + area_registry.areas["test"] = AreaEntry("test", "Test") + + moved = DEVICE.move_devices_from_managed_area( + device_registry, + area_registry, + [DeviceEntry("manually-moved", area_id="upstairs")], + "Test", + "Test2", + ) + + self.assertEqual(moved, 0) + self.assertEqual(area_registry.requested, []) + self.assertEqual(device_registry.updated, []) + def test_recognises_area_matching_a_current_wiser_room(self) -> None: area_registry = AreaRegistry() area_registry.areas["test"] = AreaEntry("test", "Test") From c0090f58dd8f57e838f59c648892d0255c04caf5 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 13:17:47 +0100 Subject: [PATCH 106/154] refactor: remove unused room name helper --- custom_components/wiser/helpers.py | 4 ---- tests/test_switch_hot_water.py | 1 - 2 files changed, 5 deletions(-) diff --git a/custom_components/wiser/helpers.py b/custom_components/wiser/helpers.py index 28cf4067..13adb10b 100644 --- a/custom_components/wiser/helpers.py +++ b/custom_components/wiser/helpers.py @@ -534,10 +534,6 @@ def build_light_unique_id_migration(data) -> dict: return {old: new for old, new in mapping.items() if old != new} -def get_room_name(data, room_id): - return f"{ENTITY_PREFIX} {data.wiserhub.rooms.get_by_id(room_id).name}" - - def get_instance_count(hass: HomeAssistant) -> int: entries = [ entry diff --git a/tests/test_switch_hot_water.py b/tests/test_switch_hot_water.py index 56ece42d..e4f58185 100644 --- a/tests/test_switch_hot_water.py +++ b/tests/test_switch_hot_water.py @@ -71,7 +71,6 @@ def hub_error_handler(func): ), get_hub_device_info=lambda _data: {"identifiers": {("wiser", "hub")}}, get_hub_via_device_info=lambda _data: {}, - get_room_name=lambda *_args: "Room", get_identifier=lambda *_args: "identifier", get_legacy_device_name=lambda *_args, **_kwargs: "Wiser HeatHub", get_legacy_unique_id=lambda *_args: "legacy-unique-id", From c0252f6a9dbbeef51810cb4e8aaf0295f3164ef6 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 13:20:36 +0100 Subject: [PATCH 107/154] fix: reconstruct historical device names --- custom_components/wiser/helpers.py | 21 +++++++++++++++-- tests/test_hub_naming.py | 36 ++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/custom_components/wiser/helpers.py b/custom_components/wiser/helpers.py index 13adb10b..b0ad522c 100644 --- a/custom_components/wiser/helpers.py +++ b/custom_components/wiser/helpers.py @@ -167,10 +167,27 @@ def get_device_name(data, device_id, device_type="device"): def get_legacy_device_name(data, device_id): """Return a physical device name used by historical entity unique IDs.""" device = data.wiserhub.devices.get_by_id(device_id) + device_room = data.wiserhub.rooms.get_by_device_id(device_id) + + if device.product_type == "iTRV": + if device_room: + if device_room.number_of_smartvalves > 1: + index = device_room.smartvalve_ids.index(device.id) + 1 + return ( + f"{ENTITY_PREFIX} {device.product_type} " + f"{device_room.name}-{index}" + ) + return f"{ENTITY_PREFIX} {device.product_type} {device_room.name}" + return f"{ENTITY_PREFIX} {device.product_type} {device.id}" + + if device.product_type == "RoomStat": + if device_room: + return f"{ENTITY_PREFIX} Thermostat {device_room.name}" + return f"{ENTITY_PREFIX} Thermostat {device.id}" + if device.product_type != "TemperatureHumiditySensor": return get_device_name(data, device_id) - device_room = data.wiserhub.rooms.get_by_device_id(device_id) if device_room: return ( f"{ENTITY_PREFIX} {device.product_type} " @@ -317,7 +334,7 @@ def build_physical_entity_unique_id_migration( ) for device in data.wiserhub.devices.all: - device_name = get_device_name(data, device.id) + device_name = get_legacy_device_name(data, device.id) product_type = device.product_type room = data.wiserhub.rooms.get_by_device_id(device.id) possible_room_names = {room.name} if room is not None else set() diff --git a/tests/test_hub_naming.py b/tests/test_hub_naming.py index ef118c35..d7645f88 100644 --- a/tests/test_hub_naming.py +++ b/tests/test_hub_naming.py @@ -290,6 +290,10 @@ def test_itrv_name_respects_legacy_option_without_changing_identity(self): self.data.legacy_naming = False self.assertEqual(self.helpers.get_device_name(self.data, 31), "Wiser iTRV") + self.assertEqual( + self.helpers.get_legacy_device_name(self.data, 31), + "Wiser iTRV Andys Bedroom", + ) identifier = self.helpers.get_identifier(self.data, 31) self.assertEqual(identifier, "WiserHeatNOTUSED device 31") @@ -300,6 +304,38 @@ def test_itrv_name_respects_legacy_option_without_changing_identity(self): ) self.assertEqual(self.helpers.get_identifier(self.data, 31), identifier) + def test_physical_entity_migration_uses_historical_itrv_name(self): + device = SimpleNamespace(id=31, product_type="iTRV") + room = SimpleNamespace( + id=7, + name="Andys Bedroom", + number_of_smartvalves=1, + smartvalve_ids=[31], + ) + self.data.legacy_naming = False + self.data.wiserhub.devices = SimpleNamespace( + all=[device], + get_by_id=lambda _device_id: device, + ) + self.data.wiserhub.rooms.get_by_device_id = lambda _device_id: room + + mapping = self.helpers.build_physical_entity_unique_id_migration( + self.data + ) + old_unique_id = self.helpers.get_unique_id( + self.data, + "binary_sensor", + "Controllable", + "Wiser iTRV Andys Bedroom Controllable", + ) + + self.assertEqual( + mapping[old_unique_id], + self.helpers.get_physical_entity_unique_id( + self.data, "binary_sensor", 31, "Controllable" + ), + ) + def test_physical_entity_unique_id_does_not_use_room_name(self): before = self.helpers.get_physical_entity_unique_id( self.data, "sensor", 31, "smartvalve_temp" From 1a1fad6abeb090165b6b1dbbc012e0530707b302 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 13:22:12 +0100 Subject: [PATCH 108/154] test: cover room migration orchestration --- tests/test_room_migration_orchestration.py | 373 +++++++++++++++++++++ 1 file changed, 373 insertions(+) create mode 100644 tests/test_room_migration_orchestration.py diff --git a/tests/test_room_migration_orchestration.py b/tests/test_room_migration_orchestration.py new file mode 100644 index 00000000..3ec21fd0 --- /dev/null +++ b/tests/test_room_migration_orchestration.py @@ -0,0 +1,373 @@ +"""Tests for Wiser room-migration orchestration.""" + +from __future__ import annotations + +import importlib.util +from pathlib import Path +import sys +from types import ModuleType, SimpleNamespace +import unittest +from unittest.mock import Mock + + +COMPONENT_PATH = Path(__file__).parents[1] / "custom_components/wiser" + + +def _module(name: str, **attributes: object) -> ModuleType: + module = ModuleType(name) + module.__dict__.update(attributes) + sys.modules[name] = module + return module + + +def _load_wiser_init() -> ModuleType: + """Load the integration module with lightweight dependency stubs.""" + _module("homeassistant") + _module("homeassistant.config_entries", ConfigEntry=object) + _module("homeassistant.const", CONF_NAME="name") + _module( + "homeassistant.core", + HomeAssistant=object, + callback=lambda function: function, + ) + _module("homeassistant.exceptions", ConfigEntryNotReady=RuntimeError) + + area_registry = _module("homeassistant.helpers.area_registry") + device_registry = _module( + "homeassistant.helpers.device_registry", + CONNECTION_NETWORK_MAC="mac", + ) + entity_registry = _module("homeassistant.helpers.entity_registry") + _module( + "homeassistant.helpers", + area_registry=area_registry, + device_registry=device_registry, + entity_registry=entity_registry, + ) + _module("homeassistant.helpers.storage", Store=object) + + package = _module("wiser_init_test") + package.__path__ = [] + constants = { + name: name.lower() + for name in ( + "CONF_AUTOMATIONS_HW_AUTO_MODE", + "CONF_AUTOMATIONS_HW_CLIMATE", + "CONF_AUTOMATIONS_HW_HEAT_MODE", + "CONF_AUTOMATIONS_HW_SENSOR_ENTITY_ID", + "CONF_AUTOMATIONS_PASSIVE", + "CONF_AUTOMATIONS_PASSIVE_TEMP_INCREMENT", + "CONF_DEPRECATED_HW_TARGET_TEMP", + "CONF_LEGACY_NAMING", + "CONF_WISER_ROOM_NAMES", + "DATA", + "UPDATE_LISTENER", + ) + } + constants.update( + DOMAIN="wiser", + ENTITY_PREFIX="Wiser", + MANUFACTURER="Drayton Wiser", + WISER_PLATFORMS=[], + WISER_SERVICES={}, + HWCycleModes=SimpleNamespace(CONTINUOUS="continuous", ONCE="once"), + ) + _module("wiser_init_test.const", **constants) + _module("wiser_init_test.coordinator", WiserUpdateCoordinator=object) + + device_helpers = { + name: Mock(name=name) + for name in ( + "assign_device_area_if_unset", + "confirmed_deleted_room_ids", + "find_physical_device_candidates", + "known_wiser_room_area_name", + "merge_legacy_hub_device", + "migrate_entity_unique_id_duplicates", + "migrate_physical_device", + "migrate_room_entities", + "migrate_room_device", + "move_devices_from_managed_area", + "register_hub_device", + "register_room_assigned_device", + "remove_room_devices", + "room_names_with_pending_deletions", + ) + } + _module("wiser_init_test.device", **device_helpers) + _module( + "wiser_init_test.entity_migration", + migrate_entity_unique_ids=Mock(), + ) + _module("wiser_init_test.frontend", JSModuleRegistration=object) + _module( + "wiser_init_test.frontend.entry_updates", + async_handle_entry_update=Mock(), + integration_reload_settings=Mock(return_value={}), + ) + _module( + "wiser_init_test.frontend.wiser_sidebar", + async_update_wiser_panel=Mock(), + ) + helper_names = ( + "build_light_unique_id_migration", + "build_physical_entity_unique_id_migration", + "get_device_name", + "get_hub_device_name", + "get_identifier", + "get_instance_count", + "get_legacy_device_identifier", + "get_legacy_room_identifier", + "get_physical_entity_unique_id", + "get_room_entity_unique_id", + "get_unique_id", + ) + _module( + "wiser_init_test.helpers", + **{name: Mock(name=name) for name in helper_names}, + ) + _module("wiser_init_test.services", async_setup_services=Mock()) + _module("wiser_init_test.update", async_unload_card_updates=Mock()) + _module("wiser_init_test.websockets", async_register_websockets=Mock()) + + spec = importlib.util.spec_from_file_location( + "wiser_init_test.__init__", COMPONENT_PATH / "__init__.py" + ) + assert spec and spec.loader + module = importlib.util.module_from_spec(spec) + sys.modules[spec.name] = module + spec.loader.exec_module(module) + return module + + +class FakeStore: + """Record delayed Home Assistant storage writes.""" + + def __init__(self) -> None: + self.saved = [] + + def async_delay_save(self, data, delay) -> None: + self.saved.append((data(), delay)) + + +class RoomMigrationOrchestrationTest(unittest.TestCase): + """Test composition of the room-migration helpers.""" + + @classmethod + def setUpClass(cls) -> None: + cls.wiser = _load_wiser_init() + + def setUp(self) -> None: + self.entry = SimpleNamespace(entry_id="entry-id") + self.room = SimpleNamespace(id=7, name="Lounge") + self.coordinator = SimpleNamespace( + wiserhub=SimpleNamespace( + system=SimpleNamespace(name="WiserHeat123456"), + rooms=SimpleNamespace(all=[self.room]), + devices=SimpleNamespace(all=[]), + ) + ) + self.store = FakeStore() + self.hass = SimpleNamespace( + data={ + "wiser": { + "entry-id": { + "data": self.coordinator, + "conf_wiser_room_names": {"7": "Living Room"}, + "room_names_store": self.store, + "missing_room_counts": {}, + } + } + }, + config_entries=SimpleNamespace( + async_update_entry=Mock( + side_effect=AssertionError("must not update config entry") + ) + ), + ) + + def test_refresh_moves_areas_and_saves_names_without_config_reload(self) -> None: + self.wiser._confirmed_deleted_room_ids = Mock(return_value=set()) + self.wiser.remove_deleted_room_devices = Mock() + self.wiser.sync_wiser_room_areas = Mock() + self.wiser.room_names_with_pending_deletions = Mock( + return_value={"7": "Lounge"} + ) + + self.wiser._sync_wiser_room_names( + self.hass, self.entry, self.coordinator + ) + + self.wiser.remove_deleted_room_devices.assert_called_once_with( + self.hass, + self.entry, + {"7": "Living Room"}, + set(), + ) + self.wiser.sync_wiser_room_areas.assert_called_once_with( + self.hass, + self.entry, + {"7": "Living Room"}, + ) + self.assertEqual(self.store.saved, [({"7": "Lounge"}, 1)]) + self.assertEqual( + self.hass.data["wiser"]["entry-id"]["conf_wiser_room_names"], + {"7": "Lounge"}, + ) + + def test_confirmed_room_removal_passes_only_deleted_room_identifiers(self) -> None: + self.wiser.get_identifier = Mock( + return_value="WiserHeat123456 room 7" + ) + self.wiser.remove_room_devices = Mock(return_value=1) + self.wiser.dr.async_get = Mock(return_value="device-registry") + self.wiser.er.async_get = Mock(return_value="entity-registry") + + removed = self.wiser.remove_deleted_room_devices( + self.hass, + self.entry, + {"7": "Living Room", "8": "Kitchen"}, + {"7"}, + ) + + self.assertEqual(removed, 1) + self.wiser.remove_room_devices.assert_called_once_with( + "device-registry", + "entity-registry", + "entry-id", + [ + ("wiser", "WiserHeat123456 room 7"), + ("wiser", "WiserHeat123456 Wiser Living Room"), + ], + ) + + def test_physical_migration_composes_power_and_energy_migrations(self) -> None: + device = SimpleNamespace( + id=42, + product_type="HeatingActuator", + firmware_version="1.0", + floor_temperature_sensor=None, + ) + physical_device = SimpleNamespace( + id="physical-device", + identifiers={("wiser", "legacy-device")}, + ) + power = SimpleNamespace( + entity_id="sensor.power", + unique_id="old-power", + device_id="physical-device", + domain="sensor", + platform="wiser", + ) + energy = SimpleNamespace( + entity_id="sensor.energy", + unique_id="old-energy", + device_id="physical-device", + domain="sensor", + platform="wiser", + ) + device_registry = SimpleNamespace() + entity_registry = SimpleNamespace(entities={}) + self.coordinator.wiserhub.devices.all = [device] + self.coordinator.wiserhub.rooms.get_by_device_id = Mock( + return_value=self.room + ) + self.wiser.dr.async_get = Mock(return_value=device_registry) + self.wiser.dr.async_entries_for_config_entry = Mock( + return_value=[physical_device] + ) + self.wiser.er.async_get = Mock(return_value=entity_registry) + self.wiser.er.async_entries_for_config_entry = Mock( + return_value=[power, energy] + ) + self.wiser.ar.async_get = Mock(return_value="area-registry") + self.wiser.get_identifier = Mock(return_value="stable-device") + self.wiser.get_legacy_device_identifier = Mock( + return_value="legacy-device" + ) + self.wiser.get_unique_id = Mock( + side_effect=lambda _data, _domain, entity_type, _device_id: ( + f"base-{entity_type}" + ) + ) + self.wiser.get_physical_entity_unique_id = Mock( + side_effect=lambda _data, _domain, device_id, entity_type: ( + f"stable-{entity_type}-{device_id}" + ) + ) + self.wiser.build_physical_entity_unique_id_migration = Mock( + return_value={ + "old-power": "stable-power-42", + "old-energy": "stable-energy-42", + } + ) + self.wiser.find_physical_device_candidates = Mock( + return_value=[physical_device] + ) + self.wiser.migrate_entity_unique_id_duplicates = Mock() + self.wiser.migrate_physical_device = Mock( + return_value=physical_device + ) + self.wiser.get_device_name = Mock(return_value="Wiser HeatingActuator") + self.wiser.assign_device_area_if_unset = Mock() + + self.wiser.migrate_physical_device_registry( + self.hass, + self.entry, + "hub-device", + {"7": "Living Room"}, + ) + + migrations = { + call.args[2]: {entry.entity_id for entry in call.args[1]} + for call in self.wiser.migrate_entity_unique_id_duplicates.call_args_list + } + self.assertEqual( + migrations, + { + "stable-power-42": {"sensor.power"}, + "stable-energy-42": {"sensor.energy"}, + }, + ) + self.wiser.migrate_physical_device.assert_called_once() + + def test_area_sync_composes_room_and_physical_devices(self) -> None: + room_device = SimpleNamespace(id="room-device", area_id="old-area") + physical_device = SimpleNamespace(id="physical-device", area_id="old-area") + physical = SimpleNamespace(id=31) + self.coordinator.wiserhub.devices.all = [physical] + self.coordinator.wiserhub.rooms.get_by_device_id = Mock( + return_value=self.room + ) + self.wiser.dr.async_get = Mock(return_value="device-registry") + self.wiser.ar.async_get = Mock(return_value="area-registry") + self.wiser.get_identifier = Mock( + side_effect=lambda _data, item_id, device_type="device": ( + f"room-{item_id}" + if device_type == "room" + else f"device-{item_id}" + ) + ) + self.wiser._device_by_identifier = Mock( + side_effect=[room_device, physical_device] + ) + self.wiser.move_devices_from_managed_area = Mock(return_value=2) + + moved = self.wiser.sync_wiser_room_areas( + self.hass, + self.entry, + {"7": "Living Room"}, + ) + + self.assertEqual(moved, 2) + self.wiser.move_devices_from_managed_area.assert_called_once_with( + "device-registry", + "area-registry", + [room_device, physical_device], + "Living Room", + "Lounge", + ) + + +if __name__ == "__main__": + unittest.main() From b5bcf86b0a25cd6e7568c93ce855ad3ef3d77088 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 14:05:52 +0100 Subject: [PATCH 109/154] fix: recover entities from historical device names --- custom_components/wiser/__init__.py | 27 ++++ custom_components/wiser/helpers.py | 162 ++++++++++++--------- tests/test_hub_naming.py | 42 ++++++ tests/test_room_migration_orchestration.py | 20 ++- 4 files changed, 179 insertions(+), 72 deletions(-) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index c7666c70..c3b6e694 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -567,6 +567,33 @@ def migrate_physical_device_registry( {stable_identifier, legacy_identifier}, stable_entity_ids, ) + identifier_prefix = f"{data.wiserhub.system.name} " + historical_device_names = { + value[len(identifier_prefix):] + for candidate in possible_devices + for domain, value in candidate.identifiers + if domain == DOMAIN and value.startswith(identifier_prefix) + } + historical_entity_migration = ( + build_physical_entity_unique_id_migration( + data, + previous_room_names, + {device.id: historical_device_names}, + {device.id}, + ) + ) + for old_unique_id, new_unique_id in historical_entity_migration.items(): + matching_entries = [ + entry + for entry in registry_entities + if entry.platform == DOMAIN + and entry.unique_id in {old_unique_id, new_unique_id} + ] + migrate_entity_unique_id_duplicates( + entity_registry, + matching_entries, + new_unique_id, + ) room = data.wiserhub.rooms.get_by_device_id(device.id) temperature_type = None old_temperature_names = set() diff --git a/custom_components/wiser/helpers.py b/custom_components/wiser/helpers.py index b0ad522c..a15f776f 100644 --- a/custom_components/wiser/helpers.py +++ b/custom_components/wiser/helpers.py @@ -313,11 +313,15 @@ def get_light_binary_sensor_unique_id(data, light, sensor_type): def build_physical_entity_unique_id_migration( - data, previous_room_names=None + data, + previous_room_names=None, + legacy_device_names_by_id=None, + device_ids=None, ) -> dict: """Map mutable-name physical entity IDs to immutable device-based IDs.""" mapping = {} previous_room_names = previous_room_names or {} + legacy_device_names_by_id = legacy_device_names_by_id or {} binary_sensor_types = ( "Smoke Alarm", "Heat Alarm", @@ -334,7 +338,10 @@ def build_physical_entity_unique_id_migration( ) for device in data.wiserhub.devices.all: - device_name = get_legacy_device_name(data, device.id) + if device_ids is not None and device.id not in device_ids: + continue + device_names = set(legacy_device_names_by_id.get(device.id, ())) + device_names.add(get_legacy_device_name(data, device.id)) product_type = device.product_type room = data.wiserhub.rooms.get_by_device_id(device.id) possible_room_names = {room.name} if room is not None else set() @@ -387,100 +394,113 @@ def build_physical_entity_unique_id_migration( # device ID, so treating these as ordinary physical-device sensors # would merge distinct channels. if product_type not in {"DimmableLight", "OnOffLight"}: - for sensor_type in binary_sensor_types: - old_name = f"{device_name} {sensor_type}" + for device_name in device_names: + for sensor_type in binary_sensor_types: + old_name = f"{device_name} {sensor_type}" + mapping[ + get_unique_id( + data, "binary_sensor", sensor_type, old_name + ) + ] = get_physical_entity_unique_id( + data, "binary_sensor", device.id, sensor_type + ) + + if product_type == "Shutter": + for device_name in device_names: + old_cover_id = get_uuid_unique_id( + f"{data.wiserhub.system.name}-Wisershutter-" + f"{device.id}-{device_name} Control" + ) + mapping[old_cover_id] = get_physical_entity_unique_id( + data, "cover", device.id, "control" + ) + for label, entity_type in ( + ("Away Mode Closes", "away_mode_closes"), + ("Respect Summer Comfort", "respect_summer_comfort"), + ): + mapping[ + get_unique_id( + data, + product_type, + f"{device_name} {label}", + device.id, + ) + ] = get_physical_entity_unique_id( + data, "switch", device.id, entity_type + ) + + if product_type in {"HeatingActuator", "CFMT"}: + for device_name in device_names: mapping[ - get_unique_id(data, "binary_sensor", sensor_type, old_name) + get_unique_id( + data, + "system", + "number", + f"{device_name} Floor Temp Offset", + ) ] = get_physical_entity_unique_id( - data, "binary_sensor", device.id, sensor_type + data, "number", device.id, "floor_temperature_offset" ) - if product_type == "Shutter": - old_cover_id = get_uuid_unique_id( - f"{data.wiserhub.system.name}-Wisershutter-" - f"{device.id}-{device_name} Control" - ) - mapping[old_cover_id] = get_physical_entity_unique_id( - data, "cover", device.id, "control" - ) - for label, entity_type in ( - ("Away Mode Closes", "away_mode_closes"), - ("Respect Summer Comfort", "respect_summer_comfort"), - ): + if product_type in {"SmartPlug", "PowerTagC"}: + for device_name in device_names: mapping[ get_unique_id( data, product_type, - f"{device_name} {label}", + f"{device_name} Switch", device.id, ) ] = get_physical_entity_unique_id( - data, "switch", device.id, entity_type + data, "switch", device.id, "outlet" ) - - if product_type in {"HeatingActuator", "CFMT"}: - mapping[ - get_unique_id( - data, - "system", - "number", - f"{device_name} Floor Temp Offset", + mapping[ + get_unique_id( + data, + product_type, + f"{device_name} Away Mode Turns Off", + device.id, + ) + ] = get_physical_entity_unique_id( + data, "switch", device.id, "away_mode_turns_off" ) - ] = get_physical_entity_unique_id( - data, "number", device.id, "floor_temperature_offset" - ) - if product_type in {"SmartPlug", "PowerTagC"}: - mapping[ - get_unique_id( + if hasattr(device, "interacts_with_room_climate"): + suffix = "Interacts With Room Climate" + for device_name in device_names: + old_id = get_legacy_unique_id( data, product_type, - f"{device_name} Switch", + f"{device_name} {suffix}", device.id, ) - ] = get_physical_entity_unique_id( - data, "switch", device.id, "outlet" - ) - mapping[ - get_unique_id( - data, - product_type, - f"{device_name} Away Mode Turns Off", - device.id, + mapping[get_uuid_unique_id(old_id)] = ( + get_physical_entity_unique_id( + data, + "switch", + device.id, + "interacts_with_room_climate", + ) ) - ] = get_physical_entity_unique_id( - data, "switch", device.id, "away_mode_turns_off" - ) - - if hasattr(device, "interacts_with_room_climate"): - suffix = "Interacts With Room Climate" - old_id = get_legacy_unique_id( - data, - product_type, - f"{get_legacy_device_name(data, device.id)} {suffix}", - device.id, - ) - mapping[get_uuid_unique_id(old_id)] = get_physical_entity_unique_id( - data, "switch", device.id, "interacts_with_room_climate" - ) for ancillary in getattr(device, "threshold_sensors", ()): suffix = f"{ancillary.quantity} Interacts With Room Climate" - old_id = get_legacy_unique_id( - data, - product_type, - f"{get_legacy_device_name(data, device.id)} {suffix}", - device.id, - ) - mapping[get_uuid_unique_id(f"{old_id}_{ancillary.id}")] = ( - get_physical_entity_unique_id( + for device_name in device_names: + old_id = get_legacy_unique_id( data, - "switch", + product_type, + f"{device_name} {suffix}", device.id, - f"{ancillary.quantity.lower()}_interacts_with_room_climate_" - f"{ancillary.id}", ) - ) + mapping[get_uuid_unique_id(f"{old_id}_{ancillary.id}")] = ( + get_physical_entity_unique_id( + data, + "switch", + device.id, + f"{ancillary.quantity.lower()}_" + f"interacts_with_room_climate_{ancillary.id}", + ) + ) return mapping diff --git a/tests/test_hub_naming.py b/tests/test_hub_naming.py index d7645f88..9899b6f8 100644 --- a/tests/test_hub_naming.py +++ b/tests/test_hub_naming.py @@ -390,6 +390,48 @@ def test_physical_entity_migration_replaces_name_based_ids(self): ), ) + def test_physical_entity_migration_uses_registry_device_names(self): + device = SimpleNamespace( + id=42, + name="Bedroom Blind", + product_type="Shutter", + ) + self.data.wiserhub.devices = SimpleNamespace( + all=[device], + get_by_id=lambda _device_id: device, + ) + + mapping = self.helpers.build_physical_entity_unique_id_migration( + self.data, + legacy_device_names_by_id={ + 42: {"Wiser Shutter Previous Bedroom Bedroom Blind"} + }, + device_ids={42}, + ) + old_binary_id = self.helpers.get_unique_id( + self.data, + "binary_sensor", + "Is Open", + "Wiser Shutter Previous Bedroom Bedroom Blind Is Open", + ) + old_cover_id = self.helpers.get_uuid_unique_id( + "WiserHeatNOTUSED-Wisershutter-42-" + "Wiser Shutter Previous Bedroom Bedroom Blind Control" + ) + + self.assertEqual( + mapping[old_binary_id], + self.helpers.get_physical_entity_unique_id( + self.data, "binary_sensor", 42, "Is Open" + ), + ) + self.assertEqual( + mapping[old_cover_id], + self.helpers.get_physical_entity_unique_id( + self.data, "cover", 42, "control" + ), + ) + def test_physical_sensor_migration_covers_humidity_power_and_energy(self): room = SimpleNamespace( id=7, diff --git a/tests/test_room_migration_orchestration.py b/tests/test_room_migration_orchestration.py index 3ec21fd0..ea6cd75f 100644 --- a/tests/test_room_migration_orchestration.py +++ b/tests/test_room_migration_orchestration.py @@ -250,7 +250,12 @@ def test_physical_migration_composes_power_and_energy_migrations(self) -> None: ) physical_device = SimpleNamespace( id="physical-device", - identifiers={("wiser", "legacy-device")}, + identifiers={ + ( + "wiser", + "WiserHeat123456 Wiser HeatingActuator Living Room", + ) + }, ) power = SimpleNamespace( entity_id="sensor.power", @@ -329,6 +334,19 @@ def test_physical_migration_composes_power_and_energy_migrations(self) -> None: "stable-energy-42": {"sensor.energy"}, }, ) + self.assertTrue( + any( + call.args[2] + == { + 42: { + "Wiser HeatingActuator Living Room", + } + } + and call.args[3] == {42} + for call in self.wiser.build_physical_entity_unique_id_migration.call_args_list + if len(call.args) == 4 + ) + ) self.wiser.migrate_physical_device.assert_called_once() def test_area_sync_composes_room_and_physical_devices(self) -> None: From 249735deba754857c827f7c8839bc110f98e002d Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 14:07:21 +0100 Subject: [PATCH 110/154] fix: clean up the final deleted room safely --- custom_components/wiser/device.py | 14 ++++++++------ tests/test_device.py | 24 +++++++++++++++++++++--- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/custom_components/wiser/device.py b/custom_components/wiser/device.py index 733aef41..d7d964d7 100644 --- a/custom_components/wiser/device.py +++ b/custom_components/wiser/device.py @@ -57,12 +57,9 @@ def confirmed_deleted_room_ids( current_room_ids, missing_counts, required_observations=2, + required_empty_observations=3, ): - """Return rooms absent from consecutive non-empty hub responses.""" - if not current_room_ids: - missing_counts.clear() - return set() - + """Return rooms absent from consecutive successful hub responses.""" missing_room_ids = set(previous_room_ids) - set(current_room_ids) for room_id in list(missing_counts): if room_id not in missing_room_ids: @@ -70,10 +67,15 @@ def confirmed_deleted_room_ids( for room_id in missing_room_ids: missing_counts[room_id] = missing_counts.get(room_id, 0) + 1 + required_count = ( + required_empty_observations + if not current_room_ids + else required_observations + ) return { room_id for room_id in missing_room_ids - if missing_counts[room_id] >= required_observations + if missing_counts[room_id] >= required_count } diff --git a/tests/test_device.py b/tests/test_device.py index dfce6427..90f4112e 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -323,13 +323,31 @@ def test_requires_two_consecutive_missing_observations(self) -> None: self.assertEqual(first, set()) self.assertEqual(second, {"7"}) - def test_empty_room_response_never_confirms_deletion(self) -> None: - missing_counts = {"7": 1} + def test_empty_room_response_requires_three_observations(self) -> None: + missing_counts = {} - confirmed = DEVICE.confirmed_deleted_room_ids( + first = DEVICE.confirmed_deleted_room_ids( + {"7"}, set(), missing_counts + ) + second = DEVICE.confirmed_deleted_room_ids( + {"7"}, set(), missing_counts + ) + third = DEVICE.confirmed_deleted_room_ids( {"7"}, set(), missing_counts ) + self.assertEqual(first, set()) + self.assertEqual(second, set()) + self.assertEqual(third, {"7"}) + self.assertEqual(missing_counts, {"7": 3}) + + def test_rooms_reappearing_after_empty_response_clear_missing_counts(self): + missing_counts = {"7": 2} + + confirmed = DEVICE.confirmed_deleted_room_ids( + {"7"}, {"7"}, missing_counts + ) + self.assertEqual(confirmed, set()) self.assertEqual(missing_counts, {}) From 21e89afe956e0b59b4e2381eff89f9ca85bd5563 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 14:08:09 +0100 Subject: [PATCH 111/154] fix: apply legacy naming to room devices --- custom_components/wiser/helpers.py | 45 +++++++++++++--- tests/test_hub_naming.py | 85 ++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+), 7 deletions(-) diff --git a/custom_components/wiser/helpers.py b/custom_components/wiser/helpers.py index a15f776f..7f162eea 100644 --- a/custom_components/wiser/helpers.py +++ b/custom_components/wiser/helpers.py @@ -102,6 +102,8 @@ def get_device_name(data, device_id, device_type="device"): return f"{ENTITY_PREFIX} {device.name}" if device.product_type in ["HeatingActuator", "CFMT"]: + if not legacy_naming: + return f"{ENTITY_PREFIX} {device.product_type}" device_room = data.wiserhub.rooms.get_by_device_id(device_id) # If device not allocated to a room return type and id only if device_room: @@ -123,7 +125,7 @@ def get_device_name(data, device_id, device_type="device"): if device.product_type in ["SmokeAlarmDevice", "ButtonPanel"]: device_room = data.wiserhub.rooms.get_by_id(device.room_id) - if device_room: + if legacy_naming and device_room: return f"{ENTITY_PREFIX} {device_room.name} {device.name}" return f"{ENTITY_PREFIX} {device.name} {device.id}" @@ -148,7 +150,7 @@ def get_device_name(data, device_id, device_type="device"): ]: device_room = data.wiserhub.rooms.get_by_device_id(device_id) # If device not allocated to a room return type and id only - if device_room: + if legacy_naming and device_room: return f"{ENTITY_PREFIX} {device.product_type} {device_room.name} {device.name}" return f"{ENTITY_PREFIX} {device.product_type} {device.name}" @@ -185,15 +187,44 @@ def get_legacy_device_name(data, device_id): return f"{ENTITY_PREFIX} Thermostat {device_room.name}" return f"{ENTITY_PREFIX} Thermostat {device.id}" - if device.product_type != "TemperatureHumiditySensor": - return get_device_name(data, device_id) + if device.product_type in {"HeatingActuator", "CFMT"}: + if device_room: + if device_room.number_of_heating_actuators > 1: + index = device_room.heating_actuator_ids.index(device.id) + 1 + return ( + f"{ENTITY_PREFIX} {device.product_type} " + f"{device_room.name}-{index}" + ) + return f"{ENTITY_PREFIX} {device.product_type} {device_room.name}" + return f"{ENTITY_PREFIX} {device.product_type} {device.id}" + + if device.product_type in {"SmokeAlarmDevice", "ButtonPanel"}: + if device_room: + return f"{ENTITY_PREFIX} {device_room.name} {device.name}" + return f"{ENTITY_PREFIX} {device.name} {device.id}" - if device_room: + if device.product_type == "TemperatureHumiditySensor" and device_room: return ( f"{ENTITY_PREFIX} {device.product_type} " f"{device_room.name} {device.name}" ) - return f"{ENTITY_PREFIX} {device.product_type} {device.name}" + if device.product_type in { + "Shutter", + "OnOffLight", + "DimmableLight", + "WindowDoorSensor", + "WaterLeakageSensor", + "MotionLightSensor", + "TemperatureHumiditySensor", + }: + if device_room: + return ( + f"{ENTITY_PREFIX} {device.product_type} " + f"{device_room.name} {device.name}" + ) + return f"{ENTITY_PREFIX} {device.product_type} {device.name}" + + return get_device_name(data, device_id) def get_identifier(data, device_id, device_type="device"): @@ -535,7 +566,7 @@ def build_light_unique_id_migration(data) -> dict: old_id = light.id new_id = light.light_id ptype = light.product_type - old_name = get_device_name(data, old_id) + old_name = get_legacy_device_name(data, old_id) new_name = f"{ENTITY_PREFIX} {light.name}" # light (name-based -> light_id-based) diff --git a/tests/test_hub_naming.py b/tests/test_hub_naming.py index 9899b6f8..8257880b 100644 --- a/tests/test_hub_naming.py +++ b/tests/test_hub_naming.py @@ -304,6 +304,91 @@ def test_itrv_name_respects_legacy_option_without_changing_identity(self): ) self.assertEqual(self.helpers.get_identifier(self.data, 31), identifier) + def test_room_assigned_device_names_respect_legacy_option(self): + room = SimpleNamespace( + id=7, + name="Andys Bedroom", + number_of_heating_actuators=1, + heating_actuator_ids=[31], + ) + devices = { + 31: SimpleNamespace( + id=31, + name="Actuator", + product_type="HeatingActuator", + room_id=7, + ), + 32: SimpleNamespace( + id=32, + name="Blind", + product_type="Shutter", + room_id=7, + ), + 33: SimpleNamespace( + id=33, + name="Smoke Alarm", + product_type="SmokeAlarmDevice", + room_id=7, + ), + } + self.data.wiserhub.devices.get_by_id = lambda device_id: devices[device_id] + self.data.wiserhub.rooms.get_by_id = lambda _room_id: room + self.data.wiserhub.rooms.get_by_device_id = lambda _device_id: room + + self.data.legacy_naming = False + self.assertEqual( + self.helpers.get_device_name(self.data, 31), + "Wiser HeatingActuator", + ) + self.assertEqual( + self.helpers.get_device_name(self.data, 32), + "Wiser Shutter Blind", + ) + self.assertEqual( + self.helpers.get_device_name(self.data, 33), + "Wiser Smoke Alarm 33", + ) + + self.data.legacy_naming = True + self.assertEqual( + self.helpers.get_device_name(self.data, 31), + "Wiser HeatingActuator Andys Bedroom", + ) + self.assertEqual( + self.helpers.get_device_name(self.data, 32), + "Wiser Shutter Andys Bedroom Blind", + ) + self.assertEqual( + self.helpers.get_device_name(self.data, 33), + "Wiser Andys Bedroom Smoke Alarm", + ) + + def test_historical_device_names_ignore_legacy_option(self): + room = SimpleNamespace( + id=7, + name="Andys Bedroom", + number_of_heating_actuators=1, + heating_actuator_ids=[31], + ) + device = SimpleNamespace( + id=31, + name="Actuator", + product_type="HeatingActuator", + room_id=7, + ) + self.data.wiserhub.devices.get_by_id = lambda _device_id: device + self.data.wiserhub.rooms.get_by_device_id = lambda _device_id: room + + self.data.legacy_naming = False + modern_name = self.helpers.get_device_name(self.data, 31) + historical_name = self.helpers.get_legacy_device_name(self.data, 31) + + self.assertEqual(modern_name, "Wiser HeatingActuator") + self.assertEqual( + historical_name, + "Wiser HeatingActuator Andys Bedroom", + ) + def test_physical_entity_migration_uses_historical_itrv_name(self): device = SimpleNamespace(id=31, product_type="iTRV") room = SimpleNamespace( From adfd962fb4692e8eeee6dec847f6633b22d99a4e Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 14:09:04 +0100 Subject: [PATCH 112/154] docs: describe room registry migration --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26aa5194..abe365b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,7 +32,7 @@ For releases before v3.3.5, see the [Full Change Log](https://github.com/asantag ### Fixed -- Fixed newly added or previously removed Wiser rooms retaining an orphaned Home Assistant device without an area assignment. +- Fixed Wiser room renames and removals creating duplicate or orphaned devices and entities. Physical devices and logical rooms now use stable identifiers, existing registry records are migrated while retaining entity IDs and history, integration-managed area assignments follow room renames, user-selected areas remain unchanged, and deleted rooms are removed after confirmation - issue [#732](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/732). - Reintroduced the previous Power and Energy entities, corrected equipment data naming on v2 hubs, and added an active state for the window/door sensor - issue [#677](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/677), PR [#690](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/690). - Fixed multi-gang dimmer lights breaking select, binary_sensor, switch, and sensor entities - issue [#681](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/681), PR [#683](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/683). - Preserved light entities across the multi-gang unique_id migration - issue [#681](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/681), PR [#683](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/683). From e68569d4dd8952e66dfbe30b0d70bb11dd2ed209 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 14:10:10 +0100 Subject: [PATCH 113/154] fix: validate stored room migration state --- custom_components/wiser/__init__.py | 22 +++++++++++++++------- tests/test_room_migration_orchestration.py | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index c3b6e694..60bb78bb 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -90,6 +90,17 @@ _LOGGER = logging.getLogger(__name__) +def _initial_room_names(stored_room_names, config_entry_room_names): + """Return validated migration and runtime room-name state.""" + if isinstance(stored_room_names, dict): + room_names = dict(stored_room_names) + return room_names, room_names + if isinstance(config_entry_room_names, dict): + room_names = dict(config_entry_room_names) + return room_names, room_names + return {}, None + + async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: """Migrate old entry.""" _LOGGER.debug( @@ -247,10 +258,9 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): ROOM_NAMES_STORAGE_KEY.format(config_entry.entry_id), ) stored_room_names = await room_names_store.async_load() - previous_room_names = ( - stored_room_names - if isinstance(stored_room_names, dict) - else config_entry.data.get(CONF_WISER_ROOM_NAMES, {}) + previous_room_names, runtime_room_names = _initial_room_names( + stored_room_names, + config_entry.data.get(CONF_WISER_ROOM_NAMES), ) # This must run before both the update listener and reload-settings snapshot. @@ -262,9 +272,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): hass.data[DOMAIN][config_entry.entry_id] = { DATA: coordinator, - CONF_WISER_ROOM_NAMES: ( - previous_room_names if stored_room_names is not None else None - ), + CONF_WISER_ROOM_NAMES: runtime_room_names, ROOM_NAMES_STORE: room_names_store, } diff --git a/tests/test_room_migration_orchestration.py b/tests/test_room_migration_orchestration.py index ea6cd75f..0d518de4 100644 --- a/tests/test_room_migration_orchestration.py +++ b/tests/test_room_migration_orchestration.py @@ -186,6 +186,24 @@ def setUp(self) -> None: ), ) + def test_invalid_storage_falls_back_to_config_entry_room_names(self) -> None: + previous, runtime = self.wiser._initial_room_names( + ["invalid-storage"], + {"7": "Living Room"}, + ) + + self.assertEqual(previous, {"7": "Living Room"}) + self.assertEqual(runtime, {"7": "Living Room"}) + + def test_invalid_storage_without_fallback_starts_uninitialised(self) -> None: + previous, runtime = self.wiser._initial_room_names( + ["invalid-storage"], + None, + ) + + self.assertEqual(previous, {}) + self.assertIsNone(runtime) + def test_refresh_moves_areas_and_saves_names_without_config_reload(self) -> None: self.wiser._confirmed_deleted_room_ids = Mock(return_value=set()) self.wiser.remove_deleted_room_devices = Mock() From 6e86525740b11da7f44f6a2ea2d4a7215c0218ea Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 14:11:55 +0100 Subject: [PATCH 114/154] fix: reconstruct legacy physical identifiers --- custom_components/wiser/helpers.py | 2 +- tests/test_hub_naming.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/custom_components/wiser/helpers.py b/custom_components/wiser/helpers.py index 7f162eea..a5f5797e 100644 --- a/custom_components/wiser/helpers.py +++ b/custom_components/wiser/helpers.py @@ -269,7 +269,7 @@ def get_legacy_device_identifier(data, device_id): else: device_name = f"{ENTITY_PREFIX} {device.product_type} {device.id}" else: - device_name = get_device_name(data, device_id) + device_name = get_legacy_device_name(data, device_id) return f"{data.wiserhub.system.name} {device_name}" diff --git a/tests/test_hub_naming.py b/tests/test_hub_naming.py index 8257880b..7c771ace 100644 --- a/tests/test_hub_naming.py +++ b/tests/test_hub_naming.py @@ -388,6 +388,10 @@ def test_historical_device_names_ignore_legacy_option(self): historical_name, "Wiser HeatingActuator Andys Bedroom", ) + self.assertEqual( + self.helpers.get_legacy_device_identifier(self.data, 31), + "WiserHeatNOTUSED Wiser HeatingActuator Andys Bedroom", + ) def test_physical_entity_migration_uses_historical_itrv_name(self): device = SimpleNamespace(id=31, product_type="iTRV") From 9f16f7917fa4ed71f7837ae0dd7571e9fd1c423f Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 14:14:33 +0100 Subject: [PATCH 115/154] fix: migrate legacy room entities --- custom_components/wiser/device.py | 19 +++++++++- tests/test_device.py | 63 +++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/custom_components/wiser/device.py b/custom_components/wiser/device.py index d7d964d7..980cc345 100644 --- a/custom_components/wiser/device.py +++ b/custom_components/wiser/device.py @@ -259,15 +259,30 @@ def migrate_room_entities( entity_type = None translation_key = getattr(entry, "translation_key", None) + unique_id = str(getattr(entry, "unique_id", "")).casefold() if entry.domain == "climate": entity_type = "climate" - elif entry.domain == "switch" and translation_key: - entity_type = f"switch_{translation_key}" + elif entry.domain == "switch": + if translation_key: + entity_type = f"switch_{translation_key}" + elif "-passive-mode-switch-" in unique_id: + entity_type = "switch_passive_mode" + elif "-room-switch-" in unique_id: + if unique_id.endswith(" window detection"): + entity_type = "switch_window_detection" + elif unique_id.endswith(" include in summer comfort"): + entity_type = "switch_include_in_summer_comfort" elif entry.domain == "sensor": if translation_key == "heating_demand": entity_type = "heating_demand" elif translation_key == "target_temperature": entity_type = "current_target_temp" + elif "-sensor-current_target_temp-" in unique_id: + entity_type = "current_target_temp" + elif "-sensor-current_temp-" in unique_id: + entity_type = "current_temp" + elif "-sensor-room-" in unique_id: + entity_type = "heating_demand" elif ( translation_key is None and "temperature" diff --git a/tests/test_device.py b/tests/test_device.py index 90f4112e..f58587e1 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -881,3 +881,66 @@ def test_migrates_all_room_name_derived_entity_types(self) -> None: {update[1]["new_unique_id"] for update in registry.updated}, {f"stable-{definition[3]}" for definition in definitions}, ) + + def test_migrates_room_entities_created_before_translation_keys(self) -> None: + definitions = ( + ( + "switch.window_detection", + "switch", + "WiserHeat-room-switch-Wiser Lounge Window Detection", + "switch_window_detection", + ), + ( + "switch.summer_comfort", + "switch", + "WiserHeat-room-switch-Wiser Lounge Include In Summer Comfort", + "switch_include_in_summer_comfort", + ), + ( + "switch.passive_mode", + "switch", + "WiserHeat-passive-mode-switch-Wiser Lounge Passive Mode-1", + "switch_passive_mode", + ), + ( + "sensor.temperature", + "sensor", + "WiserHeat-sensor-current_temp-1", + "current_temp", + ), + ( + "sensor.target_temperature", + "sensor", + "WiserHeat-sensor-current_target_temp-1", + "current_target_temp", + ), + ( + "sensor.heating_demand", + "sensor", + "WiserHeat-sensor-room-1", + "heating_demand", + ), + ) + registry = EntityRegistry( + { + entity_id: EntityEntry( + entity_id, + "room-device", + domain=domain, + unique_id=unique_id, + device_class="temperature" if domain == "sensor" else None, + ) + for entity_id, domain, unique_id, _entity_type in definitions + } + ) + + DEVICE.migrate_room_entities( + registry, + "room-device", + lambda entity_type: f"stable-{entity_type}", + ) + + self.assertEqual( + {update[1]["new_unique_id"] for update in registry.updated}, + {f"stable-{definition[3]}" for definition in definitions}, + ) From e82f6bf49dae4d45e1347d0f46cf783f88e61f32 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 14:17:41 +0100 Subject: [PATCH 116/154] fix: preserve device connections during migration --- custom_components/wiser/device.py | 17 ++++++++++++----- tests/test_device.py | 10 ++++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/custom_components/wiser/device.py b/custom_components/wiser/device.py index 980cc345..b5e7e696 100644 --- a/custom_components/wiser/device.py +++ b/custom_components/wiser/device.py @@ -201,12 +201,19 @@ def migrate_physical_device( for candidate_identifier in candidate.identifiers if candidate_identifier[0] != identifier[0] } - return device_registry.async_update_device( - canonical.id, - new_identifiers=preserved_identifiers | {identifier}, - name=name, + preserved_connections = { + connection + for candidate in candidates + for connection in getattr(candidate, "connections", set()) + } + updates = { + "new_identifiers": preserved_identifiers | {identifier}, + "name": name, **device_info, - ) + } + if preserved_connections: + updates["new_connections"] = preserved_connections + return device_registry.async_update_device(canonical.id, **updates) def migrate_entity_unique_id_duplicates( diff --git a/tests/test_device.py b/tests/test_device.py index f58587e1..77a2639e 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -26,6 +26,7 @@ class DeviceEntry: name_by_user: str | None = None created_at: datetime | None = None identifiers: set = field(default_factory=set) + connections: set = field(default_factory=set) @dataclass @@ -735,6 +736,7 @@ def test_keeps_oldest_device_and_merges_renamed_duplicate(self) -> None: ("wiser", "WiserHeat123456 Wiser iTRV Bedroom"), ("matter", "matter-device-31"), }, + connections={("mac", "aa:bb:cc:dd:ee:ff")}, ) renamed = DeviceEntry( "renamed-device", @@ -743,6 +745,7 @@ def test_keeps_oldest_device_and_merges_renamed_duplicate(self) -> None: ("wiser", "WiserHeat123456 Wiser iTRV Lounge"), ("zigbee", "zigbee-device-31"), }, + connections={("zigbee", "00:11:22:33:44:55")}, ) registry = DeviceRegistry() entities = EntityRegistry( @@ -779,6 +782,13 @@ def test_keeps_oldest_device_and_merges_renamed_duplicate(self) -> None: self.assertEqual( registry.updated[0][1]["via_device_id"], "physical-hub-id" ) + self.assertEqual( + registry.updated[0][1]["new_connections"], + { + ("mac", "aa:bb:cc:dd:ee:ff"), + ("zigbee", "00:11:22:33:44:55"), + }, + ) self.assertNotIn("via_device", registry.updated[0][1]) self.assertEqual( entities.updated, From 573b99cc0b46a00603700b6cf28332c5d9c72f44 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 16:56:04 +0100 Subject: [PATCH 117/154] fix: migrate room window detection entities --- custom_components/wiser/binary_sensor.py | 7 ++++++- custom_components/wiser/device.py | 6 ++++++ tests/test_device.py | 12 ++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/custom_components/wiser/binary_sensor.py b/custom_components/wiser/binary_sensor.py index 2242f4ec..66822425 100644 --- a/custom_components/wiser/binary_sensor.py +++ b/custom_components/wiser/binary_sensor.py @@ -23,6 +23,7 @@ get_legacy_unique_id, get_light_binary_sensor_unique_id, get_physical_entity_unique_id, + get_room_entity_unique_id, get_unique_id, get_uuid_unique_id, ) @@ -464,7 +465,11 @@ def is_on(self): @property def unique_id(self): """Return uniqueid.""" - return get_unique_id(self._data, "sensor", self._sensor_type, self._room_id) + return get_room_entity_unique_id( + self._data, + self._room_id, + f"binary_sensor_{self._attr_translation_key}", + ) @property def device_info(self): diff --git a/custom_components/wiser/device.py b/custom_components/wiser/device.py index b5e7e696..3247f732 100644 --- a/custom_components/wiser/device.py +++ b/custom_components/wiser/device.py @@ -269,6 +269,12 @@ def migrate_room_entities( unique_id = str(getattr(entry, "unique_id", "")).casefold() if entry.domain == "climate": entity_type = "climate" + elif entry.domain == "binary_sensor": + if ( + translation_key == "window_detection_active" + or translation_key is None + ): + entity_type = "binary_sensor_window_detection_active" elif entry.domain == "switch": if translation_key: entity_type = f"switch_{translation_key}" diff --git a/tests/test_device.py b/tests/test_device.py index 77a2639e..7e3afb2b 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -857,6 +857,12 @@ def test_migrates_all_room_name_derived_entity_types(self) -> None: entities = {} definitions = ( ("climate", None, None, "climate"), + ( + "binary_sensor", + "window_detection_active", + None, + "binary_sensor_window_detection_active", + ), ("switch", "window_detection", None, "switch_window_detection"), ("sensor", "heating_demand", None, "heating_demand"), ("sensor", "target_temperature", "temperature", "current_target_temp"), @@ -894,6 +900,12 @@ def test_migrates_all_room_name_derived_entity_types(self) -> None: def test_migrates_room_entities_created_before_translation_keys(self) -> None: definitions = ( + ( + "binary_sensor.window_detection_active", + "binary_sensor", + "legacy-room-window-detection-active", + "binary_sensor_window_detection_active", + ), ( "switch.window_detection", "switch", From 86933af5c25f403faee1a7d828c9a71260e93418 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 19:53:03 +0100 Subject: [PATCH 118/154] fix: remove inactive Wiser rooms --- custom_components/wiser/__init__.py | 12 ++++++------ custom_components/wiser/binary_sensor.py | 3 ++- custom_components/wiser/helpers.py | 10 ++++++++++ tests/test_hub_naming.py | 9 +++++++++ tests/test_room_migration_orchestration.py | 16 +++++++++++++--- tests/test_sensor.py | 1 + 6 files changed, 41 insertions(+), 10 deletions(-) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index 60bb78bb..acefbf22 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -63,6 +63,7 @@ from .frontend.entry_updates import async_handle_entry_update, integration_reload_settings from .frontend.wiser_sidebar import async_update_wiser_panel from .helpers import ( + active_wiser_rooms, build_light_unique_id_migration, build_physical_entity_unique_id_migration, get_device_name, @@ -739,7 +740,7 @@ def migrate_room_device_registry(hass: HomeAssistant, config_entry): device_registry = dr.async_get(hass) entity_registry = er.async_get(hass) - for room in data.wiserhub.rooms.all: + for room in active_wiser_rooms(data): device_entry = migrate_room_device( device_registry, entity_registry, @@ -764,7 +765,7 @@ def migrate_room_device_registry(hass: HomeAssistant, config_entry): def _current_wiser_room_names(coordinator): """Return Wiser room names keyed by their stable room IDs.""" return { - str(room.id): room.name for room in coordinator.wiserhub.rooms.all + str(room.id): room.name for room in active_wiser_rooms(coordinator) } @@ -846,12 +847,11 @@ def sync_wiser_room_areas(hass, config_entry, previous_room_names) -> int: data = hass.data[DOMAIN][config_entry.entry_id][DATA] device_registry = dr.async_get(hass) area_registry = ar.async_get(hass) - current_room_names = { - room.name for room in data.wiserhub.rooms.all - } + current_rooms = active_wiser_rooms(data) + current_room_names = {room.name for room in current_rooms} moved = 0 - for room in data.wiserhub.rooms.all: + for room in current_rooms: room_device = _device_by_identifier( device_registry, config_entry.entry_id, diff --git a/custom_components/wiser/binary_sensor.py b/custom_components/wiser/binary_sensor.py index 66822425..89c0095e 100644 --- a/custom_components/wiser/binary_sensor.py +++ b/custom_components/wiser/binary_sensor.py @@ -16,6 +16,7 @@ from .const import CONF_OPENTHERM_SENSORS, DATA, DOMAIN, ENTITY_PREFIX, MANUFACTURER from .entity import WiserEntityMixin from .helpers import ( + active_wiser_rooms, get_device_name, get_hub_device_info, get_hub_via_device_info, @@ -184,7 +185,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie ) # Room binary sensors - for room in data.wiserhub.rooms.all: + for room in active_wiser_rooms(data): binary_sensors.extend( [ WiserRoomWindow(data, room.id, "Window Detection Active"), diff --git a/custom_components/wiser/helpers.py b/custom_components/wiser/helpers.py index a5f5797e..3cafd953 100644 --- a/custom_components/wiser/helpers.py +++ b/custom_components/wiser/helpers.py @@ -28,6 +28,16 @@ ENTITY_UNIQUE_ID_NAMESPACE = UUID("8d42a4e1-b77b-4dda-a964-137b67c6257f") +def active_wiser_rooms(data): + """Return rooms that still have a device or controller assigned.""" + return [ + room + for room in data.wiserhub.rooms.all + if str(getattr(room, "_data", {}).get("Invalid", "")).casefold() + != "nothingassigned" + ] + + def get_hub_mac_suffix(data): """Return the last three octets of the physical hub MAC address.""" mac_address = data.wiserhub.system.network.mac_address diff --git a/tests/test_hub_naming.py b/tests/test_hub_naming.py index 7c771ace..c091aa36 100644 --- a/tests/test_hub_naming.py +++ b/tests/test_hub_naming.py @@ -105,6 +105,15 @@ def test_hub_entity_object_id_uses_mac_suffix(self) -> None: "058a52_away_mode", ) + def test_active_rooms_exclude_nothing_assigned_records(self) -> None: + active = SimpleNamespace(_data={}, id=1) + deleted = SimpleNamespace( + _data={"Invalid": "NothingAssigned"}, id=2 + ) + self.data.wiserhub.rooms.all = [active, deleted] + + self.assertEqual(self.helpers.active_wiser_rooms(self.data), [active]) + def test_hub_entity_mixin_suggests_mac_derived_object_id(self) -> None: class DefaultEntity: @property diff --git a/tests/test_room_migration_orchestration.py b/tests/test_room_migration_orchestration.py index 0d518de4..3b4973be 100644 --- a/tests/test_room_migration_orchestration.py +++ b/tests/test_room_migration_orchestration.py @@ -110,6 +110,7 @@ def _load_wiser_init() -> ModuleType: async_update_wiser_panel=Mock(), ) helper_names = ( + "active_wiser_rooms", "build_light_unique_id_migration", "build_physical_entity_unique_id_migration", "get_device_name", @@ -122,10 +123,11 @@ def _load_wiser_init() -> ModuleType: "get_room_entity_unique_id", "get_unique_id", ) - _module( - "wiser_init_test.helpers", - **{name: Mock(name=name) for name in helper_names}, + helper_stubs = {name: Mock(name=name) for name in helper_names} + helper_stubs["active_wiser_rooms"] = ( + lambda data: data.wiserhub.rooms.all ) + _module("wiser_init_test.helpers", **helper_stubs) _module("wiser_init_test.services", async_setup_services=Mock()) _module("wiser_init_test.update", async_unload_card_updates=Mock()) _module("wiser_init_test.websockets", async_register_websockets=Mock()) @@ -204,6 +206,14 @@ def test_invalid_storage_without_fallback_starts_uninitialised(self) -> None: self.assertEqual(previous, {}) self.assertIsNone(runtime) + def test_current_room_names_use_only_active_rooms(self) -> None: + self.wiser.active_wiser_rooms = Mock(return_value=[self.room]) + + self.assertEqual( + self.wiser._current_wiser_room_names(self.coordinator), + {"7": "Lounge"}, + ) + def test_refresh_moves_areas_and_saves_names_without_config_reload(self) -> None: self.wiser._confirmed_deleted_room_ids = Mock(return_value=set()) self.wiser.remove_deleted_room_devices = Mock() diff --git a/tests/test_sensor.py b/tests/test_sensor.py index d8599c39..47bab1e2 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -104,6 +104,7 @@ def available(self): ) _module( "wiser.helpers", + active_wiser_rooms=lambda data: data.wiserhub.rooms.all, get_device_area_info=lambda _data, _device_id: {}, get_device_name=lambda _data, device_id, device_type="device": ( "Wiser HeatHub" From 0b5dc73b577ea3e98e8a0022d2a71826d4267bc1 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Fri, 9 Oct 2026 11:01:43 +0100 Subject: [PATCH 119/154] fix: avoid duplicate hub MAC in entity IDs --- custom_components/wiser/entity.py | 9 ++++++++- custom_components/wiser/helpers.py | 17 ++++++++++++----- tests/test_hub_naming.py | 25 +++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/custom_components/wiser/entity.py b/custom_components/wiser/entity.py index 374a06a9..35fd487d 100644 --- a/custom_components/wiser/entity.py +++ b/custom_components/wiser/entity.py @@ -14,6 +14,13 @@ def suggested_object_id(self): hub_identifier = (DOMAIN, self._data.wiserhub.system.name) if device_info and hub_identifier in device_info.get("identifiers", set()): - return get_hub_entity_object_id(self._data, self.name) + # Home Assistant builds default entity IDs from area + effective + # device name + suggested object ID. Use the registry name here so + # a user override is handled differently from our default hub name. + device_entry = getattr(self, "device_entry", None) + device_name = None + if device_entry is not None: + device_name = device_entry.name_by_user or device_entry.name + return get_hub_entity_object_id(self._data, self.name, device_name) return super().suggested_object_id diff --git a/custom_components/wiser/helpers.py b/custom_components/wiser/helpers.py index 3cafd953..47ded2ec 100644 --- a/custom_components/wiser/helpers.py +++ b/custom_components/wiser/helpers.py @@ -52,13 +52,20 @@ def get_hub_device_name(data): return f"{ENTITY_PREFIX} HeatHub" -def get_hub_entity_object_id(data, entity_name): +def get_hub_entity_object_id(data, entity_name, device_name=None): """Return the MAC-derived entity portion of a new hub object ID.""" entity_slug = re.sub(r"[^a-z0-9]+", "_", str(entity_name).lower()).strip("_") - # Home Assistant adds the area and device portions. Supplying them here too - # would produce IDs such as ``wiser_heathub_wiser_heathub_...`` when users - # recreate entity IDs from the device page. - return f"{get_hub_mac_suffix(data).lower()}_{entity_slug}" + # Home Assistant adds the area and effective device name around this value. + # The integration's multi-hub device name already contains the MAC suffix, + # so omit it here to avoid ``..._04f8a0_04f8a0_away_mode``. + device_name = device_name or get_hub_device_name(data) + compact_device_name = re.sub(r"[^0-9A-Fa-f]", "", str(device_name)) + mac_suffix = get_hub_mac_suffix(data) + if mac_suffix.casefold() in compact_device_name.casefold(): + return entity_slug + # A user may rename the device and remove the visible MAC. Add it to the + # entity portion so resetting the entity ID still retains the hub identity. + return f"{mac_suffix.lower()}_{entity_slug}" def hub_error_handler(func): diff --git a/tests/test_hub_naming.py b/tests/test_hub_naming.py index c091aa36..ad364936 100644 --- a/tests/test_hub_naming.py +++ b/tests/test_hub_naming.py @@ -105,6 +105,22 @@ def test_hub_entity_object_id_uses_mac_suffix(self) -> None: "058a52_away_mode", ) + def test_hub_entity_object_id_does_not_repeat_device_mac_suffix(self) -> None: + self.assertEqual( + self.helpers.get_hub_entity_object_id( + self.data, "Away Mode", "Wiser HeatHub (058A52)" + ), + "away_mode", + ) + + def test_renamed_hub_entity_object_id_keeps_mac_suffix(self) -> None: + self.assertEqual( + self.helpers.get_hub_entity_object_id( + self.data, "Away Mode", "Test" + ), + "058a52_away_mode", + ) + def test_active_rooms_exclude_nothing_assigned_records(self) -> None: active = SimpleNamespace(_data={}, id=1) deleted = SimpleNamespace( @@ -139,6 +155,15 @@ def device_info(entity_self): "058a52_away_mode", ) + renamed_entity = HubEntity(self.data) + renamed_entity.device_entry = SimpleNamespace( + name="Wiser HeatHub (058A52)", name_by_user="Test" + ) + self.assertEqual( + renamed_entity.suggested_object_id, + "058a52_away_mode", + ) + def test_hub_entity_object_id_does_not_repeat_device_name(self) -> None: object_id = self.helpers.get_hub_entity_object_id(self.data, "Away Mode") self.assertNotIn("wiser_heathub", object_id) From a7fa66fa994d250345fc9d1b82cfd0711d315e1b Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Fri, 9 Oct 2026 14:10:09 +0100 Subject: [PATCH 120/154] test: support current setup dependencies --- tests/test_room_migration_orchestration.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_room_migration_orchestration.py b/tests/test_room_migration_orchestration.py index 3b4973be..43957faf 100644 --- a/tests/test_room_migration_orchestration.py +++ b/tests/test_room_migration_orchestration.py @@ -59,6 +59,7 @@ def _load_wiser_init() -> ModuleType: "CONF_AUTOMATIONS_PASSIVE_TEMP_INCREMENT", "CONF_DEPRECATED_HW_TARGET_TEMP", "CONF_LEGACY_NAMING", + "CONF_OPENTHERM_EVER_CONNECTED", "CONF_WISER_ROOM_NAMES", "DATA", "UPDATE_LISTENER", @@ -128,6 +129,11 @@ def _load_wiser_init() -> ModuleType: lambda data: data.wiserhub.rooms.all ) _module("wiser_init_test.helpers", **helper_stubs) + _module( + "wiser_init_test.opentherm_detection", + opentherm_entity_unique_ids=Mock(return_value=set()), + opentherm_is_detected=Mock(return_value=False), + ) _module("wiser_init_test.services", async_setup_services=Mock()) _module("wiser_init_test.update", async_unload_card_updates=Mock()) _module("wiser_init_test.websockets", async_register_websockets=Mock()) From b859d9eb4cc6129c14c4b8b0908806da169c12b4 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 16:30:49 +0100 Subject: [PATCH 121/154] fix: refresh system binary sensor states --- custom_components/wiser/binary_sensor.py | 11 +++-- tests/test_sensor.py | 60 ++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/custom_components/wiser/binary_sensor.py b/custom_components/wiser/binary_sensor.py index 1bf87af9..60d87fab 100644 --- a/custom_components/wiser/binary_sensor.py +++ b/custom_components/wiser/binary_sensor.py @@ -404,10 +404,13 @@ def __init__(self, coordinator, device_id=0, sensor_type="") -> None: def _handle_coordinator_update(self) -> None: """Handle updated data from the coordinator.""" _LOGGER.debug(f"{self._sensor_type} device update requested") - HeatHub = self._data.wiserhub.system.name - HeatHub = HeatHub.replace("WiserHeat","HeatHub") - return f"{HeatHub} {self._sensor_type}" - + self._state = getattr( + self._data.wiserhub.system, + self._sensor_type.replace(" ", "_").lower(), + None, + ) + self.async_write_ha_state() + @property def is_on(self): """Return the state of the sensor.""" diff --git a/tests/test_sensor.py b/tests/test_sensor.py index f46320db..37b13a69 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -536,6 +536,66 @@ def guard_for(function_name: str) -> ast.If: self.assertIsNotNone(cleanup_call) +class WiserSystemBinarySensorUpdateTest(unittest.TestCase): + """Tests for coordinator updates to system binary sensors.""" + + @classmethod + def setUpClass(cls) -> None: + source = BINARY_SENSOR_SOURCE_PATH.read_text().split( + "class RoomBinarySensor", 1 + )[0] + tree = ast.parse(source) + system_class = next( + node + for node in tree.body + if isinstance(node, ast.ClassDef) + and node.name == "SystemBinarySensor" + ) + update_method = next( + node + for node in system_class.body + if isinstance(node, ast.FunctionDef) + and node.name == "_handle_coordinator_update" + ) + update_method.decorator_list = [] + namespace = {"_LOGGER": Mock()} + exec( + compile( + ast.Module(body=[update_method], type_ignores=[]), + BINARY_SENSOR_SOURCE_PATH.name, + "exec", + ), + namespace, + ) + cls.handle_update = staticmethod(namespace["_handle_coordinator_update"]) + + def setUp(self) -> None: + self.sensor = SimpleNamespace( + _data=SimpleNamespace( + wiserhub=SimpleNamespace( + system=SimpleNamespace(summer_comfort_available=False) + ) + ), + _sensor_type="Summer Comfort Available", + _state=True, + async_write_ha_state=Mock(), + ) + + def test_coordinator_update_refreshes_state(self) -> None: + self.handle_update(self.sensor) + + self.assertFalse(self.sensor._state) + self.sensor.async_write_ha_state.assert_called_once_with() + + def test_missing_property_sets_unknown_state(self) -> None: + self.sensor._data.wiserhub.system = SimpleNamespace() + + self.handle_update(self.sensor) + + self.assertIsNone(self.sensor._state) + self.sensor.async_write_ha_state.assert_called_once_with() + + class WiserDeviceSignalSensorNameTest(unittest.TestCase): """Tests for controller and device signal sensor names.""" From aaaaf8a2e8e8b865d765a0ea9e5b8f2ad3fd31c8 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Fri, 9 Oct 2026 15:14:21 +0100 Subject: [PATCH 122/154] test: remove obsolete iTRV helper stub --- tests/test_sensor.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 47bab1e2..47311ea1 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -115,7 +115,6 @@ def available(self): get_hub_device_info=lambda _data: {"identifiers": {("wiser", "hub")}}, get_hub_via_device_info=lambda _data: {}, get_legacy_unique_id=lambda *_args: "legacy-unique-id", - get_itrv_temperature_unique_id=lambda *_args: "itrv-temperature-id", get_physical_entity_unique_id=lambda _data, domain, device_id, entity_type: ( f"physical-{domain}-{device_id}-{entity_type}" ), From 7e1ced35450bbbd2aa2165315754e8b5541056c8 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 14:31:15 +0100 Subject: [PATCH 123/154] fix: use compatible parent device identifiers --- custom_components/wiser/__init__.py | 9 +++------ custom_components/wiser/coordinator.py | 1 - custom_components/wiser/device.py | 4 ++-- custom_components/wiser/helpers.py | 7 ++----- tests/test_device.py | 6 ++++-- tests/test_hub_naming.py | 6 ++++++ 6 files changed, 17 insertions(+), 16 deletions(-) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index acefbf22..d38f8bf5 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -295,7 +295,6 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): # Register the physical hub before its entities and connected devices. hub_device = await async_update_device_registry(hass, config_entry) - coordinator.hub_device_id = hub_device.id # Physical device identifiers used to contain mutable room or device names. # Migrate them before platform setup so renames cannot duplicate devices. @@ -308,7 +307,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): # Create physical devices in their Wiser room's Home Assistant area. Later # room renames move devices only while they remain in that managed area. - register_room_assigned_devices(hass, config_entry, hub_device.id) + register_room_assigned_devices(hass, config_entry) # Move existing hub entities off the old virtual Controller record. merge_legacy_hub_device_registry(hass, config_entry) @@ -488,9 +487,7 @@ def merge_legacy_hub_device_registry(hass: HomeAssistant, config_entry): ) -def register_room_assigned_devices( - hass: HomeAssistant, config_entry, hub_device_id: str -): +def register_room_assigned_devices(hass: HomeAssistant, config_entry): """Register physical Wiser devices in their matching Wiser room.""" data = hass.data[DOMAIN][config_entry.entry_id][DATA] area_registry = ar.async_get(hass) @@ -504,7 +501,7 @@ def register_room_assigned_devices( device_registry, config_entry.entry_id, (DOMAIN, get_identifier(data, device.id)), - hub_device_id, + (DOMAIN, data.wiserhub.system.name), room.name, manufacturer=MANUFACTURER, name=get_device_name(data, device.id), diff --git a/custom_components/wiser/coordinator.py b/custom_components/wiser/coordinator.py index b8d316ef..32d02422 100644 --- a/custom_components/wiser/coordinator.py +++ b/custom_components/wiser/coordinator.py @@ -108,7 +108,6 @@ def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry) -> None: ) self.hub_version = 0 - self.hub_device_id: str | None = None self.last_update_time = datetime.now() self.last_update_status = "" self.minimum_temp = TEMP_MINIMUM diff --git a/custom_components/wiser/device.py b/custom_components/wiser/device.py index 3247f732..6342f6b5 100644 --- a/custom_components/wiser/device.py +++ b/custom_components/wiser/device.py @@ -98,7 +98,7 @@ def register_room_assigned_device( device_registry, config_entry_id, identifier, - parent_device_id, + parent_identifier, suggested_area, **device_info, ): @@ -107,7 +107,7 @@ def register_room_assigned_device( config_entry_id=config_entry_id, identifiers={identifier}, suggested_area=suggested_area, - via_device_id=parent_device_id, + via_device=parent_identifier, **device_info, ) diff --git a/custom_components/wiser/helpers.py b/custom_components/wiser/helpers.py index 47ded2ec..0d1835b3 100644 --- a/custom_components/wiser/helpers.py +++ b/custom_components/wiser/helpers.py @@ -316,11 +316,8 @@ def get_hub_device_info(data): def get_hub_via_device_info(data): - """Return the registered physical HeatHub as a parent device.""" - hub_device_id = getattr(data, "hub_device_id", None) - if hub_device_id is None: - return {} - return {"via_device_id": hub_device_id} + """Return the physical HeatHub identifier as a parent device.""" + return {"via_device": (DOMAIN, data.wiserhub.system.name)} def get_legacy_unique_id(data, device_type, entity_type, device_id): diff --git a/tests/test_device.py b/tests/test_device.py index 7e3afb2b..8eea0efa 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -291,7 +291,7 @@ def test_registers_device_with_area_and_physical_hub_parent(self) -> None: registry, "entry-id", ("wiser", "WiserHeat123456 Wiser Thermostat"), - "physical-hub-id", + ("wiser", "WiserHeat123456"), "Andys Bedroom", manufacturer="Drayton Wiser", name="Wiser Thermostat", @@ -301,7 +301,9 @@ def test_registers_device_with_area_and_physical_hub_parent(self) -> None: created = registry.created[0] self.assertEqual(created["suggested_area"], "Andys Bedroom") - self.assertEqual(created["via_device_id"], "physical-hub-id") + self.assertEqual( + created["via_device"], ("wiser", "WiserHeat123456") + ) self.assertEqual( created["identifiers"], {("wiser", "WiserHeat123456 Wiser Thermostat")}, diff --git a/tests/test_hub_naming.py b/tests/test_hub_naming.py index ad364936..1bb5c0a0 100644 --- a/tests/test_hub_naming.py +++ b/tests/test_hub_naming.py @@ -130,6 +130,12 @@ def test_active_rooms_exclude_nothing_assigned_records(self) -> None: self.assertEqual(self.helpers.active_wiser_rooms(self.data), [active]) + def test_hub_parent_uses_compatible_identifier(self) -> None: + self.assertEqual( + self.helpers.get_hub_via_device_info(self.data), + {"via_device": ("wiser", "WiserHeatNOTUSED")}, + ) + def test_hub_entity_mixin_suggests_mac_derived_object_id(self) -> None: class DefaultEntity: @property From 453ed6dfff61d10e036084c405958b35abd18c3b Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 8 Oct 2026 17:02:57 +0100 Subject: [PATCH 124/154] fix: select compatible parent device reference --- custom_components/wiser/__init__.py | 1 + custom_components/wiser/helpers.py | 7 ++++++- tests/test_hub_naming.py | 16 ++++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index d38f8bf5..cd9c2778 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -295,6 +295,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): # Register the physical hub before its entities and connected devices. hub_device = await async_update_device_registry(hass, config_entry) + coordinator.hub_device_id = hub_device.id # Physical device identifiers used to contain mutable room or device names. # Migrate them before platform setup so renames cannot duplicate devices. diff --git a/custom_components/wiser/helpers.py b/custom_components/wiser/helpers.py index 0d1835b3..a910d9e2 100644 --- a/custom_components/wiser/helpers.py +++ b/custom_components/wiser/helpers.py @@ -5,6 +5,7 @@ WiserHubAuthenticationError, WiserHubRESTError, ) +from homeassistant.const import MAJOR_VERSION, MINOR_VERSION from homeassistant.core import HomeAssistant from .const import DOMAIN, ENTITY_PREFIX, MANUFACTURER import logging @@ -316,7 +317,11 @@ def get_hub_device_info(data): def get_hub_via_device_info(data): - """Return the physical HeatHub identifier as a parent device.""" + """Return the HeatHub parent supported by this Home Assistant version.""" + if (MAJOR_VERSION, MINOR_VERSION) >= (2026, 8): + hub_device_id = getattr(data, "hub_device_id", None) + if hub_device_id is not None: + return {"via_device_id": hub_device_id} return {"via_device": (DOMAIN, data.wiserhub.system.name)} diff --git a/tests/test_hub_naming.py b/tests/test_hub_naming.py index 1bb5c0a0..b9961f8e 100644 --- a/tests/test_hub_naming.py +++ b/tests/test_hub_naming.py @@ -24,6 +24,10 @@ def _load_helpers_module() -> ModuleType: sys.modules["aioWiserHeatAPI.wiserhub"] = wiserhub sys.modules["homeassistant"] = ModuleType("homeassistant") + const = ModuleType("homeassistant.const") + const.MAJOR_VERSION = 2025 + const.MINOR_VERSION = 5 + sys.modules["homeassistant.const"] = const core = ModuleType("homeassistant.core") core.HomeAssistant = object sys.modules["homeassistant.core"] = core @@ -89,6 +93,8 @@ def setUp(self) -> None: self.data = SimpleNamespace( wiserhub=SimpleNamespace(system=system, rooms=rooms, devices=devices) ) + self.helpers.MAJOR_VERSION = 2025 + self.helpers.MINOR_VERSION = 5 def test_single_hub_has_concise_device_name(self) -> None: self.assertEqual(self.helpers.get_hub_device_name(self.data), "Wiser HeatHub") @@ -136,6 +142,16 @@ def test_hub_parent_uses_compatible_identifier(self) -> None: {"via_device": ("wiser", "WiserHeatNOTUSED")}, ) + def test_hub_parent_uses_device_id_on_current_home_assistant(self) -> None: + self.helpers.MAJOR_VERSION = 2026 + self.helpers.MINOR_VERSION = 8 + self.data.hub_device_id = "physical-hub-id" + + self.assertEqual( + self.helpers.get_hub_via_device_info(self.data), + {"via_device_id": "physical-hub-id"}, + ) + def test_hub_entity_mixin_suggests_mac_derived_object_id(self) -> None: class DefaultEntity: @property From 58363a39a876616ff2702a0575ef62094e6c66c9 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Sun, 11 Oct 2026 19:43:05 +0100 Subject: [PATCH 125/154] fix: select compatible parent during device creation --- custom_components/wiser/__init__.py | 7 +++--- custom_components/wiser/device.py | 26 +++++++++------------- tests/test_device.py | 14 ++++++------ tests/test_room_migration_orchestration.py | 4 ++++ 4 files changed, 25 insertions(+), 26 deletions(-) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index cd9c2778..0027cc68 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -68,6 +68,7 @@ build_physical_entity_unique_id_migration, get_device_name, get_hub_device_name, + get_hub_via_device_info, get_identifier, get_instance_count, get_legacy_device_identifier, @@ -502,8 +503,8 @@ def register_room_assigned_devices(hass: HomeAssistant, config_entry): device_registry, config_entry.entry_id, (DOMAIN, get_identifier(data, device.id)), - (DOMAIN, data.wiserhub.system.name), room.name, + get_hub_via_device_info(data), manufacturer=MANUFACTURER, name=get_device_name(data, device.id), model=device.product_type, @@ -719,7 +720,7 @@ def migrate_physical_device_registry( manufacturer=MANUFACTURER, model=device.product_type, sw_version=device.firmware_version, - via_device=(DOMAIN, data.wiserhub.system.name), + creation_parent_info=get_hub_via_device_info(data), via_device_id=hub_device_id, ) if room is not None: @@ -746,7 +747,7 @@ def migrate_room_device_registry(hass: HomeAssistant, config_entry): (DOMAIN, get_identifier(data, room.id, "room")), (DOMAIN, get_legacy_room_identifier(data, room.id)), get_device_name(data, room.id, "room"), - via_device=(DOMAIN, data.wiserhub.system.name), + creation_parent_info=get_hub_via_device_info(data), ) assign_device_area_if_unset( device_registry, area_registry, device_entry, room.name diff --git a/custom_components/wiser/device.py b/custom_components/wiser/device.py index 6342f6b5..e688083d 100644 --- a/custom_components/wiser/device.py +++ b/custom_components/wiser/device.py @@ -98,8 +98,8 @@ def register_room_assigned_device( device_registry, config_entry_id, identifier, - parent_identifier, suggested_area, + parent_device_info, **device_info, ): """Register a physical device in its Wiser room on first creation.""" @@ -107,7 +107,7 @@ def register_room_assigned_device( config_entry_id=config_entry_id, identifiers={identifier}, suggested_area=suggested_area, - via_device=parent_identifier, + **parent_device_info, **device_info, ) @@ -141,7 +141,8 @@ def migrate_physical_device( identifier, candidates, name, - via_device=None, + creation_parent_info=None, + via_device_id=None, **device_info, ): """Give a physical device a stable ID and merge duplicate registry rows.""" @@ -172,18 +173,12 @@ def migrate_physical_device( canonical = None if canonical is None: - create_info = { - key: value - for key, value in device_info.items() - if key != "via_device_id" - } - if via_device is not None: - create_info["via_device"] = via_device return device_registry.async_get_or_create( config_entry_id=config_entry_id, identifiers={identifier}, name=name, - **create_info, + **(creation_parent_info or {}), + **device_info, ) for duplicate in candidates: @@ -211,6 +206,8 @@ def migrate_physical_device( "name": name, **device_info, } + if via_device_id is not None: + updates["via_device_id"] = via_device_id if preserved_connections: updates["new_connections"] = preserved_connections return device_registry.async_update_device(canonical.id, **updates) @@ -405,7 +402,7 @@ def migrate_room_device( identifier, legacy_identifier, name, - via_device=None, + creation_parent_info=None, ): """Migrate or create a Wiser room device with its stable identifier.""" get_by_identifier = getattr( @@ -445,14 +442,11 @@ def migrate_room_device( name=name, ) - create_info = {} - if via_device is not None: - create_info["via_device"] = via_device return device_registry.async_get_or_create( config_entry_id=config_entry_id, identifiers={identifier}, name=name, - **create_info, + **(creation_parent_info or {}), ) diff --git a/tests/test_device.py b/tests/test_device.py index 8eea0efa..55ceba19 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -291,8 +291,8 @@ def test_registers_device_with_area_and_physical_hub_parent(self) -> None: registry, "entry-id", ("wiser", "WiserHeat123456 Wiser Thermostat"), - ("wiser", "WiserHeat123456"), "Andys Bedroom", + {"via_device_id": "physical-hub-id"}, manufacturer="Drayton Wiser", name="Wiser Thermostat", model="RoomStat", @@ -302,7 +302,7 @@ def test_registers_device_with_area_and_physical_hub_parent(self) -> None: created = registry.created[0] self.assertEqual(created["suggested_area"], "Andys Bedroom") self.assertEqual( - created["via_device"], ("wiser", "WiserHeat123456") + created["via_device_id"], "physical-hub-id" ) self.assertEqual( created["identifiers"], @@ -502,7 +502,7 @@ def test_creates_missing_room_device_before_entity_setup(self) -> None: self.identifier, self.legacy_identifier, "Wiser Room", - via_device=("wiser", "WiserHeat123456"), + creation_parent_info={"via_device_id": "physical-hub-id"}, ) result = DEVICE.assign_device_area_if_unset( device_registry, area_registry, result, "Test" @@ -516,7 +516,7 @@ def test_creates_missing_room_device_before_entity_setup(self) -> None: "config_entry_id": self.config_entry_id, "identifiers": {self.identifier}, "name": "Wiser Room", - "via_device": ("wiser", "WiserHeat123456"), + "via_device_id": "physical-hub-id", } ], ) @@ -709,7 +709,7 @@ def test_uses_identifier_parent_only_when_creating_device(self) -> None: ("wiser", "WiserHeat123456 device 31"), [], "Wiser iTRV", - via_device=("wiser", "WiserHeat123456"), + creation_parent_info={"via_device_id": "physical-hub-id"}, via_device_id="physical-hub-id", model="iTRV", ) @@ -724,7 +724,7 @@ def test_uses_identifier_parent_only_when_creating_device(self) -> None: ("wiser", "WiserHeat123456 device 31") }, "name": "Wiser iTRV", - "via_device": ("wiser", "WiserHeat123456"), + "via_device_id": "physical-hub-id", "model": "iTRV", } ], @@ -766,7 +766,7 @@ def test_keeps_oldest_device_and_merges_renamed_duplicate(self) -> None: ("wiser", "WiserHeat123456 device 31"), [renamed, old], "Wiser iTRV", - via_device=("wiser", "WiserHeat123456"), + creation_parent_info={"via_device_id": "physical-hub-id"}, via_device_id="physical-hub-id", model="iTRV", ) diff --git a/tests/test_room_migration_orchestration.py b/tests/test_room_migration_orchestration.py index 43957faf..5ba3523a 100644 --- a/tests/test_room_migration_orchestration.py +++ b/tests/test_room_migration_orchestration.py @@ -116,6 +116,7 @@ def _load_wiser_init() -> ModuleType: "build_physical_entity_unique_id_migration", "get_device_name", "get_hub_device_name", + "get_hub_via_device_info", "get_identifier", "get_instance_count", "get_legacy_device_identifier", @@ -128,6 +129,9 @@ def _load_wiser_init() -> ModuleType: helper_stubs["active_wiser_rooms"] = ( lambda data: data.wiserhub.rooms.all ) + helper_stubs["get_hub_via_device_info"] = Mock( + return_value={"via_device_id": "hub-device"} + ) _module("wiser_init_test.helpers", **helper_stubs) _module( "wiser_init_test.opentherm_detection", From 05ec88c913a203da4bfcd7189dea512aba552fab Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Sun, 11 Oct 2026 19:57:15 +0100 Subject: [PATCH 126/154] feat: add OpenTherm hot water control --- CHANGELOG.md | 2 + custom_components/wiser/__init__.py | 76 +- custom_components/wiser/config_flow.py | 216 +- custom_components/wiser/const.py | 14 + custom_components/wiser/frontend/__init__.py | 7 + .../wiser/frontend/wiser-hot-water-control.js | 1990 +++++++++++++++++ custom_components/wiser/local_schedule.py | 343 +++ .../wiser/opentherm_detection.py | 43 +- .../wiser/opentherm_hot_water.py | 674 ++++++ custom_components/wiser/services.py | 20 +- custom_components/wiser/strings.json | 30 +- custom_components/wiser/translations/de.json | 28 +- .../wiser/translations/en-GB.json | 28 +- custom_components/wiser/translations/en.json | 28 +- custom_components/wiser/translations/fr.json | 28 +- custom_components/wiser/water_heater.py | 5 + custom_components/wiser/websockets.py | 90 +- tests/test_entity_naming.py | 2 + tests/test_opentherm.py | 7 +- tests/test_opentherm_hot_water.py | 322 +++ tests/test_room_migration_orchestration.py | 12 + tests/test_sidebar_icons.py | 21 +- tests/test_ui_options.py | 132 +- 23 files changed, 4078 insertions(+), 40 deletions(-) create mode 100644 custom_components/wiser/frontend/wiser-hot-water-control.js create mode 100644 custom_components/wiser/local_schedule.py create mode 100644 custom_components/wiser/opentherm_hot_water.py create mode 100644 custom_components/wiser/water_heater.py create mode 100644 tests/test_opentherm_hot_water.py diff --git a/CHANGELOG.md b/CHANGELOG.md index abe365b3..a6e6d701 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ For releases before v3.3.5, see the [Full Change Log](https://github.com/asantag ### Added +- Added optional Wiser-only OpenTherm domestic-hot-water control with a Home Assistant water-heater entity, configurable temperature and presets, an optional external current-temperature sensor, icon mode controls, and an integration-owned weekly schedule managed from the Wiser Schedules panel. Non-timed presets can be used in schedule periods; temporary boost presets remain manual actions. - Manage frontend definitions in the integration's bundled `cards.json`, with independent card and panel installation, offline caching, and a generic panel-settings API. - Added configurable OpenTherm monitoring and controls, including relative modulation, a Delta-T sensor, expanded telemetry, and categorized diagnostics - PR [#697](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/697). @@ -29,6 +30,7 @@ For releases before v3.3.5, see the [Full Change Log](https://github.com/asantag - Wiser devices are now placed in Home Assistant areas matching their Wiser room, creating the area if it does not exist. This applies only to devices that have no area yet, so any area you assigned manually is left untouched - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693), PR [#700](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/700). - Sidebar panel visibility is now configured through the integration's UI options - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). - Card versions are now detected from the installed card bundles instead of being pinned in the integration, so card updates no longer need an integration release - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). +- OpenTherm hot-water temperature changes made in Auto mode now act as temporary overrides and are replaced by the next scheduled period. ### Fixed diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index 0027cc68..94c1c480 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -31,11 +31,17 @@ CONF_DEPRECATED_HW_TARGET_TEMP, CONF_LEGACY_NAMING, CONF_OPENTHERM_EVER_CONNECTED, + CONF_OPENTHERM_HOT_WATER_CAPABLE, + CONF_OPENTHERM_HOT_WATER_CONTROL, + CONF_OPENTHERM_HOT_WATER_MANUAL_TEMP, + CONF_OPENTHERM_HOT_WATER_PRESETS, CONF_WISER_ROOM_NAMES, DATA, + DEFAULT_OPENTHERM_HOT_WATER_MANUAL_TEMP, DOMAIN, ENTITY_PREFIX, MANUFACTURER, + OPENTHERM_HOT_WATER_SCHEDULE, UPDATE_LISTENER, WISER_PLATFORMS, WISER_SERVICES, @@ -77,8 +83,11 @@ get_room_entity_unique_id, get_unique_id, ) +from .local_schedule import OpenThermHotWaterSchedule from .opentherm_detection import ( opentherm_entity_unique_ids, + opentherm_hot_water_control_is_supported, + opentherm_hot_water_limits, opentherm_is_detected, ) from .services import async_setup_services @@ -278,6 +287,33 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): ROOM_NAMES_STORE: room_names_store, } + opentherm = coordinator.wiserhub.system.opentherm + if ( + config_entry.options.get(CONF_OPENTHERM_HOT_WATER_CONTROL, False) + and opentherm_is_detected(config_entry, opentherm) + and opentherm_hot_water_control_is_supported(config_entry, opentherm) + ): + minimum, maximum = opentherm_hot_water_limits(opentherm) + local_hot_water_schedule = OpenThermHotWaterSchedule( + hass, + config_entry.entry_id, + minimum=float(minimum), + maximum=float(maximum), + default_temperature=float( + config_entry.options.get( + CONF_OPENTHERM_HOT_WATER_MANUAL_TEMP, + DEFAULT_OPENTHERM_HOT_WATER_MANUAL_TEMP, + ) + ), + presets=config_entry.options.get( + CONF_OPENTHERM_HOT_WATER_PRESETS, [] + ), + ) + await local_hot_water_schedule.async_load() + hass.data[DOMAIN][config_entry.entry_id][ + OPENTHERM_HOT_WATER_SCHEDULE + ] = local_hot_water_schedule + # If OpenTherm connects for the first time after startup, saving the flag # causes one integration reload so its entities are added. Future outages # retain those entities and their registry/history records. @@ -369,15 +405,16 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): previous_room_names, ) - # Setup platforms + # Setup services + await async_setup_services(hass, coordinator) + + # Setup platforms after services so entities can safely restore scheduled + # actions from async_added_to_hass. await hass.config_entries.async_forward_entry_setups(config_entry, WISER_PLATFORMS) # Setup websocket services for frontend cards await async_register_websockets(hass, coordinator) - # Setup services - await async_setup_services(hass, coordinator) - # Register custom cards moodule_register = JSModuleRegistration(hass) await moodule_register.async_register() @@ -391,11 +428,11 @@ async def async_setup_entry(hass: HomeAssistant, config_entry): @callback def _remember_opentherm_connection(hass, config_entry, coordinator) -> None: - """Persist a confirmed OpenTherm connection until it is disabled. + """Persist confirmed OpenTherm connection and hot-water capability. - The flag intentionally lives in config-entry data so the existing entry - update listener reloads platforms when runtime detection changes. A Store - would persist the state but would not trigger that reload. + The flags intentionally live in config-entry data so the existing entry + update listener reloads platforms when runtime detection changes. They + also prevent a partial first response after restart from removing entities. """ system = getattr(coordinator.wiserhub, "system", None) if system is None: @@ -403,23 +440,34 @@ def _remember_opentherm_connection(hass, config_entry, coordinator) -> None: opentherm = getattr(system, "opentherm", None) remembered = config_entry.data.get(CONF_OPENTHERM_EVER_CONNECTED, False) + hot_water_capable = config_entry.data.get( + CONF_OPENTHERM_HOT_WATER_CAPABLE, False + ) + entry_data = dict(config_entry.data) if getattr(opentherm, "enabled", None) is False: if remembered: - entry_data = dict(config_entry.data) entry_data.pop(CONF_OPENTHERM_EVER_CONNECTED, None) - hass.config_entries.async_update_entry(config_entry, data=entry_data) + if hot_water_capable: + entry_data.pop(CONF_OPENTHERM_HOT_WATER_CAPABLE, None) remembered = False elif ( not remembered and getattr(opentherm, "connection_status", None) == "Connected" ): - hass.config_entries.async_update_entry( - config_entry, - data={**config_entry.data, CONF_OPENTHERM_EVER_CONNECTED: True}, - ) + entry_data[CONF_OPENTHERM_EVER_CONNECTED] = True remembered = True + boiler_parameters = getattr(opentherm, "boiler_parameters", None) + if ( + not hot_water_capable + and getattr(boiler_parameters, "hw_setpoint_read_write", None) is True + ): + entry_data[CONF_OPENTHERM_HOT_WATER_CAPABLE] = True + + if entry_data != config_entry.data: + hass.config_entries.async_update_entry(config_entry, data=entry_data) + detected = bool(opentherm and remembered) if getattr(coordinator, "_wiser_opentherm_detected", None) is detected: return diff --git a/custom_components/wiser/config_flow.py b/custom_components/wiser/config_flow.py index fed0d4b5..f6d48248 100755 --- a/custom_components/wiser/config_flow.py +++ b/custom_components/wiser/config_flow.py @@ -33,7 +33,10 @@ BooleanSelector, EntitySelector, EntitySelectorConfig, + SELECTORS, SelectSelectorMode, + Selector, + make_selector_config_schema, selector, ) from homeassistant.helpers.service_info.zeroconf import ZeroconfServiceInfo @@ -53,6 +56,10 @@ CONF_HOSTNAME, CONF_HW_BOOST_TIME, CONF_LEGACY_NAMING, + CONF_OPENTHERM_HOT_WATER_CONTROL, + CONF_OPENTHERM_HOT_WATER_MANUAL_TEMP, + CONF_OPENTHERM_HOT_WATER_PRESETS, + CONF_OPENTHERM_HOT_WATER_SENSOR_ENTITY_ID, CONF_OPENTHERM_SENSORS, CONF_RESTORE_MANUAL_TEMP_OPTION, CONF_SETPOINT_MODE, @@ -61,12 +68,16 @@ DEFAULT_BOOST_TEMP, DEFAULT_BOOST_TEMP_TIME, DEFAULT_PASSIVE_TEMP_INCREMENT, + DEFAULT_OPENTHERM_HOT_WATER_MANUAL_TEMP, + DEFAULT_OPENTHERM_HOT_WATER_PRESET_TEMP, DEFAULT_SCAN_INTERVAL, DATA, DOMAIN, WISER_RESTORE_TEMP_DEFAULT_OPTIONS, WISER_SETPOINT_MODES, HWCycleModes, + MAX_OPENTHERM_HOT_WATER_PRESETS, + OPENTHERM_HOT_WATER_DEFAULT_BOOSTS, ) from .opentherm import ( OPENTHERM_SENSOR_CATEGORIES, @@ -75,10 +86,99 @@ detected_opentherm_sensor_keys, opentherm_sensor_is_enabled, ) -from .opentherm_detection import opentherm_is_detected +from .opentherm_detection import ( + opentherm_hot_water_control_is_supported, + opentherm_hot_water_limits, + opentherm_is_detected, +) _LOGGER = logging.getLogger(__name__) + +def _default_opentherm_hot_water_presets(minimum=35.0, maximum=55.0): + """Return the default timed hot-water boosts from the original control.""" + return [ + { + "name": f"Boost {duration} Mins", + "icon": f"mdi:numeric-{index}", + "temperature": min( + max(DEFAULT_OPENTHERM_HOT_WATER_PRESET_TEMP, minimum), maximum + ), + "duration_minutes": duration, + } + for index, duration in enumerate( + OPENTHERM_HOT_WATER_DEFAULT_BOOSTS, start=1 + ) + ] + + +def _validate_opentherm_hot_water_presets( + value, minimum=35.0, maximum=55.0, *, clamp_temperature=False +): + """Validate the custom preset selector value.""" + if not isinstance(value, list): + raise vol.Invalid("Presets must be a list") + if len(value) > MAX_OPENTHERM_HOT_WATER_PRESETS: + raise vol.Invalid("Too many presets") + + presets = [] + names = set() + for item in value: + if not isinstance(item, dict): + raise vol.Invalid("Each preset must be an object") + name = str(item.get("name", "")).strip() + folded_name = name.casefold() + if not name or folded_name in {"off", "manual", "auto", "custom"}: + raise vol.Invalid("Preset name is empty or reserved") + if folded_name in names: + raise vol.Invalid("Preset names must be unique") + try: + temperature = float(item.get("temperature")) + duration = int(item.get("duration_minutes", 0)) + except (TypeError, ValueError) as err: + raise vol.Invalid( + "Preset temperature and duration must be numbers" + ) from err + icon = str(item.get("icon", "")).strip() + if clamp_temperature: + temperature = min(max(temperature, minimum), maximum) + if not minimum <= temperature <= maximum or not 0 <= duration <= 999: + raise vol.Invalid("Preset temperature or duration is out of range") + presets.append( + { + "name": name, + "icon": icon, + "temperature": temperature, + "duration_minutes": duration, + } + ) + names.add(folded_name) + return presets + + +@SELECTORS.register("opentherm_presets_v2") +class OpenThermPresetsSelector(Selector): + """Render the preset editor supplied by the Wiser frontend module.""" + + # Keep the selector name versioned. Home Assistant registers custom + # elements once per browser session, so reusing the old name would leave a + # previously loaded implementation in place. + selector_type = "opentherm_presets_v2" + CONFIG_SCHEMA = make_selector_config_schema( + { + vol.Optional("minimum", default=35.0): vol.Coerce(float), + vol.Optional("maximum", default=55.0): vol.Coerce(float), + } + ) + + def __call__(self, data): + return _validate_opentherm_hot_water_presets( + data, + float(self.config.get("minimum", 35.0)), + float(self.config.get("maximum", 55.0)), + ) + + DATA_SCHEMA = vol.Schema( { vol.Required(CONF_HOST): str, @@ -298,7 +398,7 @@ async def async_step_init(self, user_input=None): """Handle options flow.""" menu_options = ["main_params", "automation_params", "ui_options"] if self._opentherm() is not None: - menu_options.append("opentherm_sensors") + menu_options.append("opentherm") if self._equipment_available() or self.config_entry.options.get( CONF_EQUIPMENT_SENSORS, False ): @@ -308,6 +408,118 @@ async def async_step_init(self, user_input=None): menu_options=menu_options, ) + async def async_step_opentherm(self, user_input=None): + """Choose an OpenTherm feature to configure.""" + if self._opentherm() is None: + return self.async_abort(reason="opentherm_not_available") + menu_options = ["opentherm_sensors"] + if opentherm_hot_water_control_is_supported( + self.config_entry, self._opentherm() + ): + menu_options.insert(0, "opentherm_hot_water_control") + return self.async_show_menu( + step_id="opentherm", + menu_options=menu_options, + ) + + async def async_step_opentherm_hot_water_control(self, user_input=None): + """Configure Home Assistant control of the OpenTherm DHW setpoint.""" + opentherm = self._opentherm() + if opentherm is None or not opentherm_hot_water_control_is_supported( + self.config_entry, opentherm + ): + return self.async_abort(reason="opentherm_not_available") + minimum, maximum = opentherm_hot_water_limits(opentherm) + try: + manual_default = float( + self.config_entry.options.get( + CONF_OPENTHERM_HOT_WATER_MANUAL_TEMP, + DEFAULT_OPENTHERM_HOT_WATER_MANUAL_TEMP, + ) + ) + except (TypeError, ValueError): + manual_default = DEFAULT_OPENTHERM_HOT_WATER_MANUAL_TEMP + manual_default = min(max(manual_default, minimum), maximum) + try: + preset_default = _validate_opentherm_hot_water_presets( + self.config_entry.options.get( + CONF_OPENTHERM_HOT_WATER_PRESETS, + _default_opentherm_hot_water_presets(minimum, maximum), + ), + minimum, + maximum, + clamp_temperature=True, + ) + except vol.Invalid: + preset_default = _default_opentherm_hot_water_presets( + minimum, maximum + ) + errors = {} + if user_input is not None: + try: + user_input[CONF_OPENTHERM_HOT_WATER_PRESETS] = ( + _validate_opentherm_hot_water_presets( + user_input.get(CONF_OPENTHERM_HOT_WATER_PRESETS, []), + minimum, + maximum, + ) + ) + except vol.Invalid: + errors["base"] = "invalid_hot_water_presets" + else: + options = self.config_entry.options | user_input + if not user_input.get( + CONF_OPENTHERM_HOT_WATER_SENSOR_ENTITY_ID + ): + options.pop( + CONF_OPENTHERM_HOT_WATER_SENSOR_ENTITY_ID, None + ) + # Remove the prototype option now that Off follows the minimum + # domestic-hot-water temperature reported by OpenTherm. + options.pop("opentherm_hot_water_off_temperature", None) + return self.async_create_entry(data=options) + return self.async_show_form( + step_id="opentherm_hot_water_control", + data_schema=vol.Schema( + { + vol.Optional( + CONF_OPENTHERM_HOT_WATER_CONTROL, + default=self.config_entry.options.get( + CONF_OPENTHERM_HOT_WATER_CONTROL, False + ), + ): BooleanSelector(), + vol.Optional( + CONF_OPENTHERM_HOT_WATER_MANUAL_TEMP, + default=manual_default, + ): vol.All( + vol.Coerce(float), + vol.Range(min=minimum, max=maximum), + ), + vol.Optional( + CONF_OPENTHERM_HOT_WATER_SENSOR_ENTITY_ID, + description={ + "suggested_value": self.config_entry.options.get( + CONF_OPENTHERM_HOT_WATER_SENSOR_ENTITY_ID + ) + }, + ): EntitySelector( + EntitySelectorConfig( + domain="sensor", + device_class="temperature", + multiple=False, + ) + ), + vol.Optional( + CONF_OPENTHERM_HOT_WATER_PRESETS, + default=preset_default, + ): OpenThermPresetsSelector( + {"minimum": minimum, "maximum": maximum} + ), + } + ), + errors=errors, + ) + async def async_step_equipment_sensors(self, user_input=None): """Configure detailed equipment data sensors.""" if not self._equipment_available() and not self.config_entry.options.get( diff --git a/custom_components/wiser/const.py b/custom_components/wiser/const.py index 353b51f0..f579d7c2 100755 --- a/custom_components/wiser/const.py +++ b/custom_components/wiser/const.py @@ -44,6 +44,7 @@ def _load_card_manifest(): "number", "light", "cover", + "water_heater", "update", ] DATA = "data" @@ -105,8 +106,21 @@ class HWCycleModes(StrEnum): CONF_AUTOMATIONS_HW_SENSOR_ENTITY_ID = "hotwater_sensor_entity_id" CONF_DEPRECATED_HW_TARGET_TEMP = "hotwater_target_temperature" CONF_OPENTHERM_EVER_CONNECTED = "opentherm_ever_connected" +CONF_OPENTHERM_HOT_WATER_CAPABLE = "opentherm_hot_water_capable" CONF_OPENTHERM_SENSORS = "opentherm_sensors" +CONF_OPENTHERM_HOT_WATER_CONTROL = "opentherm_hot_water_control" +CONF_OPENTHERM_HOT_WATER_MANUAL_TEMP = "opentherm_hot_water_manual_temperature" +CONF_OPENTHERM_HOT_WATER_SENSOR_ENTITY_ID = ( + "opentherm_hot_water_sensor_entity_id" +) +CONF_OPENTHERM_HOT_WATER_PRESETS = "opentherm_hot_water_presets" CONF_EQUIPMENT_SENSORS = "equipment_sensors" +OPENTHERM_HOT_WATER_SCHEDULE = "opentherm_hot_water_schedule" + +DEFAULT_OPENTHERM_HOT_WATER_MANUAL_TEMP = 45.0 +DEFAULT_OPENTHERM_HOT_WATER_PRESET_TEMP = 55.0 +MAX_OPENTHERM_HOT_WATER_PRESETS = 10 +OPENTHERM_HOT_WATER_DEFAULT_BOOSTS = (15, 30, 45) # Custom Attributes ATTR_OPENTHERM_ENDPOINT = "endpoint" diff --git a/custom_components/wiser/frontend/__init__.py b/custom_components/wiser/frontend/__init__.py index 7372a655..79f5e7da 100644 --- a/custom_components/wiser/frontend/__init__.py +++ b/custom_components/wiser/frontend/__init__.py @@ -75,6 +75,13 @@ async def async_register(self): card_version, Path(__file__).parent / "wiser-icons.js" ) add_extra_js_url(self.hass, f"{URL_BASE}/wiser-icons.js?v={icon_version}") + hot_water_version = await self.hass.async_add_executor_job( + card_version, Path(__file__).parent / "wiser-hot-water-control.js" + ) + add_extra_js_url( + self.hass, + f"{URL_BASE}/wiser-hot-water-control.js?v={hot_water_version}", + ) if self.lovelace and self.resource_mode == MODE_STORAGE: await self._async_wait_for_lovelace_resources() diff --git a/custom_components/wiser/frontend/wiser-hot-water-control.js b/custom_components/wiser/frontend/wiser-hot-water-control.js new file mode 100644 index 00000000..e2d7d046 --- /dev/null +++ b/custom_components/wiser/frontend/wiser-hot-water-control.js @@ -0,0 +1,1990 @@ +const FEATURE_TYPE = "opentherm-hot-water-control-modes-feature"; +const PRESETS_FEATURE_TYPE = + "opentherm-hot-water-control-presets-feature"; +const MORE_INFO_TYPE = "opentherm-hot-water-control-more-info"; +const NATIVE_TEMPERATURE_CONTROL = + "ha-state-control-water_heater-temperature"; +const DEFAULT_MAX_WIDTH = 560; +const PRESETS_ATTRIBUTE = "opentherm_presets"; +const PRESETS_SELECTOR_KEY = "opentherm_presets_v2"; +const PRESETS_SELECTOR_TYPE = `ha-selector-${PRESETS_SELECTOR_KEY}`; +const PRESETS_DIALOG_TYPE = "opentherm-presets-dialog-v2"; +const MAX_PRESETS = 10; +const MDI_ARROW_LEFT = + "M20,11V13H8L13.5,18.5L12.08,19.92L4.16,12L12.08,4.08L13.5,5.5L8,11H20Z"; + +const localize = (hass, key, fallback, replacements) => + hass?.localize?.(key, replacements) || fallback; + +const showTemperatureError = (element, error) => { + element.dispatchEvent(new CustomEvent("hass-notification", { + bubbles: true, + composed: true, + detail: { message: error?.message || "Unable to change hot-water temperature.", duration: 10000 }, + })); +}; + +const clonePresets = (presets) => + Array.isArray(presets) + ? presets.map((preset) => ({ ...preset })) + : []; + +const presetIcon = (presets, index) => { + const preset = presets[index]; + const configuredIcon = String(preset?.icon || "").trim(); + if (configuredIcon) { + return configuredIcon; + } + return `mdi:numeric-${Math.max(1, index + 1)}`; +}; + +class OpenThermTemperatureSourceSelector extends HTMLElement { + constructor() { + super(); + this.attachShadow({ mode: "open" }); + this._formChanged = (event) => { + if (event.target !== this._form) return; + const device = event.detail?.value?.device_id; + if (device === this._device) return; + this._device = device; + this._value = { mode: this._isWiser() ? "wiser" : "custom", entity_id: this._customEntity }; + this._update(); + // Let the outer form finish applying its device change before our update. + queueMicrotask(() => { if (this.isConnected) this._emit(); }); + }; + } + + set hass(value) { this._hass = value; this._update(); } + set selector(value) { + this._selector = value?.opentherm_temperature_source || {}; + if (this._device === undefined) this._device = this._selector.device_id; + this._update(); + } + set value(value) { + this._value = value; + if (value?.mode === "custom") this._customEntity = value.entity_id; + this._update(); + } + get value() { return this._value; } + set label(value) { this._label = value; this._update(); } + set disabled(value) { this._disabled = value; this._update(); } + set required(value) { this._required = value; } + + connectedCallback() { + if (!this._toggle) { + const style = document.createElement("style"); + style.textContent = ` + :host { display: block; } + .row { display: flex; align-items: center; gap: 16px; } + .label { flex: 1; color: var(--primary-text-color); font-size: var(--ha-font-size-m, 14px); } + ha-button-toggle-group { flex: none; margin-inline-start: auto; } + ha-selector { display: block; margin-top: 12px; } + [hidden] { display: none !important; } + `; + const row = document.createElement("div"); + row.className = "row"; + this._labelElement = document.createElement("div"); + this._labelElement.className = "label"; + this._toggle = document.createElement("ha-button-toggle-group"); + this._toggle.setAttribute("no-wrap", ""); + this._toggle.addEventListener("value-changed", (event) => { + event.stopPropagation(); + if (this._disabled) return; + this._value = { mode: event.detail.value, entity_id: this._customEntity }; + this._update(); + this._emit(); + }); + this._picker = document.createElement("ha-selector"); + this._picker.selector = { entity: { domain: "sensor", device_class: "temperature" } }; + this._picker.addEventListener("value-changed", (event) => { + event.stopPropagation(); + if (this._disabled) return; + this._customEntity = event.detail.value; + this._value = { mode: "custom", entity_id: this._customEntity }; + this._emit(); + }); + row.append(this._labelElement, this._toggle); + this.shadowRoot.append(style, row, this._picker); + } + // ha-form owns the control-device field in a different shadow tree. + let parent = this.parentNode; + while (parent) { + if (parent.localName === "ha-form") { this._form = parent; break; } + parent = parent.parentNode || parent.host; + } + this._form?.addEventListener("value-changed", this._formChanged); + this._update(); + } + + disconnectedCallback() { + this._form?.removeEventListener("value-changed", this._formChanged); + this._form = undefined; + } + + _isWiser() { return this._selector?.wiser_devices?.includes(this._device) || false; } + _emit() { + this.dispatchEvent(new CustomEvent("value-changed", { + bubbles: true, composed: true, detail: { value: this._value }, + })); + } + reportValidity() { + return this._value?.mode === "wiser" || !this._isWiser() || Boolean(this._customEntity); + } + _update() { + if (!this._toggle) return; + this._labelElement.textContent = this._label || "Current temperature"; + this._toggle.buttons = [ + { value: "wiser", label: "Wiser" }, + { value: "custom", label: localize(this._hass, "ui.components.entity.entity-name-picker.mode_custom", "Custom") }, + ]; + this._toggle.active = this._value?.mode; + this._toggle.disabled = Boolean(this._disabled); + this._toggle.hidden = !this._isWiser(); + this._picker.hidden = this._isWiser() && this._value?.mode === "wiser"; + this._picker.hass = this._hass; + this._picker.value = this._customEntity; + this._picker.disabled = Boolean(this._disabled); + this._picker.required = this._isWiser() && !this._picker.hidden; + } +} + +if (!customElements.get("ha-selector-opentherm_temperature_source")) { + customElements.define("ha-selector-opentherm_temperature_source", OpenThermTemperatureSourceSelector); +} + +class OpenThermFailureNotificationsSelector extends HTMLElement { + constructor() { + super(); + this.attachShadow({ mode: "open" }); + this._value = { persistent: false, mobile: false }; + } + + set hass(value) { this._hass = value; this._update(); } + set selector(value) { + this._selector = value?.opentherm_failure_notifications || {}; + this._update(); + } + set value(value) { + this._value = { persistent: false, mobile: false, ...(value || {}) }; + this._update(); + } + get value() { return this._value; } + set label(value) { this._label = value; this._update(); } + set disabled(value) { this._disabled = value; this._update(); } + set required(value) { this._required = value; } + + connectedCallback() { + if (!this._persistentSwitch) { + const style = document.createElement("style"); + style.textContent = ` + :host { display: block; } + .heading { color: var(--primary-text-color); font-size: var(--ha-font-size-m, 14px); margin-bottom: 8px; } + .row { align-items: center; display: flex; min-height: 48px; } + .row-label { color: var(--primary-text-color); flex: 1; } + ha-switch { flex: none; } + ha-selector { display: block; margin: 4px 0 12px; } + [hidden] { display: none !important; } + `; + this._heading = document.createElement("div"); + this._heading.className = "heading"; + const persistentRow = document.createElement("div"); + persistentRow.className = "row"; + const persistentLabel = document.createElement("div"); + persistentLabel.className = "row-label"; + persistentLabel.textContent = "Persistent notification"; + this._persistentSwitch = document.createElement("ha-switch"); + this._persistentSwitch.addEventListener("change", () => { + if (this._disabled) return; + this._value = { ...this._value, persistent: this._persistentSwitch.checked }; + this._emit(); + }); + persistentRow.append(persistentLabel, this._persistentSwitch); + + const mobileRow = document.createElement("div"); + mobileRow.className = "row"; + const mobileLabel = document.createElement("div"); + mobileLabel.className = "row-label"; + mobileLabel.textContent = "Mobile notification"; + this._mobileSwitch = document.createElement("ha-switch"); + this._mobileSwitch.addEventListener("change", () => { + if (this._disabled) return; + this._value = { ...this._value, mobile: this._mobileSwitch.checked }; + this._update(); + this._emit(); + }); + mobileRow.append(mobileLabel, this._mobileSwitch); + + this._picker = document.createElement("ha-selector"); + this._picker.addEventListener("value-changed", (event) => { + event.stopPropagation(); + if (this._disabled) return; + this._value = { ...this._value, mobile_service: event.detail.value }; + this._emit(); + }); + this.shadowRoot.append(style, this._heading, persistentRow, mobileRow, this._picker); + } + this._update(); + } + + _emit() { + this.dispatchEvent(new CustomEvent("value-changed", { + bubbles: true, composed: true, detail: { value: this._value }, + })); + } + + reportValidity() { + return !this._value?.mobile || Boolean(this._value?.mobile_service); + } + + _update() { + if (!this._persistentSwitch) return; + this._heading.textContent = this._label || "Failure notifications"; + this._persistentSwitch.checked = Boolean(this._value?.persistent); + this._mobileSwitch.checked = Boolean(this._value?.mobile); + this._persistentSwitch.disabled = Boolean(this._disabled); + this._mobileSwitch.disabled = Boolean(this._disabled); + this._picker.hidden = !this._value?.mobile; + this._picker.hass = this._hass; + this._picker.selector = { + select: { + mode: "dropdown", + options: this._selector?.mobile_services || [], + }, + }; + this._picker.value = this._value?.mobile_service; + this._picker.label = "Mobile device"; + this._picker.disabled = Boolean(this._disabled); + this._picker.required = Boolean(this._value?.mobile); + } +} + +if (!customElements.get("ha-selector-opentherm_failure_notifications")) { + customElements.define( + "ha-selector-opentherm_failure_notifications", + OpenThermFailureNotificationsSelector + ); +} + +class OpenThermPresetsSelector extends HTMLElement { + constructor() { + super(); + this.attachShadow({ mode: "open" }); + } + + set hass(hass) { + this._hass = hass; + this._render(); + } + + set selector(selector) { + this._selector = selector?.[PRESETS_SELECTOR_KEY] || selector || {}; + } + + set value(value) { + this._value = clonePresets(value); + this._render(); + } + + get value() { + return this._value; + } + + set disabled(disabled) { + this._disabled = disabled; + this._render(); + } + + set label(label) { + this._label = label; + this._updateRenderedState(); + } + + set required(required) { + this._required = required; + } + + connectedCallback() { + this._ensureRendered(); + this._updateRenderedState(); + } + + reportValidity() { + return true; + } + + _openPresets() { + if (this._disabled) { + return; + } + + const dialogParams = { + label: this._label || "Presets", + presets: clonePresets(this._value), + minimum: Number(this._selector?.minimum ?? 35), + maximum: Number(this._selector?.maximum ?? 55), + saveCallback: (presets) => { + this._value = clonePresets(presets); + this.dispatchEvent( + new CustomEvent("value-changed", { + bubbles: true, + composed: true, + detail: { value: clonePresets(this._value) }, + }) + ); + this._updateRenderedState(); + }, + }; + // The options flow is already hosted inside a Home Assistant dialog. Its + // dialog manager does not consistently handle a second `show-dialog` + // event from a custom selector, so mount this editor at document level. + // Reuse the single editor element between openings to avoid duplicates. + let dialog = document.body.querySelector(PRESETS_DIALOG_TYPE); + if (!dialog) { + dialog = document.createElement(PRESETS_DIALOG_TYPE); + document.body.append(dialog); + } + dialog.hass = this._hass; + dialog.showDialog(dialogParams); + } + + _render() { + if (!this.isConnected) { + return; + } + + this._ensureRendered(); + this._updateRenderedState(); + } + + _ensureRendered() { + if (!this.shadowRoot || this._button) { + return; + } + + const style = document.createElement("style"); + style.textContent = ` + :host { display: block; } + ha-button { width: 100%; } + .summary { + color: var(--secondary-text-color); + font-size: var(--ha-font-size-s, 12px); + margin-top: var(--ha-space-1, 4px); + } + `; + + const button = document.createElement("ha-button"); + button.setAttribute("type", "button"); + button.textContent = "Presets"; + button.addEventListener("click", (event) => { + event.preventDefault(); + event.stopPropagation(); + this._openPresets(); + }); + + const summary = document.createElement("div"); + summary.className = "summary"; + + this._button = button; + this._summary = summary; + this.shadowRoot.replaceChildren(style, button, summary); + } + + _updateRenderedState() { + if (!this._button || !this._summary) { + return; + } + this._button.textContent = this._label || "Presets"; + this._button.disabled = Boolean(this._disabled); + const count = this._value?.length || 0; + this._summary.textContent = `${count} of ${MAX_PRESETS} presets configured`; + } +} + +class OpenThermPresetsDialog extends HTMLElement { + constructor() { + super(); + this.attachShadow({ mode: "open" }); + this._editingIndex = undefined; + } + + set hass(hass) { + this._hass = hass; + } + + showDialog(params) { + this._params = params; + this._minimum = Number.isFinite(params.minimum) ? params.minimum : 35; + this._maximum = Number.isFinite(params.maximum) ? params.maximum : 55; + this._presets = clonePresets(params.presets).slice(0, MAX_PRESETS); + this._editingIndex = undefined; + this._ensureDialog(); + this._dialog.open = true; + this._renderContent(); + } + + closeDialog() { + if (this._dialog) { + this._dialog.open = false; + } + return true; + } + + _ensureDialog() { + if (this._dialog) { + return; + } + + const style = document.createElement("style"); + style.textContent = ` + .preset-list { + display: flex; + flex-direction: column; + gap: var(--ha-space-2, 8px); + width: 100%; + } + .preset-section { + display: flex; + flex-direction: column; + gap: var(--ha-space-2, 8px); + } + .preset-rows { + display: flex; + flex-direction: column; + gap: var(--ha-space-2, 8px); + } + .preset-row { + align-items: center; + background: var(--secondary-background-color); + border-radius: var(--ha-border-radius-md, 12px); + display: grid; + gap: var(--ha-space-3, 12px); + grid-template-columns: auto auto minmax(0, 1fr) auto; + padding: var(--ha-space-3, 12px); + } + .drag-handle { + align-items: center; + color: var(--secondary-text-color); + cursor: grab; + display: flex; + justify-content: center; + touch-action: none; + } + .drag-handle:active { cursor: grabbing; } + .preset-row ha-icon { color: var(--primary-color); } + .preset-name { font-weight: var(--ha-font-weight-medium, 500); } + .preset-detail { + color: var(--secondary-text-color); + font-size: var(--ha-font-size-s, 12px); + margin-top: 2px; + } + .empty { + color: var(--secondary-text-color); + padding: var(--ha-space-6, 24px); + text-align: center; + } + .preset-editor-content { + display: grid; + gap: var(--ha-space-2, 8px); + grid-template-columns: minmax(0, 1fr); + width: 100%; + } + .preset-editor-content > * { + box-sizing: border-box; + min-width: 0; + width: 100%; + } + .dialog-footer { + margin-block-end: var(--ha-space-2, 8px); + margin-inline: var(--ha-space-2, 8px); + } + ha-alert { display: block; margin-bottom: var(--ha-space-3, 12px); } + ha-alert[hidden] { display: none; } + `; + + const dialog = document.createElement("ha-dialog"); + dialog.addEventListener("closed", () => { + if (this._editingIndex !== undefined && this._params) { + this._editingIndex = undefined; + this._dialog.open = false; + this._renderContent(); + window.requestAnimationFrame(() => { + if (this._params) { + this._dialog.open = true; + } + }); + return; + } + this._params = undefined; + }); + this._dialog = dialog; + this.shadowRoot.replaceChildren(style, dialog); + } + + _button(label, handler, { primary = false, danger = false } = {}) { + const button = document.createElement("ha-button"); + button.setAttribute("type", "button"); + button.textContent = label; + if (primary) { + button.setAttribute("variant", "brand"); + } + if (danger) { + button.setAttribute("variant", "danger"); + } + button.addEventListener("click", (event) => { + event.preventDefault(); + event.stopPropagation(); + handler(event); + }); + return button; + } + + _movePreset(oldIndex, newIndex) { + if ( + !Number.isInteger(oldIndex) || + !Number.isInteger(newIndex) || + oldIndex === newIndex || + oldIndex < 0 || + newIndex < 0 + ) { + return; + } + const [moved] = this._presets.splice(oldIndex, 1); + if (!moved) { + return; + } + this._presets.splice(newIndex, 0, moved); + this._renderContent(); + } + + _returnToList() { + this._editingIndex = undefined; + this._renderContent(); + } + + _renderContent() { + if (!this._dialog || !this._params) { + return; + } + + if (this._editingIndex === undefined) { + this._renderList(); + } else { + this._renderEditor(); + } + } + + _renderList() { + this._dialog.setAttribute( + "header-title", + this._params.label || "Presets" + ); + const content = document.createElement("div"); + content.className = "preset-list"; + + if (!this._presets.length) { + const empty = document.createElement("div"); + empty.className = "empty"; + empty.textContent = "No presets configured"; + content.append(empty); + } + + let rows; + if (this._presets.length) { + const section = document.createElement("div"); + section.className = "preset-section"; + const sortable = document.createElement("ha-sortable"); + sortable.setAttribute("handle-selector", ".drag-handle"); + sortable.setAttribute("draggable-selector", ".preset-row"); + sortable.setAttribute("group", "opentherm-presets"); + sortable.addEventListener("item-moved", (event) => { + event.stopPropagation(); + const { oldIndex, newIndex } = event.detail || {}; + this._movePreset(Number(oldIndex), Number(newIndex)); + }); + rows = document.createElement("div"); + rows.className = "preset-rows"; + sortable.append(rows); + section.append(sortable); + content.append(section); + } + + this._presets.forEach((preset, index) => { + const row = document.createElement("div"); + row.className = "preset-row"; + + const icon = document.createElement("ha-icon"); + icon.setAttribute("icon", presetIcon(this._presets, index)); + + const handle = document.createElement("div"); + handle.className = "drag-handle"; + handle.setAttribute("title", `Drag to reorder ${preset.name}`); + handle.setAttribute("aria-label", `Drag to reorder ${preset.name}`); + const handleIcon = document.createElement("ha-icon"); + handleIcon.setAttribute("icon", "mdi:drag-horizontal-variant"); + handle.append(handleIcon); + + const text = document.createElement("div"); + const name = document.createElement("div"); + name.className = "preset-name"; + name.textContent = preset.name; + const detail = document.createElement("div"); + detail.className = "preset-detail"; + const duration = Number(preset.duration_minutes) || 0; + const temperature = Number(preset.temperature); + detail.textContent = `${ + Number.isFinite(temperature) ? temperature : preset.temperature + } °C${duration ? ` · ${duration} min` : ""}`; + text.append(name, detail); + + const edit = this._button( + localize(this._hass, "ui.common.edit", "Edit"), + () => { + this._editingIndex = index; + this._draft = { ...preset }; + this._renderContent(); + } + ); + edit.setAttribute("appearance", "plain"); + row.append(handle, icon, text, edit); + rows?.append(row); + }); + + if (this._presets.length < MAX_PRESETS) { + const add = this._button( + localize(this._hass, "ui.common.add", "Add"), + () => { + this._editingIndex = -1; + this._draft = { + name: "", + icon: "mdi:water", + temperature: Math.min(Math.max(45, this._minimum), this._maximum), + duration_minutes: 0, + }; + this._renderContent(); + } + ); + content.append(add); + } + + const cancel = this._button( + localize(this._hass, "ui.common.cancel", "Cancel"), + () => this.closeDialog() + ); + cancel.setAttribute("appearance", "plain"); + const apply = this._button( + localize(this._hass, "ui.common.apply", "Apply"), + () => { + this._params.saveCallback(clonePresets(this._presets)); + this.closeDialog(); + }, + { primary: true } + ); + const footer = document.createElement("div"); + footer.className = "dialog-footer"; + footer.setAttribute("slot", "footer"); + footer.append(cancel, apply); + + this._dialog.replaceChildren(content, footer); + } + + _renderEditor() { + const isNew = this._editingIndex === -1; + this._dialog.setAttribute( + "header-title", + isNew + ? "Add preset" + : String(this._draft?.name || "").trim() || "Preset" + ); + + const content = document.createElement("div"); + content.className = "preset-editor-content"; + const alert = document.createElement("ha-alert"); + alert.setAttribute("alert-type", "error"); + alert.hidden = true; + content.append(alert); + + const form = document.createElement("ha-form"); + form.hass = this._hass; + form.data = { ...this._draft }; + // Keep the native HA form controls, but use a compact grid row gap in + // this small editor instead of the standard 24px form-grid spacing. + form.style.setProperty( + "--ha-space-6", + "var(--ha-space-2, 8px)" + ); + const buildSchema = () => [ + { + name: "", + type: "grid", + column_min_width: "240px", + schema: [ + { name: "name", required: true, selector: { text: {} } }, + { + name: "icon", + required: false, + selector: { icon: {} }, + }, + { + name: "temperature", + required: true, + selector: { + number: { + min: this._minimum, + max: this._maximum, + step: 1, + mode: "box", + unit_of_measurement: "°C", + }, + }, + }, + { + name: "duration_minutes", + required: true, + selector: { + number: { + min: 0, + max: 999, + step: 1, + mode: "box", + unit_of_measurement: "min", + }, + }, + }, + ], + }, + ]; + form.schema = buildSchema(); + const labels = { + name: localize(this._hass, "ui.common.name", "Name"), + icon: localize( + this._hass, + "ui.components.selectors.selector.types.icon", + "Icon" + ), + temperature: localize( + this._hass, + "ui.dialogs.more_info_control.climate.temperature", + "Temperature" + ), + duration_minutes: localize( + this._hass, + "ui.components.selectors.selector.types.duration", + "Duration" + ), + }; + form.computeLabel = (schema) => labels[schema.name] || schema.name; + form.addEventListener("value-changed", (event) => { + this._draft = { ...event.detail.value }; + if (!isNew) { + this._dialog.setAttribute( + "header-title", + String(this._draft.name || "").trim() || "Preset" + ); + } + alert.hidden = true; + }); + + this._forms = [form]; + this._alert = alert; + content.append(form); + + const cancel = this._button( + localize(this._hass, "ui.common.cancel", "Cancel"), + () => this._returnToList() + ); + cancel.setAttribute("appearance", "plain"); + const save = this._button( + localize(this._hass, "ui.common.save", "Save"), + () => this._saveDraft(), + { primary: true } + ); + const footer = document.createElement("div"); + footer.className = "dialog-footer"; + footer.setAttribute("slot", "footer"); + if (!isNew) { + const remove = this._button( + localize(this._hass, "ui.common.delete", "Delete"), + () => { + this._presets.splice(this._editingIndex, 1); + this._editingIndex = undefined; + this._renderContent(); + }, + { danger: true } + ); + remove.style.marginInlineEnd = "auto"; + footer.append(remove); + } + footer.append(cancel, save); + + const headerBack = document.createElement("ha-icon-button"); + headerBack.path = MDI_ARROW_LEFT; + headerBack.label = localize(this._hass, "ui.common.back", "Back"); + headerBack.setAttribute("slot", "headerNavigationIcon"); + headerBack.addEventListener("click", (event) => { + event.preventDefault(); + event.stopPropagation(); + this._returnToList(); + }); + this._dialog.replaceChildren(content, footer, headerBack); + } + + _saveDraft() { + if ( + this._forms?.some( + (form) => form.reportValidity && !form.reportValidity() + ) + ) { + return; + } + + const preset = { + name: String(this._draft.name || "").trim(), + icon: String(this._draft.icon || "").trim(), + temperature: Number(this._draft.temperature), + duration_minutes: Math.max( + 0, + Math.min(999, Number(this._draft.duration_minutes) || 0) + ), + }; + const duplicate = this._presets.some( + (item, index) => + index !== this._editingIndex && + String(item.name).trim().toLocaleLowerCase() === + preset.name.toLocaleLowerCase() + ); + const reserved = ["off", "manual", "auto", "custom"].includes( + preset.name.toLowerCase() + ); + if ( + !preset.name || + !Number.isFinite(preset.temperature) || + preset.temperature < this._minimum || + preset.temperature > this._maximum || + duplicate || reserved + ) { + this._alert.textContent = reserved + ? "Off, Manual, Auto and Custom are reserved names. Choose another preset name." + : duplicate + ? "Preset names must be unique." + : `Enter a name and temperature between ${this._minimum} and ${this._maximum} °C.`; + this._alert.hidden = false; + return; + } + + if (this._editingIndex === -1) { + this._presets.push(preset); + } else { + this._presets[this._editingIndex] = preset; + } + this._presets = clonePresets(this._presets); + this._editingIndex = undefined; + this._renderContent(); + } +} + +if (!customElements.get(PRESETS_SELECTOR_TYPE)) { + customElements.define(PRESETS_SELECTOR_TYPE, OpenThermPresetsSelector); +} + +if (!customElements.get(PRESETS_DIALOG_TYPE)) { + customElements.define(PRESETS_DIALOG_TYPE, OpenThermPresetsDialog); +} + +const PRIMARY_MODES = ["off", "Manual", "Auto"]; +const WATER_HEATER_OPERATION_MODE = 2; + +const BOOST_MODES = [ + "Boost 15 Mins", + "Boost 30 Mins", + "Boost 45 Mins", +]; + +const MODE_ICONS = { + off: "mdi:power", + Manual: "mdi:water-thermometer", + Auto: "mdi:calendar-clock", + "Shower 1": "mdi:shower-head", + "Shower 2": "mdi:shower", + "Boost 15 Mins": "mdi:numeric-1", + "Boost 30 Mins": "mdi:numeric-2", + "Boost 45 Mins": "mdi:numeric-3", +}; + +const supportsWaterHeater = (hass, context) => { + const entityId = context?.entity_id; + const stateObj = entityId ? hass.states[entityId] : undefined; + const supportedFeatures = Number( + stateObj?.attributes?.supported_features || 0 + ); + return Boolean( + entityId?.startsWith("water_heater.") && + stateObj && + ((supportedFeatures & WATER_HEATER_OPERATION_MODE) !== 0 || + Array.isArray(stateObj.attributes.operation_list)) + ); +}; + +const entityOperationModes = (stateObj, presetNames) => { + const operationList = stateObj?.attributes?.operation_list; + if (Array.isArray(operationList) && operationList.length) { + return operationList; + } + return presetNames.length + ? [...new Set(["off", "Manual", ...presetNames])] + : PRIMARY_MODES; +}; + +class OpenThermHotWaterControlModesCardFeature extends HTMLElement { + constructor() { + super(); + this.attachShadow({ mode: "open" }); + this._valueChanged = this._valueChanged.bind(this); + } + + static getStubConfig() { + return { type: `custom:${FEATURE_TYPE}` }; + } + + setConfig(config) { + if (!config) { + throw new Error("Invalid configuration"); + } + this._config = config; + this._render(); + } + + set hass(hass) { + this._hass = hass; + this._render(); + } + + get hass() { + return this._hass; + } + + set context(context) { + this._context = context; + this._render(); + } + + get context() { + return this._context; + } + + connectedCallback() { + this._render(); + } + + get _stateObj() { + const entityId = this._context?.entity_id; + return entityId && this._hass ? this._hass.states[entityId] : undefined; + } + + _availableModes(stateObj) { + const entityModes = entityOperationModes( + stateObj, + this._presetNames(stateObj) + ); + // Keep the main native-style control limited to the three operating + // modes. Presets have their own dropdown feature, including when an older + // tile configuration stored preset names in operation_modes. + return PRIMARY_MODES.filter((mode) => entityModes.includes(mode)); + } + + _presetData(stateObj = this._stateObj) { + const presets = stateObj?.attributes?.[PRESETS_ATTRIBUTE]; + if (!Array.isArray(presets)) { + return []; + } + + return presets + .map((preset) => { + if (!preset || typeof preset !== "object") { + return null; + } + + const name = typeof preset.name === "string" ? preset.name.trim() : ""; + if (!name) { + return null; + } + + return { + name, + icon: + typeof preset.icon === "string" && preset.icon.trim() + ? preset.icon.trim() + : MODE_ICONS[name], + }; + }) + .filter(Boolean); + } + + _presetNames(stateObj = this._stateObj) { + const presets = this._presetData(stateObj); + if (presets.length > 0) { + return presets.map((preset) => preset.name); + } + + return ( + stateObj?.attributes?.preset_modes ?? [] + ); + } + + _option(mode) { + const icon = document.createElement("ha-icon"); + const iconSrc = this._presetData().find((preset) => preset.name === mode)?.icon; + icon.setAttribute("icon", iconSrc || MODE_ICONS[mode] || "mdi:water"); + return { + value: mode, + label: mode, + ariaLabel: mode, + icon, + }; + } + + async _valueChanged(event) { + event.stopPropagation(); + const stateObj = this._stateObj; + const value = event.detail?.item?.value ?? event.detail?.value; + if (!stateObj || !value) { + return; + } + + try { + if (value === "off") { + await this._hass.callService("water_heater", "turn_off", { + entity_id: stateObj.entity_id, + }); + return; + } + + await this._hass.callService("water_heater", "set_operation_mode", { + entity_id: stateObj.entity_id, + operation_mode: value, + }); + } catch (error) { + showTemperatureError(this, error); + this._renderSignature = undefined; + this._render(); + } + } + + _render() { + if (!this.shadowRoot) { + return; + } + + const stateObj = this._stateObj; + if ( + !this._config || + !this._hass || + !stateObj || + !supportsWaterHeater(this._hass, this._context) + ) { + this.shadowRoot.replaceChildren(); + return; + } + + const availableModes = this._availableModes(stateObj); + const selectedValue = + stateObj.state === "Custom" + ? "Manual" + : availableModes.includes(stateObj.state) + ? stateObj.state + : undefined; + const renderSignature = JSON.stringify([ + stateObj.state, + stateObj.state === "unavailable", + availableModes, + this._config.max_width, + ]); + if (this._select && this._renderSignature === renderSignature) { + void this._replaceNativeCurrentlyLabel(); + return; + } + + if (this._select) { + this._select.options = availableModes.map((mode) => this._option(mode)); + this._select.value = selectedValue; + this._select.disabled = stateObj.state === "unavailable"; + this._renderSignature = renderSignature; + void this._replaceNativeCurrentlyLabel(); + return; + } + + const style = document.createElement("style"); + style.textContent = ` + :host { + display: block; + height: var(--feature-height, 42px); + } + ha-control-select { + --control-select-thickness: var(--feature-height, 42px); + --control-select-border-radius: var(--feature-border-radius, 12px); + --control-select-color: var( + --state-water_heater-active-color, + var(--primary-color) + ); + } + `; + + const select = document.createElement("ha-control-select"); + select.options = availableModes.map((mode) => this._option(mode)); + select.value = selectedValue; + select.label = localize( + this._hass, + "ui.card.water_heater.mode", + "Mode" + ); + select.hideOptionLabel = true; + select.disabled = stateObj.state === "unavailable"; + const configuredMaxWidth = Number(this._config.max_width); + select.style.maxWidth = `${ + Number.isFinite(configuredMaxWidth) && configuredMaxWidth > 0 + ? configuredMaxWidth + : DEFAULT_MAX_WIDTH + }px`; + select.style.marginInline = "auto"; + select.addEventListener("value-changed", this._valueChanged); + + this._select = select; + this._renderSignature = renderSignature; + this.shadowRoot.replaceChildren(style, select); + void this._replaceNativeCurrentlyLabel(); + } + + async _replaceNativeCurrentlyLabel() { + let parent = this; + let thermostatCard; + while (parent) { + const root = parent.getRootNode(); + parent = root?.host; + if (parent?.localName === "hui-thermostat-card") { + thermostatCard = parent; + break; + } + } + + const control = thermostatCard?.shadowRoot?.querySelector( + NATIVE_TEMPERATURE_CONTROL + ); + if (!control?.shadowRoot) { + return; + } + + if (control.updateComplete) { + await control.updateComplete; + } + + const labels = control.shadowRoot.querySelectorAll(".info > p.label"); + const currentLabel = labels[labels.length - 1]; + const value = currentLabel?.querySelector("span"); + if (!currentLabel || !value) { + return; + } + + const icon = document.createElement("ha-icon"); + icon.setAttribute("icon", "mdi:thermometer"); + icon.setAttribute( + "aria-label", + this._hass.formatEntityAttributeName?.( + this._stateObj, + "current_temperature" + ) || "Current temperature" + ); + icon.style.setProperty("--mdc-icon-size", "18px"); + currentLabel.style.display = "flex"; + currentLabel.style.alignItems = "center"; + currentLabel.style.justifyContent = "center"; + currentLabel.style.gap = "4px"; + currentLabel.replaceChildren(icon, value); + } +} + +class OpenThermHotWaterControlPresetsCardFeature extends HTMLElement { + constructor() { + super(); + this.attachShadow({ mode: "open" }); + this._valueChanged = this._valueChanged.bind(this); + } + + static getStubConfig() { + return { type: `custom:${PRESETS_FEATURE_TYPE}` }; + } + + setConfig(config) { + if (!config) { + throw new Error("Invalid configuration"); + } + this._config = config; + this._render(); + } + + set hass(hass) { + this._hass = hass; + this._render(); + } + + get hass() { + return this._hass; + } + + set context(context) { + this._context = context; + this._render(); + } + + get context() { + return this._context; + } + + connectedCallback() { + this._render(); + } + + get _stateObj() { + const entityId = this._context?.entity_id; + return entityId && this._hass ? this._hass.states[entityId] : undefined; + } + + _availableModes(stateObj) { + const presetData = this._presetData(stateObj); + const presetNames = this._presetNames(stateObj); + const entityModes = entityOperationModes(stateObj, presetNames); + const configuredModes = this._config.preset_modes + ? [...new Set([...this._config.preset_modes, ...presetNames])] + : presetNames; + + return configuredModes.filter((mode) => { + const inEntity = entityModes.includes(mode); + if (!inEntity) { + return false; + } + + if (!presetData.length) { + return BOOST_MODES.includes(mode); + } + + return presetData.some((preset) => preset.name === mode); + }); + } + + _presetData(stateObj = this._stateObj) { + const presets = stateObj?.attributes?.[PRESETS_ATTRIBUTE]; + if (!Array.isArray(presets)) { + return []; + } + + return presets + .map((preset) => { + if (!preset || typeof preset !== "object") { + return null; + } + + const name = typeof preset.name === "string" ? preset.name.trim() : ""; + if (!name) { + return null; + } + + return { + name, + icon: + typeof preset.icon === "string" && preset.icon.trim() + ? preset.icon.trim() + : MODE_ICONS[name], + durationMinutes: Number(preset.duration_minutes) || 0, + }; + }) + .filter(Boolean); + } + + _presetNames(stateObj = this._stateObj) { + const presets = this._presetData(stateObj); + if (presets.length > 0) { + return presets.map((preset) => preset.name); + } + + return stateObj?.attributes?.preset_modes ?? []; + } + + _presetIcon(mode, stateObj = this._stateObj) { + return ( + this._presetData(stateObj).find((preset) => preset.name === mode)?.icon || + MODE_ICONS[mode] + ); + } + + async _valueChanged(event) { + event.stopPropagation(); + const stateObj = this._stateObj; + const value = event.detail?.item?.value ?? event.detail?.value; + if (!stateObj || !value) { + return; + } + + try { + await this._hass.callService("water_heater", "set_operation_mode", { + entity_id: stateObj.entity_id, + operation_mode: value, + }); + } catch (error) { + showTemperatureError(this, error); + this._renderSignature = undefined; + this._render(); + } + } + + _render() { + if (!this.shadowRoot) { + return; + } + + const stateObj = this._stateObj; + if ( + !this._config || + !this._hass || + !stateObj || + !supportsWaterHeater(this._hass, this._context) + ) { + this.shadowRoot.replaceChildren(); + return; + } + + const availableModes = this._availableModes(stateObj); + this.style.display = availableModes.length ? "" : "none"; + const renderSignature = JSON.stringify([ + stateObj.state === "unavailable", + availableModes, + this._presetData(stateObj), + ]); + if (this._select && this._renderSignature === renderSignature) { + this._select.value = availableModes.includes(stateObj.state) + ? stateObj.state + : undefined; + this._select.disabled = stateObj.state === "unavailable"; + return; + } + + const style = document.createElement("style"); + style.textContent = ` + :host { + display: block; + height: auto; + } + .controls { + display: flex; + flex-direction: column; + gap: var(--feature-button-spacing, 12px); + } + ha-control-select-menu { + box-sizing: border-box; + --control-select-menu-height: var(--feature-height, 42px); + --control-select-menu-border-radius: var(--feature-border-radius, 12px); + --control-select-menu-focus-color: var(--feature-color); + display: block; + line-height: var(--ha-line-height-condensed); + width: 100%; + } + `; + + const controls = document.createElement("div"); + controls.className = "controls"; + const select = document.createElement("ha-control-select-menu"); + select.options = availableModes.map((mode) => ({ + value: mode, + label: mode, + icon: this._presetIcon(mode, stateObj), + })); + select.value = availableModes.includes(stateObj.state) + ? stateObj.state + : undefined; + select.label = localize(this._hass, "ui.card.climate.preset", "Preset"); + select.showArrow = true; + select.hideLabel = true; + const icon = document.createElement("ha-icon"); + icon.setAttribute("slot", "icon"); + icon.setAttribute("icon", "mdi:tune-variant"); + select.append(icon); + select.disabled = stateObj.state === "unavailable"; + select.addEventListener("wa-select", this._valueChanged); + controls.append(select); + + this._select = select; + this.style.gridRow = ""; + this._renderSignature = renderSignature; + this.shadowRoot.replaceChildren(style, controls); + } +} + +class OpenThermHotWaterControlMoreInfo extends HTMLElement { + constructor() { + super(); + this.attachShadow({ mode: "open" }); + } + set hass(hass) { + this._hass = hass; + this._render(); + } + + get hass() { + return this._hass; + } + + set stateObj(stateObj) { + this._stateObj = stateObj; + this._render(); + } + + get stateObj() { + return this._stateObj; + } + + _presetNames() { + const presets = this._stateObj?.attributes?.[PRESETS_ATTRIBUTE]; + if (Array.isArray(presets) && presets.length > 0) { + return presets + .map((preset) => + typeof preset?.name === "string" ? preset.name.trim() : "" + ) + .filter(Boolean); + } + + return this._stateObj?.attributes?.preset_modes ?? []; + } + + _listPresetNames() { + return this._presetNames(); + } + + connectedCallback() { + this._render(); + } + + async _ensureNativeTemperatureControl() { + if (customElements.get(NATIVE_TEMPERATURE_CONTROL)) { + return; + } + + if (!this._nativeControlPromise) { + this._nativeControlPromise = (async () => { + if (window.loadCardHelpers && this._stateObj) { + const helpers = await window.loadCardHelpers(); + const loader = helpers.createCardElement({ + type: "thermostat", + entity: this._stateObj.entity_id, + }); + loader.hass = this._hass; + } + await customElements.whenDefined(NATIVE_TEMPERATURE_CONTROL); + })(); + } + + await this._nativeControlPromise; + this._render(); + } + + _formatCurrentTemperature(stateObj) { + if (this._hass.formatEntityAttributeValue) { + return this._hass.formatEntityAttributeValue( + stateObj, + "current_temperature" + ); + } + return `${stateObj.attributes.current_temperature} ${ + stateObj.attributes.temperature_unit || "°C" + }`; + } + + _formatCurrentTemperatureLabel(stateObj) { + if (this._hass.formatEntityAttributeName) { + return this._hass.formatEntityAttributeName( + stateObj, + "current_temperature" + ); + } + return "Current temperature"; + } + + _render() { + if (!this.shadowRoot || !this._hass || !this._stateObj) { + return; + } + + if (!customElements.get(NATIVE_TEMPERATURE_CONTROL)) { + const loading = document.createElement("ha-circular-progress"); + loading.setAttribute("active", ""); + this.shadowRoot.replaceChildren(loading); + void this._ensureNativeTemperatureControl(); + return; + } + + const currentTemperature = this._stateObj.attributes.current_temperature; + if (this._temperatureControl) { + this._temperatureControl.stateObj = this._stateObj; + this._current.hidden = currentTemperature == null; + if (currentTemperature != null) { + this._currentLabel.textContent = + this._formatCurrentTemperatureLabel(this._stateObj); + this._currentValue.textContent = this._formatCurrentTemperature( + this._stateObj + ); + } + this._modes.hass = this._hass; + this._modes.context = { entity_id: this._stateObj.entity_id }; + if (this._presets) { + this._presets.hass = this._hass; + this._presets.context = { entity_id: this._stateObj.entity_id }; + } + return; + } + + const style = document.createElement("style"); + style.textContent = ` + :host { + display: block; + color: var(--primary-text-color); + } + .current { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + margin-bottom: var(--ha-space-4, 16px); + text-align: center; + } + .current .label { + color: var(--secondary-text-color); + font-size: var(--ha-font-size-m, 14px); + line-height: var(--ha-line-height-condensed, 1.2); + } + .current .value { + margin-top: var(--ha-space-1, 4px); + font-size: var(--ha-font-size-xl, 24px); + font-weight: var(--ha-font-weight-medium, 500); + line-height: var(--ha-line-height-condensed, 1.2); + } + .temperature { + display: flex; + justify-content: center; + overflow: hidden; + width: 100%; + } + ha-state-control-water_heater-temperature { + box-sizing: border-box; + width: min(100%, 320px); + padding: 8px; + } + .features { + align-items: center; + box-sizing: border-box; + display: flex; + flex-direction: column; + gap: var(--feature-button-spacing, 12px); + justify-content: center; + margin-top: var(--ha-space-4, 16px); + margin-inline: auto; + max-width: 520px; + padding-inline: var(--ha-space-4, 16px); + width: 100%; + } + .modes { + width: 100%; + } + .presets { + width: 100%; + } + ha-circular-progress { + display: block; + margin: 40px auto; + } + `; + + const content = document.createElement("div"); + + const current = document.createElement("div"); + current.className = "current"; + current.hidden = currentTemperature == null; + + const label = document.createElement("div"); + label.className = "label"; + const value = document.createElement("div"); + value.className = "value"; + if (currentTemperature != null) { + label.textContent = this._formatCurrentTemperatureLabel(this._stateObj); + value.textContent = this._formatCurrentTemperature(this._stateObj); + } + current.append(label, value); + content.append(current); + + const temperature = document.createElement("div"); + temperature.className = "temperature"; + const temperatureControl = document.createElement( + NATIVE_TEMPERATURE_CONTROL + ); + temperatureControl.stateObj = this._stateObj; + temperatureControl.preventInteractionOnScroll = true; + temperature.append(temperatureControl); + content.append(temperature); + + const features = document.createElement("div"); + features.className = "features"; + + const modesContainer = document.createElement("div"); + modesContainer.className = "modes"; + const modes = document.createElement(FEATURE_TYPE); + modes.setConfig({ + type: `custom:${FEATURE_TYPE}`, + max_width: 320, + }); + modes.hass = this._hass; + modes.context = { entity_id: this._stateObj.entity_id }; + modesContainer.append(modes); + + const presetsContainer = document.createElement("div"); + presetsContainer.className = "presets"; + const presets = document.createElement(PRESETS_FEATURE_TYPE); + const presetModes = this._listPresetNames(); + presets.setConfig({ + type: `custom:${PRESETS_FEATURE_TYPE}`, + }); + if (presetModes.length > 0) { + presets.hass = this._hass; + presets.context = { entity_id: this._stateObj.entity_id }; + presetsContainer.append(presets); + features.append(modesContainer, presetsContainer); + this._presets = presets; + } else { + features.append(modesContainer); + this._presets = undefined; + } + + content.append(features); + + this._temperatureControl = temperatureControl; + this._current = current; + this._currentLabel = label; + this._currentValue = value; + this._modes = modes; + if (presetModes.length === 0) { + this._presets = undefined; + } + this.shadowRoot.replaceChildren(style, content); + } +} + +if (!customElements.get(FEATURE_TYPE)) { + customElements.define(FEATURE_TYPE, OpenThermHotWaterControlModesCardFeature); +} + +if (!customElements.get(PRESETS_FEATURE_TYPE)) { + customElements.define( + PRESETS_FEATURE_TYPE, + OpenThermHotWaterControlPresetsCardFeature + ); +} + +if (!customElements.get(MORE_INFO_TYPE)) { + customElements.define(MORE_INFO_TYPE, OpenThermHotWaterControlMoreInfo); +} + +window.customCardFeatures = window.customCardFeatures || []; +if (!window.customCardFeatures.some((feature) => feature.type === FEATURE_TYPE)) { + window.customCardFeatures.push({ + type: FEATURE_TYPE, + name: "Hot-water control modes", + isSupported: supportsWaterHeater, + }); +} + +if ( + !window.customCardFeatures.some( + (feature) => feature.type === PRESETS_FEATURE_TYPE + ) +) { + window.customCardFeatures.push({ + type: PRESETS_FEATURE_TYPE, + name: "Hot-water control presets", + isSupported: supportsWaterHeater, + }); +} + +const OPENTHERM_FEATURE_TYPES = new Set([ + `custom:${FEATURE_TYPE}`, + `custom:${PRESETS_FEATURE_TYPE}`, +]); + +// Home Assistant normally rebuilds a custom feature after its element is +// defined. If that notification loses the cold-load race, the feature host can +// retain its temporary error element. Ask the owning view to recreate its +// cards once now that all OpenTherm feature elements are registered. +const rebuiltOpenThermFeatureTargets = new WeakSet(); + +const rebuildFailedOpenThermFeature = (rebuildTarget) => { + if ( + !OPENTHERM_FEATURE_TYPES.has(rebuildTarget?.feature?.type) || + !rebuildTarget.shadowRoot?.querySelector("hui-error-card") + ) { + return; + } + + let owner = rebuildTarget; + while (owner && owner.localName !== "hui-view") { + owner = owner.parentNode || owner.getRootNode?.().host; + } + if (!owner || rebuiltOpenThermFeatureTargets.has(owner)) { + return; + } + + rebuiltOpenThermFeatureTargets.add(owner); + rebuildTarget.dispatchEvent( + new CustomEvent("ll-rebuild", { bubbles: true, composed: true }) + ); +}; + +const INLINE_FEATURE_BACKPORT_ATTRIBUTE = + "data-opentherm-inline-feature-backport"; +const INLINE_LAYOUT_BACKPORT_ATTRIBUTE = + "data-opentherm-inline-layout-backport"; + +const removeOpenThermInlineLayout = (tile) => { + tile?.shadowRoot + ?.querySelector(`style[${INLINE_LAYOUT_BACKPORT_ATTRIBUTE}]`) + ?.remove(); + // Clean up the layout style used by versions 2.5.8 and 2.5.9. + tile?.shadowRoot + ?.querySelector("ha-tile-container") + ?.shadowRoot + ?.querySelector(`style[${INLINE_LAYOUT_BACKPORT_ATTRIBUTE}]`) + ?.remove(); +}; + +const installOpenThermInlineLayout = (tile) => { + const root = tile?.shadowRoot; + if ( + !root || + root.querySelector(`style[${INLINE_LAYOUT_BACKPORT_ATTRIBUTE}]`) + ) { + return; + } + + const style = document.createElement("style"); + style.setAttribute(INLINE_LAYOUT_BACKPORT_ATTRIBUTE, ""); + style.textContent = ` + ha-card { + display: flex !important; + flex-direction: column !important; + } + ha-card > ha-tile-container { + flex: 1 0 auto; + height: auto !important; + } + ha-card > hui-card-features[${INLINE_FEATURE_BACKPORT_ATTRIBUTE}] { + --feature-color: var(--tile-color); + box-sizing: border-box; + flex: none; + padding: 0 var(--ha-space-3, 12px) var(--ha-space-3, 12px); + width: 100%; + } + `; + root.append(style); +}; + +const needsOpenThermInlineFeatureBackport = (tile) => { + const config = tile?._config; + if ( + !config || + config.vertical || + config.features_position !== "inline" || + !Array.isArray(config.features) || + config.features.length < 2 + ) { + return false; + } + + return config.features + .slice(1) + .some((feature) => OPENTHERM_FEATURE_TYPES.has(feature.type)); +}; + +const restoreOpenThermInlineFeatures = (tile) => { + if (!tile?.shadowRoot) { + return; + } + + const injectedSelector = `hui-card-features[${INLINE_FEATURE_BACKPORT_ATTRIBUTE}]`; + const injected = tile.shadowRoot.querySelector(injectedSelector); + if (!needsOpenThermInlineFeatureBackport(tile)) { + injected?.remove(); + removeOpenThermInlineLayout(tile); + return; + } + + const container = tile.shadowRoot.querySelector("ha-tile-container"); + const card = tile.shadowRoot.querySelector("ha-card"); + if (!container || !card) { + return; + } + + // Newer Home Assistant versions render the remaining inline features + // themselves. Never duplicate or replace that native feature container. + const nativeBottomFeatures = container.querySelector( + `hui-card-features[slot="features"]:not([${INLINE_FEATURE_BACKPORT_ATTRIBUTE}])` + ); + const remainingFeatures = tile._config.features.slice(1); + const nativeFeatures = nativeBottomFeatures?.features; + const nativeHasRemainingFeatures = + Array.isArray(nativeFeatures) && + nativeFeatures.length === remainingFeatures.length && + nativeFeatures.every( + (feature, index) => feature.type === remainingFeatures[index].type + ); + if (nativeHasRemainingFeatures) { + injected?.remove(); + removeOpenThermInlineLayout(tile); + return; + } + + installOpenThermInlineLayout(tile); + + const bottomFeatures = + injected || document.createElement("hui-card-features"); + bottomFeatures.setAttribute(INLINE_FEATURE_BACKPORT_ATTRIBUTE, ""); + bottomFeatures.removeAttribute("slot"); + // Keep the mode buttons and preset selector as separate full-width rows. + bottomFeatures.columns = 1; + bottomFeatures.hass = tile.hass; + bottomFeatures.context = + tile._featureContext || { entity_id: tile._config.entity }; + bottomFeatures.color = tile._config.color; + bottomFeatures.features = remainingFeatures; + + if (bottomFeatures.parentElement !== card) { + card.append(bottomFeatures); + } +}; + +const installOpenThermInlineFeatureBackport = async () => { + await customElements.whenDefined("hui-tile-card"); + const TileCard = customElements.get("hui-tile-card"); + const prototype = TileCard?.prototype; + if (!prototype || prototype._openThermInlineFeatureBackport) { + return; + } + + prototype._openThermInlineFeatureBackport = true; + + const originalUpdated = prototype.updated; + prototype.updated = function (...args) { + const result = originalUpdated?.apply(this, args); + queueMicrotask(() => restoreOpenThermInlineFeatures(this)); + return result; + }; + + // Older Tile cards report no bottom feature rows while Inline is selected. + // Account for the restored rows so masonry and Sections layouts allocate the + // same height as the visible controls. Native mixed-layout versions expose + // _featureLayout and already include these rows in their own calculations. + const originalGetCardSize = prototype.getCardSize; + if (originalGetCardSize) { + prototype.getCardSize = function (...args) { + let size = originalGetCardSize.apply(this, args); + if ( + typeof this._featureLayout !== "function" && + needsOpenThermInlineFeatureBackport(this) + ) { + size += this._config.features.slice(1).length; + } + return size; + }; + } + + const originalGetGridOptions = prototype.getGridOptions; + if (originalGetGridOptions) { + prototype.getGridOptions = function (...args) { + const nativeOptions = originalGetGridOptions.apply(this, args); + if ( + typeof this._featureLayout === "function" || + !needsOpenThermInlineFeatureBackport(this) + ) { + return nativeOptions; + } + + const addedRows = this._config.features.slice(1).length; + return { + ...nativeOptions, + rows: + typeof nativeOptions.rows === "number" + ? nativeOptions.rows + addedRows + : nativeOptions.rows, + min_rows: + typeof nativeOptions.min_rows === "number" + ? nativeOptions.min_rows + addedRows + : nativeOptions.min_rows, + }; + }; + } + + refreshOpenThermFeatureLayout(); +}; + +const observedOpenThermFeatureRoots = new WeakSet(); +let openThermFeatureObserver; +let openThermFeatureObservationEnded = false; +let openThermFeatureObservationStopScheduled = false; + +const observeOpenThermFeatureRoot = (root) => { + if ( + !root || + openThermFeatureObservationEnded || + observedOpenThermFeatureRoots.has(root) || + (!(root instanceof Document) && !(root instanceof ShadowRoot)) + ) { + return; + } + + if (!openThermFeatureObserver) { + openThermFeatureObserver = new MutationObserver((mutations) => { + for (const mutation of mutations) { + for (const node of mutation.addedNodes) { + if (node.nodeType === Node.ELEMENT_NODE) { + refreshOpenThermFeatureLayout(node); + } + } + } + }); + } + observedOpenThermFeatureRoots.add(root); + openThermFeatureObserver.observe(root, { childList: true, subtree: true }); + if (!openThermFeatureObservationStopScheduled) { + openThermFeatureObservationStopScheduled = true; + window.setTimeout(() => { + openThermFeatureObservationEnded = true; + openThermFeatureObserver?.disconnect(); + }, 60000); + } +}; + +const refreshOpenThermFeatureLayout = (root = document) => { + observeOpenThermFeatureRoot(root); + const elements = [ + ...(root.nodeType === Node.ELEMENT_NODE ? [root] : []), + ...(root.querySelectorAll?.("*") || []), + ]; + for (const element of elements) { + if (element.localName === "hui-tile-card") { + restoreOpenThermInlineFeatures(element); + } + + if (element.localName === "hui-card-feature") { + rebuildFailedOpenThermFeature(element); + } + + if (element.shadowRoot) { + observeOpenThermFeatureRoot(element.shadowRoot); + refreshOpenThermFeatureLayout(element.shadowRoot); + } + } +}; + + +void installOpenThermInlineFeatureBackport(); diff --git a/custom_components/wiser/local_schedule.py b/custom_components/wiser/local_schedule.py new file mode 100644 index 00000000..92cbdba0 --- /dev/null +++ b/custom_components/wiser/local_schedule.py @@ -0,0 +1,343 @@ +"""Home Assistant-managed schedules for Wiser features not scheduled by the hub.""" + +from __future__ import annotations + +from copy import deepcopy +from datetime import timedelta +from time import strptime + +from homeassistant.helpers.storage import Store +from homeassistant.util import dt as dt_util + +from .const import DOMAIN + +LOCAL_HOT_WATER_SCHEDULE_ID = -1000 +LOCAL_HOT_WATER_SCHEDULE_NAME = "OpenTherm Hot Water" +LOCAL_HOT_WATER_SCHEDULE_TYPE = "HotWater" +LOCAL_SCHEDULE_STORAGE_VERSION = 1 +WEEKDAYS = ( + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + "Sunday", +) + + +def _schedule_preset_options(presets, minimum, maximum): + """Return schedule-safe presets, excluding temporary boosts.""" + options = [] + seen_names = set() + for preset in presets or []: + if not isinstance(preset, dict) or preset.get("duration_minutes", 0): + continue + name = str(preset.get("name", "")).strip() + try: + temperature = float(preset.get("temperature")) + except (TypeError, ValueError): + continue + folded_name = name.casefold() + if ( + not name + or folded_name in seen_names + or not minimum <= temperature <= maximum + ): + continue + seen_names.add(folded_name) + options.append( + { + "name": name, + "icon": str(preset.get("icon") or "mdi:water"), + "temperature": temperature, + } + ) + return options + + +def _default_schedule( + minimum, maximum=55.0, default_temperature=45.0, presets=None +): + """Return a useful split-day schedule with the minimum between periods.""" + scheduled_temperature = min( + maximum, + max(minimum, default_temperature), + ) + return { + "Id": LOCAL_HOT_WATER_SCHEDULE_ID, + "Name": LOCAL_HOT_WATER_SCHEDULE_NAME, + "Type": LOCAL_HOT_WATER_SCHEDULE_TYPE, + "SubType": LOCAL_HOT_WATER_SCHEDULE_TYPE, + "MinSetpoint": minimum, + "MaxSetpoint": maximum, + "PresetOptions": _schedule_preset_options( + presets, minimum, maximum + ), + "Assignments": [ + { + "id": LOCAL_HOT_WATER_SCHEDULE_ID, + "name": LOCAL_HOT_WATER_SCHEDULE_NAME, + } + ], + "ScheduleData": [ + { + "day": day, + "slots": [ + { + "Time": "00:00", + "Setpoint": f"{minimum:g}", + }, + { + "Time": "06:00", + "Setpoint": f"{scheduled_temperature:g}", + }, + { + "Time": "09:00", + "Setpoint": f"{minimum:g}", + }, + { + "Time": "17:00", + "Setpoint": f"{scheduled_temperature:g}", + }, + { + "Time": "22:00", + "Setpoint": f"{minimum:g}", + }, + ], + } + for day in WEEKDAYS + ], + } + + +def _validated_schedule( + schedule, + minimum, + maximum, + presets=None, + *, + replace_unknown_presets=False, +): + """Return a normalized schedule or raise ValueError.""" + if not isinstance(schedule, dict): + raise ValueError("Schedule must be an object") + days = schedule.get("ScheduleData") + if not isinstance(days, list): + raise ValueError("ScheduleData must be a list") + + preset_options = _schedule_preset_options(presets, minimum, maximum) + preset_names = { + option["name"].casefold(): option["name"] + for option in preset_options + } + normalized_days = [] + seen_days = set() + for day_data in days: + if not isinstance(day_data, dict) or day_data.get("day") not in WEEKDAYS: + raise ValueError("Schedule contains an invalid day") + day = day_data["day"] + if day in seen_days: + raise ValueError(f"Schedule contains duplicate {day} data") + seen_days.add(day) + slots = day_data.get("slots") + if not isinstance(slots, list): + raise ValueError(f"Schedule slots for {day} must be a list") + normalized_slots = [] + seen_times = set() + for slot in slots: + if not isinstance(slot, dict): + raise ValueError(f"Schedule slot for {day} must be an object") + value = str(slot.get("Time", "")) + try: + parsed_time = strptime(value, "%H:%M") + except ValueError as err: + raise ValueError(f"Invalid schedule time {value!r}") from err + raw_setpoint = slot.get("Setpoint") + raw_text = str(raw_setpoint).strip() + preset_name = preset_names.get(raw_text.casefold()) + if preset_name is not None: + normalized_setpoint = preset_name + else: + try: + setpoint = ( + minimum if raw_text.casefold() == "off" else float(raw_text) + ) + except ValueError as err: + if replace_unknown_presets: + setpoint = minimum + else: + raise ValueError( + f"Unknown hot-water preset {raw_text!r}" + ) from err + if not minimum <= setpoint <= maximum: + raise ValueError( + f"Schedule temperature must be between {minimum:g} and " + f"{maximum:g} °C" + ) + normalized_setpoint = f"{setpoint:g}" + canonical_time = f"{parsed_time.tm_hour:02}:{parsed_time.tm_min:02}" + if canonical_time in seen_times: + raise ValueError(f"Schedule contains duplicate {day} time") + seen_times.add(canonical_time) + normalized_slots.append( + { + "Time": canonical_time, + "Setpoint": normalized_setpoint, + } + ) + normalized_days.append( + { + "day": day, + "slots": sorted(normalized_slots, key=lambda slot: slot["Time"]), + } + ) + + if not any(day["slots"] for day in normalized_days): + raise ValueError("Schedule must contain at least one time slot") + normalized_by_day = {day["day"]: day for day in normalized_days} + name = str(schedule.get("Name") or LOCAL_HOT_WATER_SCHEDULE_NAME) + return { + "Id": LOCAL_HOT_WATER_SCHEDULE_ID, + "Name": name, + "Type": LOCAL_HOT_WATER_SCHEDULE_TYPE, + "SubType": LOCAL_HOT_WATER_SCHEDULE_TYPE, + "MinSetpoint": minimum, + "MaxSetpoint": maximum, + "PresetOptions": preset_options, + "Assignments": [ + { + "id": LOCAL_HOT_WATER_SCHEDULE_ID, + "name": name, + } + ], + "ScheduleData": [ + normalized_by_day.get(day, {"day": day, "slots": []}) + for day in WEEKDAYS + ], + } + + +def _schedule_position(schedule, now): + """Return current setpoint and next transition for a local datetime.""" + preset_temperatures = { + option["name"].casefold(): float(option["temperature"]) + for option in schedule.get("PresetOptions", []) + } + transitions = [] + days = {day["day"]: day["slots"] for day in schedule["ScheduleData"]} + for day_index, day in enumerate(WEEKDAYS): + for slot in days.get(day, []): + hour, minute = (int(part) for part in slot["Time"].split(":")) + raw_setpoint = str(slot["Setpoint"]).strip() + temperature = preset_temperatures.get(raw_setpoint.casefold()) + if temperature is None: + temperature = float(raw_setpoint) + transitions.append( + (day_index * 1440 + hour * 60 + minute, temperature) + ) + transitions.sort() + if not transitions: + return None, None + + current_minute = now.weekday() * 1440 + now.hour * 60 + now.minute + previous = [ + transition for transition in transitions if transition[0] <= current_minute + ] + current = previous[-1] if previous else transitions[-1] + future = [ + transition + for transition in transitions + if transition[0] > current_minute + ] + next_transition = future[0] if future else transitions[0] + days_ahead = (next_transition[0] - current_minute) % (7 * 1440) + if days_ahead == 0: + days_ahead = 7 * 1440 + next_datetime = (now + timedelta(minutes=days_ahead)).replace( + second=0, microsecond=0 + ) + return current[1], next_datetime + + +class OpenThermHotWaterSchedule: + """Persist and evaluate the integration-owned OpenTherm DHW schedule.""" + + def __init__( + self, + hass, + entry_id, + minimum=35.0, + maximum=55.0, + default_temperature=45.0, + presets=None, + ): + self._hass = hass + self._store = Store( + hass, + LOCAL_SCHEDULE_STORAGE_VERSION, + f"{DOMAIN}.{entry_id}.opentherm_hot_water_schedule", + ) + self._default = _default_schedule( + minimum, + maximum, + default_temperature, + presets, + ) + self._minimum = minimum + self._maximum = maximum + self._presets = presets or [] + self._schedule = deepcopy(self._default) + self._listeners = set() + + async def async_load(self): + """Load and validate saved data, retaining a safe default if corrupt.""" + saved = await self._store.async_load() + if saved is None: + return + try: + self._schedule = _validated_schedule( + saved, + self._minimum, + self._maximum, + self._presets, + replace_unknown_presets=True, + ) + except (TypeError, ValueError): + self._schedule = deepcopy(self._default) + + @property + def ws_schedule_data(self): + """Return data in the existing Wiser schedule-card format.""" + return deepcopy(self._schedule) + + @property + def name(self): + return self._schedule["Name"] + + def current(self, now=None): + """Return current setpoint and next transition.""" + return _schedule_position(self._schedule, now or dt_util.now()) + + def async_add_listener(self, listener): + """Subscribe an entity to saved schedule changes.""" + self._listeners.add(listener) + return lambda: self._listeners.discard(listener) + + async def async_save(self, schedule): + """Validate, persist and publish schedule changes.""" + self._schedule = _validated_schedule( + schedule, + self._minimum, + self._maximum, + self._presets, + ) + await self._store.async_save(self._schedule) + for listener in tuple(self._listeners): + listener() + + async def async_set_name(self, name): + """Rename the local schedule.""" + schedule = self.ws_schedule_data + schedule["Name"] = name + await self.async_save(schedule) diff --git a/custom_components/wiser/opentherm_detection.py b/custom_components/wiser/opentherm_detection.py index 560cd293..4158dee8 100644 --- a/custom_components/wiser/opentherm_detection.py +++ b/custom_components/wiser/opentherm_detection.py @@ -1,6 +1,12 @@ """Track whether a Wiser hub has a confirmed OpenTherm connection.""" -from .const import CONF_OPENTHERM_EVER_CONNECTED +from math import isfinite + +from .const import ( + CONF_OPENTHERM_EVER_CONNECTED, + CONF_OPENTHERM_HOT_WATER_CAPABLE, + CONF_OPENTHERM_HOT_WATER_CONTROL, +) from .helpers import get_unique_id from .opentherm import ( OPENTHERM_BINARY_SENSOR_KEYS, @@ -24,6 +30,41 @@ def opentherm_is_detected(config_entry, opentherm) -> bool: ) +def opentherm_hot_water_control_is_supported(config_entry, opentherm) -> bool: + """Return whether this entry has confirmed writable DHW support. + + An already-enabled option also counts as prior confirmation. This preserves + the entity across an upgrade or restart where the first OpenTherm response + is incomplete, before the new sticky capability flag has been stored. + """ + boiler_parameters = getattr(opentherm, "boiler_parameters", None) + return bool( + opentherm + and ( + getattr(boiler_parameters, "hw_setpoint_read_write", None) is True + or config_entry.data.get(CONF_OPENTHERM_HOT_WATER_CAPABLE, False) + or config_entry.options.get(CONF_OPENTHERM_HOT_WATER_CONTROL, False) + ) + ) + + +def opentherm_hot_water_limits(opentherm) -> tuple[float, float]: + """Return a valid boiler DHW setpoint range with safe fallbacks.""" + boiler_parameters = getattr(opentherm, "boiler_parameters", None) + try: + minimum = float( + getattr(boiler_parameters, "hw_setpoint_lower_bound", None) + ) + maximum = float( + getattr(boiler_parameters, "hw_setpoint_upper_bound", None) + ) + except (TypeError, ValueError): + return 35.0, 55.0 + if not isfinite(minimum) or not isfinite(maximum) or minimum > maximum: + return 35.0, 55.0 + return minimum, maximum + + def opentherm_entity_unique_ids(data): """Return the entity-registry IDs reserved for OpenTherm entities.""" sensor_types = { diff --git a/custom_components/wiser/opentherm_hot_water.py b/custom_components/wiser/opentherm_hot_water.py new file mode 100644 index 00000000..06d133d3 --- /dev/null +++ b/custom_components/wiser/opentherm_hot_water.py @@ -0,0 +1,674 @@ +"""OpenTherm domestic-hot-water control for Wiser.""" + +from __future__ import annotations + +import asyncio +from datetime import timedelta +import logging +from math import isfinite +from uuid import uuid4 + +from homeassistant.components.water_heater import ( + WaterHeaterEntity, + WaterHeaterEntityFeature, +) +from homeassistant.const import ( + ATTR_TEMPERATURE, + ATTR_UNIT_OF_MEASUREMENT, + STATE_OFF, + STATE_UNAVAILABLE, + STATE_UNKNOWN, + UnitOfTemperature, +) +from homeassistant.core import HomeAssistant, callback +from homeassistant.exceptions import HomeAssistantError +from homeassistant.helpers.event import ( + async_call_later, + async_track_point_in_time, + async_track_state_change_event, +) +from homeassistant.helpers.restore_state import RestoreEntity +from homeassistant.helpers.update_coordinator import CoordinatorEntity +from homeassistant.util.unit_conversion import TemperatureConverter + +from .const import ( + ATTR_HUB, + ATTR_OPENTHERM_ENDPOINT, + ATTR_OPENTHERM_PARAM, + ATTR_OPENTHERM_REQUEST_ID, + ATTR_OPENTHERM_TEMPERATURE, + CONF_OPENTHERM_HOT_WATER_CONTROL, + CONF_OPENTHERM_HOT_WATER_MANUAL_TEMP, + CONF_OPENTHERM_HOT_WATER_PRESETS, + CONF_OPENTHERM_HOT_WATER_SENSOR_ENTITY_ID, + DATA, + DEFAULT_OPENTHERM_HOT_WATER_MANUAL_TEMP, + DEFAULT_OPENTHERM_HOT_WATER_PRESET_TEMP, + DOMAIN, + EVENT_OPENTHERM_COMMAND_FAILED, + OPENTHERM_HOT_WATER_SCHEDULE, + OPENTHERM_HOT_WATER_DEFAULT_BOOSTS, + WISER_SERVICES, +) +from .entity import WiserEntityMixin +from .helpers import get_hub_device_info, get_unique_id +from .local_schedule import LOCAL_HOT_WATER_SCHEDULE_ID +from .opentherm_detection import ( + opentherm_hot_water_control_is_supported, + opentherm_hot_water_limits, + opentherm_is_detected, +) + +_LOGGER = logging.getLogger(__name__) + +MODE_MANUAL = "Manual" +MODE_AUTO = "Auto" + + +def _normalize_presets(value, minimum=35.0, maximum=55.0): + """Return safe preset dictionaries from stored options.""" + if not isinstance(value, list): + return [] + presets = [] + for item in value: + if not isinstance(item, dict): + continue + try: + temperature = float(item["temperature"]) + duration = int(item.get("duration_minutes", 0)) + except (KeyError, TypeError, ValueError): + continue + name = str(item.get("name", "")).strip() + icon = str(item.get("icon", "")).strip() + if ( + not name + or name.casefold() in {"off", "manual", "auto", "custom"} + or not 0 <= duration <= 999 + ): + continue + temperature = min(max(temperature, minimum), maximum) + presets.append( + { + "name": name, + "icon": icon, + "temperature": temperature, + "duration_minutes": duration, + } + ) + return presets + + +def _default_presets(minimum=35.0, maximum=55.0): + """Return the original control's default timed boost presets.""" + return [ + { + "name": f"Boost {duration} Mins", + "icon": f"mdi:numeric-{index}", + "temperature": min( + max(DEFAULT_OPENTHERM_HOT_WATER_PRESET_TEMP, minimum), maximum + ), + "duration_minutes": duration, + } + for index, duration in enumerate( + OPENTHERM_HOT_WATER_DEFAULT_BOOSTS, start=1 + ) + ] + + +def _finite_float(value): + """Return a finite float, or None for unavailable API data.""" + if isinstance(value, bool): + return None + try: + parsed = float(value) + except (TypeError, ValueError): + return None + return parsed if isfinite(parsed) else None + + +async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entities): + """Set up optional OpenTherm hot-water control.""" + if not config_entry.options.get(CONF_OPENTHERM_HOT_WATER_CONTROL, False): + return + + data = hass.data[DOMAIN][config_entry.entry_id][DATA] + opentherm = data.wiserhub.system.opentherm + if not opentherm_is_detected(config_entry, opentherm): + return + if not opentherm_hot_water_control_is_supported(config_entry, opentherm): + _LOGGER.warning( + "OpenTherm hot-water control is enabled but the boiler does not " + "report a writable DHW setpoint" + ) + return + + schedule = hass.data[DOMAIN][config_entry.entry_id].get( + OPENTHERM_HOT_WATER_SCHEDULE + ) + if schedule is None: + return + + async_add_entities([WiserOpenThermHotWater(data, config_entry, schedule)]) + + +class WiserOpenThermHotWater( + WiserEntityMixin, CoordinatorEntity, RestoreEntity, WaterHeaterEntity +): + """Control the boiler DHW setpoint through the Wiser OpenTherm endpoint.""" + + _attr_has_entity_name = True + _attr_translation_key = "opentherm_hot_water" + _attr_temperature_unit = UnitOfTemperature.CELSIUS + _attr_target_temperature_step = 0.5 + _attr_supported_features = ( + WaterHeaterEntityFeature.TARGET_TEMPERATURE + | WaterHeaterEntityFeature.OPERATION_MODE + | WaterHeaterEntityFeature.ON_OFF + ) + + def __init__(self, data, config_entry, schedule): + """Initialize the entity.""" + super().__init__(data) + self._data = data + self._entry_id = config_entry.entry_id + self._schedule = schedule + self._minimum, self._maximum = opentherm_hot_water_limits( + data.wiserhub.system.opentherm + ) + self._manual_temperature = float( + config_entry.options.get( + CONF_OPENTHERM_HOT_WATER_MANUAL_TEMP, + DEFAULT_OPENTHERM_HOT_WATER_MANUAL_TEMP, + ) + ) + self._manual_temperature = min( + max(self._manual_temperature, self.min_temp), self.max_temp + ) + self._presets = _normalize_presets( + config_entry.options.get( + CONF_OPENTHERM_HOT_WATER_PRESETS, + _default_presets(self._minimum, self._maximum), + ), + self._minimum, + self._maximum, + ) + self._temperature_sensor_entity_id = config_entry.options.get( + CONF_OPENTHERM_HOT_WATER_SENSOR_ENTITY_ID + ) + self._operation = MODE_AUTO + self._last_schedule_request = None + self._target_write_in_progress = False + self._cancel_schedule_timer = None + self._cancel_boost_timer = None + self._boost_deadline = None + self._pending_request_id = None + self._pending_previous_operation = None + self._pending_previous_boost_seconds = None + self._attr_unique_id = get_unique_id( + data, + "water_heater", + "opentherm_hot_water", + data.wiserhub.system.name, + ) + + @property + def device_info(self): + """Attach the entity to the physical HeatHub.""" + return get_hub_device_info(self._data) + + @property + def _opentherm(self): + return self._data.wiserhub.system.opentherm + + @property + def available(self): + """Require current coordinator and OpenTherm connectivity.""" + return bool( + super().available + and self._opentherm + and self._opentherm.connection_status == "Connected" + and getattr( + getattr(self._opentherm, "boiler_parameters", None), + "hw_setpoint_read_write", + None, + ) + is True + ) + + @property + def current_temperature(self): + """Return the measured domestic-hot-water temperature.""" + if self._temperature_sensor_entity_id: + sensor_state = self.hass.states.get( + self._temperature_sensor_entity_id + ) + if sensor_state and sensor_state.state not in ( + STATE_UNAVAILABLE, + STATE_UNKNOWN, + ): + sensor_temperature = _finite_float(sensor_state.state) + if sensor_temperature is not None: + unit = sensor_state.attributes.get( + ATTR_UNIT_OF_MEASUREMENT, + UnitOfTemperature.CELSIUS, + ) + try: + return TemperatureConverter.convert( + sensor_temperature, + unit, + UnitOfTemperature.CELSIUS, + ) + except (TypeError, ValueError): + pass + operational_data = getattr(self._opentherm, "operational_data", None) + return _finite_float(getattr(operational_data, "hw_temperature", None)) + + @property + def target_temperature(self): + """Return the setpoint reported by Wiser.""" + boiler_parameters = getattr(self._opentherm, "boiler_parameters", None) + value = getattr(boiler_parameters, "hw_setpoint", None) + if value is None: + value = getattr(self._opentherm, "hw_flow_setpoint", None) + return _finite_float(value) + + @property + def min_temp(self): + """Return the boiler-reported lower bound when available.""" + return self._minimum + + @property + def max_temp(self): + """Return the boiler-reported upper bound when available.""" + return self._maximum + + @property + def operation_list(self): + """Return the operations rendered by the hot-water mode control.""" + return [ + STATE_OFF, + MODE_MANUAL, + MODE_AUTO, + *(preset["name"] for preset in self._presets), + ] + + @property + def current_operation(self): + """Return the selected operating mode.""" + return self._operation + + @property + def extra_state_attributes(self): + """Expose the selected schedule and its next transition.""" + _, next_event = self._schedule.current() + return { + # Used by Wiser's card feature to scope its icon mode control to + # this water heater rather than every water_heater entity in HA. + "wiser_opentherm_hot_water": True, + "custom_ui_more_info": "opentherm-hot-water-control-more-info", + "opentherm_presets": self._presets, + "schedule_id": LOCAL_HOT_WATER_SCHEDULE_ID, + "schedule_name": self._schedule.name, + "next_schedule_event": next_event, + } + + async def async_added_to_hass(self): + """Restore mode, subscribe to changes, and start the local schedule.""" + await super().async_added_to_hass() + if self._temperature_sensor_entity_id: + self.async_on_remove( + async_track_state_change_event( + self.hass, + [self._temperature_sensor_entity_id], + self._async_temperature_sensor_changed, + ) + ) + previous = await self.async_get_last_state() + reset_expired_boost = False + if previous: + restored_mode = { + "manual": MODE_MANUAL, + "heat": MODE_MANUAL, + "auto": MODE_AUTO, + "off": STATE_OFF, + }.get(previous.state.lower()) + preset = self._preset_for_mode(previous.state) + if preset is not None: + # Timed boosts cannot be resumed without a saved deadline. + restored_mode = ( + MODE_MANUAL + if preset["duration_minutes"] + else preset["name"] + ) + reset_expired_boost = bool(preset["duration_minutes"]) + if restored_mode in self.operation_list: + self._operation = restored_mode + + self.async_on_remove( + self._schedule.async_add_listener(self._async_schedule_changed) + ) + self.async_on_remove( + self.hass.bus.async_listen( + EVENT_OPENTHERM_COMMAND_FAILED, + self._async_command_failed, + ) + ) + if self._operation == MODE_AUTO: + self.hass.async_create_task(self._async_apply_schedule_safely()) + elif reset_expired_boost: + # A timed boost has no persisted deadline. Restore Manual and write + # its configured target so the boiler cannot remain at boost heat. + self.hass.async_create_task(self._async_finish_boost_safely()) + self._schedule_next_transition() + + @callback + def _async_temperature_sensor_changed(self, _event): + """Publish a changed external hot-water temperature reading.""" + self.async_write_ha_state() + + @callback + def _handle_coordinator_update(self) -> None: + """Reconcile a scheduled target if its transition timer was missed.""" + if self._operation == MODE_AUTO and not self._target_write_in_progress: + temperature = self._scheduled_temperature() + if ( + temperature is not None + and (MODE_AUTO, temperature) != self._last_schedule_request + ): + self.hass.async_create_task( + self._async_apply_schedule_safely() + ) + self.async_write_ha_state() + + async def async_will_remove_from_hass(self): + """Cancel the pending schedule transition.""" + if self._cancel_schedule_timer is not None: + self._cancel_schedule_timer() + self._cancel_schedule_timer = None + self._cancel_active_boost() + await super().async_will_remove_from_hass() + + def _preset_for_mode(self, mode): + """Return the configured preset matching an operation name.""" + return next( + (preset for preset in self._presets if preset["name"] == mode), + None, + ) + + def _cancel_active_boost(self): + """Cancel a pending timed-preset return.""" + if self._cancel_boost_timer is not None: + self._cancel_boost_timer() + self._cancel_boost_timer = None + self._boost_deadline = None + + def _remaining_boost_seconds(self): + """Return the remaining timed-preset duration, if any.""" + if self._boost_deadline is None: + return None + return max( + 0, + self._boost_deadline - asyncio.get_running_loop().time(), + ) + + @callback + def _async_command_failed(self, event): + """Restore the prior UI operation after confirmed boiler rejection.""" + if event.data.get("request_id") != self._pending_request_id: + return + failed_temperature = _finite_float(event.data.get("requested")) + previous_operation = self._pending_previous_operation + previous_boost_seconds = self._pending_previous_boost_seconds + self._pending_request_id = None + self._pending_previous_operation = None + self._pending_previous_boost_seconds = None + if previous_operation not in self.operation_list: + return + self._cancel_active_boost() + self._operation = previous_operation + # A scheduled command has already had its one service-level retry. + # Remember that failed request so coordinator reconciliation does not + # send it repeatedly; a different schedule block will still be sent. + self._last_schedule_request = ( + (MODE_AUTO, failed_temperature) + if previous_operation == MODE_AUTO + and failed_temperature is not None + else None + ) + previous_preset = self._preset_for_mode(previous_operation) + if ( + previous_preset is not None + and previous_preset["duration_minutes"] + and previous_boost_seconds + ): + self._start_boost(previous_boost_seconds / 60) + self.async_write_ha_state() + + @callback + def _async_boost_finished(self, _now): + """Return a completed timed preset to Manual mode.""" + self._cancel_boost_timer = None + self._boost_deadline = None + self.hass.async_create_task(self._async_finish_boost_safely()) + + async def _async_finish_boost_safely(self): + """Apply the Manual setpoint after a timed preset expires.""" + try: + await self.async_set_operation_mode(MODE_MANUAL) + except HomeAssistantError as err: + _LOGGER.warning("Unable to end OpenTherm hot-water boost: %s", err) + + def _start_boost(self, minutes): + """Start the return timer for a timed preset.""" + self._cancel_active_boost() + if minutes: + self._boost_deadline = ( + asyncio.get_running_loop().time() + minutes * 60 + ) + self._cancel_boost_timer = async_call_later( + self.hass, + minutes * 60, + self._async_boost_finished, + ) + + @callback + def _async_schedule_changed(self) -> None: + """Apply a saved integration-owned schedule change.""" + if self._operation == MODE_AUTO: + self._last_schedule_request = None + self.hass.async_create_task(self._async_apply_schedule_safely()) + self._schedule_next_transition() + self.async_write_ha_state() + + @callback + def _schedule_next_transition(self) -> None: + """Wake the entity when the next local schedule slot starts.""" + if self._cancel_schedule_timer is not None: + self._cancel_schedule_timer() + self._cancel_schedule_timer = None + _, next_event = self._schedule.current() + if next_event is None: + return + # Run just beyond the minute boundary so schedule evaluation cannot + # observe the previous slot if wall-clock and event-loop time differ by + # a few milliseconds. Coordinator updates provide a second recovery + # path if Home Assistant sleeps through this absolute-time callback. + self._cancel_schedule_timer = async_track_point_in_time( + self.hass, + self._async_schedule_transition, + next_event + timedelta(seconds=1), + ) + + @callback + def _async_schedule_transition(self, _now) -> None: + """Apply a due slot and arm the following transition.""" + self._cancel_schedule_timer = None + self._last_schedule_request = None + if self._operation == MODE_AUTO: + self.hass.async_create_task(self._async_apply_schedule_safely()) + self._schedule_next_transition() + self.async_write_ha_state() + + def _scheduled_temperature(self): + """Resolve the current integration-owned schedule setpoint.""" + temperature, _ = self._schedule.current() + return temperature + + async def _async_apply_schedule_safely(self): + """Apply a background schedule transition without leaking task errors.""" + try: + await self._async_apply_schedule() + except HomeAssistantError as err: + _LOGGER.warning("Unable to apply OpenTherm hot-water schedule: %s", err) + + async def _async_apply_schedule( + self, previous_operation=None, previous_boost_seconds=None + ): + """Apply the active block once, including attribute-only transitions.""" + temperature = self._scheduled_temperature() + request = (MODE_AUTO, temperature) + if temperature is None or request == self._last_schedule_request: + return + self._last_schedule_request = request + try: + await self._async_set_target( + temperature, + previous_operation=previous_operation, + previous_boost_seconds=previous_boost_seconds, + ) + except HomeAssistantError: + self._last_schedule_request = None + raise + + async def _async_set_target( + self, + temperature, + previous_operation=None, + previous_boost_seconds=None, + ): + """Use Wiser's existing serialized write and confirmation path.""" + if not self.min_temp <= temperature <= self.max_temp: + raise HomeAssistantError( + f"Hot-water target must be between {self.min_temp:g} and " + f"{self.max_temp:g} °C" + ) + request_id = uuid4().hex + self._pending_request_id = request_id + self._pending_previous_operation = ( + self._operation + if previous_operation is None + else previous_operation + ) + self._pending_previous_boost_seconds = ( + self._remaining_boost_seconds() + if previous_boost_seconds is None + else previous_boost_seconds + ) + # The service refreshes the coordinator before returning. Suppress + # Auto reconciliation during that refresh so it cannot race this + # foreground write and send the schedule target prematurely. + self._target_write_in_progress = True + try: + await self.hass.services.async_call( + DOMAIN, + WISER_SERVICES["SERVICE_SEND_OPENTHERM_COMMAND"], + { + ATTR_HUB: self._entry_id, + ATTR_OPENTHERM_ENDPOINT: "preDefinedRemoteBoilerParameters", + ATTR_OPENTHERM_PARAM: "dhwSetpoint", + ATTR_OPENTHERM_TEMPERATURE: temperature, + ATTR_OPENTHERM_REQUEST_ID: request_id, + }, + blocking=True, + context=self._context, + ) + except HomeAssistantError: + if self._pending_request_id == request_id: + self._pending_request_id = None + self._pending_previous_operation = None + self._pending_previous_boost_seconds = None + raise + finally: + self._target_write_in_progress = False + + async def async_set_temperature(self, **kwargs): + """Set a target, retaining Auto as an override until its next slot.""" + temperature = _finite_float(kwargs.get(ATTR_TEMPERATURE)) + if temperature is None: + return + auto_override = self._operation == MODE_AUTO + previous_schedule_request = self._last_schedule_request + if auto_override: + # Mark the current block before writing because the OpenTherm + # service refreshes the coordinator while the call is in flight. + self._last_schedule_request = ( + MODE_AUTO, + self._scheduled_temperature(), + ) + try: + await self._async_set_target(temperature) + except HomeAssistantError: + self._last_schedule_request = previous_schedule_request + raise + self._cancel_active_boost() + if auto_override: + # Treat a temperature adjustment in Auto like Wiser's native + # temporary override. Mark the current schedule block as handled + # so coordinator refreshes do not immediately replace it. The next + # scheduled callback clears this marker and applies its setpoint. + self._last_schedule_request = ( + MODE_AUTO, + self._scheduled_temperature(), + ) + else: + self._operation = MODE_MANUAL + self._last_schedule_request = None + self.async_write_ha_state() + + async def async_set_operation_mode(self, operation_mode): + """Select off, manual, or scheduled operation.""" + if operation_mode not in self.operation_list: + raise HomeAssistantError( + f"Unsupported hot-water operation mode: {operation_mode}" + ) + preset = self._preset_for_mode(operation_mode) + previous_operation = self._operation + previous_boost_seconds = self._remaining_boost_seconds() + if operation_mode == STATE_OFF: + await self._async_set_target(self.min_temp) + elif operation_mode == MODE_MANUAL: + await self._async_set_target(self._manual_temperature) + elif preset is not None: + await self._async_set_target(preset["temperature"]) + elif operation_mode != MODE_AUTO: + raise HomeAssistantError( + f"Unknown hot-water preset: {operation_mode}" + ) + self._cancel_active_boost() + self._operation = operation_mode + self._last_schedule_request = None + if operation_mode == MODE_AUTO: + try: + await self._async_apply_schedule( + previous_operation=previous_operation, + previous_boost_seconds=previous_boost_seconds, + ) + except HomeAssistantError: + # Auto changes the local operation before applying its first + # schedule target. Restore the prior UI mode if that initial + # foreground command could not be sent at all. + self._operation = previous_operation + self._last_schedule_request = None + self.async_write_ha_state() + raise + elif preset is not None: + self._start_boost(preset["duration_minutes"]) + self.async_write_ha_state() + + async def async_turn_on(self, **kwargs): + """Resume automatic scheduled operation.""" + await self.async_set_operation_mode(MODE_AUTO) + + async def async_turn_off(self, **kwargs): + """Apply the configured minimum/off setpoint.""" + await self.async_set_operation_mode(STATE_OFF) diff --git a/custom_components/wiser/services.py b/custom_components/wiser/services.py index 990aad9b..0ffb7e3e 100644 --- a/custom_components/wiser/services.py +++ b/custom_components/wiser/services.py @@ -449,10 +449,25 @@ async def verify_on_next_update(): remove_listener = instance.async_add_listener(update_received.set) retry_sent = False retry_error = None + notification_id = ( + f"wiser_opentherm_" + f"{getattr(instance.wiserhub.system, 'name', 'hub')}_{param}" + ) deadline = ( asyncio.get_running_loop().time() + OPENTHERM_CONFIRMATION_WINDOW ) + async def dismiss_previous_failure(): + """Remove a stale warning after a later confirmed command.""" + await hass.services.async_call( + "persistent_notification", + "dismiss", + { + "notification_id": notification_id + }, + blocking=False, + ) + async def report_failure_if_still_mismatched(): """Report only a mismatch that survives the full window.""" if ( @@ -531,9 +546,7 @@ async def report_failure_if_still_mismatched(): { "title": title, "message": message, - "notification_id": ( - f"wiser_opentherm_{instance.wiserhub.system.name}_{param}" - ), + "notification_id": notification_id, }, blocking=False, ) @@ -573,6 +586,7 @@ async def report_failure_if_still_mismatched(): return if matches: if retry_sent or timed_out: + await dismiss_previous_failure() return continue diff --git a/custom_components/wiser/strings.json b/custom_components/wiser/strings.json index 30cfdd5a..4b2db53f 100755 --- a/custom_components/wiser/strings.json +++ b/custom_components/wiser/strings.json @@ -27,6 +27,7 @@ "not_wiser_hub": "The discovered device is not a Wiser Heat Hub." }, "error": { + "invalid_hot_water_presets": "One or more hot-water presets are invalid.", "auth_failure": "Unable to authenticate with the Wiser hub. Check the secret key and try again.", "timeout_error": "Timed out trying to connect to the Wiser hub. Check the IP address and try again.", "timeout_error_discovery": "Timed out trying to connect to the Wiser hub. Check that your hub is still online and try again.", @@ -41,7 +42,7 @@ "menu_options": { "main_params": "Main Parameters", "automation_params": "Automation Parameters", - "opentherm_sensors": "OpenTherm sensors", + "opentherm": "OpenTherm", "equipment_sensors": "Equipment sensors", "ui_options": "UI options" } @@ -106,6 +107,14 @@ "equipment_sensors": "Expose an additional sensor containing detailed equipment attributes for each compatible smart plug, PowerTag, and heating actuator." } }, + "opentherm": { + "title": "OpenTherm", + "description": "Configure OpenTherm features.", + "menu_options": { + "opentherm_hot_water_control": "Hot water control", + "opentherm_sensors": "Sensors" + } + }, "opentherm_sensors": { "title": "OpenTherm sensors", "description": "Choose a category of detected OpenTherm attributes.", @@ -116,6 +125,20 @@ "opentherm_status": "Status and diagnostics" } }, + "opentherm_hot_water_control": { + "title": "OpenTherm hot-water control", + "description": "Optionally control the boiler domestic-hot-water setpoint through Wiser. The integration creates an OpenTherm Hot Water schedule in the Wiser Schedules panel. Off uses the minimum hot-water temperature reported by OpenTherm.", + "data": { + "opentherm_hot_water_control": "Enable hot-water control", + "opentherm_hot_water_manual_temperature": "Manual temperature", + "opentherm_hot_water_sensor_entity_id": "Optional external temperature sensor.", + "opentherm_hot_water_presets": "Presets" + }, + "data_description": { + "opentherm_hot_water_manual_temperature": "Temperature used by Manual mode.", + "opentherm_hot_water_sensor_entity_id": "Optional temperature sensor used for the current water temperature. OpenTherm is used when the sensor is unavailable." + } + }, "opentherm_readings": { "title": "OpenTherm readings", "description": "Choose which detected OpenTherm readings are exposed as sensor entities.", @@ -243,6 +266,11 @@ "name": "Floor temperature" } }, + "water_heater": { + "opentherm_hot_water": { + "name": "OpenTherm hot water" + } + }, "number": { "away_mode_target_temperature": { "name": "Away mode target temperature" }, "floor_temperature_offset": { "name": "Floor temperature offset" }, diff --git a/custom_components/wiser/translations/de.json b/custom_components/wiser/translations/de.json index a4d801c2..0cc4d82b 100644 --- a/custom_components/wiser/translations/de.json +++ b/custom_components/wiser/translations/de.json @@ -27,6 +27,7 @@ "not_wiser_hub": "Das erkannte Gerät ist kein Wiser Heat Hub." }, "error": { + "invalid_hot_water_presets": "Eine oder mehrere Warmwasservoreinstellungen sind ungültig.", "auth_failure": "Authentifizierung beim Wiser Heat Hub fehlgeschlagen. Überprüfen Sie den geheimen Schlüssel und versuchen Sie es erneut.", "timeout_error": "Zeitüberschreitung bei der Verbindung zum Wiser Heat Hub. Überprüfen Sie die IP-Adresse und versuchen Sie es erneut.", "timeout_error_discovery": "Zeitüberschreitung bei der Verbindung zum Wiser Heat Hub. Überprüfen Sie, ob Ihr Hub noch online ist, und versuchen Sie es erneut.", @@ -41,7 +42,7 @@ "menu_options": { "main_params": "Hauptparameter", "automation_params": "Automatisierungsparameter", - "opentherm_sensors": "OpenTherm-Sensoren", + "opentherm": "OpenTherm", "equipment_sensors": "Gerätesensoren", "ui_options": "UI-Optionen" } @@ -106,6 +107,14 @@ "equipment_sensors": "Stellt für jede kompatible intelligente Steckdose, jedes PowerTag und jeden Heizungsaktor einen zusätzlichen Sensor mit detaillierten Geräteattributen bereit." } }, + "opentherm": { + "title": "OpenTherm", + "description": "OpenTherm-Funktionen konfigurieren.", + "menu_options": { + "opentherm_hot_water_control": "Warmwassersteuerung", + "opentherm_sensors": "Sensoren" + } + }, "opentherm_sensors": { "title": "OpenTherm-Sensoren", "description": "Wählen Sie eine Kategorie erkannter OpenTherm-Attribute.", @@ -116,6 +125,20 @@ "opentherm_status": "Status und Diagnose" } }, + "opentherm_hot_water_control": { + "title": "OpenTherm-Warmwassersteuerung", + "description": "Steuert optional den Warmwasser-Sollwert des Kessels über Wiser. Die Integration erstellt den Zeitplan „OpenTherm Hot Water“ im Wiser-Zeitplanbereich. Aus verwendet die von OpenTherm gemeldete minimale Warmwassertemperatur.", + "data": { + "opentherm_hot_water_control": "Warmwassersteuerung aktivieren", + "opentherm_hot_water_manual_temperature": "Manuelle Temperatur", + "opentherm_hot_water_sensor_entity_id": "Optionaler externer Temperatursensor.", + "opentherm_hot_water_presets": "Voreinstellungen" + }, + "data_description": { + "opentherm_hot_water_manual_temperature": "Temperatur für den manuellen Modus.", + "opentherm_hot_water_sensor_entity_id": "Optionaler Temperatursensor für die aktuelle Wassertemperatur. Wenn der Sensor nicht verfügbar ist, wird OpenTherm verwendet." + } + }, "opentherm_readings": { "title": "OpenTherm-Messwerte", "description": "Wählen Sie aus, welche erkannten OpenTherm-Messwerte als Sensorentitäten bereitgestellt werden.", @@ -241,6 +264,9 @@ }, "floor_temperature": { "name": "Fußbodentemperatur" } }, + "water_heater": { + "opentherm_hot_water": { "name": "OpenTherm-Warmwasser" } + }, "number": { "away_mode_target_temperature": { "name": "Zieltemperatur im Abwesenheitsmodus" }, "floor_temperature_offset": { "name": "Korrektur der Fußbodentemperatur" }, diff --git a/custom_components/wiser/translations/en-GB.json b/custom_components/wiser/translations/en-GB.json index d2000cb9..2feb1bf8 100644 --- a/custom_components/wiser/translations/en-GB.json +++ b/custom_components/wiser/translations/en-GB.json @@ -27,6 +27,7 @@ "not_wiser_hub": "The discovered device is not a Wiser Heat Hub." }, "error": { + "invalid_hot_water_presets": "One or more hot-water presets are invalid.", "auth_failure": "Unable to authenticate with the Wiser hub. Check the secret key and try again.", "timeout_error": "Timed out trying to connect to the Wiser hub. Check the IP address and try again.", "timeout_error_discovery": "Timed out trying to connect to the Wiser hub. Check that your hub is still online and try again.", @@ -41,7 +42,7 @@ "menu_options": { "main_params": "Main Parameters", "automation_params": "Automation Parameters", - "opentherm_sensors": "OpenTherm sensors", + "opentherm": "OpenTherm", "equipment_sensors": "Equipment sensors", "ui_options": "UI options" } @@ -106,6 +107,14 @@ "equipment_sensors": "Expose an additional sensor containing detailed equipment attributes for each compatible smart plug, PowerTag, and heating actuator." } }, + "opentherm": { + "title": "OpenTherm", + "description": "Configure OpenTherm features.", + "menu_options": { + "opentherm_hot_water_control": "Hot water control", + "opentherm_sensors": "Sensors" + } + }, "opentherm_sensors": { "title": "OpenTherm sensors", "description": "Choose a category of detected OpenTherm attributes.", @@ -116,6 +125,20 @@ "opentherm_status": "Status and diagnostics" } }, + "opentherm_hot_water_control": { + "title": "OpenTherm hot-water control", + "description": "Optionally control the boiler domestic-hot-water setpoint through Wiser. The integration creates an OpenTherm Hot Water schedule in the Wiser Schedules panel. Off uses the minimum hot-water temperature reported by OpenTherm.", + "data": { + "opentherm_hot_water_control": "Enable hot-water control", + "opentherm_hot_water_manual_temperature": "Manual temperature", + "opentherm_hot_water_sensor_entity_id": "Optional external temperature sensor.", + "opentherm_hot_water_presets": "Presets" + }, + "data_description": { + "opentherm_hot_water_manual_temperature": "Temperature used by Manual mode.", + "opentherm_hot_water_sensor_entity_id": "Optional temperature sensor used for the current water temperature. OpenTherm is used when the sensor is unavailable." + } + }, "opentherm_readings": { "title": "OpenTherm readings", "description": "Choose which detected OpenTherm readings are exposed as sensor entities.", @@ -241,6 +264,9 @@ }, "floor_temperature": { "name": "Floor temperature" } }, + "water_heater": { + "opentherm_hot_water": { "name": "OpenTherm hot water" } + }, "number": { "away_mode_target_temperature": { "name": "Away mode target temperature" }, "floor_temperature_offset": { "name": "Floor temperature offset" }, diff --git a/custom_components/wiser/translations/en.json b/custom_components/wiser/translations/en.json index a6dc522e..74815018 100755 --- a/custom_components/wiser/translations/en.json +++ b/custom_components/wiser/translations/en.json @@ -27,6 +27,7 @@ "not_wiser_hub": "The discovered device is not a Wiser Heat Hub." }, "error": { + "invalid_hot_water_presets": "One or more hot-water presets are invalid.", "auth_failure": "Unable to authenticate with the Wiser hub. Check the secret key and try again.", "timeout_error": "Timed out trying to connect to the Wiser hub. Check the IP address and try again.", "timeout_error_discovery": "Timed out trying to connect to the Wiser hub. Check that your hub is still online and try again.", @@ -41,7 +42,7 @@ "menu_options": { "main_params": "Main Parameters", "automation_params": "Automation Parameters", - "opentherm_sensors": "OpenTherm sensors", + "opentherm": "OpenTherm", "equipment_sensors": "Equipment sensors", "ui_options": "UI options" } @@ -106,6 +107,14 @@ "equipment_sensors": "Expose an additional sensor containing detailed equipment attributes for each compatible smart plug, PowerTag, and heating actuator." } }, + "opentherm": { + "title": "OpenTherm", + "description": "Configure OpenTherm features.", + "menu_options": { + "opentherm_hot_water_control": "Hot water control", + "opentherm_sensors": "Sensors" + } + }, "opentherm_sensors": { "title": "OpenTherm sensors", "description": "Choose a category of detected OpenTherm attributes.", @@ -116,6 +125,20 @@ "opentherm_status": "Status and diagnostics" } }, + "opentherm_hot_water_control": { + "title": "OpenTherm hot-water control", + "description": "Optionally control the boiler domestic-hot-water setpoint through Wiser. The integration creates an OpenTherm Hot Water schedule in the Wiser Schedules panel. Off uses the minimum hot-water temperature reported by OpenTherm.", + "data": { + "opentherm_hot_water_control": "Enable hot-water control", + "opentherm_hot_water_manual_temperature": "Manual temperature", + "opentherm_hot_water_sensor_entity_id": "Optional external temperature sensor.", + "opentherm_hot_water_presets": "Presets" + }, + "data_description": { + "opentherm_hot_water_manual_temperature": "Temperature used by Manual mode.", + "opentherm_hot_water_sensor_entity_id": "Optional temperature sensor used for the current water temperature. OpenTherm is used when the sensor is unavailable." + } + }, "opentherm_readings": { "title": "OpenTherm readings", "description": "Choose which detected OpenTherm readings are exposed as sensor entities.", @@ -241,6 +264,9 @@ }, "floor_temperature": { "name": "Floor temperature" } }, + "water_heater": { + "opentherm_hot_water": { "name": "OpenTherm hot water" } + }, "number": { "away_mode_target_temperature": { "name": "Away mode target temperature" }, "floor_temperature_offset": { "name": "Floor temperature offset" }, diff --git a/custom_components/wiser/translations/fr.json b/custom_components/wiser/translations/fr.json index c9624c73..677106e0 100644 --- a/custom_components/wiser/translations/fr.json +++ b/custom_components/wiser/translations/fr.json @@ -27,6 +27,7 @@ "not_wiser_hub": "L’appareil détecté n’est pas une passerelle Wiser." }, "error": { + "invalid_hot_water_presets": "Un ou plusieurs préréglages d’eau chaude sont invalides.", "auth_failure": "Impossible de s’authentifier auprès de la box Wiser. Vérifiez la clé secrète et réessayez.", "timeout_error": "Le délai de connexion à la box Wiser a expiré. Vérifiez l’adresse IP et réessayez.", "timeout_error_discovery": "Le délai de connexion à la box Wiser a expiré. Vérifiez que votre box Wiser est toujours en ligne et réessayez.", @@ -41,7 +42,7 @@ "menu_options": { "main_params": "Paramètres principaux", "automation_params": "Paramètres d'automatisation", - "opentherm_sensors": "Capteurs OpenTherm", + "opentherm": "OpenTherm", "equipment_sensors": "Capteurs d’équipement", "ui_options": "Options de l’interface" } @@ -106,6 +107,14 @@ "equipment_sensors": "Expose un capteur supplémentaire contenant les attributs détaillés de l’équipement pour chaque prise intelligente, PowerTag et actionneur de chauffage compatible." } }, + "opentherm": { + "title": "OpenTherm", + "description": "Configurer les fonctions OpenTherm.", + "menu_options": { + "opentherm_hot_water_control": "Commande d’eau chaude", + "opentherm_sensors": "Capteurs" + } + }, "opentherm_sensors": { "title": "Capteurs OpenTherm", "description": "Choisissez une catégorie d’attributs OpenTherm détectés.", @@ -116,6 +125,20 @@ "opentherm_status": "État et diagnostics" } }, + "opentherm_hot_water_control": { + "title": "Commande d’eau chaude OpenTherm", + "description": "Contrôle facultativement la consigne d’eau chaude sanitaire de la chaudière via Wiser. L’intégration crée le planning « OpenTherm Hot Water » dans le panneau des plannings Wiser. Le mode Arrêt utilise la température minimale d’eau chaude indiquée par OpenTherm.", + "data": { + "opentherm_hot_water_control": "Activer la commande d’eau chaude", + "opentherm_hot_water_manual_temperature": "Température manuelle", + "opentherm_hot_water_sensor_entity_id": "Capteur de température externe facultatif.", + "opentherm_hot_water_presets": "Préréglages" + }, + "data_description": { + "opentherm_hot_water_manual_temperature": "Température utilisée en mode manuel.", + "opentherm_hot_water_sensor_entity_id": "Capteur de température facultatif utilisé pour la température actuelle de l’eau. OpenTherm est utilisé lorsque le capteur est indisponible." + } + }, "opentherm_readings": { "title": "Mesures OpenTherm", "description": "Choisissez les mesures OpenTherm détectées à exposer en tant qu’entités de capteur.", @@ -241,6 +264,9 @@ }, "floor_temperature": { "name": "Température du sol" } }, + "water_heater": { + "opentherm_hot_water": { "name": "Eau chaude OpenTherm" } + }, "number": { "away_mode_target_temperature": { "name": "Température cible du mode absence" }, "floor_temperature_offset": { "name": "Décalage de température du sol" }, diff --git a/custom_components/wiser/water_heater.py b/custom_components/wiser/water_heater.py new file mode 100644 index 00000000..181953e1 --- /dev/null +++ b/custom_components/wiser/water_heater.py @@ -0,0 +1,5 @@ +"""Water-heater entities for Wiser.""" + +from .opentherm_hot_water import async_setup_entry + +__all__ = ["async_setup_entry"] diff --git a/custom_components/wiser/websockets.py b/custom_components/wiser/websockets.py index 96a58294..d8b0e3c6 100644 --- a/custom_components/wiser/websockets.py +++ b/custom_components/wiser/websockets.py @@ -9,7 +9,11 @@ from aioWiserHeatAPI.exceptions import WiserScheduleError from aioWiserHeatAPI.schedule import WiserScheduleTypeEnum from homeassistant.helpers.dispatcher import async_dispatcher_connect -from .const import DATA, DOMAIN +from .const import DATA, DOMAIN, OPENTHERM_HOT_WATER_SCHEDULE +from .local_schedule import ( + LOCAL_HOT_WATER_SCHEDULE_ID, + LOCAL_HOT_WATER_SCHEDULE_TYPE, +) from .frontend.wiser_sidebar import ( save_panel_config, save_wiser_panel_tabs, @@ -55,6 +59,13 @@ def unsubscribe_listeners(): async def async_register_websockets(hass, data): + def get_entry_for_hub(hub: str): + """Return the integration runtime data for the requested hub.""" + for entry_id, entry_data in hass.data[DOMAIN].items(): + if not hub or entry_data[DATA].wiserhub.system.name == hub: + return entry_data + return None + def get_hub_name(config_entry_id): try: api = hass.data[DOMAIN][config_entry_id][DATA] @@ -63,14 +74,13 @@ def get_hub_name(config_entry_id): return None def get_api_for_hub(hub: str): - if hub: - for entry_id in hass.data[DOMAIN]: - if hass.data[DOMAIN][entry_id][DATA].wiserhub.system.name == hub: - return hass.data[DOMAIN][entry_id][DATA] - return None - else: - for entry_id in hass.data[DOMAIN]: - return hass.data[DOMAIN][entry_id][DATA] + entry_data = get_entry_for_hub(hub) + return entry_data[DATA] if entry_data else None + + def get_local_hot_water_schedule(hub: str): + """Return this hub's integration-owned hot-water schedule, if enabled.""" + entry_data = get_entry_for_hub(hub) + return entry_data.get(OPENTHERM_HOT_WATER_SCHEDULE) if entry_data else None def get_entity_from_entity_id(entity: str): """Get wiser entity from entity_id""" @@ -187,6 +197,21 @@ async def websocket_get_schedules( } ) + local_schedule = get_local_hot_water_schedule(msg.get("hub")) + if local_schedule and ( + not schedule_type + or schedule_type.lower() + == LOCAL_HOT_WATER_SCHEDULE_TYPE.lower() + ): + output.append( + { + "Id": LOCAL_HOT_WATER_SCHEDULE_ID, + "Type": LOCAL_HOT_WATER_SCHEDULE_TYPE, + "Name": local_schedule.name, + "Assignments": 1, + } + ) + connection.send_result(msg["id"], sorted(output, key=lambda n: n["Name"])) else: connection.send_error(msg["id"], "wiser error", "hub not recognised") @@ -236,6 +261,16 @@ async def websocket_get_schedule_by_id( schedule_id = msg.get("schedule_id") d = get_api_for_hub(msg.get("hub")) if d: + local_schedule = get_local_hot_water_schedule(msg.get("hub")) + if ( + schedule_id == LOCAL_HOT_WATER_SCHEDULE_ID + and schedule_type == LOCAL_HOT_WATER_SCHEDULE_TYPE.lower() + and local_schedule + ): + connection.send_result( + msg["id"], local_schedule.ws_schedule_data + ) + return schedule_type_enum = WiserScheduleTypeEnum[schedule_type] schedule = d.wiserhub.schedules.get_by_id(schedule_type_enum, schedule_id) if schedule: @@ -334,6 +369,13 @@ async def websocket_assign_schedule( schedule_id = msg.get("schedule_id") d = get_api_for_hub(msg.get("hub")) if d: + if schedule_id == LOCAL_HOT_WATER_SCHEDULE_ID: + connection.send_error( + msg["id"], + "wiser error", + "The integration-owned OpenTherm hot-water schedule cannot be assigned", + ) + return schedule_type_enum = WiserScheduleTypeEnum[schedule_type] schedule = d.wiserhub.schedules.get_by_id(schedule_type_enum, schedule_id) if schedule: @@ -390,6 +432,11 @@ async def websocket_rename_schedule( name = msg["schedule_name"] d = get_api_for_hub(msg.get("hub")) if d: + local_schedule = get_local_hot_water_schedule(msg.get("hub")) + if schedule_id == LOCAL_HOT_WATER_SCHEDULE_ID and local_schedule: + await local_schedule.async_set_name(name) + connection.send_result(msg["id"], "success") + return schedule_type_enum = WiserScheduleTypeEnum[schedule_type] schedule = d.wiserhub.schedules.get_by_id(schedule_type_enum, schedule_id) if schedule: @@ -423,6 +470,13 @@ async def websocket_delete_schedule( schedule_id = msg["schedule_id"] d = get_api_for_hub(msg.get("hub")) if d: + if schedule_id == LOCAL_HOT_WATER_SCHEDULE_ID: + connection.send_error( + msg["id"], + "wiser error", + "The integration-owned OpenTherm hot-water schedule cannot be deleted", + ) + return schedule_type_enum = WiserScheduleTypeEnum[schedule_type] schedule = d.wiserhub.schedules.get_by_id(schedule_type_enum, schedule_id) if schedule: @@ -475,6 +529,17 @@ async def websocket_save_schedule( new_schedule = msg["schedule"] d = get_api_for_hub(msg.get("hub")) if d: + local_schedule = get_local_hot_water_schedule(msg.get("hub")) + if schedule_id == LOCAL_HOT_WATER_SCHEDULE_ID and local_schedule: + try: + await local_schedule.async_save(new_schedule) + except (TypeError, ValueError) as err: + connection.send_error( + msg["id"], "invalid_schedule", str(err) + ) + return + connection.send_result(msg["id"], "success") + return schedule_type_enum = WiserScheduleTypeEnum[schedule_type] schedule = d.wiserhub.schedules.get_by_id(schedule_type_enum, schedule_id) if schedule: @@ -509,6 +574,13 @@ async def websocket_copy_schedule( to_schedule_id = msg["to_schedule_id"] d = get_api_for_hub(msg.get("hub")) if d: + if LOCAL_HOT_WATER_SCHEDULE_ID in (schedule_id, to_schedule_id): + connection.send_error( + msg["id"], + "wiser error", + "The integration-owned OpenTherm hot-water schedule cannot be copied", + ) + return schedule_type_enum = WiserScheduleTypeEnum[schedule_type] schedule = d.wiserhub.schedules.get_by_id(schedule_type_enum, schedule_id) if schedule: diff --git a/tests/test_entity_naming.py b/tests/test_entity_naming.py index 12a8c935..1cd200ea 100644 --- a/tests/test_entity_naming.py +++ b/tests/test_entity_naming.py @@ -18,6 +18,7 @@ "climate.py": {"WiserTempProbe", "WiserRoom", "WiserHotWater"}, "cover.py": {"WiserShutter"}, "light.py": {"WiserLight"}, + "opentherm_hot_water.py": {"WiserOpenThermHotWater"}, "number.py": { "WiserAwayModeTempNumber", "WiserFloorTempSensorNumber", @@ -43,6 +44,7 @@ "WiserDiscomfortIndoorTempNumber", "WiserDiscomfortOutdoorTempNumber", }, + "opentherm_hot_water.py": {"WiserOpenThermHotWater"}, "select.py": {"WiserSelectEntity"}, "sensor.py": {"WiserSensor"}, "switch.py": {"WiserSwitch"}, diff --git a/tests/test_opentherm.py b/tests/test_opentherm.py index 18e22d82..4a6d3576 100644 --- a/tests/test_opentherm.py +++ b/tests/test_opentherm.py @@ -697,7 +697,12 @@ async def test_initial_mismatch_is_retried_when_no_update_arrives(self): transport = self.first.wiserhub.system.opentherm._wiser_rest_controller._do_hub_action self.assertEqual(transport.await_count, 2) self.assertEqual(self.first.async_refresh.await_count, 2) - self.hass.services.async_call.assert_not_awaited() + self.hass.services.async_call.assert_awaited_once_with( + "persistent_notification", + "dismiss", + {"notification_id": "wiser_opentherm_hub_dhwFlowSetpoint"}, + blocking=False, + ) self.hass.bus.async_fire.assert_not_called() async def test_matching_feedback_is_not_retried(self): diff --git a/tests/test_opentherm_hot_water.py b/tests/test_opentherm_hot_water.py new file mode 100644 index 00000000..147a1a2f --- /dev/null +++ b/tests/test_opentherm_hot_water.py @@ -0,0 +1,322 @@ +"""Focused tests for the integration-owned OpenTherm hot-water schedule.""" + +import ast +from copy import deepcopy +from datetime import datetime, timedelta +from pathlib import Path +from time import strptime +import unittest + + +COMPONENT = Path(__file__).parents[1] / "custom_components/wiser" +WEEKDAYS = ( + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + "Sunday", +) + + +def _load_schedule_helpers(): + """Load pure schedule helpers without requiring Home Assistant.""" + tree = ast.parse((COMPONENT / "local_schedule.py").read_text()) + selected = [ + node + for node in tree.body + if isinstance(node, ast.FunctionDef) + and node.name + in { + "_schedule_preset_options", + "_default_schedule", + "_validated_schedule", + "_schedule_position", + } + ] + namespace = { + "deepcopy": deepcopy, + "timedelta": timedelta, + "strptime": strptime, + "LOCAL_HOT_WATER_SCHEDULE_ID": -1000, + "LOCAL_HOT_WATER_SCHEDULE_NAME": "OpenTherm Hot Water", + "LOCAL_HOT_WATER_SCHEDULE_TYPE": "HotWater", + "WEEKDAYS": WEEKDAYS, + } + exec( + compile(ast.Module(body=selected, type_ignores=[]), "", "exec"), + namespace, + ) + return namespace + + +HELPERS = _load_schedule_helpers() +default_schedule = HELPERS["_default_schedule"] +validated_schedule = HELPERS["_validated_schedule"] +schedule_position = HELPERS["_schedule_position"] + + +class OpenThermHotWaterScheduleTest(unittest.TestCase): + def test_control_uses_water_heater_operations(self): + source = (COMPONENT / "opentherm_hot_water.py").read_text() + self.assertIn( + "CoordinatorEntity, RestoreEntity, WaterHeaterEntity", source + ) + self.assertIn("STATE_OFF,", source) + self.assertIn("MODE_MANUAL,", source) + self.assertIn("MODE_AUTO,", source) + + def test_card_feature_uses_hot_water_mode_icons(self): + source = (COMPONENT / "frontend/wiser-hot-water-control.js").read_text() + self.assertIn('off: "mdi:power"', source) + self.assertIn('Manual: "mdi:water-thermometer"', source) + self.assertIn('Auto: "mdi:calendar-clock"', source) + self.assertIn('operation_mode: value', source) + self.assertIn( + '"opentherm-hot-water-control-presets-feature"', source + ) + self.assertIn('name: "Hot-water control modes"', source) + self.assertIn('name: "Hot-water control presets"', source) + + def test_control_exposes_configured_presets(self): + source = (COMPONENT / "opentherm_hot_water.py").read_text() + self.assertIn('"opentherm_presets": self._presets', source) + self.assertIn('*(preset["name"] for preset in self._presets)', source) + self.assertIn('self._start_boost(preset["duration_minutes"])', source) + + def test_external_temperature_sensor_updates_and_falls_back_to_opentherm(self): + source = (COMPONENT / "opentherm_hot_water.py").read_text() + self.assertIn("CONF_OPENTHERM_HOT_WATER_SENSOR_ENTITY_ID", source) + self.assertIn("self.hass.states.get(", source) + self.assertIn("TemperatureConverter.convert(", source) + self.assertIn("async_track_state_change_event(", source) + self.assertIn("self._async_temperature_sensor_changed", source) + self.assertIn( + 'getattr(operational_data, "hw_temperature", None)', source + ) + + def test_preset_editor_opens_directly_from_nested_options_dialog(self): + source = (COMPONENT / "frontend/wiser-hot-water-control.js").read_text() + self.assertIn('PRESETS_SELECTOR_KEY = "opentherm_presets_v2"', source) + self.assertIn("document.body.querySelector(PRESETS_DIALOG_TYPE)", source) + self.assertIn("document.body.append(dialog)", source) + self.assertIn("dialog.showDialog(dialogParams)", source) + + def test_restart_of_timed_boost_reapplies_manual_target(self): + source = (COMPONENT / "opentherm_hot_water.py").read_text() + self.assertIn("reset_expired_boost = bool", source) + self.assertIn( + "self.hass.async_create_task(self._async_finish_boost_safely())", + source, + ) + + def test_confirmed_command_failure_restores_previous_ui_operation(self): + source = (COMPONENT / "opentherm_hot_water.py").read_text() + self.assertIn("ATTR_OPENTHERM_REQUEST_ID: request_id", source) + self.assertIn("EVENT_OPENTHERM_COMMAND_FAILED", source) + self.assertIn("self._operation = previous_operation", source) + self.assertIn("self._cancel_active_boost()", source) + self.assertIn("self._pending_previous_boost_seconds", source) + self.assertIn("self._start_boost(previous_boost_seconds / 60)", source) + self.assertIn("self._operation = previous_operation", source) + self.assertIn("(MODE_AUTO, failed_temperature)", source) + self.assertIn("except HomeAssistantError:", source) + + def test_preset_editor_uses_boiler_temperature_limits(self): + source = (COMPONENT / "frontend/wiser-hot-water-control.js").read_text() + self.assertIn("min: this._minimum", source) + self.assertIn("max: this._maximum", source) + self.assertNotIn("temperature between 35 and 55", source) + + def test_presets_are_list_only(self): + source = (COMPONENT / "frontend/wiser-hot-water-control.js").read_text() + self.assertNotIn("display_style", source) + self.assertNotIn('displayStyle.label = "Show as"', source) + self.assertIn( + "return PRIMARY_MODES.filter((mode) => entityModes.includes(mode))", + source, + ) + + def test_default_schedule_starts_safe_and_covers_every_day(self): + schedule = default_schedule(35) + self.assertEqual(schedule["Id"], -1000) + self.assertEqual(schedule["Type"], "HotWater") + self.assertEqual(schedule["MinSetpoint"], 35) + self.assertEqual(schedule["MaxSetpoint"], 55) + self.assertEqual( + [day["day"] for day in schedule["ScheduleData"]], list(WEEKDAYS) + ) + self.assertTrue( + all( + day["slots"] + == [ + {"Time": "00:00", "Setpoint": "35"}, + {"Time": "06:00", "Setpoint": "45"}, + {"Time": "09:00", "Setpoint": "35"}, + {"Time": "17:00", "Setpoint": "45"}, + {"Time": "22:00", "Setpoint": "35"}, + ] + for day in schedule["ScheduleData"] + ) + ) + + def test_schedule_uses_latest_slot_and_reports_next_transition(self): + schedule = default_schedule(35) + monday = schedule["ScheduleData"][0] + monday["slots"] = [ + {"Time": "06:00", "Setpoint": "50"}, + {"Time": "08:00", "Setpoint": "35"}, + ] + value, next_event = schedule_position( + schedule, datetime(2026, 10, 5, 7, 0) + ) + self.assertEqual(value, 50) + self.assertEqual(next_event, datetime(2026, 10, 5, 8, 0)) + + def test_schedule_wraps_to_the_previous_and_next_week(self): + schedule = default_schedule(35) + for day in schedule["ScheduleData"]: + day["slots"] = [] + schedule["ScheduleData"][6]["slots"] = [ + {"Time": "22:00", "Setpoint": "48"} + ] + value, next_event = schedule_position( + schedule, datetime(2026, 10, 5, 5, 0) + ) + self.assertEqual(value, 48) + self.assertEqual(next_event, datetime(2026, 10, 11, 22, 0)) + + def test_single_slot_at_current_time_advances_one_week(self): + schedule = default_schedule(35) + for day in schedule["ScheduleData"]: + day["slots"] = [] + schedule["ScheduleData"][0]["slots"] = [ + {"Time": "06:00", "Setpoint": "50"} + ] + value, next_event = schedule_position( + schedule, datetime(2026, 10, 5, 6, 0) + ) + self.assertEqual(value, 50) + self.assertEqual(next_event, datetime(2026, 10, 12, 6, 0)) + + def test_schedule_changes_at_exact_sunday_minute(self): + schedule = default_schedule(35) + sunday = schedule["ScheduleData"][6] + sunday["slots"] = [ + {"Time": "14:00", "Setpoint": "49"}, + {"Time": "19:15", "Setpoint": "45"}, + ] + + value, next_event = schedule_position( + schedule, datetime(2026, 10, 11, 19, 15, 32) + ) + + self.assertEqual(value, 45) + self.assertEqual(next_event, datetime(2026, 10, 12, 0, 0)) + + def test_schedule_has_timer_and_coordinator_recovery_paths(self): + source = (COMPONENT / "opentherm_hot_water.py").read_text() + self.assertIn("async_track_point_in_time(", source) + self.assertIn("next_event + timedelta(seconds=1)", source) + self.assertIn("def _handle_coordinator_update", source) + self.assertIn( + "(MODE_AUTO, temperature) != self._last_schedule_request", + source, + ) + + def test_temperature_change_in_auto_is_a_temporary_override(self): + source = (COMPONENT / "opentherm_hot_water.py").read_text() + self.assertIn("auto_override = self._operation == MODE_AUTO", source) + self.assertIn("previous_schedule_request =", source) + self.assertIn("self._target_write_in_progress = True", source) + self.assertIn( + "self._operation == MODE_AUTO and not self._target_write_in_progress", + source, + ) + self.assertIn("if auto_override:", source) + self.assertIn("self._scheduled_temperature()", source) + self.assertIn("self._operation = MODE_MANUAL", source) + + def test_validation_normalizes_and_rejects_unsafe_setpoints(self): + schedule = default_schedule(35) + schedule["ScheduleData"][0]["slots"] = [ + {"Time": "08:30", "Setpoint": "45.5"}, + {"Time": "06:00", "Setpoint": 50}, + ] + normalized = validated_schedule(schedule, 35, 55) + self.assertEqual( + [slot["Time"] for slot in normalized["ScheduleData"][0]["slots"]], + ["06:00", "08:30"], + ) + + schedule["ScheduleData"][0]["slots"][0]["Setpoint"] = 60 + with self.assertRaises(ValueError): + validated_schedule(schedule, 35, 55) + + def test_schedule_card_off_value_uses_safe_low_setpoint(self): + schedule = default_schedule(40) + schedule["ScheduleData"][0]["slots"][0]["Setpoint"] = "Off" + normalized = validated_schedule(schedule, 40, 55) + self.assertEqual( + normalized["ScheduleData"][0]["slots"][0]["Setpoint"], "40" + ) + + def test_non_timed_presets_can_be_scheduled_and_resolve_to_temperature(self): + presets = [ + { + "name": "Hand wash", + "icon": "mdi:hand-wash", + "temperature": 42, + "duration_minutes": 0, + }, + { + "name": "Boost 30 Mins", + "icon": "mdi:numeric-1", + "temperature": 50, + "duration_minutes": 30, + }, + ] + schedule = default_schedule(35, 55, 45, presets) + self.assertEqual( + schedule["PresetOptions"], + [ + { + "name": "Hand wash", + "icon": "mdi:hand-wash", + "temperature": 42.0, + } + ], + ) + schedule["ScheduleData"][0]["slots"] = [ + {"Time": "06:00", "Setpoint": "hand WASH"} + ] + normalized = validated_schedule(schedule, 35, 55, presets) + self.assertEqual( + normalized["ScheduleData"][0]["slots"][0]["Setpoint"], + "Hand wash", + ) + value, _ = schedule_position( + normalized, datetime(2026, 10, 5, 7, 0) + ) + self.assertEqual(value, 42) + + schedule["ScheduleData"][0]["slots"][0]["Setpoint"] = ( + "Boost 30 Mins" + ) + with self.assertRaisesRegex(ValueError, "Unknown hot-water preset"): + validated_schedule(schedule, 35, 55, presets) + + def test_removed_preset_falls_back_to_safe_minimum_when_loading(self): + schedule = default_schedule(35) + schedule["ScheduleData"][0]["slots"][0]["Setpoint"] = "Deleted" + normalized = validated_schedule( + schedule, 35, 55, [], replace_unknown_presets=True + ) + self.assertEqual( + normalized["ScheduleData"][0]["slots"][0]["Setpoint"], "35" + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_room_migration_orchestration.py b/tests/test_room_migration_orchestration.py index 5ba3523a..44be180d 100644 --- a/tests/test_room_migration_orchestration.py +++ b/tests/test_room_migration_orchestration.py @@ -60,8 +60,13 @@ def _load_wiser_init() -> ModuleType: "CONF_DEPRECATED_HW_TARGET_TEMP", "CONF_LEGACY_NAMING", "CONF_OPENTHERM_EVER_CONNECTED", + "CONF_OPENTHERM_HOT_WATER_CAPABLE", + "CONF_OPENTHERM_HOT_WATER_CONTROL", + "CONF_OPENTHERM_HOT_WATER_MANUAL_TEMP", + "CONF_OPENTHERM_HOT_WATER_PRESETS", "CONF_WISER_ROOM_NAMES", "DATA", + "OPENTHERM_HOT_WATER_SCHEDULE", "UPDATE_LISTENER", ) } @@ -69,6 +74,7 @@ def _load_wiser_init() -> ModuleType: DOMAIN="wiser", ENTITY_PREFIX="Wiser", MANUFACTURER="Drayton Wiser", + DEFAULT_OPENTHERM_HOT_WATER_MANUAL_TEMP=45.0, WISER_PLATFORMS=[], WISER_SERVICES={}, HWCycleModes=SimpleNamespace(CONTINUOUS="continuous", ONCE="once"), @@ -136,8 +142,14 @@ def _load_wiser_init() -> ModuleType: _module( "wiser_init_test.opentherm_detection", opentherm_entity_unique_ids=Mock(return_value=set()), + opentherm_hot_water_control_is_supported=Mock(return_value=False), + opentherm_hot_water_limits=Mock(return_value=(35.0, 55.0)), opentherm_is_detected=Mock(return_value=False), ) + _module( + "wiser_init_test.local_schedule", + OpenThermHotWaterSchedule=Mock(), + ) _module("wiser_init_test.services", async_setup_services=Mock()) _module("wiser_init_test.update", async_unload_card_updates=Mock()) _module("wiser_init_test.websockets", async_register_websockets=Mock()) diff --git a/tests/test_sidebar_icons.py b/tests/test_sidebar_icons.py index 3e35c1ea..63d25ab8 100644 --- a/tests/test_sidebar_icons.py +++ b/tests/test_sidebar_icons.py @@ -3,7 +3,7 @@ from pathlib import Path from types import SimpleNamespace import unittest -from unittest.mock import AsyncMock, Mock +from unittest.mock import AsyncMock, Mock, call ROOT = Path(__file__).resolve().parents[1] / "custom_components/wiser/frontend" @@ -36,6 +36,21 @@ async def test_icons_register_after_static_path_without_lovelace(self): ) register.side_effect = lambda *args: host._async_register_path.assert_awaited_once() await namespace["async_register"](host) - version.assert_called_once_with(ROOT / "wiser-icons.js") - register.assert_called_once_with(host.hass, "/wiser/wiser-icons.js?v=sha256-icons") + self.assertEqual( + version.call_args_list, + [ + call(ROOT / "wiser-icons.js"), + call(ROOT / "wiser-hot-water-control.js"), + ], + ) + self.assertEqual( + register.call_args_list, + [ + call(host.hass, "/wiser/wiser-icons.js?v=sha256-icons"), + call( + host.hass, + "/wiser/wiser-hot-water-control.js?v=sha256-icons", + ), + ], + ) host._async_wait_for_lovelace_resources.assert_not_awaited() diff --git a/tests/test_ui_options.py b/tests/test_ui_options.py index 3202fe2d..fa31c179 100644 --- a/tests/test_ui_options.py +++ b/tests/test_ui_options.py @@ -71,6 +71,9 @@ def setUp(self): "CONF_LEGACY_NAMING": "legacy_naming", "CONF_EQUIPMENT_SENSORS": "equipment_sensors", "CONF_OPENTHERM_EVER_CONNECTED": "opentherm_ever_connected", + "CONF_OPENTHERM_HOT_WATER_CAPABLE": "opentherm_hot_water_capable", + "CONF_OPENTHERM_HOT_WATER_CONTROL": "opentherm_hot_water_control", + "CONF_OPENTHERM_HOT_WATER_SENSOR_ENTITY_ID": "opentherm_hot_water_sensor_entity_id", "CONF_SHOW_WISER_SIDEBAR": "show_wiser_sidebar", "CONF_NAME": "name", "DATA": "data", @@ -161,6 +164,96 @@ def test_first_opentherm_connection_is_remembered_once(self): update.assert_not_called() sync_registry.assert_not_called() + def test_writable_hot_water_capability_is_remembered(self): + sync_registry = Mock() + self.namespace["_sync_opentherm_entity_registry"] = sync_registry + functions = load_functions( + "__init__.py", {"_remember_opentherm_connection"}, self.namespace + ) + update = Mock() + hass = SimpleNamespace( + config_entries=SimpleNamespace(async_update_entry=update) + ) + entry = SimpleNamespace( + data={"opentherm_ever_connected": True} + ) + opentherm = SimpleNamespace( + enabled=True, + connection_status="Connected", + boiler_parameters=SimpleNamespace(hw_setpoint_read_write=True), + ) + coordinator = SimpleNamespace( + wiserhub=SimpleNamespace( + system=SimpleNamespace(opentherm=opentherm) + ) + ) + + functions._remember_opentherm_connection(hass, entry, coordinator) + + update.assert_called_once_with( + entry, + data={ + "opentherm_ever_connected": True, + "opentherm_hot_water_capable": True, + }, + ) + + def test_hot_water_support_survives_capability_data_gap(self): + functions = load_functions( + "opentherm_detection.py", + {"opentherm_hot_water_control_is_supported"}, + self.namespace, + ) + opentherm = SimpleNamespace(boiler_parameters=SimpleNamespace()) + + self.assertTrue( + functions.opentherm_hot_water_control_is_supported( + SimpleNamespace( + data={"opentherm_hot_water_capable": True}, options={} + ), + opentherm, + ) + ) + self.assertTrue( + functions.opentherm_hot_water_control_is_supported( + SimpleNamespace( + data={}, options={"opentherm_hot_water_control": True} + ), + opentherm, + ) + ) + + def test_hot_water_presets_follow_boiler_limits(self): + self.namespace.update( + vol=SimpleNamespace(Invalid=ValueError), + MAX_OPENTHERM_HOT_WATER_PRESETS=10, + DEFAULT_OPENTHERM_HOT_WATER_PRESET_TEMP=55.0, + OPENTHERM_HOT_WATER_DEFAULT_BOOSTS=(15, 30, 45), + ) + functions = load_functions( + "config_flow.py", + { + "_default_opentherm_hot_water_presets", + "_validate_opentherm_hot_water_presets", + }, + self.namespace, + ) + defaults = functions._default_opentherm_hot_water_presets(40, 50) + self.assertTrue( + all(preset["temperature"] == 50 for preset in defaults) + ) + stored = [{ + "name": "Boost", + "temperature": 55, + "duration_minutes": 15, + }] + with self.assertRaises(ValueError): + functions._validate_opentherm_hot_water_presets(stored, 40, 50) + clamped = functions._validate_opentherm_hot_water_presets( + stored, 40, 50, clamp_temperature=True + ) + self.assertEqual(clamped[0]["temperature"], 50) + def test_disabling_opentherm_clears_remembered_connection(self): sync_registry = Mock() self.namespace["_sync_opentherm_entity_registry"] = sync_registry @@ -379,6 +472,7 @@ async def test_menu_available_without_opentherm(self): ) result = await functions.async_step_init(flow) self.assertIn("ui_options", result["menu_options"]) + self.assertNotIn("opentherm", result["menu_options"]) self.assertNotIn("equipment_sensors", result["menu_options"]) async def test_equipment_menu_is_below_opentherm(self): @@ -393,10 +487,44 @@ async def test_equipment_menu_is_below_opentherm(self): ) result = await functions.async_step_init(flow) self.assertLess( - result["menu_options"].index("opentherm_sensors"), + result["menu_options"].index("opentherm"), result["menu_options"].index("equipment_sensors"), ) + async def test_opentherm_menu_groups_control_and_sensors(self): + self.namespace["opentherm_hot_water_control_is_supported"] = ( + lambda entry, opentherm: True + ) + functions = load_functions( + "config_flow.py", {"async_step_opentherm"}, self.namespace + ) + flow = SimpleNamespace( + _opentherm=lambda: object(), + config_entry=SimpleNamespace(), + async_show_menu=lambda **kwargs: kwargs, + ) + result = await functions.async_step_opentherm(flow) + self.assertEqual(result["step_id"], "opentherm") + self.assertEqual( + result["menu_options"], + ["opentherm_hot_water_control", "opentherm_sensors"], + ) + + async def test_opentherm_menu_hides_unsupported_hot_water_control(self): + self.namespace["opentherm_hot_water_control_is_supported"] = ( + lambda entry, opentherm: False + ) + functions = load_functions( + "config_flow.py", {"async_step_opentherm"}, self.namespace + ) + flow = SimpleNamespace( + _opentherm=lambda: object(), + config_entry=SimpleNamespace(), + async_show_menu=lambda **kwargs: kwargs, + ) + result = await functions.async_step_opentherm(flow) + self.assertEqual(result["menu_options"], ["opentherm_sensors"]) + async def test_equipment_menu_does_not_require_opentherm(self): functions = load_functions( "config_flow.py", {"async_step_init"}, self.namespace @@ -409,7 +537,7 @@ async def test_equipment_menu_does_not_require_opentherm(self): ) result = await functions.async_step_init(flow) self.assertIn("equipment_sensors", result["menu_options"]) - self.assertNotIn("opentherm_sensors", result["menu_options"]) + self.assertNotIn("opentherm", result["menu_options"]) async def test_enabled_equipment_option_remains_available_during_data_gap(self): self.namespace.update( From e5bf50974e1f29e60023cf4eaace8f4638a08e14 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Tue, 13 Oct 2026 10:39:36 +0100 Subject: [PATCH 127/154] fix: avoid blocking light commands during refresh --- custom_components/wiser/light.py | 62 ++++++++++++++++++++-------- tests/test_light_optimistic_state.py | 53 +++++++++++++++++------- 2 files changed, 81 insertions(+), 34 deletions(-) diff --git a/custom_components/wiser/light.py b/custom_components/wiser/light.py index 19e203e0..7d832ee9 100644 --- a/custom_components/wiser/light.py +++ b/custom_components/wiser/light.py @@ -80,6 +80,24 @@ async def async_force_update(self, delay: int = 0): await asyncio.sleep(delay) await self._data.async_refresh() + async def _async_confirm_command(self, gen: int) -> None: + """Refresh the hub after it has had time to apply a light command.""" + try: + await self.async_force_update(2) + finally: + # A newer command owns the optimistic state. Its confirmation task + # will clear that state after the hub has processed the newer value. + if gen == self._optimistic_gen: + self._clear_optimistic_state() + + @callback + def _schedule_command_confirmation(self, gen: int) -> None: + """Confirm a command without delaying the Home Assistant service call.""" + self.hass.async_create_task( + self._async_confirm_command(gen), + f"Wiser light command confirmation: {self.entity_id}", + ) + @callback def _handle_coordinator_update(self) -> None: _LOGGER.debug(f"{self.name} updating") @@ -211,43 +229,51 @@ def extra_state_attributes(self): @hub_error_handler async def async_turn_on(self, **kwargs): """Turn light on.""" - if ATTR_BRIGHTNESS in kwargs: - percentage = round((int(kwargs[ATTR_BRIGHTNESS]) / 255) * 100) - _LOGGER.debug(f"Setting brightness of {self.name} to {percentage}%") - await self._device.set_current_percentage(percentage) - self._optimistic_percentage = percentage - else: - _LOGGER.debug(f"Turning on {self.name}") - await self._device.turn_on() - # Reflect the command in the UI immediately (the hub only reports the new - # state a few seconds later); the refresh below then confirms it. self._optimistic_gen += 1 gen = self._optimistic_gen self._optimistic_is_on = True + percentage = None + if ATTR_BRIGHTNESS in kwargs: + percentage = round((int(kwargs[ATTR_BRIGHTNESS]) / 255) * 100) + self._optimistic_percentage = percentage self.async_write_ha_state() + try: - await self.async_force_update(2) - finally: - # Only the latest command clears the optimistic state; a superseded - # command must leave the newer command's value untouched. + if percentage is not None: + _LOGGER.debug(f"Setting brightness of {self.name} to {percentage}%") + await self._device.set_current_percentage(percentage) + else: + _LOGGER.debug(f"Turning on {self.name}") + await self._device.turn_on() + except Exception: if gen == self._optimistic_gen: self._clear_optimistic_state() + raise + + # The hub applies its Zigbee command asynchronously. Refresh after the + # existing two-second settling period, but do not hold open the HA + # service call while waiting for state confirmation. + self._schedule_command_confirmation(gen) return True @hub_error_handler async def async_turn_off(self, **kwargs): """Turn light off.""" - _LOGGER.debug(f"Turning off {self.name}") - await self._device.turn_off() self._optimistic_gen += 1 gen = self._optimistic_gen self._optimistic_is_on = False + self._optimistic_percentage = None self.async_write_ha_state() + try: - await self.async_force_update(2) - finally: + _LOGGER.debug(f"Turning off {self.name}") + await self._device.turn_off() + except Exception: if gen == self._optimistic_gen: self._clear_optimistic_state() + raise + + self._schedule_command_confirmation(gen) return True @callback diff --git a/tests/test_light_optimistic_state.py b/tests/test_light_optimistic_state.py index 8bb5cb96..238bd0a0 100644 --- a/tests/test_light_optimistic_state.py +++ b/tests/test_light_optimistic_state.py @@ -137,30 +137,51 @@ def _light(self, *, is_on=False): async def _noop_async(self, *_args, **_kwargs): return None - def test_single_command_clears_optimistic(self): + def test_single_command_returns_before_confirmation(self): light, device = self._light(is_on=False) - light.async_force_update = self._noop_async + scheduled = [] + light._schedule_command_confirmation = scheduled.append + asyncio.run(light.async_turn_on()) - # The one and only command clears its own optimistic state on cleanup. + + self.assertIs(light._optimistic_is_on, True) + self.assertTrue(light.is_on) + self.assertEqual(scheduled, [1]) + + def test_superseded_confirmation_does_not_clobber_newer(self): + light, device = self._light(is_on=False) + light._optimistic_gen = 2 + light._optimistic_is_on = False + light.async_force_update = self._noop_async + + asyncio.run(light._async_confirm_command(1)) + + self.assertIs(light._optimistic_is_on, False) + + def test_latest_confirmation_clears_optimistic_state(self): + light, device = self._light(is_on=False) + light._optimistic_gen = 1 + light._optimistic_is_on = True + light.async_force_update = self._noop_async + + asyncio.run(light._async_confirm_command(1)) + self.assertIsNone(light._optimistic_is_on) - self.assertTrue(light.is_on) # falls through to the (now on) device - def test_superseded_command_does_not_clobber_newer(self): + def test_failed_command_restores_hub_state(self): light, device = self._light(is_on=False) + light._schedule_command_confirmation = lambda _gen: None - # Command A is turn_on. While A awaits its follow-up refresh, a newer - # command B (turn_off) lands: it bumps the generation and sets its own - # optimistic value. A's cleanup must then leave B's value alone. - async def force_update_with_intervening_command(delay=0): - light._optimistic_gen += 1 - light._optimistic_is_on = False # command B = turn off + async def fail(): + raise RuntimeError("command failed") - light.async_force_update = force_update_with_intervening_command - asyncio.run(light.async_turn_on()) # command A + device.turn_on = fail - # Without the generation guard, A's finally would wipe this back to None - # and the UI would revert to the stale device state. - self.assertIs(light._optimistic_is_on, False) + with self.assertRaisesRegex(RuntimeError, "command failed"): + asyncio.run(light.async_turn_on()) + + self.assertIsNone(light._optimistic_is_on) + self.assertFalse(light.is_on) def test_coordinator_update_clears_optimistic_once_confirmed(self): light, device = self._light(is_on=False) From cc2b5c41e47468a045dd67df65854f3823a12efe Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Tue, 13 Oct 2026 12:12:43 +0100 Subject: [PATCH 128/154] fix: retry stale light command confirmation --- custom_components/wiser/light.py | 18 ++++++++++++- tests/test_light_optimistic_state.py | 40 +++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/custom_components/wiser/light.py b/custom_components/wiser/light.py index 7d832ee9..1172a070 100644 --- a/custom_components/wiser/light.py +++ b/custom_components/wiser/light.py @@ -83,10 +83,21 @@ async def async_force_update(self, delay: int = 0): async def _async_confirm_command(self, gen: int) -> None: """Refresh the hub after it has had time to apply a light command.""" try: - await self.async_force_update(2) + # Some hubs acknowledge the REST command before its Zigbee result is + # visible in hub data. Keep the optimistic state through one stale + # read and try once more instead of reverting until the next scan. + for _attempt in range(2): + await self.async_force_update(2) + if gen != self._optimistic_gen or ( + self._optimistic_is_on is None + and self._optimistic_percentage is None + ): + return finally: # A newer command owns the optimistic state. Its confirmation task # will clear that state after the hub has processed the newer value. + # If both confirmation reads remained stale, return to the real hub + # state rather than leaving an optimistic value indefinitely. if gen == self._optimistic_gen: self._clear_optimistic_state() @@ -114,6 +125,11 @@ def _handle_coordinator_update(self) -> None: and self._device.is_on == self._optimistic_is_on ): self._optimistic_is_on = None + if ( + self._optimistic_percentage is not None + and self._device.current_percentage == self._optimistic_percentage + ): + self._optimistic_percentage = None self.async_write_ha_state() @property diff --git a/tests/test_light_optimistic_state.py b/tests/test_light_optimistic_state.py index 238bd0a0..c1fb0517 100644 --- a/tests/test_light_optimistic_state.py +++ b/tests/test_light_optimistic_state.py @@ -162,12 +162,38 @@ def test_latest_confirmation_clears_optimistic_state(self): light, device = self._light(is_on=False) light._optimistic_gen = 1 light._optimistic_is_on = True - light.async_force_update = self._noop_async + refreshes = [] + + async def stale_refresh(*_args, **_kwargs): + refreshes.append(True) + + light.async_force_update = stale_refresh asyncio.run(light._async_confirm_command(1)) + self.assertEqual(len(refreshes), 2) self.assertIsNone(light._optimistic_is_on) + def test_stale_first_refresh_retries_until_hub_confirms(self): + light, device = self._light(is_on=False) + light._optimistic_gen = 1 + light._optimistic_is_on = True + refreshes = [] + + async def refresh(*_args, **_kwargs): + refreshes.append(True) + if len(refreshes) == 2: + device.is_on = True + light._handle_coordinator_update() + + light.async_force_update = refresh + + asyncio.run(light._async_confirm_command(1)) + + self.assertEqual(len(refreshes), 2) + self.assertIsNone(light._optimistic_is_on) + self.assertTrue(light.is_on) + def test_failed_command_restores_hub_state(self): light, device = self._light(is_on=False) light._schedule_command_confirmation = lambda _gen: None @@ -199,6 +225,18 @@ def test_coordinator_update_clears_optimistic_once_confirmed(self): self.assertIsNone(light._optimistic_is_on) self.assertTrue(light.is_on) + def test_brightness_optimistic_state_waits_for_matching_hub_value(self): + light, device = self._light(is_on=True) + light._optimistic_percentage = 60 + + device.current_percentage = 20 + light._handle_coordinator_update() + self.assertEqual(light._optimistic_percentage, 60) + + device.current_percentage = 60 + light._handle_coordinator_update() + self.assertIsNone(light._optimistic_percentage) + if __name__ == "__main__": unittest.main() From e4553dc1418b512564ac0114bf2964f812b31c6d Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Tue, 13 Oct 2026 12:16:46 +0100 Subject: [PATCH 129/154] fix: improve smart plug command confirmation --- custom_components/wiser/button.py | 2 +- custom_components/wiser/cover.py | 2 +- custom_components/wiser/light.py | 2 + custom_components/wiser/number.py | 8 ++-- custom_components/wiser/select.py | 2 +- custom_components/wiser/switch.py | 68 +++++++++++++++++++++++++++---- tests/test_switch_hot_water.py | 66 ++++++++++++++++++++++++++---- 7 files changed, 128 insertions(+), 22 deletions(-) diff --git a/custom_components/wiser/button.py b/custom_components/wiser/button.py index ebd23aae..a0a13aab 100644 --- a/custom_components/wiser/button.py +++ b/custom_components/wiser/button.py @@ -84,7 +84,7 @@ async def async_force_update(self, delay: int = 0): """Force an update from the hub.""" _LOGGER.debug("Hub update initiated by %s", self._name) if delay: - asyncio.sleep(delay) + await asyncio.sleep(delay) state = await self.async_get_last_state() if state is not None and state.state is not None: self.__last_pressed = ( # pylint: disable=unused-private-member diff --git a/custom_components/wiser/cover.py b/custom_components/wiser/cover.py index b990fa3b..def76882 100644 --- a/custom_components/wiser/cover.py +++ b/custom_components/wiser/cover.py @@ -81,7 +81,7 @@ def __init__(self, coordinator, shutter_id) -> None: async def async_force_update(self, delay: int = 0): _LOGGER.debug(f"Hub update initiated by {self.name}") if delay: - asyncio.sleep(delay) + await asyncio.sleep(delay) await self._data.async_refresh() @callback diff --git a/custom_components/wiser/light.py b/custom_components/wiser/light.py index 1172a070..c2cfbd33 100644 --- a/custom_components/wiser/light.py +++ b/custom_components/wiser/light.py @@ -87,6 +87,8 @@ async def _async_confirm_command(self, gen: int) -> None: # visible in hub data. Keep the optimistic state through one stale # read and try once more instead of reverting until the next scan. for _attempt in range(2): + if gen != self._optimistic_gen: + return await self.async_force_update(2) if gen != self._optimistic_gen or ( self._optimistic_is_on is None diff --git a/custom_components/wiser/number.py b/custom_components/wiser/number.py index 12fda50a..0e9e336c 100644 --- a/custom_components/wiser/number.py +++ b/custom_components/wiser/number.py @@ -87,7 +87,7 @@ def __init__(self, coordinator, name) -> None: async def async_force_update(self, delay: int = 0): _LOGGER.debug(f"Hub update initiated by {self._name}") if delay: - asyncio.sleep(delay) + await asyncio.sleep(delay) await self._data.async_refresh() @callback @@ -172,7 +172,7 @@ def __init__(self, coordinator, actuator, device_type) -> None: async def async_force_update(self, delay: int = 0): _LOGGER.debug(f"Hub update initiated by {self._name}") if delay: - asyncio.sleep(delay) + await asyncio.sleep(delay) await self._data.async_refresh() @callback @@ -268,7 +268,7 @@ def __init__(self, coordinator, name) -> None: async def async_force_update(self, delay: int = 0): _LOGGER.debug(f"Hub update initiated by {self._name}") if delay: - asyncio.sleep(delay) + await asyncio.sleep(delay) await self._data.async_refresh() @callback @@ -352,7 +352,7 @@ def __init__(self, coordinator, name) -> None: async def async_force_update(self, delay: int = 0): _LOGGER.debug(f"Hub update initiated by {self._name}") if delay: - asyncio.sleep(delay) + await asyncio.sleep(delay) await self._data.async_refresh() @callback diff --git a/custom_components/wiser/select.py b/custom_components/wiser/select.py index b6966cf4..70cc374f 100644 --- a/custom_components/wiser/select.py +++ b/custom_components/wiser/select.py @@ -89,7 +89,7 @@ def __init__(self, coordinator) -> None: async def async_force_update(self, delay: int = 0): _LOGGER.debug(f"Hub update initiated by {self._attr_translation_key}") if delay: - asyncio.sleep(delay) + await asyncio.sleep(delay) await self._data.async_refresh() @callback diff --git a/custom_components/wiser/switch.py b/custom_components/wiser/switch.py index ad21b371..be4c4395 100755 --- a/custom_components/wiser/switch.py +++ b/custom_components/wiser/switch.py @@ -508,6 +508,36 @@ def __init__(self, data, plugId, name) -> None: self._device = self._data.wiserhub.devices.get_by_id(self._device_id) self._schedule = self._device.schedule self._is_on = self._device.is_on + self._optimistic_is_on = None + self._optimistic_gen = 0 + + async def _async_confirm_command(self, gen: int) -> None: + """Refresh until the hub reports the accepted smart-plug command.""" + try: + for _attempt in range(2): + if gen != self._optimistic_gen: + return + await self.async_force_update(2) + if gen != self._optimistic_gen or self._optimistic_is_on is None: + return + finally: + if gen == self._optimistic_gen: + self._clear_optimistic_state() + + @callback + def _schedule_command_confirmation(self, gen: int) -> None: + """Confirm a command without delaying the Home Assistant service call.""" + self.hass.async_create_task( + self._async_confirm_command(gen), + f"Wiser smart plug command confirmation: {self.entity_id}", + ) + + @callback + def _clear_optimistic_state(self) -> None: + """Return the entity to the latest state reported by the hub.""" + self._optimistic_is_on = None + self._is_on = self._device.is_on + self.async_write_ha_state() @callback def _handle_coordinator_update(self) -> None: @@ -515,7 +545,12 @@ def _handle_coordinator_update(self) -> None: super()._handle_coordinator_update() self._device = self._data.wiserhub.devices.get_by_id(self._device_id) self._schedule = self._device.schedule - self._is_on = self._device.is_on + if ( + self._optimistic_is_on is None + or self._device.is_on == self._optimistic_is_on + ): + self._is_on = self._device.is_on + self._optimistic_is_on = None self.async_write_ha_state() @property @@ -567,22 +602,39 @@ def extra_state_attributes(self): @hub_error_handler async def async_turn_on(self, **kwargs): """Turn the device on.""" - await self._device.turn_on() - # Publish the accepted command immediately. The hub takes a few seconds - # to report the new value, so waiting for the refresh leaves every HA - # dashboard card showing the previous state in the meantime. + self._optimistic_gen += 1 + gen = self._optimistic_gen + self._optimistic_is_on = True self._is_on = True self.async_write_ha_state() - await self.async_force_update(2) + + try: + await self._device.turn_on() + except Exception: + if gen == self._optimistic_gen: + self._clear_optimistic_state() + raise + + self._schedule_command_confirmation(gen) return True @hub_error_handler async def async_turn_off(self, **kwargs): """Turn the device off.""" - await self._device.turn_off() + self._optimistic_gen += 1 + gen = self._optimistic_gen + self._optimistic_is_on = False self._is_on = False self.async_write_ha_state() - await self.async_force_update(2) + + try: + await self._device.turn_off() + except Exception: + if gen == self._optimistic_gen: + self._clear_optimistic_state() + raise + + self._schedule_command_confirmation(gen) return True diff --git a/tests/test_switch_hot_water.py b/tests/test_switch_hot_water.py index e4f58185..fccba6f6 100644 --- a/tests/test_switch_hot_water.py +++ b/tests/test_switch_hot_water.py @@ -213,23 +213,75 @@ async def refresh(delay=0): events.append(("refresh", delay, switch.is_on)) switch.async_force_update = refresh - return switch, plug, events + scheduled = [] + switch._schedule_command_confirmation = scheduled.append + return switch, plug, events, scheduled - def test_turn_on_publishes_on_before_delayed_refresh(self) -> None: - switch, plug, events = self._switch(is_on=False) + def test_turn_on_publishes_on_before_background_confirmation(self) -> None: + switch, plug, events, scheduled = self._switch(is_on=False) asyncio.run(switch.async_turn_on()) self.assertEqual(plug.commands, ["turn_on"]) - self.assertEqual(events, [("write", True, "On"), ("refresh", 2, True)]) + self.assertEqual(events, [("write", True, "On")]) + self.assertEqual(scheduled, [1]) - def test_turn_off_publishes_off_before_delayed_refresh(self) -> None: - switch, plug, events = self._switch(is_on=True) + def test_turn_off_publishes_off_before_background_confirmation(self) -> None: + switch, plug, events, scheduled = self._switch(is_on=True) asyncio.run(switch.async_turn_off()) self.assertEqual(plug.commands, ["turn_off"]) - self.assertEqual(events, [("write", False, "Off"), ("refresh", 2, False)]) + self.assertEqual(events, [("write", False, "Off")]) + self.assertEqual(scheduled, [1]) + + def test_stale_first_refresh_retries_until_hub_confirms(self) -> None: + switch, plug, events, scheduled = self._switch(is_on=False) + asyncio.run(switch.async_turn_on()) + refreshes = [] + + async def refresh(*_args, **_kwargs): + refreshes.append(True) + if len(refreshes) == 2: + plug.is_on = True + switch._handle_coordinator_update() + + switch.async_force_update = refresh + asyncio.run(switch._async_confirm_command(1)) + + self.assertEqual(len(refreshes), 2) + self.assertIsNone(switch._optimistic_is_on) + self.assertTrue(switch.is_on) + + def test_superseded_confirmation_does_not_clobber_newer_command(self) -> None: + switch, plug, events, scheduled = self._switch(is_on=True) + switch._optimistic_gen = 2 + switch._optimistic_is_on = False + switch._is_on = False + + asyncio.run(switch._async_confirm_command(1)) + + self.assertIs(switch._optimistic_is_on, False) + self.assertFalse(switch.is_on) + + def test_failed_command_restores_hub_state(self) -> None: + switch, plug, events, scheduled = self._switch(is_on=False) + + async def fail(): + raise RuntimeError("command failed") + + plug.turn_on = fail + + with self.assertRaisesRegex(RuntimeError, "command failed"): + asyncio.run(switch.async_turn_on()) + + self.assertEqual(scheduled, []) + self.assertIsNone(switch._optimistic_is_on) + self.assertFalse(switch.is_on) + self.assertEqual( + events, + [("write", True, "On"), ("write", False, "Off")], + ) if __name__ == "__main__": From afc51ae07b5e806faa4feb8f0e7bee2bfd51249c Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Tue, 13 Oct 2026 12:20:08 +0100 Subject: [PATCH 130/154] fix: cancel obsolete command confirmations --- custom_components/wiser/light.py | 17 ++++++++- custom_components/wiser/switch.py | 13 ++++++- tests/test_light_optimistic_state.py | 48 +++++++++++++++++++++++++ tests/test_switch_hot_water.py | 54 ++++++++++++++++++++++++++++ 4 files changed, 130 insertions(+), 2 deletions(-) diff --git a/custom_components/wiser/light.py b/custom_components/wiser/light.py index c2cfbd33..48fe0fba 100644 --- a/custom_components/wiser/light.py +++ b/custom_components/wiser/light.py @@ -72,6 +72,7 @@ def __init__(self, coordinator, light_id) -> None: # optimistic state if it is still the latest, so rapid toggles don't let # an earlier command wipe a newer command's value. self._optimistic_gen = 0 + self._confirmation_task = None _LOGGER.debug(f"{self._data.wiserhub.system.name} {self.name} initialise") async def async_force_update(self, delay: int = 0): @@ -106,11 +107,25 @@ async def _async_confirm_command(self, gen: int) -> None: @callback def _schedule_command_confirmation(self, gen: int) -> None: """Confirm a command without delaying the Home Assistant service call.""" - self.hass.async_create_task( + # A newer command makes the previous confirmation obsolete. Cancelling + # it also avoids an unnecessary full hub refresh after a rapid toggle. + if self._confirmation_task is not None: + self._confirmation_task.cancel() + self._confirmation_task = self.hass.async_create_task( self._async_confirm_command(gen), f"Wiser light command confirmation: {self.entity_id}", ) + async def async_will_remove_from_hass(self) -> None: + """Cancel delayed confirmation when Home Assistant removes the entity.""" + # Invalidate the task before cancellation so its finally block cannot + # write state for an entity that is being unloaded. + self._optimistic_gen += 1 + if self._confirmation_task is not None: + self._confirmation_task.cancel() + self._confirmation_task = None + await super().async_will_remove_from_hass() + @callback def _handle_coordinator_update(self) -> None: _LOGGER.debug(f"{self.name} updating") diff --git a/custom_components/wiser/switch.py b/custom_components/wiser/switch.py index be4c4395..881dfaab 100755 --- a/custom_components/wiser/switch.py +++ b/custom_components/wiser/switch.py @@ -510,6 +510,7 @@ def __init__(self, data, plugId, name) -> None: self._is_on = self._device.is_on self._optimistic_is_on = None self._optimistic_gen = 0 + self._confirmation_task = None async def _async_confirm_command(self, gen: int) -> None: """Refresh until the hub reports the accepted smart-plug command.""" @@ -527,11 +528,21 @@ async def _async_confirm_command(self, gen: int) -> None: @callback def _schedule_command_confirmation(self, gen: int) -> None: """Confirm a command without delaying the Home Assistant service call.""" - self.hass.async_create_task( + if self._confirmation_task is not None: + self._confirmation_task.cancel() + self._confirmation_task = self.hass.async_create_task( self._async_confirm_command(gen), f"Wiser smart plug command confirmation: {self.entity_id}", ) + async def async_will_remove_from_hass(self) -> None: + """Cancel delayed confirmation when Home Assistant removes the entity.""" + self._optimistic_gen += 1 + if self._confirmation_task is not None: + self._confirmation_task.cancel() + self._confirmation_task = None + await super().async_will_remove_from_hass() + @callback def _clear_optimistic_state(self) -> None: """Return the entity to the latest state reported by the hub.""" diff --git a/tests/test_light_optimistic_state.py b/tests/test_light_optimistic_state.py index c1fb0517..a201a418 100644 --- a/tests/test_light_optimistic_state.py +++ b/tests/test_light_optimistic_state.py @@ -49,6 +49,9 @@ class CoordinatorEntity: def __init__(self, *args: object) -> None: pass + async def async_will_remove_from_hass(self) -> None: + self.removed = True + _module( "homeassistant.helpers.update_coordinator", CoordinatorEntity=CoordinatorEntity ) @@ -237,6 +240,51 @@ def test_brightness_optimistic_state_waits_for_matching_hub_value(self): light._handle_coordinator_update() self.assertIsNone(light._optimistic_percentage) + def test_new_confirmation_cancels_superseded_task(self): + light, _device = self._light(is_on=False) + tasks = [] + + class FakeTask: + cancelled = False + + def cancel(self): + self.cancelled = True + + def create_task(coro, _name): + coro.close() + task = FakeTask() + tasks.append(task) + return task + + light.hass = SimpleNamespace(async_create_task=create_task) + light.entity_id = "light.test" + + light._schedule_command_confirmation(1) + light._schedule_command_confirmation(2) + + self.assertTrue(tasks[0].cancelled) + self.assertFalse(tasks[1].cancelled) + + def test_removal_invalidates_and_cancels_confirmation(self): + light, _device = self._light(is_on=False) + + class FakeTask: + cancelled = False + + def cancel(self): + self.cancelled = True + + task = FakeTask() + light._confirmation_task = task + previous_gen = light._optimistic_gen + + asyncio.run(light.async_will_remove_from_hass()) + + self.assertTrue(task.cancelled) + self.assertEqual(light._optimistic_gen, previous_gen + 1) + self.assertIsNone(light._confirmation_task) + self.assertTrue(light.removed) + if __name__ == "__main__": unittest.main() diff --git a/tests/test_switch_hot_water.py b/tests/test_switch_hot_water.py index fccba6f6..dc171b0d 100644 --- a/tests/test_switch_hot_water.py +++ b/tests/test_switch_hot_water.py @@ -46,6 +46,9 @@ class CoordinatorEntity: def __init__(self, *args: object) -> None: pass + async def async_will_remove_from_hass(self) -> None: + self.removed = True + _module( "homeassistant.helpers.update_coordinator", CoordinatorEntity=CoordinatorEntity ) @@ -283,6 +286,57 @@ async def fail(): [("write", True, "On"), ("write", False, "Off")], ) + def test_new_confirmation_cancels_superseded_task(self) -> None: + switch, _plug, _events, _scheduled = self._switch(is_on=False) + tasks = [] + + class FakeTask: + cancelled = False + + def cancel(self): + self.cancelled = True + + def create_task(coro, _name): + coro.close() + task = FakeTask() + tasks.append(task) + return task + + switch.hass = SimpleNamespace(async_create_task=create_task) + switch.entity_id = "switch.test" + + # Restore the real method replaced by the helper's command spy. + switch._schedule_command_confirmation = ( + self.switch_module.WiserSmartPlugSwitch._schedule_command_confirmation.__get__( + switch + ) + ) + switch._schedule_command_confirmation(1) + switch._schedule_command_confirmation(2) + + self.assertTrue(tasks[0].cancelled) + self.assertFalse(tasks[1].cancelled) + + def test_removal_invalidates_and_cancels_confirmation(self) -> None: + switch, _plug, _events, _scheduled = self._switch(is_on=False) + + class FakeTask: + cancelled = False + + def cancel(self): + self.cancelled = True + + task = FakeTask() + switch._confirmation_task = task + previous_gen = switch._optimistic_gen + + asyncio.run(switch.async_will_remove_from_hass()) + + self.assertTrue(task.cancelled) + self.assertEqual(switch._optimistic_gen, previous_gen + 1) + self.assertIsNone(switch._confirmation_task) + self.assertTrue(switch.removed) + if __name__ == "__main__": unittest.main() From 80e6148c7598f982ea91a2df3be2ad5f7f6b5696 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Tue, 13 Oct 2026 14:48:46 +0100 Subject: [PATCH 131/154] fix: add passive mode support for UFH rooms --- custom_components/wiser/switch.py | 13 ++++++++++++- tests/test_switch_hot_water.py | 32 +++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/custom_components/wiser/switch.py b/custom_components/wiser/switch.py index ad21b371..3816e6ef 100755 --- a/custom_components/wiser/switch.py +++ b/custom_components/wiser/switch.py @@ -112,6 +112,17 @@ ] +def _room_supports_passive_mode(room) -> bool: + """Return whether a room has a heating device passive mode can control.""" + # Radiator rooms expose SmartValveIds, while UFH rooms expose an + # UnderFloorHeatingId instead. Both are controlled through the same room + # target-temperature API used by passive mode. + return ( + room.number_of_smartvalves > 0 + or room.underfloor_heating_id is not None + ) + + async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entities): """Add the Wiser System Switch entities.""" data = hass.data[DOMAIN][config_entry.entry_id][DATA] # Get Handler @@ -227,7 +238,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie # Add Room passive mode switches if data.enable_automations_passive_mode: for room in data.wiserhub.rooms.all: - if room.number_of_smartvalves > 0: + if _room_supports_passive_mode(room): wiser_switches.append( WiserPassiveModeSwitch( hass, data, room.id, f"Wiser Passive Mode {room.name}" diff --git a/tests/test_switch_hot_water.py b/tests/test_switch_hot_water.py index e4f58185..0650ef35 100644 --- a/tests/test_switch_hot_water.py +++ b/tests/test_switch_hot_water.py @@ -165,6 +165,38 @@ def test_turn_off_overrides_hot_water_state_to_off(self) -> None: self.assertEqual(self._override_calls, ["Off"]) +class WiserPassiveModeRoomSupportTest(unittest.TestCase): + """Tests for deciding which rooms receive a passive-mode switch.""" + + @classmethod + def setUpClass(cls) -> None: + cls.switch_module = _load_switch_module() + + def test_supports_smart_valve_room(self) -> None: + room = SimpleNamespace( + number_of_smartvalves=1, + underfloor_heating_id=None, + ) + + self.assertTrue(self.switch_module._room_supports_passive_mode(room)) + + def test_supports_ufh_only_room(self) -> None: + room = SimpleNamespace( + number_of_smartvalves=0, + underfloor_heating_id=4, + ) + + self.assertTrue(self.switch_module._room_supports_passive_mode(room)) + + def test_ignores_room_without_heating_device(self) -> None: + room = SimpleNamespace( + number_of_smartvalves=0, + underfloor_heating_id=None, + ) + + self.assertFalse(self.switch_module._room_supports_passive_mode(room)) + + class _FakeSmartPlug: def __init__(self, *, is_on: bool) -> None: self.is_on = is_on From 1ecf252f40fce6d75c559423c672019fa5c1a145 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Tue, 13 Oct 2026 14:52:34 +0100 Subject: [PATCH 132/154] feat: expose smoke alarm operating states --- custom_components/wiser/binary_sensor.py | 21 ++++++ custom_components/wiser/strings.json | 3 + custom_components/wiser/translations/de.json | 3 + .../wiser/translations/en-GB.json | 3 + custom_components/wiser/translations/en.json | 3 + custom_components/wiser/translations/fr.json | 3 + tests/test_sensor.py | 65 ++++++++++++++++++- 7 files changed, 100 insertions(+), 1 deletion(-) diff --git a/custom_components/wiser/binary_sensor.py b/custom_components/wiser/binary_sensor.py index 81826c63..00fc3093 100644 --- a/custom_components/wiser/binary_sensor.py +++ b/custom_components/wiser/binary_sensor.py @@ -171,6 +171,9 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie WiserFaultWarning(data, device.id, "Fault Warning"), WiserRemoteAlarm(data, device.id, "Remote Alarm"), WiserBatteryDefect(data, device.id, "Battery Defect"), + WiserACMains(data, device.id, "AC Mains"), + WiserTestMode(data, device.id, "Test Mode"), + WiserHushMode(data, device.id, "Hush Mode"), ] ) @@ -535,6 +538,24 @@ class WiserRemoteAlarm(BaseBinarySensor): """Smoke Alarm sensor.""" +class WiserACMains(BaseBinarySensor): + """Smoke alarm mains-power status sensor.""" + + _attr_device_class = BinarySensorDeviceClass.POWER + + +class WiserTestMode(BaseBinarySensor): + """Smoke alarm test-mode status sensor.""" + + _attr_icon = "mdi:test-tube" + + +class WiserHushMode(BaseBinarySensor): + """Smoke alarm hush-mode status sensor.""" + + _attr_icon = "mdi:volume-off" + + class WiserEquipment(BaseBinarySensor): """Binary sensor backed by optional equipment data.""" diff --git a/custom_components/wiser/strings.json b/custom_components/wiser/strings.json index 30cfdd5a..9f8e2f20 100755 --- a/custom_components/wiser/strings.json +++ b/custom_components/wiser/strings.json @@ -297,6 +297,9 @@ "fault_warning": { "name": "Fault warning" }, "remote_alarm": { "name": "Remote alarm" }, "battery_defect": { "name": "Battery defect" }, + "ac_mains": { "name": "AC mains" }, + "test_mode": { "name": "Test mode" }, + "hush_mode": { "name": "Hush mode" }, "controllable": { "name": "Controllable" }, "pcm_mode": { "name": "PCM mode" }, "window_detection_active": { "name": "Window detection active" }, diff --git a/custom_components/wiser/translations/de.json b/custom_components/wiser/translations/de.json index a4d801c2..23bdd7e8 100644 --- a/custom_components/wiser/translations/de.json +++ b/custom_components/wiser/translations/de.json @@ -295,6 +295,9 @@ "fault_warning": { "name": "Fehlerwarnung" }, "remote_alarm": { "name": "Fernalarm" }, "battery_defect": { "name": "Batteriedefekt" }, + "ac_mains": { "name": "Netzstrom" }, + "test_mode": { "name": "Testmodus" }, + "hush_mode": { "name": "Stummschaltungsmodus" }, "controllable": { "name": "Steuerbar" }, "pcm_mode": { "name": "PCM-Modus" }, "window_detection_active": { "name": "Fenstererkennung aktiv" }, diff --git a/custom_components/wiser/translations/en-GB.json b/custom_components/wiser/translations/en-GB.json index d2000cb9..14598fac 100644 --- a/custom_components/wiser/translations/en-GB.json +++ b/custom_components/wiser/translations/en-GB.json @@ -295,6 +295,9 @@ "fault_warning": { "name": "Fault warning" }, "remote_alarm": { "name": "Remote alarm" }, "battery_defect": { "name": "Battery defect" }, + "ac_mains": { "name": "AC mains" }, + "test_mode": { "name": "Test mode" }, + "hush_mode": { "name": "Hush mode" }, "controllable": { "name": "Controllable" }, "pcm_mode": { "name": "PCM mode" }, "window_detection_active": { "name": "Window detection active" }, diff --git a/custom_components/wiser/translations/en.json b/custom_components/wiser/translations/en.json index a6dc522e..e5dd405f 100755 --- a/custom_components/wiser/translations/en.json +++ b/custom_components/wiser/translations/en.json @@ -295,6 +295,9 @@ "fault_warning": { "name": "Fault warning" }, "remote_alarm": { "name": "Remote alarm" }, "battery_defect": { "name": "Battery defect" }, + "ac_mains": { "name": "AC mains" }, + "test_mode": { "name": "Test mode" }, + "hush_mode": { "name": "Hush mode" }, "controllable": { "name": "Controllable" }, "pcm_mode": { "name": "PCM mode" }, "window_detection_active": { "name": "Window detection active" }, diff --git a/custom_components/wiser/translations/fr.json b/custom_components/wiser/translations/fr.json index c9624c73..3ca0e2a2 100644 --- a/custom_components/wiser/translations/fr.json +++ b/custom_components/wiser/translations/fr.json @@ -295,6 +295,9 @@ "fault_warning": { "name": "Avertissement de défaut" }, "remote_alarm": { "name": "Alarme distante" }, "battery_defect": { "name": "Défaut de batterie" }, + "ac_mains": { "name": "Alimentation secteur" }, + "test_mode": { "name": "Mode test" }, + "hush_mode": { "name": "Mode silencieux" }, "controllable": { "name": "Contrôlable" }, "pcm_mode": { "name": "Mode PCM" }, "window_detection_active": { "name": "Détection de fenêtre active" }, diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 1b344e03..eea78b46 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -115,6 +115,7 @@ def available(self): get_hub_device_info=lambda _data: {"identifiers": {("wiser", "hub")}}, get_hub_via_device_info=lambda _data: {}, get_legacy_unique_id=lambda *_args: "legacy-unique-id", + get_light_binary_sensor_unique_id=lambda *_args: "light-binary-id", get_physical_entity_unique_id=lambda _data, domain, device_id, entity_type: ( f"physical-{domain}-{device_id}-{entity_type}" ), @@ -311,7 +312,13 @@ class BinarySensorEntity: assert spec and spec.loader module = importlib.util.module_from_spec(spec) sys.modules[spec.name] = module - spec.loader.exec_module(module) + # The classes exercised here precede WiserStateActive, whose structural + # pattern matching requires a newer Python than the lightweight local test + # runtime. Home Assistant itself runs a supported newer Python version. + source = BINARY_SENSOR_SOURCE_PATH.read_text(encoding="utf-8").split( + "class WiserStateActive", 1 + )[0] + exec(compile(source, BINARY_SENSOR_SOURCE_PATH, "exec"), module.__dict__) return module @@ -1427,6 +1434,62 @@ def test_capability_flag_is_a_diagnostic_entity(self): self.assertEqual(sensor._attr_entity_category, "diagnostic") +class WiserSmokeAlarmStatusSensorTest(unittest.TestCase): + """Tests for smoke-alarm status fields exposed by the API.""" + + @classmethod + def setUpClass(cls): + cls.binary_sensor_module = _load_binary_sensor_module() + + def setUp(self): + self.device = SimpleNamespace( + ac_mains=True, + test_mode=False, + hush_mode=True, + product_type="SmokeAlarmDevice", + firmware_version="1.0", + ) + self.data = SimpleNamespace( + last_update_success=True, + wiserhub=SimpleNamespace( + devices=SimpleNamespace(get_by_id=lambda _device_id: self.device), + rooms=SimpleNamespace(get_by_device_id=lambda _device_id: None), + system=SimpleNamespace(name="WiserHeat123456"), + ), + ) + + def test_reads_ac_mains_state(self): + sensor = self.binary_sensor_module.WiserACMains( + self.data, 7, "AC Mains" + ) + sensor.async_write_ha_state = Mock() + + self.assertTrue(sensor.is_on) + self.assertEqual(sensor._attr_device_class, "power") + + self.device.ac_mains = False + sensor._handle_coordinator_update() + + self.assertFalse(sensor.is_on) + sensor.async_write_ha_state.assert_called_once_with() + + def test_reads_test_mode_state(self): + sensor = self.binary_sensor_module.WiserTestMode( + self.data, 7, "Test Mode" + ) + + self.assertFalse(sensor.is_on) + self.assertEqual(sensor._attr_icon, "mdi:test-tube") + + def test_reads_hush_mode_state(self): + sensor = self.binary_sensor_module.WiserHushMode( + self.data, 7, "Hush Mode" + ) + + self.assertTrue(sensor.is_on) + self.assertEqual(sensor._attr_icon, "mdi:volume-off") + + class WiserEquipmentBinarySensorTest(unittest.TestCase): """Tests for binary sensors backed by optional equipment data.""" From 1cae39a5c9642f1198611f3fa08984bd260e3858 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Tue, 13 Oct 2026 15:01:30 +0100 Subject: [PATCH 133/154] feat: add EV charger entities --- custom_components/wiser/config_flow.py | 1 + custom_components/wiser/helpers.py | 3 + custom_components/wiser/sensor.py | 27 +++++++ custom_components/wiser/strings.json | 1 + custom_components/wiser/switch.py | 71 ++++++++++++++++++- custom_components/wiser/translations/de.json | 1 + .../wiser/translations/en-GB.json | 1 + custom_components/wiser/translations/en.json | 1 + custom_components/wiser/translations/fr.json | 1 + tests/test_sensor.py | 4 +- tests/test_switch_hot_water.py | 60 ++++++++++++++++ 11 files changed, 168 insertions(+), 3 deletions(-) diff --git a/custom_components/wiser/config_flow.py b/custom_components/wiser/config_flow.py index fed0d4b5..c6e6e0e4 100755 --- a/custom_components/wiser/config_flow.py +++ b/custom_components/wiser/config_flow.py @@ -290,6 +290,7 @@ def all_devices(collection_name): "power_tags", "power_tags_c", "heating_actuators", + "evse", ) for device in all_devices(collection_name) ) diff --git a/custom_components/wiser/helpers.py b/custom_components/wiser/helpers.py index a910d9e2..14a8eee0 100644 --- a/custom_components/wiser/helpers.py +++ b/custom_components/wiser/helpers.py @@ -138,6 +138,9 @@ def get_device_name(data, device_id, device_type="device"): if device.product_type == "SmartPlug": return f"{ENTITY_PREFIX} {device.name}" + if device.product_type == "EVSE": + return f"{ENTITY_PREFIX} {device.name}" + if device.product_type in ["PowerTagE", "LoadControl"]: return f"{ENTITY_PREFIX} {device.name}" diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index 34687611..53f33826 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -316,6 +316,33 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie ) + # Add EV charger electrical telemetry. EVSE devices are published by the + # Gen 2 hub as Equipment records rather than as SmartPlug records. + if data.wiserhub.devices.evse: + _LOGGER.debug("Setting up EV charger power sensors") + for evse in data.wiserhub.devices.evse.all: + if equipment_sensors_enabled: + wiser_sensors.append(WiserEquipmentSensor(data, evse.id)) + wiser_sensors.extend( + [ + WiserLTSPowerSensor( + data, evse.id, sensor_type="Power", name="Power" + ), + WiserLTSPowerSensor( + data, + evse.id, + sensor_type="Energy", + name="Total Energy", + ), + WiserCurrentVoltageSensor( + data, evse.id, sensor_type="Voltage" + ), + WiserCurrentVoltageSensor( + data, evse.id, sensor_type="Current" + ), + ] + ) + # Add power sensors for PTE (v2Hub) if data.wiserhub.devices.power_tags: for power_tag in data.wiserhub.devices.power_tags.all: diff --git a/custom_components/wiser/strings.json b/custom_components/wiser/strings.json index 30cfdd5a..63bdb70d 100755 --- a/custom_components/wiser/strings.json +++ b/custom_components/wiser/strings.json @@ -275,6 +275,7 @@ "device_lock": { "name": "Device lock" }, "identify": { "name": "Identify" }, "outlet": { "name": "Outlet" }, + "ev_charger": { "name": "EV charger" }, "away_mode_turns_off": { "name": "Away mode turns off" }, "away_mode_closes": { "name": "Away mode closes" }, "passive_mode": { "name": "Passive mode" }, diff --git a/custom_components/wiser/switch.py b/custom_components/wiser/switch.py index ad21b371..669fcfcc 100755 --- a/custom_components/wiser/switch.py +++ b/custom_components/wiser/switch.py @@ -16,7 +16,14 @@ from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.update_coordinator import CoordinatorEntity -from .const import DATA, DOMAIN, ENTITY_PREFIX, HOT_WATER, MANUFACTURER +from .const import ( + DATA, + DOMAIN, + ENTITY_PREFIX, + HOT_WATER, + MANUFACTURER, + MANUFACTURER_SCHNEIDER, +) from .entity import WiserEntityMixin from .helpers import ( get_device_name, @@ -196,6 +203,11 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie ] ) + # EV chargers use the hub's Equipment control states rather than the + # SmartPlug RequestOutput command. + for evse in data.wiserhub.devices.evse.all: + wiser_switches.append(WiserEVSESwitch(data, evse.id)) + # Add threshold sensor interacts with room climate switch for device in data.wiserhub.devices.all: if hasattr(device, "interacts_with_room_climate"): @@ -586,6 +598,63 @@ async def async_turn_off(self, **kwargs): return True +class WiserEVSESwitch(WiserSwitch): + """Switch that allows or force-disables EV charging.""" + + def __init__(self, data, device_id) -> None: + self._device_id = device_id + super().__init__(data, "EV Charger", "", "evse", "mdi:ev-station") + self._attr_translation_key = "ev_charger" + self._device = self._data.wiserhub.devices.evse.get_by_id(device_id) + self._is_on = self._device.is_on + + @callback + def _handle_coordinator_update(self) -> None: + """Refresh state from the latest equipment record.""" + super()._handle_coordinator_update() + self._device = self._data.wiserhub.devices.evse.get_by_id(self._device_id) + self._is_on = self._device.is_on + self.async_write_ha_state() + + @property + def unique_id(self): + """Return a stable physical-device entity ID.""" + return get_physical_entity_unique_id( + self._data, "switch", self._device_id, "ev_charger" + ) + + @property + def device_info(self): + """Return EV charger device registry information.""" + return { + "name": get_device_name(self._data, self._device_id), + "identifiers": {(DOMAIN, get_identifier(self._data, self._device_id))}, + "manufacturer": MANUFACTURER_SCHNEIDER, + "model": self._device.model, + "sw_version": self._device.firmware_version, + **get_hub_via_device_info(self._data), + } + + @property + def extra_state_attributes(self): + """Return the hub's current EVSE control state.""" + return {"control_state": self._device.control_state} + + @hub_error_handler + async def async_turn_on(self, **kwargs): + """Return charging control to the Wiser system.""" + await self._device.turn_on() + await self.async_force_update() + return True + + @hub_error_handler + async def async_turn_off(self, **kwargs): + """Force charging consumption off.""" + await self._device.turn_off() + await self.async_force_update() + return True + + class WiserSmartPlugAwayActionSwitch(WiserSwitch): """Plug SwitchEntity Class.""" diff --git a/custom_components/wiser/translations/de.json b/custom_components/wiser/translations/de.json index a4d801c2..b588177e 100644 --- a/custom_components/wiser/translations/de.json +++ b/custom_components/wiser/translations/de.json @@ -273,6 +273,7 @@ "device_lock": { "name": "Gerätesperre" }, "identify": { "name": "Identifizieren" }, "outlet": { "name": "Steckdose" }, + "ev_charger": { "name": "EV-Ladegerät" }, "away_mode_turns_off": { "name": "Abwesenheitsmodus schaltet aus" }, "away_mode_closes": { "name": "Abwesenheitsmodus schließt" }, "passive_mode": { "name": "Passivmodus" }, diff --git a/custom_components/wiser/translations/en-GB.json b/custom_components/wiser/translations/en-GB.json index d2000cb9..3d798b57 100644 --- a/custom_components/wiser/translations/en-GB.json +++ b/custom_components/wiser/translations/en-GB.json @@ -273,6 +273,7 @@ "device_lock": { "name": "Device lock" }, "identify": { "name": "Identify" }, "outlet": { "name": "Socket" }, + "ev_charger": { "name": "EV charger" }, "away_mode_turns_off": { "name": "Away mode turns off" }, "away_mode_closes": { "name": "Away mode closes" }, "passive_mode": { "name": "Passive mode" }, diff --git a/custom_components/wiser/translations/en.json b/custom_components/wiser/translations/en.json index a6dc522e..44a9f3a3 100755 --- a/custom_components/wiser/translations/en.json +++ b/custom_components/wiser/translations/en.json @@ -273,6 +273,7 @@ "device_lock": { "name": "Device lock" }, "identify": { "name": "Identify" }, "outlet": { "name": "Outlet" }, + "ev_charger": { "name": "EV charger" }, "away_mode_turns_off": { "name": "Away mode turns off" }, "away_mode_closes": { "name": "Away mode closes" }, "passive_mode": { "name": "Passive mode" }, diff --git a/custom_components/wiser/translations/fr.json b/custom_components/wiser/translations/fr.json index c9624c73..ac62d7e0 100644 --- a/custom_components/wiser/translations/fr.json +++ b/custom_components/wiser/translations/fr.json @@ -273,6 +273,7 @@ "device_lock": { "name": "Verrouillage de l’appareil" }, "identify": { "name": "Identifier" }, "outlet": { "name": "Prise" }, + "ev_charger": { "name": "Chargeur de véhicule électrique" }, "away_mode_turns_off": { "name": "Le mode absence éteint" }, "away_mode_closes": { "name": "Le mode absence ferme" }, "passive_mode": { "name": "Mode passif" }, diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 1b344e03..054aab6e 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -740,8 +740,8 @@ def test_detailed_equipment_readings_are_opt_in(self) -> None: 'config_entry.options.get(\n CONF_EQUIPMENT_SENSORS, False', setup_source, ) - self.assertEqual(setup_source.count("WiserEquipmentSensor("), 4) - self.assertEqual(setup_source.count("if equipment_sensors_enabled"), 4) + self.assertEqual(setup_source.count("WiserEquipmentSensor("), 5) + self.assertEqual(setup_source.count("if equipment_sensors_enabled"), 5) self.assertNotIn("equipment_id > 0", setup_source) self.assertIn("power_tags_c", setup_source) self.assertNotIn('legacy_name="Equipment Energy Delivered"', setup_source) diff --git a/tests/test_switch_hot_water.py b/tests/test_switch_hot_water.py index e4f58185..33fce1fb 100644 --- a/tests/test_switch_hot_water.py +++ b/tests/test_switch_hot_water.py @@ -59,6 +59,7 @@ def __init__(self, *args: object) -> None: ENTITY_PREFIX="Wiser", HOT_WATER="hot_water", MANUFACTURER="Drayton", + MANUFACTURER_SCHNEIDER="Schneider Electric", ) def hub_error_handler(func): @@ -232,5 +233,64 @@ def test_turn_off_publishes_off_before_delayed_refresh(self) -> None: self.assertEqual(events, [("write", False, "Off"), ("refresh", 2, False)]) +class _FakeEVSE: + def __init__(self, *, is_on: bool) -> None: + self.is_on = is_on + self.control_state = "selfManagement" if is_on else "consumptionForceOff" + self.model = "EVSCKT/OUTLET/1" + self.firmware_version = "2.10.0" + self.commands = [] + + async def turn_on(self) -> None: + self.commands.append("turn_on") + + async def turn_off(self) -> None: + self.commands.append("turn_off") + + +class WiserEVSESwitchTest(unittest.TestCase): + """Tests for EV charger switch commands and registry identity.""" + + @classmethod + def setUpClass(cls) -> None: + cls.switch_module = _load_switch_module() + + def _switch(self, *, is_on: bool): + device = _FakeEVSE(is_on=is_on) + evse = SimpleNamespace(get_by_id=lambda _id: device) + data = SimpleNamespace( + wiserhub=SimpleNamespace( + system=SimpleNamespace(name="WiserHeat045XXX"), + devices=SimpleNamespace(evse=evse), + ) + ) + switch = self.switch_module.WiserEVSESwitch(data, 12) + switch.async_force_update = self._noop_async + return switch, device + + async def _noop_async(self, *_args, **_kwargs) -> None: + return None + + def test_turn_on_returns_control_to_wiser(self) -> None: + switch, device = self._switch(is_on=False) + + asyncio.run(switch.async_turn_on()) + + self.assertEqual(device.commands, ["turn_on"]) + + def test_turn_off_force_disables_charging(self) -> None: + switch, device = self._switch(is_on=True) + + asyncio.run(switch.async_turn_off()) + + self.assertEqual(device.commands, ["turn_off"]) + + def test_uses_physical_device_identity(self) -> None: + switch, _device = self._switch(is_on=True) + + self.assertEqual(switch.unique_id, "physical-entity-id") + self.assertEqual(switch.device_info["model"], "EVSCKT/OUTLET/1") + + if __name__ == "__main__": unittest.main() From 34d9401fa3c499c2f19b12c29ccab9bbf11969bf Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Tue, 13 Oct 2026 15:01:53 +0100 Subject: [PATCH 134/154] fix: retain compatibility with released API --- custom_components/wiser/sensor.py | 5 +++-- custom_components/wiser/switch.py | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index 53f33826..0cc8247d 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -318,9 +318,10 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie # Add EV charger electrical telemetry. EVSE devices are published by the # Gen 2 hub as Equipment records rather than as SmartPlug records. - if data.wiserhub.devices.evse: + evse_collection = getattr(data.wiserhub.devices, "evse", None) + if evse_collection: _LOGGER.debug("Setting up EV charger power sensors") - for evse in data.wiserhub.devices.evse.all: + for evse in evse_collection.all: if equipment_sensors_enabled: wiser_sensors.append(WiserEquipmentSensor(data, evse.id)) wiser_sensors.extend( diff --git a/custom_components/wiser/switch.py b/custom_components/wiser/switch.py index 669fcfcc..ee0bed85 100755 --- a/custom_components/wiser/switch.py +++ b/custom_components/wiser/switch.py @@ -205,8 +205,10 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie # EV chargers use the hub's Equipment control states rather than the # SmartPlug RequestOutput command. - for evse in data.wiserhub.devices.evse.all: - wiser_switches.append(WiserEVSESwitch(data, evse.id)) + evse_collection = getattr(data.wiserhub.devices, "evse", None) + if evse_collection: + for evse in evse_collection.all: + wiser_switches.append(WiserEVSESwitch(data, evse.id)) # Add threshold sensor interacts with room climate switch for device in data.wiserhub.devices.all: From d46393361af53e4067e728bdf406fd6ab8800eb8 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Wed, 14 Oct 2026 09:51:15 +0100 Subject: [PATCH 135/154] fix: use native names for light entities --- custom_components/wiser/binary_sensor.py | 5 +- custom_components/wiser/helpers.py | 27 +++++++++++ custom_components/wiser/light.py | 8 ++-- custom_components/wiser/select.py | 12 ++--- custom_components/wiser/switch.py | 9 ++-- tests/test_entity_naming.py | 1 + tests/test_light_optimistic_state.py | 1 + tests/test_light_unique_id_migration.py | 58 ++++++++++++++++++++++-- tests/test_sensor.py | 2 + tests/test_switch_hot_water.py | 1 + 10 files changed, 102 insertions(+), 22 deletions(-) diff --git a/custom_components/wiser/binary_sensor.py b/custom_components/wiser/binary_sensor.py index 81826c63..122d9079 100644 --- a/custom_components/wiser/binary_sensor.py +++ b/custom_components/wiser/binary_sensor.py @@ -13,7 +13,7 @@ from homeassistant.helpers import entity_registry as er from homeassistant.helpers.update_coordinator import CoordinatorEntity -from .const import CONF_OPENTHERM_SENSORS, DATA, DOMAIN, ENTITY_PREFIX, MANUFACTURER +from .const import CONF_OPENTHERM_SENSORS, DATA, DOMAIN, MANUFACTURER from .entity import WiserEntityMixin from .helpers import ( active_wiser_rooms, @@ -23,6 +23,7 @@ get_identifier, get_legacy_unique_id, get_light_binary_sensor_unique_id, + get_light_entity_name, get_physical_entity_unique_id, get_room_entity_unique_id, get_unique_id, @@ -602,7 +603,7 @@ def __init__(self, coordinator, light_id, sensor_type=""): @property def name(self): """Return the name of the sensor.""" - return f"{ENTITY_PREFIX} {self._light.name} {self._sensor_type}" + return get_light_entity_name(self._data, self._light, self._sensor_type) @property def unique_id(self): diff --git a/custom_components/wiser/helpers.py b/custom_components/wiser/helpers.py index a910d9e2..9dd4de00 100644 --- a/custom_components/wiser/helpers.py +++ b/custom_components/wiser/helpers.py @@ -184,6 +184,33 @@ def get_device_name(data, device_id, device_type="device"): return f"{ENTITY_PREFIX} {device_type}" +def get_light_entity_name(data, light, entity_name): + """Return a device-relative name for an entity belonging to a light. + + The hub repeats the physical device name in each light channel name. With + Home Assistant's native entity naming enabled, including that portion here + causes the device name to appear twice. Keep only a real channel suffix so + multi-gang devices remain distinguishable. + """ + light_name = str(getattr(light, "name", "")).strip() + if getattr(data, "legacy_naming", False): + return " ".join( + part for part in (ENTITY_PREFIX, light_name, entity_name) if part + ) + + physical_device = data.wiserhub.devices.get_by_id(light.id) + device_name = str(getattr(physical_device, "name", "")).strip() + + channel_name = light_name + if device_name: + if light_name.casefold() == device_name.casefold(): + channel_name = "" + elif light_name.casefold().startswith(f"{device_name} ".casefold()): + channel_name = light_name[len(device_name) :].strip() + + return " ".join(part for part in (channel_name, entity_name) if part) + + def get_legacy_device_name(data, device_id): """Return a physical device name used by historical entity unique IDs.""" device = data.wiserhub.devices.get_by_id(device_id) diff --git a/custom_components/wiser/light.py b/custom_components/wiser/light.py index 19e203e0..a6211e56 100644 --- a/custom_components/wiser/light.py +++ b/custom_components/wiser/light.py @@ -11,12 +11,13 @@ from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.update_coordinator import CoordinatorEntity -from .const import DATA, DOMAIN, ENTITY_PREFIX, MANUFACTURER_SCHNEIDER +from .const import DATA, DOMAIN, MANUFACTURER_SCHNEIDER from .entity import WiserEntityMixin from .helpers import ( get_device_name, get_hub_via_device_info, get_identifier, + get_light_entity_name, get_unique_id, hub_error_handler, ) @@ -118,10 +119,7 @@ def is_on(self): @property def name(self): """Return the name of the Device.""" - # Use the per-channel light name directly. It already carries room and - # channel (e.g. "Badezimmer Badewanne") and is distinct per channel, so - # the two channels of a multi-gang dimmer no longer collide. - return f"{ENTITY_PREFIX} {self._device.name} Light" + return get_light_entity_name(self._data, self._device, "Light") @property def icon(self): diff --git a/custom_components/wiser/select.py b/custom_components/wiser/select.py index b6966cf4..a30cd063 100644 --- a/custom_components/wiser/select.py +++ b/custom_components/wiser/select.py @@ -3,7 +3,6 @@ from .const import ( DATA, DOMAIN, - ENTITY_PREFIX, HOT_WATER, MANUFACTURER, ) @@ -12,6 +11,7 @@ from .helpers import ( get_device_name, get_hub_via_device_info, + get_light_entity_name, get_unique_id, get_identifier, hub_error_handler, @@ -260,9 +260,7 @@ def _handle_coordinator_update(self) -> None: @property def name(self): """Return Name of device.""" - # Per-channel light name so the two channels of a multi-gang dimmer do - # not collide (WiserSelectEntity.name would use the shared device id). - return f"{ENTITY_PREFIX} {self._device.name} Mode" + return get_light_entity_name(self._data, self._device, "Mode") @property def unique_id(self): @@ -324,7 +322,9 @@ def unique_id(self): @property def name(self): """Return Name of device.""" - return f"{ENTITY_PREFIX} {self._device.name} Power On Behaviour" + return get_light_entity_name( + self._data, self._device, "Power On Behaviour" + ) @property def current_option(self) -> str: @@ -376,7 +376,7 @@ def unique_id(self): @property def name(self): """Return Name of device.""" - return f"{ENTITY_PREFIX} {self._device.name} Led Indicator" + return get_light_entity_name(self._data, self._device, "LED Indicator") @property def current_option(self) -> str: diff --git a/custom_components/wiser/switch.py b/custom_components/wiser/switch.py index ad21b371..64df71fc 100755 --- a/custom_components/wiser/switch.py +++ b/custom_components/wiser/switch.py @@ -16,13 +16,14 @@ from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.update_coordinator import CoordinatorEntity -from .const import DATA, DOMAIN, ENTITY_PREFIX, HOT_WATER, MANUFACTURER +from .const import DATA, DOMAIN, HOT_WATER, MANUFACTURER from .entity import WiserEntityMixin from .helpers import ( get_device_name, get_hub_device_info, get_hub_via_device_info, get_identifier, + get_light_entity_name, get_physical_entity_unique_id, get_room_entity_unique_id, get_unique_id, @@ -671,9 +672,9 @@ def _handle_coordinator_update(self) -> None: @property def name(self): """Return the name of the Device.""" - # Per-channel light name so the two channels of a multi-gang dimmer do - # not collide. - return f"{ENTITY_PREFIX} {self._light.name} Away Mode Turns Off" + return get_light_entity_name( + self._data, self._light, "Away Mode Turns Off" + ) @property def unique_id(self): diff --git a/tests/test_entity_naming.py b/tests/test_entity_naming.py index 12a8c935..25979909 100644 --- a/tests/test_entity_naming.py +++ b/tests/test_entity_naming.py @@ -182,6 +182,7 @@ def test_unique_ids_do_not_depend_on_new_entity_names(self) -> None: def test_all_entity_unique_ids_are_uuid_backed(self) -> None: uuid_helpers = { + "get_light_binary_sensor_unique_id", "get_physical_entity_unique_id", "get_room_entity_unique_id", "get_unique_id", diff --git a/tests/test_light_optimistic_state.py b/tests/test_light_optimistic_state.py index 8bb5cb96..80672259 100644 --- a/tests/test_light_optimistic_state.py +++ b/tests/test_light_optimistic_state.py @@ -71,6 +71,7 @@ def hub_error_handler(func): get_device_name=lambda *_a, **_k: "Wiser Light", get_hub_via_device_info=lambda _data: {}, get_identifier=lambda *_a, **_k: "identifier", + get_light_entity_name=lambda _data, _light, entity_name: entity_name, get_unique_id=lambda *_a, **_k: "unique-id", hub_error_handler=hub_error_handler, ) diff --git a/tests/test_light_unique_id_migration.py b/tests/test_light_unique_id_migration.py index 8ebf30d1..34aca44d 100644 --- a/tests/test_light_unique_id_migration.py +++ b/tests/test_light_unique_id_migration.py @@ -42,6 +42,7 @@ def _load_helpers_module() -> ModuleType: WiserHubRESTError=type("WiserHubRESTError", (Exception,), {}), ) _module("homeassistant") + _module("homeassistant.const", MAJOR_VERSION=2026, MINOR_VERSION=10) _module("homeassistant.core", HomeAssistant=object) package = _module("wiser") @@ -70,15 +71,28 @@ def _hub_data(): _light(device_id=101, light_id=1, product_type="DimmableLight", name="Diele"), _light(device_id=102, light_id=2, product_type="OnOffLight", name="Flur"), # Two-gang dimmer: both channels share physical device id 200. - _light(device_id=200, light_id=3, product_type="DimmableLight", name="Bad Dusche"), - _light(device_id=200, light_id=4, product_type="DimmableLight", name="Bad Wanne"), + _light( + device_id=200, + light_id=3, + product_type="DimmableLight", + name="DualRelay Lightsource1", + ), + _light( + device_id=200, + light_id=4, + product_type="DimmableLight", + name="DualRelay Lightsource2", + ), ] - # get_device_name resolves the physical device; only single-gang ids should - # ever be looked up (multi-gang is skipped before this is called). Raising on - # an unexpected id turns an accidental multi-gang resolution into a failure. + # get_device_name resolves the physical device during migration, while the + # light naming helper also uses it to remove the shared device portion from + # a multi-gang channel name. devices_by_id = { 101: SimpleNamespace(id=101, product_type="DimmableLight", name="Diele"), 102: SimpleNamespace(id=102, product_type="OnOffLight", name="Flur"), + 200: SimpleNamespace( + id=200, product_type="DimmableLight", name="DualRelay" + ), } rooms_by_device = { 101: SimpleNamespace(name="Diele"), @@ -172,6 +186,40 @@ def test_no_room_light_uses_type_and_name(self) -> None: old = self._unique_id("device", "light", "Wiser OnOffLight Flur Light") self.assertEqual(mapping[old], self._unique_id("device", "light", 2)) + def test_single_light_entity_name_omits_physical_device_name(self) -> None: + data = _hub_data() + light = data.wiserhub.devices.lights.all[0] + + self.assertEqual( + self.helpers.get_light_entity_name( + data, light, "Away Mode Turns Off" + ), + "Away Mode Turns Off", + ) + + def test_multi_gang_entity_name_keeps_only_channel_name(self) -> None: + data = _hub_data() + light = data.wiserhub.devices.lights.all[2] + + self.assertEqual( + self.helpers.get_light_entity_name( + data, light, "Away Mode Turns Off" + ), + "Lightsource1 Away Mode Turns Off", + ) + + def test_legacy_naming_retains_full_light_name(self) -> None: + data = _hub_data() + data.legacy_naming = True + light = data.wiserhub.devices.lights.all[0] + + self.assertEqual( + self.helpers.get_light_entity_name( + data, light, "Away Mode Turns Off" + ), + "Wiser Diele Away Mode Turns Off", + ) + def test_multi_gang_channels_are_skipped(self) -> None: mapping = self._mapping() # No mapping may reference the shared physical device id 200 ... diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 1b344e03..de040986 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -115,6 +115,8 @@ def available(self): get_hub_device_info=lambda _data: {"identifiers": {("wiser", "hub")}}, get_hub_via_device_info=lambda _data: {}, get_legacy_unique_id=lambda *_args: "legacy-unique-id", + get_light_binary_sensor_unique_id=lambda *_args: "light-binary-sensor-id", + get_light_entity_name=lambda _data, _light, entity_name: entity_name, get_physical_entity_unique_id=lambda _data, domain, device_id, entity_type: ( f"physical-{domain}-{device_id}-{entity_type}" ), diff --git a/tests/test_switch_hot_water.py b/tests/test_switch_hot_water.py index e4f58185..950b558a 100644 --- a/tests/test_switch_hot_water.py +++ b/tests/test_switch_hot_water.py @@ -74,6 +74,7 @@ def hub_error_handler(func): get_identifier=lambda *_args: "identifier", get_legacy_device_name=lambda *_args, **_kwargs: "Wiser HeatHub", get_legacy_unique_id=lambda *_args: "legacy-unique-id", + get_light_entity_name=lambda _data, _light, entity_name: entity_name, get_physical_entity_unique_id=lambda *_args: "physical-entity-id", get_room_entity_unique_id=lambda *_args: "room-entity-id", get_unique_id=lambda *_args: "unique-id", From 8039170b87c8968cf3cfc869557a074af9da8386 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Wed, 14 Oct 2026 12:55:32 +0100 Subject: [PATCH 136/154] fix: strip Wiser prefix from light entity names --- custom_components/wiser/helpers.py | 32 +++++++++++++++++++++---- tests/test_light_unique_id_migration.py | 26 ++++++++++++++++++++ 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/custom_components/wiser/helpers.py b/custom_components/wiser/helpers.py index 9dd4de00..22db6557 100644 --- a/custom_components/wiser/helpers.py +++ b/custom_components/wiser/helpers.py @@ -200,13 +200,37 @@ def get_light_entity_name(data, light, entity_name): physical_device = data.wiserhub.devices.get_by_id(light.id) device_name = str(getattr(physical_device, "name", "")).strip() + product_type = str(getattr(physical_device, "product_type", "")).strip() + + # Some hub models include Wiser and/or the product type in the physical + # device name, while their channel names omit those prefixes. Compare all + # equivalent device-name forms so only the physical-device portion is + # removed from the channel name. + device_names = {device_name} + metadata_prefixes = tuple( + prefix for prefix in (ENTITY_PREFIX, product_type) if prefix + ) + pending_names = [device_name] + while pending_names: + candidate = pending_names.pop() + for prefix in metadata_prefixes: + marker = f"{prefix} " + if candidate.casefold().startswith(marker.casefold()): + stripped = candidate[len(marker) :].strip() + if stripped and stripped not in device_names: + device_names.add(stripped) + pending_names.append(stripped) channel_name = light_name - if device_name: - if light_name.casefold() == device_name.casefold(): + for candidate in sorted(device_names, key=len, reverse=True): + if candidate and light_name.casefold() == candidate.casefold(): channel_name = "" - elif light_name.casefold().startswith(f"{device_name} ".casefold()): - channel_name = light_name[len(device_name) :].strip() + break + if candidate and light_name.casefold().startswith( + f"{candidate} ".casefold() + ): + channel_name = light_name[len(candidate) :].strip() + break return " ".join(part for part in (channel_name, entity_name) if part) diff --git a/tests/test_light_unique_id_migration.py b/tests/test_light_unique_id_migration.py index 34aca44d..5f3db5b2 100644 --- a/tests/test_light_unique_id_migration.py +++ b/tests/test_light_unique_id_migration.py @@ -208,6 +208,32 @@ def test_multi_gang_entity_name_keeps_only_channel_name(self) -> None: "Lightsource1 Away Mode Turns Off", ) + def test_prefixed_device_name_is_removed_from_channel_name(self) -> None: + light = _light( + device_id=300, + light_id=5, + product_type="DimmableLight", + name="Dobbeltrelæ Bordlampe", + ) + physical_device = SimpleNamespace( + id=300, + product_type="DimmableLight", + name="Wiser Dobbeltrelæ", + ) + data = SimpleNamespace( + legacy_naming=False, + wiserhub=SimpleNamespace( + devices=SimpleNamespace( + get_by_id=lambda _device_id: physical_device + ) + ), + ) + + self.assertEqual( + self.helpers.get_light_entity_name(data, light, "Is Dimmable"), + "Bordlampe Is Dimmable", + ) + def test_legacy_naming_retains_full_light_name(self) -> None: data = _hub_data() data.legacy_naming = True From 161dfc4f13ee03cf2a3d29e9ded774ed2bc02fe1 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Wed, 14 Oct 2026 13:03:58 +0100 Subject: [PATCH 137/154] fix: resolve dual relay names from button panel --- custom_components/wiser/helpers.py | 18 ++++++++++++- tests/test_light_unique_id_migration.py | 34 +++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/custom_components/wiser/helpers.py b/custom_components/wiser/helpers.py index 22db6557..69b25047 100644 --- a/custom_components/wiser/helpers.py +++ b/custom_components/wiser/helpers.py @@ -198,7 +198,23 @@ def get_light_entity_name(data, light, entity_name): part for part in (ENTITY_PREFIX, light_name, entity_name) if part ) - physical_device = data.wiserhub.devices.get_by_id(light.id) + devices = data.wiserhub.devices + # Combined dual-relay/dimmer units expose a ButtonPanel and multiple Light + # views with the same physical ID. The generic lookup may return one of + # the light channels, whose name cannot be used to remove the shared device + # prefix from another channel. Prefer the physical ButtonPanel view. + physical_device = next( + ( + device + for device in getattr(devices, "all", ()) + if getattr(device, "id", None) == light.id + and hasattr(device, "number_of_gangs") + and hasattr(device, "events") + ), + None, + ) + if physical_device is None: + physical_device = devices.get_by_id(light.id) device_name = str(getattr(physical_device, "name", "")).strip() product_type = str(getattr(physical_device, "product_type", "")).strip() diff --git a/tests/test_light_unique_id_migration.py b/tests/test_light_unique_id_migration.py index 5f3db5b2..ac0d991a 100644 --- a/tests/test_light_unique_id_migration.py +++ b/tests/test_light_unique_id_migration.py @@ -234,6 +234,40 @@ def test_prefixed_device_name_is_removed_from_channel_name(self) -> None: "Bordlampe Is Dimmable", ) + def test_dual_relay_uses_button_panel_name_when_device_ids_collide(self) -> None: + light = _light( + device_id=300, + light_id=5, + product_type="DimmableLight", + name="Dobbeltrelæ Bordlampe", + ) + other_light = SimpleNamespace( + id=300, + product_type="DimmableLight", + name="Dobbeltrelæ Loftlampe", + ) + button_panel = SimpleNamespace( + id=300, + product_type="DimmableLight", + name="Dobbeltrelæ", + number_of_gangs=2, + events=[], + ) + data = SimpleNamespace( + legacy_naming=False, + wiserhub=SimpleNamespace( + devices=SimpleNamespace( + all=[other_light, button_panel], + get_by_id=lambda _device_id: other_light, + ) + ), + ) + + self.assertEqual( + self.helpers.get_light_entity_name(data, light, "Is Dimmable"), + "Bordlampe Is Dimmable", + ) + def test_legacy_naming_retains_full_light_name(self) -> None: data = _hub_data() data.legacy_naming = True From 9a4754d4a8ff3abbc3a8e44e1087f9283fc0daa8 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Wed, 14 Oct 2026 13:18:25 +0100 Subject: [PATCH 138/154] fix: match dual relay channels by node id --- custom_components/wiser/helpers.py | 14 +++++++++++--- tests/test_light_unique_id_migration.py | 11 ++++++++--- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/custom_components/wiser/helpers.py b/custom_components/wiser/helpers.py index 69b25047..88079e66 100644 --- a/custom_components/wiser/helpers.py +++ b/custom_components/wiser/helpers.py @@ -202,14 +202,22 @@ def get_light_entity_name(data, light, entity_name): # Combined dual-relay/dimmer units expose a ButtonPanel and multiple Light # views with the same physical ID. The generic lookup may return one of # the light channels, whose name cannot be used to remove the shared device - # prefix from another channel. Prefer the physical ButtonPanel view. + # prefix from another channel. Some two-gang channels also use synthetic + # IDs, so prefer the physical ButtonPanel view by its shared Zigbee node. + light_node_id = getattr(light, "node_id", None) physical_device = next( ( device for device in getattr(devices, "all", ()) - if getattr(device, "id", None) == light.id - and hasattr(device, "number_of_gangs") + if hasattr(device, "number_of_gangs") and hasattr(device, "events") + and ( + getattr(device, "id", None) == light.id + or ( + light_node_id not in (None, 0) + and getattr(device, "node_id", None) == light_node_id + ) + ) ), None, ) diff --git a/tests/test_light_unique_id_migration.py b/tests/test_light_unique_id_migration.py index ac0d991a..a5a3b849 100644 --- a/tests/test_light_unique_id_migration.py +++ b/tests/test_light_unique_id_migration.py @@ -234,22 +234,27 @@ def test_prefixed_device_name_is_removed_from_channel_name(self) -> None: "Bordlampe Is Dimmable", ) - def test_dual_relay_uses_button_panel_name_when_device_ids_collide(self) -> None: + def test_dual_relay_uses_button_panel_name_for_synthetic_channel_ids( + self, + ) -> None: light = _light( - device_id=300, + device_id=300001, light_id=5, product_type="DimmableLight", name="Dobbeltrelæ Bordlampe", ) + light.node_id = 42 other_light = SimpleNamespace( - id=300, + id=300002, product_type="DimmableLight", name="Dobbeltrelæ Loftlampe", + node_id=42, ) button_panel = SimpleNamespace( id=300, product_type="DimmableLight", name="Dobbeltrelæ", + node_id=42, number_of_gangs=2, events=[], ) From 493cf8c578dbc1d69d553cdf70e85ba5cf77a2e6 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Wed, 14 Oct 2026 13:30:32 +0100 Subject: [PATCH 139/154] fix: use embedded device name for light channels --- custom_components/wiser/helpers.py | 56 ++++++++++++++++--------- tests/test_light_unique_id_migration.py | 7 ++-- 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/custom_components/wiser/helpers.py b/custom_components/wiser/helpers.py index 88079e66..c5e6373c 100644 --- a/custom_components/wiser/helpers.py +++ b/custom_components/wiser/helpers.py @@ -199,32 +199,50 @@ def get_light_entity_name(data, light, entity_name): ) devices = data.wiserhub.devices + # aioWiserHeatAPI composes light.name from the physical device Name and + # the per-channel Name. The released API does not expose the former as a + # public property, so read its source value directly when available. A + # future API can expose device_name without changing this integration. + source_data = getattr(light, "_data", {}) + device_name = str( + getattr(light, "device_name", "") + or ( + source_data.get("Name", "") + if isinstance(source_data, dict) + else "" + ) + ).strip() + physical_device = None + # Combined dual-relay/dimmer units expose a ButtonPanel and multiple Light # views with the same physical ID. The generic lookup may return one of # the light channels, whose name cannot be used to remove the shared device # prefix from another channel. Some two-gang channels also use synthetic # IDs, so prefer the physical ButtonPanel view by its shared Zigbee node. light_node_id = getattr(light, "node_id", None) - physical_device = next( - ( - device - for device in getattr(devices, "all", ()) - if hasattr(device, "number_of_gangs") - and hasattr(device, "events") - and ( - getattr(device, "id", None) == light.id - or ( - light_node_id not in (None, 0) - and getattr(device, "node_id", None) == light_node_id + if not device_name: + physical_device = next( + ( + device + for device in getattr(devices, "all", ()) + if hasattr(device, "number_of_gangs") + and hasattr(device, "events") + and ( + getattr(device, "id", None) == light.id + or ( + light_node_id not in (None, 0) + and getattr(device, "node_id", None) == light_node_id + ) ) - ) - ), - None, - ) - if physical_device is None: - physical_device = devices.get_by_id(light.id) - device_name = str(getattr(physical_device, "name", "")).strip() - product_type = str(getattr(physical_device, "product_type", "")).strip() + ), + None, + ) + if physical_device is None: + physical_device = devices.get_by_id(light.id) + device_name = str(getattr(physical_device, "name", "")).strip() + product_type = str( + getattr(physical_device or light, "product_type", "") + ).strip() # Some hub models include Wiser and/or the product type in the physical # device name, while their channel names omit those prefixes. Compare all diff --git a/tests/test_light_unique_id_migration.py b/tests/test_light_unique_id_migration.py index a5a3b849..92f5ed90 100644 --- a/tests/test_light_unique_id_migration.py +++ b/tests/test_light_unique_id_migration.py @@ -234,7 +234,7 @@ def test_prefixed_device_name_is_removed_from_channel_name(self) -> None: "Bordlampe Is Dimmable", ) - def test_dual_relay_uses_button_panel_name_for_synthetic_channel_ids( + def test_dual_relay_uses_embedded_name_for_synthetic_channel_ids( self, ) -> None: light = _light( @@ -243,18 +243,19 @@ def test_dual_relay_uses_button_panel_name_for_synthetic_channel_ids( product_type="DimmableLight", name="Dobbeltrelæ Bordlampe", ) + light._data = {"Name": "Dobbeltrelæ"} light.node_id = 42 other_light = SimpleNamespace( id=300002, product_type="DimmableLight", name="Dobbeltrelæ Loftlampe", - node_id=42, + node_id=84, ) button_panel = SimpleNamespace( id=300, product_type="DimmableLight", name="Dobbeltrelæ", - node_id=42, + node_id=21, number_of_gangs=2, events=[], ) From ded761d30b9bd1903e773e9b01a6a489fc8f5c40 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Wed, 14 Oct 2026 13:38:23 +0100 Subject: [PATCH 140/154] fix: omit channel name for single-source lights --- custom_components/wiser/helpers.py | 41 ++++++++++++++++++------- tests/test_light_unique_id_migration.py | 28 ++++++++++++++++- 2 files changed, 57 insertions(+), 12 deletions(-) diff --git a/custom_components/wiser/helpers.py b/custom_components/wiser/helpers.py index c5e6373c..70063461 100644 --- a/custom_components/wiser/helpers.py +++ b/custom_components/wiser/helpers.py @@ -199,6 +199,25 @@ def get_light_entity_name(data, light, entity_name): ) devices = data.wiserhub.devices + light_node_id = getattr(light, "node_id", None) + lights = getattr(getattr(devices, "lights", None), "all", None) + related_lights = ( + [ + candidate + for candidate in lights + if getattr(candidate, "id", None) == light.id + or ( + light_node_id not in (None, 0) + and getattr(candidate, "node_id", None) == light_node_id + ) + ] + if lights is not None + else None + ) + has_multiple_channels = ( + len(related_lights) > 1 if related_lights is not None else None + ) + # aioWiserHeatAPI composes light.name from the physical device Name and # the per-channel Name. The released API does not expose the former as a # public property, so read its source value directly when available. A @@ -219,7 +238,6 @@ def get_light_entity_name(data, light, entity_name): # the light channels, whose name cannot be used to remove the shared device # prefix from another channel. Some two-gang channels also use synthetic # IDs, so prefer the physical ButtonPanel view by its shared Zigbee node. - light_node_id = getattr(light, "node_id", None) if not device_name: physical_device = next( ( @@ -263,16 +281,17 @@ def get_light_entity_name(data, light, entity_name): device_names.add(stripped) pending_names.append(stripped) - channel_name = light_name - for candidate in sorted(device_names, key=len, reverse=True): - if candidate and light_name.casefold() == candidate.casefold(): - channel_name = "" - break - if candidate and light_name.casefold().startswith( - f"{candidate} ".casefold() - ): - channel_name = light_name[len(candidate) :].strip() - break + channel_name = "" if has_multiple_channels is False else light_name + if channel_name: + for candidate in sorted(device_names, key=len, reverse=True): + if candidate and light_name.casefold() == candidate.casefold(): + channel_name = "" + break + if candidate and light_name.casefold().startswith( + f"{candidate} ".casefold() + ): + channel_name = light_name[len(candidate) :].strip() + break return " ".join(part for part in (channel_name, entity_name) if part) diff --git a/tests/test_light_unique_id_migration.py b/tests/test_light_unique_id_migration.py index 92f5ed90..be85c3e0 100644 --- a/tests/test_light_unique_id_migration.py +++ b/tests/test_light_unique_id_migration.py @@ -234,6 +234,31 @@ def test_prefixed_device_name_is_removed_from_channel_name(self) -> None: "Bordlampe Is Dimmable", ) + def test_single_dimmer_omits_its_only_light_source_name(self) -> None: + light = _light( + device_id=400, + light_id=6, + product_type="DimmableLight", + name="Dimmer Loftlampe", + ) + light._data = {"Name": "Dimmer"} + light.node_id = 50 + data = SimpleNamespace( + legacy_naming=False, + wiserhub=SimpleNamespace( + devices=SimpleNamespace( + all=[light], + lights=SimpleNamespace(all=[light]), + get_by_id=lambda _device_id: light, + ) + ), + ) + + self.assertEqual( + self.helpers.get_light_entity_name(data, light, "Is Dimmable"), + "Is Dimmable", + ) + def test_dual_relay_uses_embedded_name_for_synthetic_channel_ids( self, ) -> None: @@ -249,7 +274,7 @@ def test_dual_relay_uses_embedded_name_for_synthetic_channel_ids( id=300002, product_type="DimmableLight", name="Dobbeltrelæ Loftlampe", - node_id=84, + node_id=42, ) button_panel = SimpleNamespace( id=300, @@ -264,6 +289,7 @@ def test_dual_relay_uses_embedded_name_for_synthetic_channel_ids( wiserhub=SimpleNamespace( devices=SimpleNamespace( all=[other_light, button_panel], + lights=SimpleNamespace(all=[light, other_light]), get_by_id=lambda _device_id: other_light, ) ), From ffcfca85aea25d2e3ddef9b7fae7c4d7f211117e Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Wed, 14 Oct 2026 15:12:09 +0100 Subject: [PATCH 141/154] fix: handle command confirmation refresh errors --- custom_components/wiser/light.py | 1 + custom_components/wiser/switch.py | 1 + tests/test_light_optimistic_state.py | 15 +++++++++++++++ tests/test_switch_hot_water.py | 17 +++++++++++++++++ 4 files changed, 34 insertions(+) diff --git a/custom_components/wiser/light.py b/custom_components/wiser/light.py index 83cd7d10..04fde449 100644 --- a/custom_components/wiser/light.py +++ b/custom_components/wiser/light.py @@ -82,6 +82,7 @@ async def async_force_update(self, delay: int = 0): await asyncio.sleep(delay) await self._data.async_refresh() + @hub_error_handler async def _async_confirm_command(self, gen: int) -> None: """Refresh the hub after it has had time to apply a light command.""" try: diff --git a/custom_components/wiser/switch.py b/custom_components/wiser/switch.py index eea2deae..5d3e908c 100755 --- a/custom_components/wiser/switch.py +++ b/custom_components/wiser/switch.py @@ -513,6 +513,7 @@ def __init__(self, data, plugId, name) -> None: self._optimistic_gen = 0 self._confirmation_task = None + @hub_error_handler async def _async_confirm_command(self, gen: int) -> None: """Refresh until the hub reports the accepted smart-plug command.""" try: diff --git a/tests/test_light_optimistic_state.py b/tests/test_light_optimistic_state.py index bff9db2b..03f11c8d 100644 --- a/tests/test_light_optimistic_state.py +++ b/tests/test_light_optimistic_state.py @@ -178,6 +178,21 @@ async def stale_refresh(*_args, **_kwargs): self.assertEqual(len(refreshes), 2) self.assertIsNone(light._optimistic_is_on) + def test_failed_confirmation_clears_optimistic_state(self): + light, _device = self._light(is_on=False) + light._optimistic_gen = 1 + light._optimistic_is_on = True + + async def fail_refresh(*_args, **_kwargs): + raise RuntimeError("refresh failed") + + light.async_force_update = fail_refresh + + with self.assertRaisesRegex(RuntimeError, "refresh failed"): + asyncio.run(light._async_confirm_command(1)) + + self.assertIsNone(light._optimistic_is_on) + def test_stale_first_refresh_retries_until_hub_confirms(self): light, device = self._light(is_on=False) light._optimistic_gen = 1 diff --git a/tests/test_switch_hot_water.py b/tests/test_switch_hot_water.py index cb373a90..c78e07c7 100644 --- a/tests/test_switch_hot_water.py +++ b/tests/test_switch_hot_water.py @@ -257,6 +257,23 @@ async def refresh(*_args, **_kwargs): self.assertIsNone(switch._optimistic_is_on) self.assertTrue(switch.is_on) + def test_failed_confirmation_restores_hub_state(self) -> None: + switch, _plug, _events, _scheduled = self._switch(is_on=False) + switch._optimistic_gen = 1 + switch._optimistic_is_on = True + switch._is_on = True + + async def fail_refresh(*_args, **_kwargs): + raise RuntimeError("refresh failed") + + switch.async_force_update = fail_refresh + + with self.assertRaisesRegex(RuntimeError, "refresh failed"): + asyncio.run(switch._async_confirm_command(1)) + + self.assertIsNone(switch._optimistic_is_on) + self.assertFalse(switch.is_on) + def test_superseded_confirmation_does_not_clobber_newer_command(self) -> None: switch, plug, events, scheduled = self._switch(is_on=True) switch._optimistic_gen = 2 From 266a3223df2894bb865bb85caf13b29d3cbec389 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 15 Oct 2026 10:12:53 +0100 Subject: [PATCH 142/154] feat: add Spanish Hungarian Dutch and Portuguese translations --- custom_components/wiser/translations/es.json | 651 +++++++++++++++++++ custom_components/wiser/translations/hu.json | 403 ++++++++++++ custom_components/wiser/translations/nl.json | 651 +++++++++++++++++++ custom_components/wiser/translations/pt.json | 651 +++++++++++++++++++ 4 files changed, 2356 insertions(+) create mode 100644 custom_components/wiser/translations/es.json create mode 100644 custom_components/wiser/translations/hu.json create mode 100644 custom_components/wiser/translations/nl.json create mode 100644 custom_components/wiser/translations/pt.json diff --git a/custom_components/wiser/translations/es.json b/custom_components/wiser/translations/es.json new file mode 100644 index 00000000..47c89715 --- /dev/null +++ b/custom_components/wiser/translations/es.json @@ -0,0 +1,651 @@ +{ + "config": { + "flow_title": "{name}", + "step": { + "user": { + "title": "Wiser Configuración del concentrador de calor", + "description": "Ingrese la dirección IP y la clave secreta obtenida del concentrador.", + "data": { + "host": "Dirección IP o nombre de host", + "port": "Número de puerto", + "password": "Clave secreta" + } + }, + "zeroconf_confirm": { + "title": "Wiser Configuración del Heat Hub ({name})", + "description": "Introduzca la clave secreta obtenida del hub.", + "data": { + "host": "Dirección IP o nombre de host", + "port": "Número de puerto", + "password": "Clave secreta" + } + } + }, + "abort": { + "already_in_progress": "Wiser La configuración del Heat Hub ya está en progreso.", + "already_configured": "Este dispositivo ya está configurado.", + "not_wiser_hub": "El dispositivo descubierto no es un Heat Hub Wiser." + }, + "error": { + "auth_failure": "No se puede autenticar con el concentrador Wiser. Verifique la clave secreta y vuelva a intentarlo.", + "timeout_error": "Se agotó el tiempo de espera al intentar conectarse al concentrador Wiser. Verifique la dirección IP e inténtelo nuevamente.", + "timeout_error_discovery": "Se agotó el tiempo de espera al intentar conectarse al concentrador Wiser. Verifique que su hub todavía esté en línea e inténtelo nuevamente.", + "unknown": "Error desconocido al conectarse al concentrador Wiser. Por favor revise los registros." + } + }, + "options": { + "step": { + "init": { + "title": "Wiser Opciones de integración", + "description": "Seleccionar parámetros para modificar", + "menu_options": { + "main_params": "Parámetros principales", + "automation_params": "Parámetros de automatización", + "opentherm_sensors": "OpenTherm sensores", + "equipment_sensors": "Sensores de equipo", + "ui_options": "Opciones de UI" + } + }, + "ui_options": { + "title": "Opciones de UI", + "data": { + "legacy_naming": "Nomenclatura heredada", + "show_wiser_sidebar": "Mostrar Wiser en la barra lateral" + }, + "data_description": { + "legacy_naming": "Incluir nombres de habitaciones en Nombres de dispositivos Wiser. Si está habilitado, el uso de Home Assistant para regenerar ID de entidad con el formato predeterminado en Configuración → Sistema → Formato de ID de entidad (Home Assistant 2026.8 y posterior) duplicará los nombres de área cuando el área y los nombres de sala Wiser coincidan. Cambiar esta opción no cambia el nombre de los ID de entidad existentes." + } + }, + "main_params": { + "title": "Wiser Opciones de integración", + "description": "Parámetros principales", + "data": { + "host": "Dirección IP o nombre de host", + "port": "Número de puerto", + "scan_interval": "Intervalo de escaneo (segundos)", + "heating_boost_temp": "Temperatura de refuerzo de calefacción predeterminada (°C)", + "heating_boost_time": "Duración predeterminada del refuerzo de calefacción (minutos)", + "hotwater_boost_time": "Duración predeterminada del refuerzo de agua caliente (minutos)", + "setpoint_mode": "Modo de punto de ajuste", + "restore_manual_temp_option": "Utilice esta temperatura si no se almacena ninguna temperatura manual" + } + }, + "automation_params": { + "title": "Wiser Opciones de integración", + "description": "Habilitar automatizaciones integradas", + "sections": { + "automations_passive_mode": { + "name": "Modo pasivo", + "description": "Habilitar la capacidad TRV pasiva. Cada habitación necesita estar habilitada para su funcionamiento.", + "data": { + "automations_passive_mode": "Modo pasivo", + "passive_mode_temperature_increments": "Incrementos de temperatura en modo pasivo" + } + }, + "hotwater_climate": { + "name": "Control climático de agua caliente", + "description": "Habilita el control climático de agua caliente. Consulte la wiki para obtener más detalles.", + "data": { + "hotwater_climate": "Habilita la entidad climática", + "experimental_mode": "Habilita el modo de trabajo experimental", + "hotwater_auto_mode": "Modo automático de agua caliente", + "hotwater_heat_mode": "Modo de calentamiento de agua caliente", + "hotwater_boost_mode": "Modo de refuerzo de agua caliente", + "hotwater_sensor_entity_id": "Sensor de temperatura de agua caliente" + } + } + } + }, + "equipment_sensors": { + "title": "Sensores de equipos", + "description": "Configure entidades de datos detalladas de equipos para dispositivos compatibles.", + "data": { + "equipment_sensors": "Habilitar sensores de datos del equipo" + }, + "data_description": { + "equipment_sensors": "Exponer un sensor adicional que contiene atributos de equipo detallados para cada enchufe inteligente, PowerTag y actuador de calefacción compatibles. Sensores" + } + }, + "opentherm_sensors": { + "title": "OpenTherm", + "description": "Elija una categoría de atributos OpenTherm detectados.", + "menu_options": { + "opentherm_readings": "Lecturas", + "opentherm_central_heating": "Calefacción central", + "opentherm_hot_water": "Agua caliente", + "opentherm_status": "Estado y diagnóstico" + } + }, + "opentherm_readings": { + "title": "OpenTherm Lecturas", + "description": "Elige qué detectado OpenTherm Las lecturas se exponen como entidades sensoras.", + "data": { + "ch_flow_temperature": "Temperatura de ida de la caldera", + "ch_pressure_bar": "Presión de calefacción", + "ch_return_temperature": "Temperatura de retorno de la caldera", + "delta_t": "Delta-T", + "boiler_exhaust_temperature": "Temperatura de escape de la caldera", + "estimated_boiler_output": "Potencia estimada de la caldera", + "hw_flow_rate": "Caudal de agua caliente nominal", + "hw_temperature": "Temperatura agua caliente sanitaria", + "maximum_capacity_kw": "Capacidad máxima caldera", + "minimum_modulation_level": "Nivel mínimo de modulación", + "relative_modulation_level": "Nivel relativo de modulación", + "room_temperature": "Temperatura ambiente" + } + }, + "opentherm_central_heating": { + "title": "OpenTherm calefacción central", + "description": "Elija qué atributos de calefacción central detectados se exponen como entidades.", + "data": { + "boiler_ch_max_setpoint_read_write": "Lectura/escritura del punto de ajuste máximo de la caldera", + "boiler_ch_max_setpoint_transfer_enable": "Transferencia del punto de ajuste máximo de la caldera habilitada", + "boiler_ch_setpoint": "Punto de ajuste de la caldera", + "boiler_ch_setpoint_lower_bound": "Límite inferior del punto de ajuste de la caldera", + "boiler_ch_setpoint_upper_bound": "Límite superior del punto de ajuste de la caldera", + "ch_flow_active_lower_setpoint": "Flujo CH activo punto de ajuste inferior", + "ch_flow_active_upper_setpoint": "Flujo CH punto de ajuste superior activo", + "ch1_flow_enabled": "Flujo CH1 habilitado", + "ch1_flow_setpoint": "Punto de ajuste flujo CH1", + "ch2_flow_enabled": "Flujo CH2 habilitado", + "ch2_flow_setpoint": "Punto de ajuste flujo CH2", + "room_setpoint": "Punto de ajuste de la habitación" + } + }, + "opentherm_hot_water": { + "title": "OpenTherm agua caliente", + "description": "Elija qué atributos de agua caliente detectados se exponen como entidades.", + "data": { + "boiler_hw_setpoint": "Punto de consigna de agua caliente de la caldera", + "boiler_hw_setpoint_lower_bound": "Límite inferior del punto de consigna de agua caliente de la caldera", + "boiler_hw_setpoint_read_write": "Lectura/escritura del punto de consigna de agua caliente de la caldera", + "boiler_hw_setpoint_transfer_enable": "Transferencia del punto de consigna de agua caliente de la caldera habilitada", + "boiler_hw_setpoint_upper_bound": "Límite superior del punto de consigna de agua caliente de la caldera", + "hw_enabled": "Agua caliente habilitada", + "hw_flow_setpoint": "Punto de ajuste del flujo de agua caliente" + } + }, + "opentherm_status": { + "title": "Estado y diagnóstico de OpenTherm", + "description": "Elija qué estados detectados y atributos de diagnóstico se exponen como entidades de sensor.", + "data": { + "boiler_fault": "Fallo caldera", + "central_heating_active": "Calefacción central activa", + "central_heating_2_active": "Calefacción central 2 activa", + "connection_status": "Estado de conexión", + "coprocessor_update_status": "OpenTherm estado de actualización del coprocesador", + "coprocessor_version": "OpenTherm versión del coprocesador", + "cooling_active": "Enfriamiento activo", + "diagnostic_event": "Evento de diagnóstico", + "flame_active": "Llama activa", + "flame_statistics": "Estadísticas de llama", + "hot_water_active": "Agua caliente activa", + "operating_mode": "Modo de funcionamiento", + "slave_status": "OpenTherm Estado de esclavo", + "tracked_room_id": "ID de habitación rastreada" + } + } + }, + "abort": { + "opentherm_not_available": "Los datos de OpenTherm no están disponibles para este concentrador Wiser.", + "equipment_not_available": "Los datos del equipo no están disponibles para este concentrador Wiser." + } + }, + "services": { + "set_opentherm_parameter": { + "name": "Establece el parámetro OpenTherm", + "description": "Cambia un parámetro de temperatura OpenTherm compatible en el concentrador Wiser.", + "fields": { + "parameter": { + "name": "Parámetro", + "description": "OpenTherm Parámetro de temperatura a cambiar. El punto final API requerido se selecciona automáticamente." + }, + "temperature": { + "name": "Temperatura", + "description": "Utilice una temperatura dentro de los límites informados por su caldera." + }, + "hub": { + "name": "Wiser concentrador", + "description": "Seleccione un concentrador solo cuando tenga varios concentradores Wiser." + } + } + } + }, + "selector": { + "opentherm_parameter": { + "options": { + "chFlowActiveLowerSetpoint": "Consigna inferior de calefacción central activa", + "chFlowActiveUpperSetpoint": "Consigna superior de calefacción central activa", + "dhwFlowSetpoint": "Consigna caudal de agua caliente del hub", + "dhwSetpoint": "Consigna de agua caliente de caldera", + "maxChSetpoint": "Consigna máxima de calefacción central de caldera" + } + } + }, + "exceptions": { + "opentherm_temperature_required": { + "message": "Proporcione una temperatura OpenTherm." + }, + "opentherm_hub_not_found": { + "message": "No se encontró el concentrador Wiser especificado." + }, + "opentherm_hub_not_loaded": { + "message": "El concentrador Wiser especificado no está cargado." + }, + "opentherm_hub_required": { + "message": "Seleccione un concentrador Wiser cuando esté configurado más de un concentrador." + }, + "opentherm_not_supported": { + "message": "Este concentrador no tiene la funcionalidad OpenTherm." + }, + "opentherm_invalid_parameter": { + "message": "El parámetro o valor OpenTherm no es válido: {error}" + }, + "opentherm_write_failed": { + "message": "No se puede establecer el parámetro OpenTherm {parameter}: {error}" + }, + "opentherm_confirmation_failed": { + "message": "El parámetro OpenTherm {parameter} no permaneció en {requested} °C después de un reintento y la segunda ventana de confirmación de {window}. Wiser informa {reported} °C. No se enviarán más reintentos." + }, + "opentherm_retry_failed": { + "message": "El parámetro OpenTherm {parameter} no permaneció en {requested} °C y no se pudo enviar su reintento: {error}. Wiser informes {reported} °C. No se enviarán más reintentos." + }, + "opentherm_notification_title": { + "message": "Wiser Comando OpenTherm" + } + }, + "entity": { + "climate": { + "heating": { + "name": "Calefacción" + }, + "floor_temperature": { + "name": "Temperatura del suelo" + } + }, + "number": { + "away_mode_target_temperature": { + "name": "Temperatura objetivo del modo ausente" + }, + "floor_temperature_offset": { + "name": "Compensación de la temperatura del suelo" + }, + "indoor_discomfort_temperature": { + "name": "Temperatura de incomodidad interior" + }, + "outdoor_discomfort_temperature": { + "name": "Temperatura exterior incómoda" + } + }, + "select": { + "mode": { + "name": "Modo" + }, + "power_on_behavior": { + "name": "Comportamiento de encendido" + }, + "led_indicator": { + "name": "Indicador LED" + } + }, + "button": { + "boost_all_heating": { + "name": "Impulsar toda la calefacción" + }, + "cancel_all_heating_overrides": { + "name": "Cancelar todas las anulaciones de calefacción" + }, + "boost_hot_water": { + "name": "Impulsar el agua caliente" + }, + "cancel_hot_water_overrides": { + "name": "Cancelar anulaciones de agua caliente" + }, + "toggle_hot_water": { + "name": "Alternar agua caliente" + }, + "moment": { + "name": "Momento: {name}" + } + }, + "switch": { + "valve_protection": { + "name": "Protección de válvula" + }, + "eco_mode": { + "name": "Modo Eco" + }, + "away_mode_affects_hot_water": { + "name": "El modo Ausente afecta el agua caliente" + }, + "comfort_mode": { + "name": "Modo Confort" + }, + "away_mode": { + "name": "Modo Ausente" + }, + "daylight_saving": { + "name": "Horario de verano" + }, + "summer_comfort_enabled": { + "name": "Confort de verano habilitado" + }, + "window_detection": { + "name": "Detección de ventana" + }, + "include_in_summer_comfort": { + "name": "Incluir en el confort de verano" + }, + "device_lock": { + "name": "Bloqueo del dispositivo" + }, + "identify": { + "name": "Identificar" + }, + "outlet": { + "name": "Outlet" + }, + "away_mode_turns_off": { + "name": "El modo Ausente se apaga" + }, + "away_mode_closes": { + "name": "El modo Ausente se cierra" + }, + "passive_mode": { + "name": "Modo pasivo" + }, + "respect_summer_comfort": { + "name": "Respetar el confort de verano" + }, + "interacts_with_room_climate": { + "name": "Interactúa con el clima ambiental" + }, + "humidity_interacts_with_room_climate": { + "name": "La humedad interactúa con el clima ambiental" + }, + "temperature_interacts_with_room_climate": { + "name": "La temperatura interactúa con el clima ambiental" + }, + "illuminance_interacts_with_room_climate": { + "name": "La iluminancia interactúa con el clima ambiental" + }, + "sensor_interacts_with_room_climate": { + "name": "{sensor} interactúa con el clima ambiental" + }, + "manual_heat": { + "name": "Calefacción manual" + }, + "hot_water": { + "name": "Agua caliente" + } + }, + "binary_sensor": { + "summer_discomfort_prevention": { + "name": "Prevención de molestias de verano" + }, + "summer_comfort_available": { + "name": "Confort de verano disponible" + }, + "pcm_device_limit_reached": { + "name": "Límite del dispositivo PCM alcanzado" + }, + "smoke_alarm": { + "name": "Alarma de humo" + }, + "heat_alarm": { + "name": "Alarma de calor" + }, + "tamper_alarm": { + "name": "Alarma de manipulación" + }, + "fault_warning": { + "name": "Advertencia de fallo" + }, + "remote_alarm": { + "name": "Alarma remota" + }, + "battery_defect": { + "name": "Defecto de batería" + }, + "controllable": { + "name": "Controlable" + }, + "pcm_mode": { + "name": "Modo PCM" + }, + "window_detection_active": { + "name": "Detección de ventana activa" + }, + "is_dimmable": { + "name": "Regulable" + }, + "is_led_indicator_supported": { + "name": "Indicador LED compatible" + }, + "is_output_mode_supported": { + "name": "Modo de salida compatible" + }, + "is_power_on_behaviour_supported": { + "name": "Comportamiento de encendido compatible" + }, + "is_tilt_supported": { + "name": "Inclinación compatible" + }, + "is_open": { + "name": "Abierto" + }, + "is_closed": { + "name": "Cerrado" + }, + "active": { + "name": "Activo" + }, + "boiler_ch_max_setpoint_read_write": { + "name": "Lectura/escritura del setpoint máximo de caldera" + }, + "boiler_ch_max_setpoint_transfer_enable": { + "name": "Transferencia del setpoint máximo de caldera habilitada" + }, + "boiler_fault": { + "name": "Fallo de caldera" + }, + "boiler_hw_setpoint_read_write": { + "name": "Lectura/escritura de setpoint de agua caliente de caldera" + }, + "boiler_hw_setpoint_transfer_enable": { + "name": "Agua caliente de caldera transferencia de setpoint habilitada" + }, + "central_heating_2_active": { + "name": "Calefacción central 2 activa" + }, + "central_heating_active": { + "name": "Calefacción central activa" + }, + "ch1_flow_enabled": { + "name": "Flujo CH1 habilitado" + }, + "ch2_flow_enabled": { + "name": "Flujo CH2 habilitado" + }, + "cooling_active": { + "name": "Refrigeración activa" + }, + "diagnostic_event": { + "name": "Evento de diagnóstico" + }, + "flame_active": { + "name": "Llama activa" + }, + "hot_water_active": { + "name": "Agua caliente activa" + }, + "hw_enabled": { + "name": "Agua caliente habilitada" + } + }, + "sensor": { + "signal": { + "name": "Señal" + }, + "cloud": { + "name": "Nube" + }, + "heating_operation_mode": { + "name": "Modo funcionamiento calefacción" + }, + "heating": { + "name": "Calefacción", + "state": { + "off": "Apagado", + "on": "Encendido" + } + }, + "heating_channel": { + "name": "Canal calefacción {channel}", + "state": { + "off": "Apagado", + "on": "Encendido" + } + }, + "hot_water": { + "name": "Agua caliente", + "state": { + "off": "Apagado", + "on": "Encendido" + } + }, + "hot_water_operation_mode": { + "name": "Modo funcionamiento agua caliente" + }, + "target_temperature": { + "name": "Temperatura objetivo" + }, + "floor_temperature": { + "name": "Temperatura del suelo" + }, + "boiler_flow_temperature": { + "name": "Temperatura de ida de la caldera" + }, + "boiler_return_temperature": { + "name": "Temperatura de retorno de la caldera" + }, + "flame_statistics": { + "name": "Estadísticas de llama" + }, + "boiler_ch_setpoint": { + "name": "Punto de ajuste de calefacción de caldera" + }, + "boiler_ch_setpoint_lower_bound": { + "name": "Caldera de calefacción Límite inferior del punto de consigna" + }, + "boiler_ch_setpoint_upper_bound": { + "name": "Límite superior del punto de consigna de calefacción de caldera" + }, + "boiler_exhaust_temperature": { + "name": "Temperatura de escape de la caldera" + }, + "boiler_hw_setpoint": { + "name": "Punto de consigna de agua caliente de la caldera" + }, + "boiler_hw_setpoint_lower_bound": { + "name": "Límite inferior del punto de consigna de agua caliente de la caldera" + }, + "boiler_hw_setpoint_upper_bound": { + "name": "Límite superior del punto de consigna de agua caliente de la caldera" + }, + "ch1_flow_setpoint": { + "name": "Punto de ajuste de flujo CH1" + }, + "ch2_flow_setpoint": { + "name": "Punto de ajuste de flujo de CH2" + }, + "ch_flow_active_lower_setpoint": { + "name": "Punto de ajuste inferior activo de flujo de CH" + }, + "ch_flow_active_upper_setpoint": { + "name": "Punto de ajuste superior activo de flujo de CH" + }, + "ch_pressure_bar": { + "name": "Presión de CH" + }, + "connection_status": { + "name": "Estado de conexión" + }, + "coprocessor_update_status": { + "name": "OpenTherm estado de actualización del coprocesador" + }, + "coprocessor_version": { + "name": "OpenTherm versión del coprocesador" + }, + "delta_t": { + "name": "Delta-T" + }, + "estimated_boiler_output": { + "name": "Potencia estimada de la caldera" + }, + "hw_flow_rate": { + "name": "Caudal de agua caliente" + }, + "hw_flow_setpoint": { + "name": "Punto de ajuste del caudal de agua caliente" + }, + "hw_temperature": { + "name": "Temperatura del agua caliente" + }, + "maximum_capacity_kw": { + "name": "Capacidad máxima de la caldera" + }, + "minimum_modulation_level": { + "name": "Nivel mínimo de modulación" + }, + "operating_mode": { + "name": "Modo de funcionamiento" + }, + "relative_modulation_level": { + "name": "Nivel de modulación relativo" + }, + "room_setpoint": { + "name": "Consigna ambiente" + }, + "room_temperature": { + "name": "Temperatura ambiente" + }, + "slave_status": { + "name": "OpenTherm estado esclavo" + }, + "tracked_room_id": { + "name": "ID de habitación rastreada" + }, + "heating_demand": { + "name": "Demanda de calefacción" + }, + "heating_demand_channel": { + "name": "Canal de demanda de calefacción {channel}" + }, + "hot_water_demand": { + "name": "Demanda de agua caliente" + }, + "total_energy": { + "name": "Energía total" + }, + "energy_delivered": { + "name": "Energía entregada" + }, + "energy_received": { + "name": "Energía recibida" + }, + "equipment_power": { + "name": "Equipo" + } + } + }, + "device_automation": { + "trigger_type": { + "started_heating": "{entity_name} inicia la calefacción", + "stopped_heating": "{entity_name} deja de calentar", + "boosted": "{entity_name} se potencia", + "target_temperature_increased": "{entity_name} temperatura objetivo aumentada", + "target_temperature_decreased": "{entity_name} temperatura objetivo disminuida" + } + } +} diff --git a/custom_components/wiser/translations/hu.json b/custom_components/wiser/translations/hu.json new file mode 100644 index 00000000..e57a2b6c --- /dev/null +++ b/custom_components/wiser/translations/hu.json @@ -0,0 +1,403 @@ +{ + "config": { + "flow_title": "{name}", + "step": { + "user": { + "title": "Wiser fűtési központ beállítása", + "description": "Adja meg a központ IP-címét és a hozzá tartozó titkos kulcsot.", + "data": { + "host": "IP-cím vagy állomásnév", + "port": "Portszám", + "password": "Titkos kulcs" + } + }, + "zeroconf_confirm": { + "title": "Wiser fűtési központ beállítása ({name})", + "description": "Adja meg a központtól kapott titkos kulcsot.", + "data": { + "host": "IP-cím vagy állomásnév", + "port": "Portszám", + "password": "Titkos kulcs" + } + } + }, + "abort": { + "already_in_progress": "A Wiser fűtési központ konfigurálása már folyamatban van.", + "already_configured": "Ez az eszköz már konfigurálva van.", + "not_wiser_hub": "A felismert eszköz nem Wiser fűtési központ." + }, + "error": { + "auth_failure": "Nem sikerült hitelesíteni a Wiser központnál. Ellenőrizze a titkos kulcsot, majd próbálja újra.", + "timeout_error": "Időtúllépés történt a Wiser központhoz való csatlakozáskor. Ellenőrizze az IP-címet, majd próbálja újra.", + "timeout_error_discovery": "Időtúllépés történt a Wiser központhoz való csatlakozáskor. Ellenőrizze, hogy a központ továbbra is elérhető-e, majd próbálja újra.", + "unknown": "Ismeretlen hiba történt a Wiser központhoz való csatlakozáskor. Ellenőrizze a naplókat." + } + }, + "options": { + "step": { + "init": { + "title": "Wiser integráció beállításai", + "description": "Válassza ki a módosítandó paramétereket", + "menu_options": { + "main_params": "Fő paraméterek", + "automation_params": "Automatizálási paraméterek", + "opentherm_sensors": "OpenTherm érzékelők", + "equipment_sensors": "Berendezésérzékelők", + "ui_options": "Felhasználói felület beállításai" + } + }, + "ui_options": { + "title": "Felhasználói felület beállításai", + "data": { + "legacy_naming": "Korábbi elnevezési mód", + "show_wiser_sidebar": "Wiser megjelenítése az oldalsávon" + }, + "data_description": { + "legacy_naming": "A helyiségek neveinek hozzáadása a Wiser-eszközök nevéhez. Ha engedélyezve van, az entitásazonosítók Home Assistant általi újragenerálása az alapértelmezett formátummal a Beállítások → Rendszer → Entitásazonosító-formátum menüben (Home Assistant 2026.8-tól) megkettőzi a területneveket, ha a terület és a Wiser-helyiség neve megegyezik. A beállítás módosítása nem nevezi át a meglévő entitásazonosítókat." + } + }, + "main_params": { + "title": "Wiser integráció beállításai", + "description": "Fő paraméterek", + "data": { + "host": "IP-cím vagy állomásnév", + "port": "Portszám", + "scan_interval": "Lekérdezési időköz (másodperc)", + "heating_boost_temp": "Fűtési gyorsfelfűtés alapértelmezett hőmérséklete (°C)", + "heating_boost_time": "Fűtési gyorsfelfűtés alapértelmezett időtartama (perc)", + "hotwater_boost_time": "Melegvíz-gyorsfelfűtés alapértelmezett időtartama (perc)", + "setpoint_mode": "Célhőmérséklet-beállítási mód", + "restore_manual_temp_option": "Ezt a hőmérsékletet használja, ha nincs tárolt kézi hőmérséklet" + } + }, + "automation_params": { + "title": "Wiser integráció beállításai", + "description": "Beépített automatizálások engedélyezése", + "sections": { + "automations_passive_mode": { + "name": "Passzív mód", + "description": "A passzív termosztatikus radiátorszelep (TRV) funkció engedélyezése. A működéshez helyiségenként külön engedélyezni kell.", + "data": { + "automations_passive_mode": "Passzív mód", + "passive_mode_temperature_increments": "Passzív mód hőmérsékleti lépésköze" + } + }, + "hotwater_climate": { + "name": "Melegvíz-hőmérséklet szabályozása", + "description": "A melegvíz-hőmérséklet szabályozásának engedélyezése. Részletek a wikiben.", + "data": { + "hotwater_climate": "Klímaentitás engedélyezése", + "experimental_mode": "Kísérleti üzemmód engedélyezése", + "hotwater_auto_mode": "Melegvíz automatikus módja", + "hotwater_heat_mode": "Melegvíz fűtési módja", + "hotwater_boost_mode": "Melegvíz gyorsfelfűtési módja", + "hotwater_sensor_entity_id": "Melegvíz-hőmérséklet érzékelője" + } + } + } + }, + "equipment_sensors": { + "title": "Berendezésérzékelők", + "description": "Részletes berendezésadat-entitások beállítása kompatibilis eszközökhöz.", + "data": { + "equipment_sensors": "Berendezésadat-érzékelők engedélyezése" + }, + "data_description": { + "equipment_sensors": "További érzékelő megjelenítése részletes berendezésjellemzőkkel minden kompatibilis okoskonnektorhoz, PowerTag eszközhöz és fűtési szelepmozgatóhoz." + } + }, + "opentherm_sensors": { + "title": "OpenTherm érzékelők", + "description": "Válasszon kategóriát a felismert OpenTherm-attribútumok közül.", + "menu_options": { + "opentherm_readings": "Mért értékek", + "opentherm_central_heating": "Központi fűtés", + "opentherm_hot_water": "Meleg víz", + "opentherm_status": "Állapot és diagnosztika" + } + }, + "opentherm_readings": { + "title": "OpenTherm mért értékek", + "description": "Válassza ki, mely felismert OpenTherm-mért értékek jelenjenek meg érzékelőentitásként.", + "data": { + "ch_flow_temperature": "Kazán előremenő hőmérséklete", + "ch_pressure_bar": "Központi fűtés nyomása", + "ch_return_temperature": "Kazán visszatérő hőmérséklete", + "delta_t": "Hőmérséklet-különbség (ΔT)", + "boiler_exhaust_temperature": "Kazán füstgázhőmérséklete", + "estimated_boiler_output": "Kazán becsült teljesítménye", + "hw_flow_rate": "Melegvíz térfogatárama", + "hw_temperature": "Melegvíz hőmérséklete", + "maximum_capacity_kw": "Kazán maximális teljesítménye", + "minimum_modulation_level": "Minimális modulációs szint", + "relative_modulation_level": "Relatív modulációs szint", + "room_temperature": "Helyiség hőmérséklete" + } + }, + "opentherm_central_heating": { + "title": "OpenTherm központi fűtés", + "description": "Válassza ki, mely felismert központifűtés-attribútumok jelenjenek meg entitásként.", + "data": { + "boiler_ch_max_setpoint_read_write": "Kazán központifűtés-maximális célértékének olvasása/írása", + "boiler_ch_max_setpoint_transfer_enable": "Kazán központifűtés-maximális célértékének átvitele engedélyezve", + "boiler_ch_setpoint": "Kazán központifűtés-célértéke", + "boiler_ch_setpoint_lower_bound": "Kazán központifűtés-célértékének alsó határa", + "boiler_ch_setpoint_upper_bound": "Kazán központifűtés-célértékének felső határa", + "ch_flow_active_lower_setpoint": "Központi fűtés előremenő aktív alsó célértéke", + "ch_flow_active_upper_setpoint": "Központi fűtés előremenő aktív felső célértéke", + "ch1_flow_enabled": "1. fűtési kör előremenő ága engedélyezve", + "ch1_flow_setpoint": "1. fűtési kör előremenő célértéke", + "ch2_flow_enabled": "2. fűtési kör előremenő ága engedélyezve", + "ch2_flow_setpoint": "2. fűtési kör előremenő célértéke", + "room_setpoint": "Helyiség célhőmérséklete" + } + }, + "opentherm_hot_water": { + "title": "OpenTherm meleg víz", + "description": "Válassza ki, mely felismert melegvíz-attribútumok jelenjenek meg entitásként.", + "data": { + "boiler_hw_setpoint": "Kazán melegvíz-célhőmérséklete", + "boiler_hw_setpoint_lower_bound": "Kazán melegvíz-célhőmérsékletének alsó határa", + "boiler_hw_setpoint_read_write": "Kazán melegvíz-célhőmérsékletének olvasása/írása", + "boiler_hw_setpoint_transfer_enable": "Kazán melegvíz-célhőmérsékletének átvitele engedélyezve", + "boiler_hw_setpoint_upper_bound": "Kazán melegvíz-célhőmérsékletének felső határa", + "hw_enabled": "Melegvíz-készítés engedélyezve", + "hw_flow_setpoint": "Melegvíz előremenő célhőmérséklete" + } + }, + "opentherm_status": { + "title": "OpenTherm állapot és diagnosztika", + "description": "Válassza ki, mely felismert állapot- és diagnosztikai attribútumok jelenjenek meg érzékelőentitásként.", + "data": { + "boiler_fault": "Kazánhiba", + "central_heating_active": "Központi fűtés aktív", + "central_heating_2_active": "2. központi fűtési kör aktív", + "connection_status": "Kapcsolat állapota", + "coprocessor_update_status": "OpenTherm koprocesszor frissítési állapota", + "coprocessor_version": "OpenTherm koprocesszor verziója", + "cooling_active": "Hűtés aktív", + "diagnostic_event": "Diagnosztikai esemény", + "flame_active": "Láng aktív", + "flame_statistics": "Lángstatisztika", + "hot_water_active": "Melegvíz-készítés aktív", + "operating_mode": "Üzemmód", + "slave_status": "OpenTherm alárendelt eszköz állapota", + "tracked_room_id": "Követett helyiség azonosítója" + } + } + }, + "abort": { + "opentherm_not_available": "Ehhez a Wiser központhoz nem érhetők el OpenTherm-adatok.", + "equipment_not_available": "Ehhez a Wiser központhoz nem érhetők el berendezésadatok." + } + }, + "services": { + "set_opentherm_parameter": { + "name": "OpenTherm-paraméter beállítása", + "description": "Egy támogatott OpenTherm-hőmérsékleti paraméter módosítása a Wiser központon.", + "fields": { + "parameter": { + "name": "Paraméter", + "description": "A módosítandó OpenTherm-hőmérsékleti paraméter. A szükséges API-végpont automatikusan kerül kiválasztásra." + }, + "temperature": { + "name": "Hőmérséklet", + "description": "A kazán által megadott határértékeken belüli hőmérsékletet használjon." + }, + "hub": { + "name": "Wiser központ", + "description": "Csak akkor válasszon központot, ha több Wiser központja van." + } + } + } + }, + "selector": { + "opentherm_parameter": { + "options": { + "chFlowActiveLowerSetpoint": "Központi fűtés aktív alsó célhőmérséklete", + "chFlowActiveUpperSetpoint": "Központi fűtés aktív felső célhőmérséklete", + "dhwFlowSetpoint": "Központ melegvíz-előremenő célhőmérséklete", + "dhwSetpoint": "Kazán melegvíz-célhőmérséklete", + "maxChSetpoint": "Kazán központifűtés-maximális célhőmérséklete" + } + } + }, + "exceptions": { + "opentherm_temperature_required": { "message": "Adjon meg egy OpenTherm-hőmérsékletet." }, + "opentherm_hub_not_found": { "message": "A megadott Wiser központ nem található." }, + "opentherm_hub_not_loaded": { "message": "A megadott Wiser központ nincs betöltve." }, + "opentherm_hub_required": { "message": "Ha több központ van konfigurálva, válasszon egy Wiser központot." }, + "opentherm_not_supported": { "message": "Ez a központ nem támogatja az OpenTherm funkciót." }, + "opentherm_invalid_parameter": { "message": "Érvénytelen OpenTherm-paraméter vagy érték: {error}" }, + "opentherm_write_failed": { "message": "Nem sikerült beállítani az OpenTherm-paramétert ({parameter}): {error}" }, + "opentherm_confirmation_failed": { "message": "Az OpenTherm-paraméter ({parameter}) egy újrapróbálkozás és a {window} másodperces ellenőrzési időablak után sem maradt a kért {requested} °C értéken. A Wiser által jelentett érték: {reported} °C. Nem történik további újrapróbálkozás." }, + "opentherm_retry_failed": { "message": "Az OpenTherm-paraméter ({parameter}) nem maradt a kért {requested} °C értéken, és az újrapróbálkozást nem sikerült elküldeni: {error}. A Wiser által jelentett érték: {reported} °C. Nem történik további újrapróbálkozás." }, + "opentherm_notification_title": { "message": "Wiser OpenTherm parancs" } + }, + "entity": { + "climate": { + "heating": { + "name": "Fűtés" + }, + "floor_temperature": { + "name": "Padlóhőmérséklet" + } + }, + "number": { + "away_mode_target_temperature": { "name": "Távolléti mód célhőmérséklete" }, + "floor_temperature_offset": { "name": "Padlóhőmérséklet korrekciója" }, + "indoor_discomfort_temperature": { "name": "Beltéri diszkomfort-hőmérséklet" }, + "outdoor_discomfort_temperature": { "name": "Kültéri diszkomfort-hőmérséklet" } + }, + "select": { + "mode": { "name": "Mód" }, + "power_on_behavior": { "name": "Bekapcsolás utáni viselkedés" }, + "led_indicator": { "name": "LED-jelzőfény" } + }, + "button": { + "boost_all_heating": { "name": "Összes fűtés gyorsfelfűtése" }, + "cancel_all_heating_overrides": { "name": "Összes fűtési felülbírálás törlése" }, + "boost_hot_water": { "name": "Melegvíz gyorsfelfűtése" }, + "cancel_hot_water_overrides": { "name": "Melegvíz-felülbírálások törlése" }, + "toggle_hot_water": { "name": "Melegvíz be-/kikapcsolása" }, + "moment": { "name": "Pillanat: {name}" } + }, + "switch": { + "valve_protection": { "name": "Szelepvédelem" }, + "eco_mode": { "name": "Takarékos mód" }, + "away_mode_affects_hot_water": { "name": "A távolléti mód a melegvízre is hatással van" }, + "comfort_mode": { "name": "Komfort mód" }, + "away_mode": { "name": "Távolléti mód" }, + "daylight_saving": { "name": "Nyári időszámítás" }, + "summer_comfort_enabled": { "name": "Nyári komfort engedélyezve" }, + "window_detection": { "name": "Ablaknyitás-érzékelés" }, + "include_in_summer_comfort": { "name": "Bevonás a nyári komfortba" }, + "device_lock": { "name": "Eszköz zárolása" }, + "identify": { "name": "Azonosítás" }, + "outlet": { "name": "Aljzat" }, + "away_mode_turns_off": { "name": "Távolléti módban kikapcsol" }, + "away_mode_closes": { "name": "Távolléti módban bezár" }, + "passive_mode": { "name": "Passzív mód" }, + "respect_summer_comfort": { "name": "Nyári komfort figyelembevétele" }, + "interacts_with_room_climate": { "name": "Hatással van a helyiség klímaszabályozására" }, + "humidity_interacts_with_room_climate": { "name": "A páratartalom hatással van a helyiség klímaszabályozására" }, + "temperature_interacts_with_room_climate": { "name": "A hőmérséklet hatással van a helyiség klímaszabályozására" }, + "illuminance_interacts_with_room_climate": { "name": "A megvilágítás hatással van a helyiség klímaszabályozására" }, + "sensor_interacts_with_room_climate": { "name": "A(z) {sensor} hatással van a helyiség klímaszabályozására" }, + "manual_heat": { "name": "Kézi fűtés" }, + "hot_water": { "name": "Meleg víz" } + }, + "binary_sensor": { + "summer_discomfort_prevention": { "name": "Nyári túlmelegedés megelőzése" }, + "summer_comfort_available": { "name": "Nyári komfort elérhető" }, + "pcm_device_limit_reached": { "name": "Elérte a PCM-eszközök maximális számát" }, + "smoke_alarm": { "name": "Füstjelzés" }, + "heat_alarm": { "name": "Hőriasztás" }, + "tamper_alarm": { "name": "Szabotázsriasztás" }, + "fault_warning": { "name": "Hibajelzés" }, + "remote_alarm": { "name": "Távoli riasztás" }, + "battery_defect": { "name": "Akkumulátorhiba" }, + "controllable": { "name": "Vezérelhető" }, + "pcm_mode": { "name": "PCM mód" }, + "window_detection_active": { "name": "Ablaknyitás-érzékelés aktív" }, + "is_dimmable": { "name": "Fényerőszabályozható" }, + "is_led_indicator_supported": { "name": "LED-jelzőfény támogatott" }, + "is_output_mode_supported": { "name": "Kimeneti mód támogatott" }, + "is_power_on_behaviour_supported": { "name": "Bekapcsolás utáni viselkedés támogatott" }, + "is_tilt_supported": { "name": "Döntés támogatott" }, + "is_open": { "name": "Nyitva" }, + "is_closed": { "name": "Zárva" }, + "active": { "name": "Aktív" }, + "boiler_ch_max_setpoint_read_write": { "name": "Kazán központifűtés-maximális célértékének olvasása/írása" }, + "boiler_ch_max_setpoint_transfer_enable": { "name": "Kazán központifűtés-maximális célértékének átvitele engedélyezve" }, + "boiler_fault": { "name": "Kazánhiba" }, + "boiler_hw_setpoint_read_write": { "name": "Kazán melegvíz-célhőmérsékletének olvasása/írása" }, + "boiler_hw_setpoint_transfer_enable": { "name": "Kazán melegvíz-célhőmérsékletének átvitele engedélyezve" }, + "central_heating_2_active": { "name": "2. központi fűtési kör aktív" }, + "central_heating_active": { "name": "Központi fűtés aktív" }, + "ch1_flow_enabled": { "name": "1. fűtési kör előremenő ága engedélyezve" }, + "ch2_flow_enabled": { "name": "2. fűtési kör előremenő ága engedélyezve" }, + "cooling_active": { "name": "Hűtés aktív" }, + "diagnostic_event": { "name": "Diagnosztikai esemény" }, + "flame_active": { "name": "Láng aktív" }, + "hot_water_active": { "name": "Melegvíz-készítés aktív" }, + "hw_enabled": { "name": "Melegvíz-készítés engedélyezve" } + }, + "sensor": { + "signal": { "name": "Jel" }, + "cloud": { "name": "Felhő" }, + "heating_operation_mode": { "name": "Fűtési üzemmód" }, + "heating": { + "name": "Fűtés", + "state": { + "off": "[%key:common::state::off%]", + "on": "[%key:common::state::on%]" + } + }, + "heating_channel": { + "name": "Fűtési csatorna {channel}", + "state": { + "off": "[%key:common::state::off%]", + "on": "[%key:common::state::on%]" + } + }, + "hot_water": { + "name": "Meleg víz", + "state": { + "off": "[%key:common::state::off%]", + "on": "[%key:common::state::on%]" + } + }, + "hot_water_operation_mode": { "name": "Melegvíz üzemmód" }, + "target_temperature": { "name": "Célhőmérséklet" }, + "floor_temperature": { "name": "Padlóhőmérséklet" }, + "boiler_flow_temperature": { "name": "Kazán előremenő hőmérséklete" }, + "boiler_return_temperature": { "name": "Kazán visszatérő hőmérséklete" }, + "flame_statistics": { "name": "Lángstatisztika" }, + "boiler_ch_setpoint": { "name": "Kazán központifűtés-célértéke" }, + "boiler_ch_setpoint_lower_bound": { "name": "Kazán központifűtés-célértékének alsó határa" }, + "boiler_ch_setpoint_upper_bound": { "name": "Kazán központifűtés-célértékének felső határa" }, + "boiler_exhaust_temperature": { "name": "Kazán füstgázhőmérséklete" }, + "boiler_hw_setpoint": { "name": "Kazán melegvíz-célhőmérséklete" }, + "boiler_hw_setpoint_lower_bound": { "name": "Kazán melegvíz-célhőmérsékletének alsó határa" }, + "boiler_hw_setpoint_upper_bound": { "name": "Kazán melegvíz-célhőmérsékletének felső határa" }, + "ch1_flow_setpoint": { "name": "1. fűtési kör előremenő célértéke" }, + "ch2_flow_setpoint": { "name": "2. fűtési kör előremenő célértéke" }, + "ch_flow_active_lower_setpoint": { "name": "Központi fűtés előremenő aktív alsó célértéke" }, + "ch_flow_active_upper_setpoint": { "name": "Központi fűtés előremenő aktív felső célértéke" }, + "ch_pressure_bar": { "name": "Központi fűtés nyomása" }, + "connection_status": { "name": "Kapcsolat állapota" }, + "coprocessor_update_status": { "name": "OpenTherm koprocesszor frissítési állapota" }, + "coprocessor_version": { "name": "OpenTherm koprocesszor verziója" }, + "delta_t": { "name": "Hőmérséklet-különbség (ΔT)" }, + "estimated_boiler_output": { "name": "Kazán becsült teljesítménye" }, + "hw_flow_rate": { "name": "Melegvíz térfogatárama" }, + "hw_flow_setpoint": { "name": "Melegvíz előremenő célhőmérséklete" }, + "hw_temperature": { "name": "Melegvíz hőmérséklete" }, + "maximum_capacity_kw": { "name": "Kazán maximális teljesítménye" }, + "minimum_modulation_level": { "name": "Minimális modulációs szint" }, + "operating_mode": { "name": "Üzemmód" }, + "relative_modulation_level": { "name": "Relatív modulációs szint" }, + "room_setpoint": { "name": "Helyiség célhőmérséklete" }, + "room_temperature": { "name": "Helyiség hőmérséklete" }, + "slave_status": { "name": "OpenTherm alárendelt eszköz állapota" }, + "tracked_room_id": { "name": "Követett helyiség azonosítója" }, + "heating_demand": { "name": "Fűtési igény" }, + "heating_demand_channel": { "name": "Fűtési igény – {channel}. csatorna" }, + "hot_water_demand": { "name": "Melegvíz-igény" }, + "total_energy": { "name": "Összes energia" }, + "energy_delivered": { "name": "Leadott energia" }, + "energy_received": { "name": "Felvett energia" }, + "equipment_power": { "name": "Berendezés teljesítménye" } + } + }, + "device_automation": { + "trigger_type": { + "started_heating": "{entity_name} fűtése elindul", + "stopped_heating": "{entity_name} fűtése leáll", + "boosted": "{entity_name} gyorsfelfűtése aktiválódik", + "target_temperature_increased": "{entity_name} célhőmérséklete emelkedett", + "target_temperature_decreased": "{entity_name} célhőmérséklete csökkent" + } + } +} \ No newline at end of file diff --git a/custom_components/wiser/translations/nl.json b/custom_components/wiser/translations/nl.json new file mode 100644 index 00000000..3411cc80 --- /dev/null +++ b/custom_components/wiser/translations/nl.json @@ -0,0 +1,651 @@ +{ + "config": { + "flow_title": "{name}", + "step": { + "user": { + "title": "Wiser Installatie warmtehub", + "description": "Voer het IP-adres en de geheime sleutel in die u van de hub hebt verkregen.", + "data": { + "host": "IP-adres of hostnaam", + "port": "Poortnummer", + "password": "Geheime sleutel" + } + }, + "zeroconf_confirm": { + "title": "Wiser Installatie warmtehub ({name})", + "description": "Voer in de geheime sleutel verkregen van de hub.", + "data": { + "host": "IP-adres of hostnaam", + "port": "Poortnummer", + "password": "Geheime sleutel" + } + } + }, + "abort": { + "already_in_progress": "Wiser De configuratie van de warmtehub wordt al uitgevoerd.", + "already_configured": "Dit apparaat is al geconfigureerd.", + "not_wiser_hub": "Het ontdekte apparaat is geen Wiser Warmtehub." + }, + "error": { + "auth_failure": "Kan niet verifiëren met de Wiser-hub. Controleer de geheime sleutel en probeer het opnieuw.", + "timeout_error": "Er is een time-out opgetreden bij het verbinden met de Wiser-hub. Controleer het IP-adres en probeer het opnieuw.", + "timeout_error_discovery": "Er is een time-out opgetreden bij het verbinden met de Wiser-hub. Controleer of uw hub nog steeds online is en probeer het opnieuw.", + "unknown": "Onbekende fout bij het verbinden met de Wiser-hub. Controleer de logboeken." + } + }, + "options": { + "step": { + "init": { + "title": "Wiser Integratieopties", + "description": "Selecteer parameters om te wijzigen", + "menu_options": { + "main_params": "Hoofdparameters", + "automation_params": "Automatiseringsparameters", + "opentherm_sensors": "OpenTherm-sensoren", + "equipment_sensors": "Apparatuursensoren", + "ui_options": "UI-opties" + } + }, + "ui_options": { + "title": "UI-opties", + "data": { + "legacy_naming": "Oude naamgeving", + "show_wiser_sidebar": "Toon Wiser in zijbalk" + }, + "data_description": { + "legacy_naming": "Neem kamernamen op in Wiser apparaatnamen. Indien ingeschakeld, zal het gebruik van Home Assistant om entiteits-ID's opnieuw te genereren met het standaardformaat in Instellingen → Systeem → Entiteits-ID-formaat (Home Assistant 2026.8 en later) gebiedsnamen dupliceren wanneer het gebied en de Wiser kamernamen overeenkomen. Als u deze optie wijzigt, worden de bestaande entiteit-ID's niet hernoemd." + } + }, + "main_params": { + "title": "Wiser Integratieopties", + "description": "Hoofdparameters", + "data": { + "host": "IP-adres of hostnaam", + "port": "Poortnummer", + "scan_interval": "Scaninterval (sec)", + "heating_boost_temp": "Standaard verwarmingsboosttemperatuur (°C)", + "heating_boost_time": "Standaard verwarmingsboostduur (min.)", + "hotwater_boost_time": "Standaard warmwaterboostduur (min.)", + "setpoint_mode": "Instelpuntmodus", + "restore_manual_temp_option": "Gebruik deze temperatuur als er geen handmatige temperatuur is opgeslagen" + } + }, + "automation_params": { + "title": "Wiser Integratieopties", + "description": "Ingebouwde automatiseringen inschakelen", + "sections": { + "automations_passive_mode": { + "name": "Passieve modus", + "description": "Passieve TRV-mogelijkheden inschakelen. Elke kamer moet worden ingeschakeld om te kunnen functioneren.", + "data": { + "automations_passive_mode": "Passieve modus", + "passive_mode_temperature_increments": "Passieve modus Temperatuurverhogingen" + } + }, + "hotwater_climate": { + "name": "Warmwaterklimaatregeling", + "description": "Schakel klimaatregeling voor warm water in. Zie de wiki voor details.", + "data": { + "hotwater_climate": "Schakel de klimaatentiteit in", + "experimental_mode": "Schakel de experimentele werkmodus in", + "hotwater_auto_mode": "Automatische modus voor warm water", + "hotwater_heat_mode": "Modus voor warm water", + "hotwater_boost_mode": "Modus voor warm water boost", + "hotwater_sensor_entity_id": "Warmwatertemperatuursensor" + } + } + } + }, + "equipment_sensors": { + "title": "Apparatuursensoren", + "description": "Configureer gedetailleerde apparatuurgegevensentiteiten voor compatibele apparaten.", + "data": { + "equipment_sensors": "Schakel apparatuurgegevenssensoren in" + }, + "data_description": { + "equipment_sensors": "Stel een extra sensor bloot met gedetailleerde apparatuurkenmerken voor elke compatibele slimme stekker, PowerTag en verwarmingsactuator." + } + }, + "opentherm_sensors": { + "title": "OpenTherm-sensoren", + "description": "Kies een categorie gedetecteerde OpenTherm-attributen.", + "menu_options": { + "opentherm_readings": "Uitlezingen", + "opentherm_central_heating": "Centrale verwarming", + "opentherm_hot_water": "Warm water", + "opentherm_status": "Status en diagnostiek" + } + }, + "opentherm_readings": { + "title": "OpenTherm uitlezingen", + "description": "Kies welke gedetecteerde OpenTherm-metingen worden weergegeven als sensorentiteiten.", + "data": { + "ch_flow_temperature": "Ketelaanvoertemperatuur", + "ch_pressure_bar": "CV-druk", + "ch_return_temperature": "Ketelretourtemperatuur", + "delta_t": "Delta-T", + "boiler_exhaust_temperature": "Ketelafvoertemperatuur", + "estimated_boiler_output": "Geschat ketelvermogen", + "hw_flow_rate": "Warmwaterdebiet", + "hw_temperature": "Warmwatertemperatuur", + "maximum_capacity_kw": "Maximaal ketelvermogen", + "minimum_modulation_level": "Minimaal modulatieniveau", + "relative_modulation_level": "Relatief modulatieniveau", + "room_temperature": "Kamertemperatuur" + } + }, + "opentherm_central_heating": { + "title": "OpenTherm centrale verwarming", + "description": "Kies welke gedetecteerde kenmerken voor centrale verwarming als entiteiten worden weergegeven.", + "data": { + "boiler_ch_max_setpoint_read_write": "Ketel CH maximum setpoint lezen/schrijven", + "boiler_ch_max_setpoint_transfer_enable": "Ketel CH maximum setpoint overdracht ingeschakeld", + "boiler_ch_setpoint": "Ketel CH setpoint", + "boiler_ch_setpoint_lower_bound": "Ketel CH setpoint ondergrens", + "boiler_ch_setpoint_upper_bound": "Ketel CH setpoint bovengrens", + "ch_flow_active_lower_setpoint": "CH-debiet actief onderste setpoint", + "ch_flow_active_upper_setpoint": "CH-debiet actief bovenste setpoint", + "ch1_flow_enabled": "CH1-debiet ingeschakeld", + "ch1_flow_setpoint": "CH1 debiet-setpoint", + "ch2_flow_enabled": "CH2-debiet ingeschakeld", + "ch2_flow_setpoint": "CH2-debiet instelpunt", + "room_setpoint": "Instelpunt kamer" + } + }, + "opentherm_hot_water": { + "title": "OpenTherm warm water", + "description": "Kies welke gedetecteerde warmwaterkenmerken als entiteiten worden weergegeven.", + "data": { + "boiler_hw_setpoint": "Ketelwarmwaterinstelpunt", + "boiler_hw_setpoint_lower_bound": "Ketelwarmwaterinstelpunt ondergrens", + "boiler_hw_setpoint_read_write": "Ketelwarmwaterinstelpunt lezen/schrijven", + "boiler_hw_setpoint_transfer_enable": "Ketelwarmwaterinstelpuntoverdracht ingeschakeld", + "boiler_hw_setpoint_upper_bound": "Ketelwarmwaterinstelpunt bovengrens", + "hw_enabled": "Heet water ingeschakeld", + "hw_flow_setpoint": "Instelpunt warmwaterdebiet" + } + }, + "opentherm_status": { + "title": "OpenTherm status en diagnostiek", + "description": "Kies welke gedetecteerde status en diagnostische kenmerken worden weergegeven als sensorentiteiten.", + "data": { + "boiler_fault": "Ketelstoring", + "central_heating_active": "Centrale verwarming actief", + "central_heating_2_active": "Centrale verwarming 2 actief", + "connection_status": "Verbindingsstatus", + "coprocessor_update_status": "OpenTherm Updatestatus coprocessor", + "coprocessor_version": "OpenTherm coprocessorversie", + "cooling_active": "Koeling actief", + "diagnostic_event": "Diagnosegebeurtenis", + "flame_active": "Vlam actief", + "flame_statistics": "Vlamstatistieken", + "hot_water_active": "Warm water actief", + "operating_mode": "Bedrijfsmodus", + "slave_status": "OpenTherm slave-status", + "tracked_room_id": "Getraceerde kamer-ID" + } + } + }, + "abort": { + "opentherm_not_available": "OpenTherm-gegevens zijn niet beschikbaar voor deze Wiser naaf.", + "equipment_not_available": "Er zijn geen uitrustingsgegevens beschikbaar voor deze Wiser-hub." + } + }, + "services": { + "set_opentherm_parameter": { + "name": "OpenTherm-parameter instellen", + "description": "Wijzigt een ondersteunde OpenTherm-temperatuurparameter op de Wiser-hub.", + "fields": { + "parameter": { + "name": "Parameter", + "description": "OpenTherm temperatuurparameter die moet worden gewijzigd. Het vereiste API-eindpunt wordt automatisch geselecteerd." + }, + "temperature": { + "name": "Temperatuur", + "description": "Gebruik een temperatuur binnen de grenzen die door uw ketel worden gerapporteerd." + }, + "hub": { + "name": "Wiser hub", + "description": "Selecteer alleen een hub als u meerdere Wiser hubs heeft." + } + } + } + }, + "selector": { + "opentherm_parameter": { + "options": { + "chFlowActiveLowerSetpoint": "Actieve CV-onderinstelling", + "chFlowActiveUpperSetpoint": "Actieve CV-boveninstelling", + "dhwFlowSetpoint": "Hub warmwateraanvoersetpoint", + "dhwSetpoint": "Ketel warmwatersetpoint", + "maxChSetpoint": "Ketel maximale CV-setpoint" + } + } + }, + "exceptions": { + "opentherm_temperature_required": { + "message": "Geef een OpenTherm-temperatuur op." + }, + "opentherm_hub_not_found": { + "message": "De opgegeven Wiser-hub is niet gevonden." + }, + "opentherm_hub_not_loaded": { + "message": "De opgegeven Wiser-hub is niet geladen." + }, + "opentherm_hub_required": { + "message": "Selecteer een Wiser-hub als er meer dan één hub is geconfigureerd." + }, + "opentherm_not_supported": { + "message": "Deze hub heeft geen OpenTherm-functionaliteit." + }, + "opentherm_invalid_parameter": { + "message": "De parameter of waarde OpenTherm is ongeldig: {error}" + }, + "opentherm_write_failed": { + "message": "Kan parameter OpenTherm niet instellen {parameter}: {error}" + }, + "opentherm_confirmation_failed": { + "message": "OpenTherm-parameter {parameter} bleef niet op {requested} °C na één nieuwe poging en het {window}-tweede bevestigingsvenster. Wiser rapporteert {reported} °C. Er wordt geen nieuwe poging meer verzonden." + }, + "opentherm_retry_failed": { + "message": "OpenTherm-parameter {parameter} bleef niet op {requested} °C en de nieuwe poging kon niet worden verzonden: {error}. Wiser meldt {reported} °C. Er wordt geen nieuwe poging meer verzonden." + }, + "opentherm_notification_title": { + "message": "Wiser OpenTherm commando" + } + }, + "entity": { + "climate": { + "heating": { + "name": "Verwarming" + }, + "floor_temperature": { + "name": "Vloertemperatuur" + } + }, + "number": { + "away_mode_target_temperature": { + "name": "Doeltemperatuur afwezigheidsmodus" + }, + "floor_temperature_offset": { + "name": "Offset vloertemperatuur" + }, + "indoor_discomfort_temperature": { + "name": "Ongemakkelijke temperatuur binnen" + }, + "outdoor_discomfort_temperature": { + "name": "Ongemakkelijke temperatuur buiten" + } + }, + "select": { + "mode": { + "name": "Modus" + }, + "power_on_behavior": { + "name": "Inschakelgedrag" + }, + "led_indicator": { + "name": "LED-indicator" + } + }, + "button": { + "boost_all_heating": { + "name": "Alle verwarming stimuleren" + }, + "cancel_all_heating_overrides": { + "name": "Alle verwarmingsoverrides annuleren" + }, + "boost_hot_water": { + "name": "Warm water boost" + }, + "cancel_hot_water_overrides": { + "name": "Warmwateroverrides annuleren" + }, + "toggle_hot_water": { + "name": "Warm water omschakelen" + }, + "moment": { + "name": "Moment: {name}" + } + }, + "switch": { + "valve_protection": { + "name": "Klepbescherming" + }, + "eco_mode": { + "name": "Eco-modus" + }, + "away_mode_affects_hot_water": { + "name": "Afwezig-modus beïnvloedt warm water" + }, + "comfort_mode": { + "name": "Comfort-modus" + }, + "away_mode": { + "name": "Afwezig-modus" + }, + "daylight_saving": { + "name": "Zomertijd" + }, + "summer_comfort_enabled": { + "name": "Zomercomfort ingeschakeld" + }, + "window_detection": { + "name": "Raamdetectie" + }, + "include_in_summer_comfort": { + "name": "Meenemen in zomercomfort" + }, + "device_lock": { + "name": "Apparaatvergrendeling" + }, + "identify": { + "name": "Identificeren" + }, + "outlet": { + "name": "Outlet" + }, + "away_mode_turns_off": { + "name": "Afwezig-modus wordt uitgeschakeld" + }, + "away_mode_closes": { + "name": "Afwezig-modus sluit" + }, + "passive_mode": { + "name": "Passieve modus" + }, + "respect_summer_comfort": { + "name": "Respecteer het zomercomfort" + }, + "interacts_with_room_climate": { + "name": "Heeft invloed op het binnenklimaat" + }, + "humidity_interacts_with_room_climate": { + "name": "Vochtigheid heeft invloed op het binnenklimaat" + }, + "temperature_interacts_with_room_climate": { + "name": "Temperatuur heeft invloed op het binnenklimaat" + }, + "illuminance_interacts_with_room_climate": { + "name": "Verlichtingssterkte heeft invloed op het binnenklimaat" + }, + "sensor_interacts_with_room_climate": { + "name": "{sensor} interageert met het binnenklimaat" + }, + "manual_heat": { + "name": "Handmatige verwarming" + }, + "hot_water": { + "name": "Warm water" + } + }, + "binary_sensor": { + "summer_discomfort_prevention": { + "name": "Preventie van zomerongemakken" + }, + "summer_comfort_available": { + "name": "Zomercomfort beschikbaar" + }, + "pcm_device_limit_reached": { + "name": "PCM-apparaatlimiet bereikt" + }, + "smoke_alarm": { + "name": "Rookmelder" + }, + "heat_alarm": { + "name": "Hittealarm" + }, + "tamper_alarm": { + "name": "Sabotagealarm" + }, + "fault_warning": { + "name": "Foutwaarschuwing" + }, + "remote_alarm": { + "name": "Alarm op afstand" + }, + "battery_defect": { + "name": "Batterij defect" + }, + "controllable": { + "name": "Bestuurbaar" + }, + "pcm_mode": { + "name": "PCM-modus" + }, + "window_detection_active": { + "name": "Raamdetectie actief" + }, + "is_dimmable": { + "name": "Dimbaar" + }, + "is_led_indicator_supported": { + "name": "LED-indicator ondersteund" + }, + "is_output_mode_supported": { + "name": "Uitgangsmodus ondersteund" + }, + "is_power_on_behaviour_supported": { + "name": "Inschakelgedrag ondersteund" + }, + "is_tilt_supported": { + "name": "Kantelfunctie ondersteund" + }, + "is_open": { + "name": "Open" + }, + "is_closed": { + "name": "Gesloten" + }, + "active": { + "name": "Actief" + }, + "boiler_ch_max_setpoint_read_write": { + "name": "Ketel CH maximaal setpoint lezen/schrijven" + }, + "boiler_ch_max_setpoint_transfer_enable": { + "name": "Ketel CV maximum setpoint overdracht ingeschakeld" + }, + "boiler_fault": { + "name": "Ketel storing" + }, + "boiler_hw_setpoint_read_write": { + "name": "Ketel warm water setpoint lezen/schrijven" + }, + "boiler_hw_setpoint_transfer_enable": { + "name": "Ketel warm water setpoint overdracht ingeschakeld" + }, + "central_heating_2_active": { + "name": "Centrale verwarming 2 actief" + }, + "central_heating_active": { + "name": "Centrale verwarming actief" + }, + "ch1_flow_enabled": { + "name": "CH1-stroom ingeschakeld" + }, + "ch2_flow_enabled": { + "name": "CH2-stroom ingeschakeld" + }, + "cooling_active": { + "name": "Koeling actief" + }, + "diagnostic_event": { + "name": "Diagnosegebeurtenis" + }, + "flame_active": { + "name": "Vlam actief" + }, + "hot_water_active": { + "name": "Warm water actief" + }, + "hw_enabled": { + "name": "Warm water ingeschakeld" + } + }, + "sensor": { + "signal": { + "name": "Signaal" + }, + "cloud": { + "name": "Cloud" + }, + "heating_operation_mode": { + "name": "Verwarmingsmodus" + }, + "heating": { + "name": "Verwarming", + "state": { + "off": "Uit", + "on": "Aan" + } + }, + "heating_channel": { + "name": "Verwarmingskanaal {channel}", + "state": { + "off": "Uit", + "on": "Aan" + } + }, + "hot_water": { + "name": "Warm water", + "state": { + "off": "Uit", + "on": "Aan" + } + }, + "hot_water_operation_mode": { + "name": "Warmwaterbedrijfsmodus" + }, + "target_temperature": { + "name": "Streeftemperatuur" + }, + "floor_temperature": { + "name": "Vloertemperatuur" + }, + "boiler_flow_temperature": { + "name": "Ketelaanvoertemperatuur" + }, + "boiler_return_temperature": { + "name": "Ketelretourtemperatuur" + }, + "flame_statistics": { + "name": "Vlamstatistieken" + }, + "boiler_ch_setpoint": { + "name": "Ketel CV-instelpunt" + }, + "boiler_ch_setpoint_lower_bound": { + "name": "Ketel CH-instelpunt ondergrens" + }, + "boiler_ch_setpoint_upper_bound": { + "name": "Ketel CV-instelpunt bovengrens" + }, + "boiler_exhaust_temperature": { + "name": "Ketelafvoertemperatuur" + }, + "boiler_hw_setpoint": { + "name": "Ketel heet waterinstelpunt" + }, + "boiler_hw_setpoint_lower_bound": { + "name": "Ketelwarmwaterinstelpunt ondergrens" + }, + "boiler_hw_setpoint_upper_bound": { + "name": "Ketelwarmwaterinstelpunt bovengrens" + }, + "ch1_flow_setpoint": { + "name": "CH1 debietinstelpunt" + }, + "ch2_flow_setpoint": { + "name": "CH2 aanvoer setpoint" + }, + "ch_flow_active_lower_setpoint": { + "name": "CH aanvoer actief onderste setpoint" + }, + "ch_flow_active_upper_setpoint": { + "name": "CH aanvoer actief bovenste setpoint" + }, + "ch_pressure_bar": { + "name": "CV druk" + }, + "connection_status": { + "name": "Verbindingsstatus" + }, + "coprocessor_update_status": { + "name": "OpenTherm updatestatus coprocessor" + }, + "coprocessor_version": { + "name": "OpenTherm coprocessorversie" + }, + "delta_t": { + "name": "Delta-T" + }, + "estimated_boiler_output": { + "name": "Geschat ketelvermogen" + }, + "hw_flow_rate": { + "name": "Warmwaterdebiet" + }, + "hw_flow_setpoint": { + "name": "Instelpunt warmwaterdebiet" + }, + "hw_temperature": { + "name": "Warmwatertemperatuur" + }, + "maximum_capacity_kw": { + "name": "Maximaal ketelvermogen" + }, + "minimum_modulation_level": { + "name": "Minimaal modulatieniveau" + }, + "operating_mode": { + "name": "Bedrijfsmodus" + }, + "relative_modulation_level": { + "name": "Relatief modulatieniveau" + }, + "room_setpoint": { + "name": "Gewenste ruimteruimte" + }, + "room_temperature": { + "name": "Kamertemperatuur" + }, + "slave_status": { + "name": "OpenTherm slave-status" + }, + "tracked_room_id": { + "name": "Getraceerde kamer-ID" + }, + "heating_demand": { + "name": "Verwarmingsvraag" + }, + "heating_demand_channel": { + "name": "Verwarmingsvraagkanaal {channel}" + }, + "hot_water_demand": { + "name": "Warmwatervraag" + }, + "total_energy": { + "name": "Totale energie" + }, + "energy_delivered": { + "name": "Geleverde energie" + }, + "energy_received": { + "name": "Ontvangen energie" + }, + "equipment_power": { + "name": "Apparatuur" + } + } + }, + "device_automation": { + "trigger_type": { + "started_heating": "{entity_name} begint met verwarmen", + "stopped_heating": "{entity_name} stopt met verwarmen", + "boosted": "{entity_name} wordt versterkt", + "target_temperature_increased": "{entity_name} doeltemperatuur verhoogd", + "target_temperature_decreased": "{entity_name} doeltemperatuur verlaagd" + } + } +} diff --git a/custom_components/wiser/translations/pt.json b/custom_components/wiser/translations/pt.json new file mode 100644 index 00000000..1f372de7 --- /dev/null +++ b/custom_components/wiser/translations/pt.json @@ -0,0 +1,651 @@ +{ + "config": { + "flow_title": "{name}", + "step": { + "user": { + "title": "Wiser Configuração do hub de calor", + "description": "Insira o endereço IP e a chave secreta obtidas do hub.", + "data": { + "host": "Endereço IP ou nome de host", + "port": "Número da porta", + "password": "Chave secreta" + } + }, + "zeroconf_confirm": { + "title": "Wiser Configuração do hub de aquecimento ({name})", + "description": "Insira a chave secreta obtida do hub.", + "data": { + "host": "Endereço IP ou nome de host", + "port": "Número da porta", + "password": "Chave secreta" + } + } + }, + "abort": { + "already_in_progress": "Wiser A configuração do Heat Hub já está em andamento.", + "already_configured": "Este dispositivo já está configurado.", + "not_wiser_hub": "O dispositivo descoberto não é um Heat Hub Wiser." + }, + "error": { + "auth_failure": "Não é possível autenticar com o hub Wiser. Verifique a chave secreta e tente novamente.", + "timeout_error": "Tempo limite esgotado ao tentar conectar-se ao hub Wiser. Verifique o endereço IP e tente novamente.", + "timeout_error_discovery": "Tempo limite esgotado ao tentar conectar-se ao hub Wiser. Verifique se o seu hub ainda está online e tente novamente.", + "unknown": "Erro desconhecido ao conectar ao hub Wiser. Por favor, verifique os registros." + } + }, + "options": { + "step": { + "init": { + "title": "Wiser Opções de integração", + "description": "Selecione parâmetros para alterar", + "menu_options": { + "main_params": "Parâmetros principais", + "automation_params": "Parâmetros de automação", + "opentherm_sensors": "Sensores OpenTherm", + "equipment_sensors": "Sensores de equipamento", + "ui_options": "Opções de UI" + } + }, + "ui_options": { + "title": "Opções de UI", + "data": { + "legacy_naming": "Nomenclatura legada", + "show_wiser_sidebar": "Mostrar Wiser na barra lateral" + }, + "data_description": { + "legacy_naming": "Incluir espaço nomes em nomes de dispositivos Wiser. Se ativado, usar Home Assistant para regenerar IDs de entidade com o formato padrão em Configurações → Sistema → Formato de ID de entidade (Home Assistant 2026.8 e posterior) duplicará os nomes das áreas quando os nomes da área e da sala Wiser corresponderem. A alteração desta opção não renomeia os IDs de entidade existentes." + } + }, + "main_params": { + "title": "Wiser Opções de integração", + "description": "Parâmetros principais", + "data": { + "host": "Endereço IP ou nome do host", + "port": "Número da porta", + "scan_interval": "Intervalo de varredura (seg)", + "heating_boost_temp": "Temperatura padrão do reforço de aquecimento (°C)", + "heating_boost_time": "Duração padrão do reforço de aquecimento (minutos)", + "hotwater_boost_time": "Duração padrão do reforço de água quente (minutos)", + "setpoint_mode": "Modo de ponto de ajuste", + "restore_manual_temp_option": "Use esta temperatura se não A temperatura manual é armazenada" + } + }, + "automation_params": { + "title": "Wiser Opções de integração", + "description": "Habilitar automações integradas", + "sections": { + "automations_passive_mode": { + "name": "Modo passivo", + "description": "Habilitar capacidade TRV passiva. Cada sala precisa ser habilitada para funcionar.", + "data": { + "automations_passive_mode": "Modo passivo", + "passive_mode_temperature_increments": "Incrementos de temperatura no modo passivo" + } + }, + "hotwater_climate": { + "name": "Controle climático de água quente", + "description": "Ativa o controle climático de água quente. Veja o wiki para detalhes.", + "data": { + "hotwater_climate": "Ativar a entidade climática", + "experimental_mode": "Ativar modo de trabalho experimental", + "hotwater_auto_mode": "Modo automático de água quente", + "hotwater_heat_mode": "Modo de aquecimento de água quente", + "hotwater_boost_mode": "Modo de reforço de água quente", + "hotwater_sensor_entity_id": "Sensor de temperatura de água quente" + } + } + } + }, + "equipment_sensors": { + "title": "Sensores de equipamento", + "description": "Configure entidades de dados de equipamento detalhadas para dispositivos compatíveis.", + "data": { + "equipment_sensors": "Habilitar sensores de dados do equipamento" + }, + "data_description": { + "equipment_sensors": "Exponha um sensor adicional contendo atributos detalhados do equipamento para cada plugue inteligente, PowerTag e atuador de aquecimento compatível." + } + }, + "opentherm_sensors": { + "title": "Sensores OpenTherm", + "description": "Escolha uma categoria de atributos OpenTherm detectados.", + "menu_options": { + "opentherm_readings": "Leituras", + "opentherm_central_heating": "Aquecimento central", + "opentherm_hot_water": "Água quente", + "opentherm_status": "Estado e diagnóstico" + } + }, + "opentherm_readings": { + "title": "Leituras OpenTherm", + "description": "Escolha qual as leituras OpenTherm detectadas são expostas como entidades de sensor.", + "data": { + "ch_flow_temperature": "Temperatura de fluxo da caldeira", + "ch_pressure_bar": "Pressão CH", + "ch_return_temperature": "Temperatura de retorno da caldeira", + "delta_t": "Delta-T", + "boiler_exhaust_temperature": "Temperatura de exaustão da caldeira", + "estimated_boiler_output": "Potência estimada da caldeira", + "hw_flow_rate": "Vazão de água quente", + "hw_temperature": "Temperatura da água quente", + "maximum_capacity_kw": "Capacidade máxima da caldeira", + "minimum_modulation_level": "Nível mínimo de modulação", + "relative_modulation_level": "Nível de modulação relativa", + "room_temperature": "Temperatura ambiente" + } + }, + "opentherm_central_heating": { + "title": "OpenTherm aquecimento central", + "description": "Escolha quais atributos de aquecimento central detectados são expostos como entidades.", + "data": { + "boiler_ch_max_setpoint_read_write": "Leitura/escrita do ponto de ajuste máximo do CH da caldeira", + "boiler_ch_max_setpoint_transfer_enable": "Transferência máxima do ponto de ajuste do CH da caldeira habilitada", + "boiler_ch_setpoint": "Ponto de ajuste do CH da caldeira", + "boiler_ch_setpoint_lower_bound": "Limite inferior do ponto de ajuste do CH da caldeira", + "boiler_ch_setpoint_upper_bound": "Limite superior do ponto de ajuste do CH da caldeira", + "ch_flow_active_lower_setpoint": "Ponto de ajuste inferior ativo de fluxo CH", + "ch_flow_active_upper_setpoint": "Ponto de ajuste superior ativo de fluxo CH", + "ch1_flow_enabled": "Fluxo CH1 habilitado", + "ch1_flow_setpoint": "Ponto de ajuste de fluxo CH1", + "ch2_flow_enabled": "Fluxo CH2 habilitado", + "ch2_flow_setpoint": "Fluxo CH2 ponto de ajuste", + "room_setpoint": "Ponto de ajuste da sala" + } + }, + "opentherm_hot_water": { + "title": "OpenTherm água quente", + "description": "Escolha quais atributos de água quente detectados são expostos como entidades.", + "data": { + "boiler_hw_setpoint": "Ponto de ajuste de água quente da caldeira", + "boiler_hw_setpoint_lower_bound": "Limite inferior do ponto de ajuste de água quente da caldeira", + "boiler_hw_setpoint_read_write": "Leitura/escrita do ponto de ajuste de água quente da caldeira", + "boiler_hw_setpoint_transfer_enable": "Transferência do ponto de ajuste de água quente da caldeira habilitada", + "boiler_hw_setpoint_upper_bound": "Ponto de ajuste de água quente da caldeira limite superior", + "hw_enabled": "Água quente habilitada", + "hw_flow_setpoint": "Ponto de ajuste do fluxo de água quente" + } + }, + "opentherm_status": { + "title": "OpenTherm status e diagnóstico", + "description": "Escolha quais status detectados e atributos de diagnóstico são expostos como entidades de sensor.", + "data": { + "boiler_fault": "Avaria na caldeira", + "central_heating_active": "Aquecimento central activo", + "central_heating_2_active": "Aquecimento central 2 activo", + "connection_status": "Estado da ligação", + "coprocessor_update_status": "OpenTherm Estado de actualização do coprocessador", + "coprocessor_version": "OpenTherm versão do coprocessador", + "cooling_active": "Resfriamento ativo", + "diagnostic_event": "Evento de diagnóstico", + "flame_active": "Chama ativa", + "flame_statistics": "Estatísticas de chama", + "hot_water_active": "Água quente ativa", + "operating_mode": "Modo de operação", + "slave_status": "OpenTherm status escravo", + "tracked_room_id": "ID da sala rastreada" + } + } + }, + "abort": { + "opentherm_not_available": "OpenTherm Os dados não estão disponíveis para este Wiser centro.", + "equipment_not_available": "Os dados do equipamento não estão disponíveis para este hub Wiser." + } + }, + "services": { + "set_opentherm_parameter": { + "name": "Definir parâmetro OpenTherm", + "description": "Altera um parâmetro de temperatura OpenTherm compatível no hub Wiser. Parâmetro", + "fields": { + "parameter": { + "name": "", + "description": "OpenTherm Parâmetro de temperatura a ser alterado. O endpoint de API necessário é selecionado automaticamente." + }, + "temperature": { + "name": "Temperatura", + "description": "Utilize uma temperatura dentro dos limites informados pela sua caldeira." + }, + "hub": { + "name": "Hub Wiser", + "description": "Selecione um hub somente quando você tiver vários hubs Wiser." + } + } + } + }, + "selector": { + "opentherm_parameter": { + "options": { + "chFlowActiveLowerSetpoint": "Ponto de ajuste inferior de aquecimento central ativo", + "chFlowActiveUpperSetpoint": "Ponto de ajuste superior de aquecimento central ativo", + "dhwFlowSetpoint": "Ponto de ajuste de fluxo de água quente do hub", + "dhwSetpoint": "Ponto de ajuste de água quente da caldeira", + "maxChSetpoint": "Ponto de ajuste máximo de aquecimento central da caldeira" + } + } + }, + "exceptions": { + "opentherm_temperature_required": { + "message": "Forneça uma temperatura OpenTherm." + }, + "opentherm_hub_not_found": { + "message": "O hub Wiser especificado não foi localizado." + }, + "opentherm_hub_not_loaded": { + "message": "O hub Wiser especificado não está carregado." + }, + "opentherm_hub_required": { + "message": "Selecione um hub Wiser quando mais de um hub estiver configurado." + }, + "opentherm_not_supported": { + "message": "Este hub não possui a funcionalidade OpenTherm." + }, + "opentherm_invalid_parameter": { + "message": "O parâmetro ou valor OpenTherm é inválido: {error}" + }, + "opentherm_write_failed": { + "message": "Não é possível definir o parâmetro OpenTherm {parameter}: {error}" + }, + "opentherm_confirmation_failed": { + "message": "O parâmetro OpenTherm {parameter} não permaneceu em {requested} °C após uma nova tentativa e a janela de confirmação de segundo {window}. Wiser relata {reported} °C. Nenhuma nova tentativa será enviada." + }, + "opentherm_retry_failed": { + "message": "O parâmetro OpenTherm {parameter} não permaneceu em {requested} °C e sua nova tentativa não pôde ser enviada: {error}. Wiser relata {reported} °C. Nenhuma nova tentativa será enviada." + }, + "opentherm_notification_title": { + "message": "Wiser Comando OpenTherm" + } + }, + "entity": { + "climate": { + "heating": { + "name": "Aquecimento" + }, + "floor_temperature": { + "name": "Temperatura do piso" + } + }, + "number": { + "away_mode_target_temperature": { + "name": "Temperatura alvo do modo ausente" + }, + "floor_temperature_offset": { + "name": "Deslocamento da temperatura do piso" + }, + "indoor_discomfort_temperature": { + "name": "Temperatura de desconforto interno" + }, + "outdoor_discomfort_temperature": { + "name": "Temperatura de desconforto externo" + } + }, + "select": { + "mode": { + "name": "Modo" + }, + "power_on_behavior": { + "name": "Comportamento de inicialização" + }, + "led_indicator": { + "name": "Indicador LED" + } + }, + "button": { + "boost_all_heating": { + "name": "Aumentar todo o aquecimento" + }, + "cancel_all_heating_overrides": { + "name": "Cancelar todas as substituições de aquecimento" + }, + "boost_hot_water": { + "name": "Aumentar a água quente" + }, + "cancel_hot_water_overrides": { + "name": "Cancelar substituições de água quente" + }, + "toggle_hot_water": { + "name": "Alternar água quente" + }, + "moment": { + "name": "Momento: {name}" + } + }, + "switch": { + "valve_protection": { + "name": "Proteção da válvula" + }, + "eco_mode": { + "name": "Modo Eco" + }, + "away_mode_affects_hot_water": { + "name": "O modo ausente afeta a água quente" + }, + "comfort_mode": { + "name": "Modo conforto" + }, + "away_mode": { + "name": "Modo ausente" + }, + "daylight_saving": { + "name": "Horário de verão" + }, + "summer_comfort_enabled": { + "name": "Conforto de verão habilitado" + }, + "window_detection": { + "name": "Detecção de janela" + }, + "include_in_summer_comfort": { + "name": "Incluir no conforto do verão" + }, + "device_lock": { + "name": "Bloqueio de dispositivo" + }, + "identify": { + "name": "Identificar" + }, + "outlet": { + "name": "Tomada" + }, + "away_mode_turns_off": { + "name": "O modo ausente desliga" + }, + "away_mode_closes": { + "name": "O modo ausente fecha" + }, + "passive_mode": { + "name": "Modo passivo" + }, + "respect_summer_comfort": { + "name": "Respeite o conforto do verão" + }, + "interacts_with_room_climate": { + "name": "Interage com o clima ambiente" + }, + "humidity_interacts_with_room_climate": { + "name": "A umidade interage com o clima ambiente" + }, + "temperature_interacts_with_room_climate": { + "name": "A temperatura interage com o clima ambiente" + }, + "illuminance_interacts_with_room_climate": { + "name": "A iluminação interage com o clima ambiente" + }, + "sensor_interacts_with_room_climate": { + "name": "{sensor} interage com o clima ambiente" + }, + "manual_heat": { + "name": "Aquecimento manual" + }, + "hot_water": { + "name": "Água quente" + } + }, + "binary_sensor": { + "summer_discomfort_prevention": { + "name": "Prevenção de desconforto no verão" + }, + "summer_comfort_available": { + "name": "Conforto de verão disponível" + }, + "pcm_device_limit_reached": { + "name": "Limite do dispositivo PCM atingido" + }, + "smoke_alarm": { + "name": "Alarme de fumaça" + }, + "heat_alarm": { + "name": "Alarme de calor" + }, + "tamper_alarm": { + "name": "Alarme de violação" + }, + "fault_warning": { + "name": "Aviso de falha" + }, + "remote_alarm": { + "name": "Alarme remoto" + }, + "battery_defect": { + "name": "Defeito na bateria" + }, + "controllable": { + "name": "Controlável" + }, + "pcm_mode": { + "name": "Modo PCM" + }, + "window_detection_active": { + "name": "Detecção de janela ativa" + }, + "is_dimmable": { + "name": "Regulável" + }, + "is_led_indicator_supported": { + "name": "Indicador LED compatível" + }, + "is_output_mode_supported": { + "name": "Modo de saída compatível" + }, + "is_power_on_behaviour_supported": { + "name": "Comportamento de inicialização suportado" + }, + "is_tilt_supported": { + "name": "Inclinação suportada" + }, + "is_open": { + "name": "Aberto" + }, + "is_closed": { + "name": "Fechado" + }, + "active": { + "name": "Ativo" + }, + "boiler_ch_max_setpoint_read_write": { + "name": "Leitura/gravação do ponto de ajuste máximo do CH da caldeira" + }, + "boiler_ch_max_setpoint_transfer_enable": { + "name": "Transferência máxima do ponto de ajuste do CH da caldeira habilitada" + }, + "boiler_fault": { + "name": "Falha da caldeira" + }, + "boiler_hw_setpoint_read_write": { + "name": "Leitura/escrita do ponto de ajuste de água quente da caldeira" + }, + "boiler_hw_setpoint_transfer_enable": { + "name": "Transferência do ponto de ajuste de água quente da caldeira habilitada" + }, + "central_heating_2_active": { + "name": "Aquecimento central 2 ativo" + }, + "central_heating_active": { + "name": "Aquecimento central ativo" + }, + "ch1_flow_enabled": { + "name": "Fluxo CH1 habilitado" + }, + "ch2_flow_enabled": { + "name": "Fluxo CH2 habilitado" + }, + "cooling_active": { + "name": "Resfriamento ativo" + }, + "diagnostic_event": { + "name": "Evento de diagnóstico" + }, + "flame_active": { + "name": "Chama ativa" + }, + "hot_water_active": { + "name": "Água quente ativa" + }, + "hw_enabled": { + "name": "Água quente ativada" + } + }, + "sensor": { + "signal": { + "name": "Sinal" + }, + "cloud": { + "name": "Nuvem" + }, + "heating_operation_mode": { + "name": "Modo de operação de aquecimento" + }, + "heating": { + "name": "Aquecimento", + "state": { + "off": "Desligado", + "on": "Ligado" + } + }, + "heating_channel": { + "name": "Canal de aquecimento {channel}", + "state": { + "off": "Desligado", + "on": "Ligado" + } + }, + "hot_water": { + "name": "Água quente", + "state": { + "off": "Desligado", + "on": "Ligado" + } + }, + "hot_water_operation_mode": { + "name": "Modo de operação de água quente" + }, + "target_temperature": { + "name": "Temperatura alvo" + }, + "floor_temperature": { + "name": "Temperatura do piso" + }, + "boiler_flow_temperature": { + "name": "Temperatura de fluxo da caldeira" + }, + "boiler_return_temperature": { + "name": "Temperatura de retorno da caldeira" + }, + "flame_statistics": { + "name": "Estatísticas de chama" + }, + "boiler_ch_setpoint": { + "name": "Ponto de ajuste do CH da caldeira" + }, + "boiler_ch_setpoint_lower_bound": { + "name": "Limite inferior do ponto de ajuste do CH da caldeira" + }, + "boiler_ch_setpoint_upper_bound": { + "name": "Limite superior do ponto de ajuste do CH da caldeira" + }, + "boiler_exhaust_temperature": { + "name": "Temperatura de exaustão da caldeira" + }, + "boiler_hw_setpoint": { + "name": "Ponto de ajuste de água quente da caldeira" + }, + "boiler_hw_setpoint_lower_bound": { + "name": "Limite inferior do ponto de ajuste de água quente da caldeira" + }, + "boiler_hw_setpoint_upper_bound": { + "name": "Ponto de ajuste de água quente da caldeira limite superior" + }, + "ch1_flow_setpoint": { + "name": "Ponto de ajuste de fluxo CH1" + }, + "ch2_flow_setpoint": { + "name": "Ponto de ajuste de fluxo CH2" + }, + "ch_flow_active_lower_setpoint": { + "name": "Ponto de ajuste inferior ativo de fluxo CH" + }, + "ch_flow_active_upper_setpoint": { + "name": "Ponto de ajuste superior ativo de fluxo CH" + }, + "ch_pressure_bar": { + "name": "Pressão CH" + }, + "connection_status": { + "name": "Status de conexão" + }, + "coprocessor_update_status": { + "name": "OpenTherm Status de atualização do coprocessador" + }, + "coprocessor_version": { + "name": "OpenTherm versão do coprocessador" + }, + "delta_t": { + "name": "Delta-T" + }, + "estimated_boiler_output": { + "name": "Saída estimada da caldeira" + }, + "hw_flow_rate": { + "name": "Taxa de fluxo de água quente" + }, + "hw_flow_setpoint": { + "name": "Ponto de ajuste do fluxo de água quente" + }, + "hw_temperature": { + "name": "Temperatura da água quente" + }, + "maximum_capacity_kw": { + "name": "Capacidade máxima da caldeira" + }, + "minimum_modulation_level": { + "name": "Nível mínimo de modulação" + }, + "operating_mode": { + "name": "Modo de operação" + }, + "relative_modulation_level": { + "name": "Nível de modulação relativo" + }, + "room_setpoint": { + "name": "Ponto de ajuste da sala" + }, + "room_temperature": { + "name": "Temperatura ambiente" + }, + "slave_status": { + "name": "OpenTherm status escravo" + }, + "tracked_room_id": { + "name": "ID da sala rastreada" + }, + "heating_demand": { + "name": "Demanda de aquecimento" + }, + "heating_demand_channel": { + "name": "Canal de demanda de aquecimento {channel}" + }, + "hot_water_demand": { + "name": "Demanda de água quente" + }, + "total_energy": { + "name": "Energia total" + }, + "energy_delivered": { + "name": "Energia fornecida" + }, + "energy_received": { + "name": "Energia recebida" + }, + "equipment_power": { + "name": "Equipamento" + } + } + }, + "device_automation": { + "trigger_type": { + "started_heating": "{entity_name} inicia o aquecimento", + "stopped_heating": "{entity_name} para de aquecer", + "boosted": "{entity_name} é aumentado", + "target_temperature_increased": "{entity_name} temperatura alvo aumentada", + "target_temperature_decreased": "A temperatura alvo do {entity_name} diminuiu" + } + } +} From dfd11641304716f70165ea886af859c917769157 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 15 Oct 2026 14:23:09 +0100 Subject: [PATCH 143/154] feat: expose smoke alarm report count --- custom_components/wiser/sensor.py | 68 ++++++++++++++++--- custom_components/wiser/strings.json | 1 + custom_components/wiser/translations/de.json | 1 + .../wiser/translations/en-GB.json | 1 + custom_components/wiser/translations/en.json | 1 + custom_components/wiser/translations/fr.json | 1 + tests/test_sensor.py | 19 ++++++ 7 files changed, 84 insertions(+), 8 deletions(-) diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index 34687611..a96632de 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -373,15 +373,18 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie if room.roomstat_id: wiser_sensors.append(WiserLTSHumiditySensor(data, room.roomstat_id)) - # Add temp sensors for smoke alarms - wiser_sensors.extend( - WiserLTSTempSensor( - data, - device.id, - sensor_type="smokealarm_temp", + # Add smoke-alarm sensors + for device in data.wiserhub.devices.smokealarms.all: + wiser_sensors.extend( + [ + WiserLTSTempSensor( + data, + device.id, + sensor_type="smokealarm_temp", + ), + WiserSmokeAlarmReportCountSensor(data, device.id), + ] ) - for device in data.wiserhub.devices.smokealarms.all - ) # Add temp sensors for ITRVs _LOGGER.debug("Setting up smartvalve remperature sensors") @@ -602,6 +605,55 @@ def device_info(self): } +class WiserSmokeAlarmReportCountSensor(WiserSensor): + """Diagnostic count of reports received from a smoke alarm.""" + + _attr_entity_category = EntityCategory.DIAGNOSTIC + _attr_icon = "mdi:counter" + + def __init__(self, data, device_id=0) -> None: + """Initialize the report-count sensor.""" + super().__init__( + data, + device_id, + "report_count", + translation_key="report_count", + ) + self._device = self._data.wiserhub.devices.get_by_id(self._device_id) + self._state = self._device.report_count + + @callback + def _handle_coordinator_update(self) -> None: + """Refresh the report count.""" + super()._handle_coordinator_update() + self._device = self._data.wiserhub.devices.get_by_id(self._device_id) + self._state = self._device.report_count + self.async_write_ha_state() + + @property + def unique_id(self): + """Return a name-independent unique ID.""" + return get_physical_entity_unique_id( + self._data, + "sensor", + self._device_id, + "report_count", + ) + + @property + def device_info(self): + """Attach the entity to its physical smoke-alarm device.""" + return { + "name": get_device_name(self._data, self._device_id), + "identifiers": {(DOMAIN, get_identifier(self._data, self._device_id))}, + "manufacturer": MANUFACTURER, + "model": self._device.product_type, + "sw_version": self._device.firmware_version, + **get_device_area_info(self._data, self._device_id), + **get_hub_via_device_info(self._data), + } + + class WiserDeviceSignalSensor(WiserSensor): """Definition of Wiser Device Sensor.""" diff --git a/custom_components/wiser/strings.json b/custom_components/wiser/strings.json index 9f8e2f20..5be14d17 100755 --- a/custom_components/wiser/strings.json +++ b/custom_components/wiser/strings.json @@ -328,6 +328,7 @@ }, "sensor": { "signal": { "name": "Signal" }, + "report_count": { "name": "Report count" }, "cloud": { "name": "Cloud" }, "heating_operation_mode": { "name": "Heating operation mode" }, "heating": { diff --git a/custom_components/wiser/translations/de.json b/custom_components/wiser/translations/de.json index 23bdd7e8..55dd936f 100644 --- a/custom_components/wiser/translations/de.json +++ b/custom_components/wiser/translations/de.json @@ -326,6 +326,7 @@ }, "sensor": { "signal": { "name": "Signal" }, + "report_count": { "name": "Berichtsanzahl" }, "cloud": { "name": "Cloud" }, "heating_operation_mode": { "name": "Heizungsbetriebsart" }, "heating": { diff --git a/custom_components/wiser/translations/en-GB.json b/custom_components/wiser/translations/en-GB.json index 14598fac..64386d6c 100644 --- a/custom_components/wiser/translations/en-GB.json +++ b/custom_components/wiser/translations/en-GB.json @@ -326,6 +326,7 @@ }, "sensor": { "signal": { "name": "Signal" }, + "report_count": { "name": "Report count" }, "cloud": { "name": "Cloud" }, "heating_operation_mode": { "name": "Heating operation mode" }, "heating": { diff --git a/custom_components/wiser/translations/en.json b/custom_components/wiser/translations/en.json index e5dd405f..cfe9bc31 100755 --- a/custom_components/wiser/translations/en.json +++ b/custom_components/wiser/translations/en.json @@ -326,6 +326,7 @@ }, "sensor": { "signal": { "name": "Signal" }, + "report_count": { "name": "Report count" }, "cloud": { "name": "Cloud" }, "heating_operation_mode": { "name": "Heating operation mode" }, "heating": { diff --git a/custom_components/wiser/translations/fr.json b/custom_components/wiser/translations/fr.json index 3ca0e2a2..7c839fb1 100644 --- a/custom_components/wiser/translations/fr.json +++ b/custom_components/wiser/translations/fr.json @@ -326,6 +326,7 @@ }, "sensor": { "signal": { "name": "Signal" }, + "report_count": { "name": "Nombre de rapports" }, "cloud": { "name": "Cloud" }, "heating_operation_mode": { "name": "Mode de fonctionnement du chauffage" }, "heating": { diff --git a/tests/test_sensor.py b/tests/test_sensor.py index eea78b46..a86bdc54 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -1440,12 +1440,14 @@ class WiserSmokeAlarmStatusSensorTest(unittest.TestCase): @classmethod def setUpClass(cls): cls.binary_sensor_module = _load_binary_sensor_module() + cls.sensor_module = _load_sensor_module() def setUp(self): self.device = SimpleNamespace( ac_mains=True, test_mode=False, hush_mode=True, + report_count=42, product_type="SmokeAlarmDevice", firmware_version="1.0", ) @@ -1489,6 +1491,23 @@ def test_reads_hush_mode_state(self): self.assertTrue(sensor.is_on) self.assertEqual(sensor._attr_icon, "mdi:volume-off") + def test_reads_report_count_and_refreshes(self): + sensor = self.sensor_module.WiserSmokeAlarmReportCountSensor( + self.data, 7 + ) + sensor.async_write_ha_state = Mock() + + self.assertEqual(sensor.native_value, 42) + self.assertEqual(sensor._attr_entity_category, "diagnostic") + self.assertEqual(sensor._attr_icon, "mdi:counter") + self.assertEqual(sensor.unique_id, "physical-sensor-7-report_count") + + self.device.report_count = 43 + sensor._handle_coordinator_update() + + self.assertEqual(sensor.native_value, 43) + sensor.async_write_ha_state.assert_called_once_with() + class WiserEquipmentBinarySensorTest(unittest.TestCase): """Tests for binary sensors backed by optional equipment data.""" From 6b11228017fa0e7d9daca6b9307ae072d892a121 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Fri, 16 Oct 2026 12:51:37 +0100 Subject: [PATCH 144/154] feat: expand Wiser translation support --- custom_components/wiser/translations/da.json | 652 +++++++++++++++++++ custom_components/wiser/translations/es.json | 156 ++--- custom_components/wiser/translations/fi.json | 652 +++++++++++++++++++ custom_components/wiser/translations/hu.json | 14 +- custom_components/wiser/translations/nb.json | 652 +++++++++++++++++++ custom_components/wiser/translations/nl.json | 142 ++-- custom_components/wiser/translations/pt.json | 108 +-- custom_components/wiser/translations/sv.json | 652 +++++++++++++++++++ tests/test_entity_naming.py | 8 +- 9 files changed, 2821 insertions(+), 215 deletions(-) create mode 100644 custom_components/wiser/translations/da.json create mode 100644 custom_components/wiser/translations/fi.json create mode 100644 custom_components/wiser/translations/nb.json create mode 100644 custom_components/wiser/translations/sv.json diff --git a/custom_components/wiser/translations/da.json b/custom_components/wiser/translations/da.json new file mode 100644 index 00000000..89944715 --- /dev/null +++ b/custom_components/wiser/translations/da.json @@ -0,0 +1,652 @@ +{ + "config": { + "flow_title": "{name}", + "step": { + "user": { + "title": "Opsætning af Wiser Heat Hub", + "description": "Indtast IP-adressen og den hemmelige nøgle, der er hentet fra hubben.", + "data": { + "host": "IP-adresse eller værtsnavn", + "port": "Portnummer", + "password": "Hemmelig nøgle" + } + }, + "zeroconf_confirm": { + "title": "Opsætning af Wiser Heat Hub ({name})", + "description": "Indtast den hemmelige nøgle, der er hentet fra hubben.", + "data": { + "host": "IP-adresse eller værtsnavn", + "port": "Portnummer", + "password": "Hemmelig nøgle" + } + } + }, + "abort": { + "already_in_progress": "Konfigurationen af Wiser Heat Hub er allerede i gang.", + "already_configured": "Denne enhed er allerede konfigureret.", + "not_wiser_hub": "Den fundne enhed er ikke en Wiser Heat Hub." + }, + "error": { + "auth_failure": "Godkendelse med Wiser-hubben mislykkedes. Kontrollér den hemmelige nøgle, og prøv igen.", + "timeout_error": "Forbindelsen til Wiser-hubben fik timeout. Kontrollér IP-adressen, og prøv igen.", + "timeout_error_discovery": "Forbindelsen til Wiser-hubben fik timeout. Kontrollér, at hubben stadig er online, og prøv igen.", + "unknown": "Ukendt fejl ved forbindelse til Wiser-hubben. Kontrollér logfilerne." + } + }, + "options": { + "step": { + "init": { + "title": "Indstillinger for Wiser-integrationen", + "description": "Vælg parametre, der skal ændres", + "menu_options": { + "main_params": "Hovedparametre", + "automation_params": "Automatiseringsparametre", + "opentherm_sensors": "OpenTherm-sensorer", + "equipment_sensors": "Udstyrssensorer", + "ui_options": "Brugerfladeindstillinger" + } + }, + "ui_options": { + "title": "Brugerfladeindstillinger", + "data": { + "legacy_naming": "Ældre navngivning", + "show_wiser_sidebar": "Vis Wiser i sidepanelet" + }, + "data_description": { + "legacy_naming": "Medtag rumnavne i Wiser-enhedsnavne. Hvis dette er aktiveret, vil regenerering af entitets-id'er i Home Assistant med standardformatet under Indstillinger → System → Entitets-id-format (Home Assistant 2026.8 og nyere) duplikere områdenavne, når området og Wiser-rummet har samme navn. Ændring af denne indstilling omdøber ikke eksisterende entitets-id'er." + } + }, + "main_params": { + "title": "Indstillinger for Wiser-integrationen", + "description": "Hovedparametre", + "data": { + "host": "IP-adresse eller værtsnavn", + "port": "Portnummer", + "scan_interval": "Scanningsinterval (sek.)", + "heating_boost_temp": "Standardtemperatur for varmeboost (°C)", + "heating_boost_time": "Standardvarighed for varmeboost (min.)", + "hotwater_boost_time": "Standardvarighed for varmtvandsboost (min.)", + "setpoint_mode": "Indstillingspunkttilstand", + "restore_manual_temp_option": "Brug denne temperatur, hvis der ikke er gemt en manuel temperatur" + } + }, + "automation_params": { + "title": "Indstillinger for Wiser-integrationen", + "description": "Aktivér indbyggede automatiseringer", + "sections": { + "automations_passive_mode": { + "name": "Passiv tilstand", + "description": "Aktivér passiv TRV-funktion. Hvert rum skal aktiveres, før funktionen virker.", + "data": { + "automations_passive_mode": "Passiv tilstand", + "passive_mode_temperature_increments": "Temperaturtrin for passiv tilstand" + } + }, + "hotwater_climate": { + "name": "Klimastyring af varmt vand", + "description": "Aktivér klimastyring af varmt vand. Se wikien for detaljer.", + "data": { + "hotwater_climate": "Aktivér klimaentiteten", + "experimental_mode": "Aktivér eksperimentel driftstilstand", + "hotwater_auto_mode": "Automatisk varmtvandstilstand", + "hotwater_heat_mode": "Varmtvandsopvarmningstilstand", + "hotwater_boost_mode": "Varmtvandsboosttilstand", + "hotwater_sensor_entity_id": "Varmtvandstemperatursensor" + } + } + } + }, + "equipment_sensors": { + "title": "Udstyrssensorer", + "description": "Konfigurer entiteter med detaljerede udstyrsdata for kompatible enheder.", + "data": { + "equipment_sensors": "Aktivér udstyrsdatasensorer" + }, + "data_description": { + "equipment_sensors": "Vis en ekstra sensor med detaljerede udstyrsattributter for hvert kompatibelt smartstik, PowerTag og varmeaktuator." + } + }, + "opentherm_sensors": { + "title": "OpenTherm-sensorer", + "description": "Vælg en kategori af registrerede OpenTherm-attributter.", + "menu_options": { + "opentherm_readings": "Målinger", + "opentherm_central_heating": "Centralvarme", + "opentherm_hot_water": "Varmt vand", + "opentherm_status": "Status og diagnosticering" + } + }, + "opentherm_readings": { + "title": "OpenTherm-målinger", + "description": "Vælg, hvilke registrerede OpenTherm-målinger der vises som sensorentiteter.", + "data": { + "ch_flow_temperature": "Kedlens fremløbstemperatur", + "ch_pressure_bar": "Centralvarmetryk", + "ch_return_temperature": "Kedlens returtemperatur", + "delta_t": "Delta-T", + "boiler_exhaust_temperature": "Kedlens røggastemperatur", + "estimated_boiler_output": "Anslået kedelydelse", + "hw_flow_rate": "Varmtvandsflow", + "hw_temperature": "Varmtvandstemperatur", + "maximum_capacity_kw": "Maksimal kedelkapacitet", + "minimum_modulation_level": "Mindste modulationsniveau", + "relative_modulation_level": "Relativt modulationsniveau", + "room_temperature": "Rumtemperatur" + } + }, + "opentherm_central_heating": { + "title": "OpenTherm-centralvarme", + "description": "Vælg, hvilke registrerede centralvarmeattributter der vises som entiteter.", + "data": { + "boiler_ch_max_setpoint_read_write": "Læsning/skrivning af kedlens maksimale centralvarmeindstillingspunkt", + "boiler_ch_max_setpoint_transfer_enable": "Overførsel af kedlens maksimale centralvarmeindstillingspunkt aktiveret", + "boiler_ch_setpoint": "Kedlens centralvarmeindstillingspunkt", + "boiler_ch_setpoint_lower_bound": "Nedre grænse for kedlens centralvarmeindstillingspunkt", + "boiler_ch_setpoint_upper_bound": "Øvre grænse for kedlens centralvarmeindstillingspunkt", + "ch_flow_active_lower_setpoint": "Aktivt nedre centralvarmefremløbsindstillingspunkt", + "ch_flow_active_upper_setpoint": "Aktivt øvre centralvarmefremløbsindstillingspunkt", + "ch1_flow_enabled": "Centralvarmekreds 1 fremløb aktiveret", + "ch1_flow_setpoint": "Centralvarmekreds 1 fremløbsindstillingspunkt", + "ch2_flow_enabled": "Centralvarmekreds 2 fremløb aktiveret", + "ch2_flow_setpoint": "Centralvarmekreds 2 fremløbsindstillingspunkt", + "room_setpoint": "Rumindstillingspunkt" + } + }, + "opentherm_hot_water": { + "title": "OpenTherm-varmt vand", + "description": "Vælg, hvilke registrerede varmtvandsattributter der vises som entiteter.", + "data": { + "boiler_hw_setpoint": "Kedlens varmtvandsindstillingspunkt", + "boiler_hw_setpoint_lower_bound": "Nedre grænse for kedlens varmtvandsindstillingspunkt", + "boiler_hw_setpoint_read_write": "Læsning/skrivning af kedlens varmtvandsindstillingspunkt", + "boiler_hw_setpoint_transfer_enable": "Overførsel af kedlens varmtvandsindstillingspunkt aktiveret", + "boiler_hw_setpoint_upper_bound": "Øvre grænse for kedlens varmtvandsindstillingspunkt", + "hw_enabled": "Varmt vand aktiveret", + "hw_flow_setpoint": "Varmtvandsfremløbets indstillingspunkt" + } + }, + "opentherm_status": { + "title": "OpenTherm-status og diagnosticering", + "description": "Vælg, hvilke registrerede status- og diagnosticeringsattributter der vises som sensorentiteter.", + "data": { + "boiler_fault": "Kedelfejl", + "central_heating_active": "Centralvarme aktiv", + "central_heating_2_active": "Centralvarme 2 aktiv", + "connection_status": "Forbindelsesstatus", + "coprocessor_update_status": "Opdateringsstatus for OpenTherm-coprocessor", + "coprocessor_version": "Version af OpenTherm-coprocessor", + "cooling_active": "Køling aktiv", + "diagnostic_event": "Diagnosticeringshændelse", + "flame_active": "Flamme aktiv", + "flame_statistics": "Flammestatistik", + "hot_water_active": "Varmt vand aktivt", + "operating_mode": "Driftstilstand", + "slave_status": "OpenTherm-slavestatus", + "tracked_room_id": "Id for overvåget rum" + } + } + }, + "abort": { + "opentherm_not_available": "OpenTherm-data er ikke tilgængelige for denne Wiser-hub.", + "equipment_not_available": "Udstyrsdata er ikke tilgængelige for denne Wiser-hub." + } + }, + "services": { + "set_opentherm_parameter": { + "name": "Indstil OpenTherm-parameter", + "description": "Ændrer en understøttet OpenTherm-temperaturparameter på Wiser-hubben.", + "fields": { + "parameter": { + "name": "Parameter", + "description": "OpenTherm-temperaturparameteren, der skal ændres. Det nødvendige API-slutpunkt vælges automatisk." + }, + "temperature": { + "name": "Temperatur", + "description": "Brug en temperatur inden for de grænser, som kedlen rapporterer." + }, + "hub": { + "name": "Wiser-hub", + "description": "Vælg kun en hub, når du har flere Wiser-hubber." + } + } + } + }, + "selector": { + "opentherm_parameter": { + "options": { + "chFlowActiveLowerSetpoint": "Aktivt nedre centralvarmeindstillingspunkt", + "chFlowActiveUpperSetpoint": "Aktivt øvre centralvarmeindstillingspunkt", + "dhwFlowSetpoint": "Hubbens varmtvandsfremløbsindstillingspunkt", + "dhwSetpoint": "Kedlens varmtvandsindstillingspunkt", + "maxChSetpoint": "Kedlens maksimale centralvarmeindstillingspunkt" + } + } + }, + "exceptions": { + "opentherm_temperature_required": { + "message": "Angiv en OpenTherm-temperatur." + }, + "opentherm_hub_not_found": { + "message": "Den angivne Wiser-hub blev ikke fundet." + }, + "opentherm_hub_not_loaded": { + "message": "Den angivne Wiser-hub er ikke indlæst." + }, + "opentherm_hub_required": { + "message": "Vælg en Wiser-hub, når mere end én hub er konfigureret." + }, + "opentherm_not_supported": { + "message": "Denne hub understøtter ikke OpenTherm." + }, + "opentherm_invalid_parameter": { + "message": "OpenTherm-parameteren eller værdien er ugyldig: {error}" + }, + "opentherm_write_failed": { + "message": "OpenTherm-parameteren {parameter} kunne ikke indstilles: {error}" + }, + "opentherm_confirmation_failed": { + "message": "OpenTherm-parameteren {parameter} forblev ikke på {requested} °C efter ét nyt forsøg og bekræftelsesperioden på {window} sekunder. Wiser rapporterer {reported} °C. Der sendes ikke flere forsøg." + }, + "opentherm_retry_failed": { + "message": "OpenTherm-parameteren {parameter} forblev ikke på {requested} °C, og et nyt forsøg kunne ikke sendes: {error}. Wiser rapporterer {reported} °C. Der sendes ikke flere forsøg." + }, + "opentherm_notification_title": { + "message": "Wiser OpenTherm-kommando" + } + }, + "entity": { + "climate": { + "heating": { + "name": "Opvarmning" + }, + "floor_temperature": { + "name": "Gulvtemperatur" + } + }, + "number": { + "away_mode_target_temperature": { + "name": "Måltemperatur for fraværstilstand" + }, + "floor_temperature_offset": { + "name": "Forskydning af gulvtemperatur" + }, + "indoor_discomfort_temperature": { + "name": "Indendørs ubehagstemperatur" + }, + "outdoor_discomfort_temperature": { + "name": "Udendørs ubehagstemperatur" + } + }, + "select": { + "mode": { + "name": "Tilstand" + }, + "power_on_behavior": { + "name": "Startadfærd" + }, + "led_indicator": { + "name": "LED-indikator" + } + }, + "button": { + "boost_all_heating": { + "name": "Boost al opvarmning" + }, + "cancel_all_heating_overrides": { + "name": "Annuller alle varmetilsidesættelser" + }, + "boost_hot_water": { + "name": "Boost varmt vand" + }, + "cancel_hot_water_overrides": { + "name": "Annuller alle varmtvandstilsidesættelser" + }, + "toggle_hot_water": { + "name": "Slå varmt vand til/fra" + }, + "moment": { + "name": "Moment: {name}" + } + }, + "switch": { + "valve_protection": { + "name": "Ventilbeskyttelse" + }, + "eco_mode": { + "name": "Økotilstand" + }, + "away_mode_affects_hot_water": { + "name": "Fraværstilstand påvirker varmt vand" + }, + "comfort_mode": { + "name": "Komforttilstand" + }, + "away_mode": { + "name": "Fraværstilstand" + }, + "daylight_saving": { + "name": "Sommertid" + }, + "summer_comfort_enabled": { + "name": "Sommerkomfort aktiveret" + }, + "window_detection": { + "name": "Vinduesregistrering" + }, + "include_in_summer_comfort": { + "name": "Medtag i sommerkomfort" + }, + "device_lock": { + "name": "Enhedslås" + }, + "identify": { + "name": "Identificer" + }, + "outlet": { + "name": "Stikkontakt" + }, + "away_mode_turns_off": { + "name": "Fraværstilstand slukker" + }, + "away_mode_closes": { + "name": "Fraværstilstand lukker" + }, + "passive_mode": { + "name": "Passiv tilstand" + }, + "respect_summer_comfort": { + "name": "Respekter sommerkomfort" + }, + "interacts_with_room_climate": { + "name": "Interagerer med rumklima" + }, + "humidity_interacts_with_room_climate": { + "name": "Luftfugtighed interagerer med rumklima" + }, + "temperature_interacts_with_room_climate": { + "name": "Temperatur interagerer med rumklima" + }, + "illuminance_interacts_with_room_climate": { + "name": "Belysningsstyrke interagerer med rumklima" + }, + "sensor_interacts_with_room_climate": { + "name": "{sensor} interagerer med rumklima" + }, + "manual_heat": { + "name": "Manuel opvarmning" + }, + "hot_water": { + "name": "Varmt vand" + } + }, + "binary_sensor": { + "summer_discomfort_prevention": { + "name": "Forebyggelse af sommerubehag" + }, + "summer_comfort_available": { + "name": "Sommerkomfort tilgængelig" + }, + "pcm_device_limit_reached": { + "name": "Grænsen for PCM-enheder er nået" + }, + "smoke_alarm": { + "name": "Røgalarm" + }, + "heat_alarm": { + "name": "Varmealarm" + }, + "tamper_alarm": { + "name": "Manipulationsalarm" + }, + "fault_warning": { + "name": "Fejladvarsel" + }, + "remote_alarm": { + "name": "Fjernalarm" + }, + "battery_defect": { + "name": "Batterifejl" + }, + "controllable": { + "name": "Kan styres" + }, + "pcm_mode": { + "name": "PCM-tilstand" + }, + "window_detection_active": { + "name": "Vinduesregistrering aktiv" + }, + "is_dimmable": { + "name": "Kan dæmpes" + }, + "is_led_indicator_supported": { + "name": "LED-indikator understøttes" + }, + "is_output_mode_supported": { + "name": "Udgangstilstand understøttes" + }, + "is_power_on_behaviour_supported": { + "name": "Startadfærd understøttes" + }, + "is_tilt_supported": { + "name": "Hældning understøttes" + }, + "is_open": { + "name": "Åben" + }, + "is_closed": { + "name": "Lukket" + }, + "active": { + "name": "Aktiv" + }, + "boiler_ch_max_setpoint_read_write": { + "name": "Læsning/skrivning af kedlens maksimale centralvarmeindstillingspunkt" + }, + "boiler_ch_max_setpoint_transfer_enable": { + "name": "Overførsel af kedlens maksimale centralvarmeindstillingspunkt aktiveret" + }, + "boiler_fault": { + "name": "Kedelfejl" + }, + "boiler_hw_setpoint_read_write": { + "name": "Læsning/skrivning af kedlens varmtvandsindstillingspunkt" + }, + "boiler_hw_setpoint_transfer_enable": { + "name": "Overførsel af kedlens varmtvandsindstillingspunkt aktiveret" + }, + "central_heating_2_active": { + "name": "Centralvarme 2 aktiv" + }, + "central_heating_active": { + "name": "Centralvarme aktiv" + }, + "ch1_flow_enabled": { + "name": "Centralvarmekreds 1 fremløb aktiveret" + }, + "ch2_flow_enabled": { + "name": "Centralvarmekreds 2 fremløb aktiveret" + }, + "cooling_active": { + "name": "Køling aktiv" + }, + "diagnostic_event": { + "name": "Diagnosticeringshændelse" + }, + "flame_active": { + "name": "Flamme aktiv" + }, + "hot_water_active": { + "name": "Varmt vand aktivt" + }, + "hw_enabled": { + "name": "Varmt vand aktiveret" + } + }, + "sensor": { + "signal": { + "name": "Signal" + }, + "cloud": { + "name": "Sky" + }, + "heating_operation_mode": { + "name": "Driftstilstand for opvarmning" + }, + "heating": { + "name": "Opvarmning", + "state": { + "off": "Fra", + "on": "Til" + } + }, + "heating_channel": { + "name": "Varmekanal {channel}", + "state": { + "off": "Fra", + "on": "Til" + } + }, + "hot_water": { + "name": "Varmt vand", + "state": { + "off": "Fra", + "on": "Til" + } + }, + "hot_water_operation_mode": { + "name": "Driftstilstand for varmt vand" + }, + "target_temperature": { + "name": "Måltemperatur" + }, + "floor_temperature": { + "name": "Gulvtemperatur" + }, + "boiler_flow_temperature": { + "name": "Kedlens fremløbstemperatur" + }, + "boiler_return_temperature": { + "name": "Kedlens returtemperatur" + }, + "flame_statistics": { + "name": "Flammestatistik" + }, + "boiler_ch_setpoint": { + "name": "Kedlens centralvarmeindstillingspunkt" + }, + "boiler_ch_setpoint_lower_bound": { + "name": "Nedre grænse for kedlens centralvarmeindstillingspunkt" + }, + "boiler_ch_setpoint_upper_bound": { + "name": "Øvre grænse for kedlens centralvarmeindstillingspunkt" + }, + "boiler_exhaust_temperature": { + "name": "Kedlens røggastemperatur" + }, + "boiler_hw_setpoint": { + "name": "Kedlens varmtvandsindstillingspunkt" + }, + "boiler_hw_setpoint_lower_bound": { + "name": "Nedre grænse for kedlens varmtvandsindstillingspunkt" + }, + "boiler_hw_setpoint_upper_bound": { + "name": "Øvre grænse for kedlens varmtvandsindstillingspunkt" + }, + "ch1_flow_setpoint": { + "name": "Centralvarmekreds 1 fremløbsindstillingspunkt" + }, + "ch2_flow_setpoint": { + "name": "Centralvarmekreds 2 fremløbsindstillingspunkt" + }, + "ch_flow_active_lower_setpoint": { + "name": "Aktivt nedre centralvarmefremløbsindstillingspunkt" + }, + "ch_flow_active_upper_setpoint": { + "name": "Aktivt øvre centralvarmefremløbsindstillingspunkt" + }, + "ch_pressure_bar": { + "name": "Centralvarmetryk" + }, + "connection_status": { + "name": "Forbindelsesstatus" + }, + "coprocessor_update_status": { + "name": "Opdateringsstatus for OpenTherm-coprocessor" + }, + "coprocessor_version": { + "name": "Version af OpenTherm-coprocessor" + }, + "delta_t": { + "name": "Delta-T" + }, + "estimated_boiler_output": { + "name": "Anslået kedelydelse" + }, + "hw_flow_rate": { + "name": "Varmtvandsflow" + }, + "hw_flow_setpoint": { + "name": "Varmtvandsfremløbets indstillingspunkt" + }, + "hw_temperature": { + "name": "Varmtvandstemperatur" + }, + "maximum_capacity_kw": { + "name": "Maksimal kedelkapacitet" + }, + "minimum_modulation_level": { + "name": "Mindste modulationsniveau" + }, + "operating_mode": { + "name": "Driftstilstand" + }, + "relative_modulation_level": { + "name": "Relativt modulationsniveau" + }, + "room_setpoint": { + "name": "Rumindstillingspunkt" + }, + "room_temperature": { + "name": "Rumtemperatur" + }, + "slave_status": { + "name": "OpenTherm-slavestatus" + }, + "tracked_room_id": { + "name": "Id for overvåget rum" + }, + "heating_demand": { + "name": "Varmebehov" + }, + "heating_demand_channel": { + "name": "Varmebehovskanal {channel}" + }, + "hot_water_demand": { + "name": "Varmtvandsbehov" + }, + "total_energy": { + "name": "Samlet energi" + }, + "energy_delivered": { + "name": "Leveret energi" + }, + "energy_received": { + "name": "Modtaget energi" + }, + "equipment_power": { + "name": "Udstyr" + } + } + }, + "device_automation": { + "trigger_type": { + "started_heating": "{entity_name} starter opvarmning", + "stopped_heating": "{entity_name} stopper opvarmning", + "boosted": "{entity_name} er boostet", + "target_temperature_increased": "Måltemperaturen for {entity_name} er hævet", + "target_temperature_decreased": "Måltemperaturen for {entity_name} er sænket" + } + } +} + diff --git a/custom_components/wiser/translations/es.json b/custom_components/wiser/translations/es.json index 47c89715..dd9a98be 100644 --- a/custom_components/wiser/translations/es.json +++ b/custom_components/wiser/translations/es.json @@ -3,8 +3,8 @@ "flow_title": "{name}", "step": { "user": { - "title": "Wiser Configuración del concentrador de calor", - "description": "Ingrese la dirección IP y la clave secreta obtenida del concentrador.", + "title": "Configuración del Heat Hub Wiser", + "description": "Introduzca la dirección IP y la clave secreta obtenida del hub.", "data": { "host": "Dirección IP o nombre de host", "port": "Número de puerto", @@ -12,7 +12,7 @@ } }, "zeroconf_confirm": { - "title": "Wiser Configuración del Heat Hub ({name})", + "title": "Configuración del Heat Hub Wiser ({name})", "description": "Introduzca la clave secreta obtenida del hub.", "data": { "host": "Dirección IP o nombre de host", @@ -22,56 +22,56 @@ } }, "abort": { - "already_in_progress": "Wiser La configuración del Heat Hub ya está en progreso.", + "already_in_progress": "La configuración del Heat Hub Wiser ya está en curso.", "already_configured": "Este dispositivo ya está configurado.", "not_wiser_hub": "El dispositivo descubierto no es un Heat Hub Wiser." }, "error": { - "auth_failure": "No se puede autenticar con el concentrador Wiser. Verifique la clave secreta y vuelva a intentarlo.", - "timeout_error": "Se agotó el tiempo de espera al intentar conectarse al concentrador Wiser. Verifique la dirección IP e inténtelo nuevamente.", - "timeout_error_discovery": "Se agotó el tiempo de espera al intentar conectarse al concentrador Wiser. Verifique que su hub todavía esté en línea e inténtelo nuevamente.", - "unknown": "Error desconocido al conectarse al concentrador Wiser. Por favor revise los registros." + "auth_failure": "No se pudo autenticar con el hub Wiser. Compruebe la clave secreta y vuelva a intentarlo.", + "timeout_error": "Se agotó el tiempo de espera al conectarse al hub Wiser. Compruebe la dirección IP y vuelva a intentarlo.", + "timeout_error_discovery": "Se agotó el tiempo de espera al conectarse al hub Wiser. Compruebe que el hub siga en línea y vuelva a intentarlo.", + "unknown": "Se produjo un error desconocido al conectarse al hub Wiser. Consulte los registros." } }, "options": { "step": { "init": { - "title": "Wiser Opciones de integración", - "description": "Seleccionar parámetros para modificar", + "title": "Opciones de la integración Wiser", + "description": "Seleccione los parámetros que desea modificar", "menu_options": { "main_params": "Parámetros principales", "automation_params": "Parámetros de automatización", "opentherm_sensors": "OpenTherm sensores", "equipment_sensors": "Sensores de equipo", - "ui_options": "Opciones de UI" + "ui_options": "Opciones de la interfaz de usuario" } }, "ui_options": { - "title": "Opciones de UI", + "title": "Opciones de la interfaz de usuario", "data": { "legacy_naming": "Nomenclatura heredada", "show_wiser_sidebar": "Mostrar Wiser en la barra lateral" }, "data_description": { - "legacy_naming": "Incluir nombres de habitaciones en Nombres de dispositivos Wiser. Si está habilitado, el uso de Home Assistant para regenerar ID de entidad con el formato predeterminado en Configuración → Sistema → Formato de ID de entidad (Home Assistant 2026.8 y posterior) duplicará los nombres de área cuando el área y los nombres de sala Wiser coincidan. Cambiar esta opción no cambia el nombre de los ID de entidad existentes." + "legacy_naming": "Incluye los nombres de las habitaciones en los nombres de los dispositivos Wiser. Si se habilita, al usar Home Assistant para regenerar los ID de entidad con el formato predeterminado en Configuración → Sistema → Formato de ID de entidad (Home Assistant 2026.8 y posteriores), se duplicarán los nombres de área cuando coincidan con los nombres de las habitaciones Wiser. Cambiar esta opción no modifica los ID de entidad existentes." } }, "main_params": { - "title": "Wiser Opciones de integración", + "title": "Opciones de la integración Wiser", "description": "Parámetros principales", "data": { "host": "Dirección IP o nombre de host", "port": "Número de puerto", - "scan_interval": "Intervalo de escaneo (segundos)", + "scan_interval": "Intervalo de actualización (segundos)", "heating_boost_temp": "Temperatura de refuerzo de calefacción predeterminada (°C)", "heating_boost_time": "Duración predeterminada del refuerzo de calefacción (minutos)", "hotwater_boost_time": "Duración predeterminada del refuerzo de agua caliente (minutos)", - "setpoint_mode": "Modo de punto de ajuste", - "restore_manual_temp_option": "Utilice esta temperatura si no se almacena ninguna temperatura manual" + "setpoint_mode": "Modo de consigna", + "restore_manual_temp_option": "Usar esta temperatura si no hay ninguna temperatura manual almacenada" } }, "automation_params": { - "title": "Wiser Opciones de integración", + "title": "Opciones de la integración Wiser", "description": "Habilitar automatizaciones integradas", "sections": { "automations_passive_mode": { @@ -86,8 +86,8 @@ "name": "Control climático de agua caliente", "description": "Habilita el control climático de agua caliente. Consulte la wiki para obtener más detalles.", "data": { - "hotwater_climate": "Habilita la entidad climática", - "experimental_mode": "Habilita el modo de trabajo experimental", + "hotwater_climate": "Habilitar la entidad de climatización", + "experimental_mode": "Habilitar el modo de funcionamiento experimental", "hotwater_auto_mode": "Modo automático de agua caliente", "hotwater_heat_mode": "Modo de calentamiento de agua caliente", "hotwater_boost_mode": "Modo de refuerzo de agua caliente", @@ -103,11 +103,11 @@ "equipment_sensors": "Habilitar sensores de datos del equipo" }, "data_description": { - "equipment_sensors": "Exponer un sensor adicional que contiene atributos de equipo detallados para cada enchufe inteligente, PowerTag y actuador de calefacción compatibles. Sensores" + "equipment_sensors": "Expone un sensor adicional con atributos detallados del equipo para cada enchufe inteligente, PowerTag y actuador de calefacción compatible." } }, "opentherm_sensors": { - "title": "OpenTherm", + "title": "Sensores OpenTherm", "description": "Elija una categoría de atributos OpenTherm detectados.", "menu_options": { "opentherm_readings": "Lecturas", @@ -117,8 +117,8 @@ } }, "opentherm_readings": { - "title": "OpenTherm Lecturas", - "description": "Elige qué detectado OpenTherm Las lecturas se exponen como entidades sensoras.", + "title": "Lecturas OpenTherm", + "description": "Elija qué lecturas OpenTherm detectadas se muestran como entidades de sensor.", "data": { "ch_flow_temperature": "Temperatura de ida de la caldera", "ch_pressure_bar": "Presión de calefacción", @@ -126,34 +126,34 @@ "delta_t": "Delta-T", "boiler_exhaust_temperature": "Temperatura de escape de la caldera", "estimated_boiler_output": "Potencia estimada de la caldera", - "hw_flow_rate": "Caudal de agua caliente nominal", - "hw_temperature": "Temperatura agua caliente sanitaria", - "maximum_capacity_kw": "Capacidad máxima caldera", + "hw_flow_rate": "Caudal de agua caliente", + "hw_temperature": "Temperatura del agua caliente", + "maximum_capacity_kw": "Capacidad máxima de la caldera", "minimum_modulation_level": "Nivel mínimo de modulación", "relative_modulation_level": "Nivel relativo de modulación", "room_temperature": "Temperatura ambiente" } }, "opentherm_central_heating": { - "title": "OpenTherm calefacción central", + "title": "Calefacción central OpenTherm", "description": "Elija qué atributos de calefacción central detectados se exponen como entidades.", "data": { - "boiler_ch_max_setpoint_read_write": "Lectura/escritura del punto de ajuste máximo de la caldera", - "boiler_ch_max_setpoint_transfer_enable": "Transferencia del punto de ajuste máximo de la caldera habilitada", - "boiler_ch_setpoint": "Punto de ajuste de la caldera", - "boiler_ch_setpoint_lower_bound": "Límite inferior del punto de ajuste de la caldera", - "boiler_ch_setpoint_upper_bound": "Límite superior del punto de ajuste de la caldera", - "ch_flow_active_lower_setpoint": "Flujo CH activo punto de ajuste inferior", - "ch_flow_active_upper_setpoint": "Flujo CH punto de ajuste superior activo", + "boiler_ch_max_setpoint_read_write": "Lectura/escritura de la consigna máxima de calefacción de la caldera", + "boiler_ch_max_setpoint_transfer_enable": "Transferencia de la consigna máxima de calefacción de la caldera habilitada", + "boiler_ch_setpoint": "Consigna de calefacción de la caldera", + "boiler_ch_setpoint_lower_bound": "Límite inferior de la consigna de calefacción de la caldera", + "boiler_ch_setpoint_upper_bound": "Límite superior de la consigna de calefacción de la caldera", + "ch_flow_active_lower_setpoint": "Consigna inferior activa del caudal de calefacción", + "ch_flow_active_upper_setpoint": "Consigna superior activa del caudal de calefacción", "ch1_flow_enabled": "Flujo CH1 habilitado", - "ch1_flow_setpoint": "Punto de ajuste flujo CH1", + "ch1_flow_setpoint": "Consigna de caudal CH1", "ch2_flow_enabled": "Flujo CH2 habilitado", - "ch2_flow_setpoint": "Punto de ajuste flujo CH2", - "room_setpoint": "Punto de ajuste de la habitación" + "ch2_flow_setpoint": "Consigna de caudal CH2", + "room_setpoint": "Consigna de la habitación" } }, "opentherm_hot_water": { - "title": "OpenTherm agua caliente", + "title": "Agua caliente OpenTherm", "description": "Elija qué atributos de agua caliente detectados se exponen como entidades.", "data": { "boiler_hw_setpoint": "Punto de consigna de agua caliente de la caldera", @@ -162,26 +162,26 @@ "boiler_hw_setpoint_transfer_enable": "Transferencia del punto de consigna de agua caliente de la caldera habilitada", "boiler_hw_setpoint_upper_bound": "Límite superior del punto de consigna de agua caliente de la caldera", "hw_enabled": "Agua caliente habilitada", - "hw_flow_setpoint": "Punto de ajuste del flujo de agua caliente" + "hw_flow_setpoint": "Consigna del caudal de agua caliente" } }, "opentherm_status": { "title": "Estado y diagnóstico de OpenTherm", "description": "Elija qué estados detectados y atributos de diagnóstico se exponen como entidades de sensor.", "data": { - "boiler_fault": "Fallo caldera", + "boiler_fault": "Fallo de la caldera", "central_heating_active": "Calefacción central activa", "central_heating_2_active": "Calefacción central 2 activa", "connection_status": "Estado de conexión", - "coprocessor_update_status": "OpenTherm estado de actualización del coprocesador", - "coprocessor_version": "OpenTherm versión del coprocesador", + "coprocessor_update_status": "Estado de actualización del coprocesador OpenTherm", + "coprocessor_version": "Versión del coprocesador OpenTherm", "cooling_active": "Enfriamiento activo", "diagnostic_event": "Evento de diagnóstico", "flame_active": "Llama activa", "flame_statistics": "Estadísticas de llama", "hot_water_active": "Agua caliente activa", "operating_mode": "Modo de funcionamiento", - "slave_status": "OpenTherm Estado de esclavo", + "slave_status": "Estado esclavo OpenTherm", "tracked_room_id": "ID de habitación rastreada" } } @@ -198,15 +198,15 @@ "fields": { "parameter": { "name": "Parámetro", - "description": "OpenTherm Parámetro de temperatura a cambiar. El punto final API requerido se selecciona automáticamente." + "description": "Parámetro de temperatura OpenTherm que se desea cambiar. El endpoint de API necesario se selecciona automáticamente." }, "temperature": { "name": "Temperatura", "description": "Utilice una temperatura dentro de los límites informados por su caldera." }, "hub": { - "name": "Wiser concentrador", - "description": "Seleccione un concentrador solo cuando tenga varios concentradores Wiser." + "name": "Hub Wiser", + "description": "Seleccione un hub únicamente si tiene varios hubs Wiser." } } } @@ -245,13 +245,13 @@ "message": "No se puede establecer el parámetro OpenTherm {parameter}: {error}" }, "opentherm_confirmation_failed": { - "message": "El parámetro OpenTherm {parameter} no permaneció en {requested} °C después de un reintento y la segunda ventana de confirmación de {window}. Wiser informa {reported} °C. No se enviarán más reintentos." + "message": "El parámetro OpenTherm {parameter} no se mantuvo en {requested} °C tras un reintento y el periodo de confirmación de {window} segundos. Wiser informa de {reported} °C. No se realizarán más reintentos." }, "opentherm_retry_failed": { - "message": "El parámetro OpenTherm {parameter} no permaneció en {requested} °C y no se pudo enviar su reintento: {error}. Wiser informes {reported} °C. No se enviarán más reintentos." + "message": "El parámetro OpenTherm {parameter} no se mantuvo en {requested} °C y no se pudo enviar el reintento: {error}. Wiser informa de {reported} °C. No se realizarán más reintentos." }, "opentherm_notification_title": { - "message": "Wiser Comando OpenTherm" + "message": "Comando OpenTherm de Wiser" } }, "entity": { @@ -274,7 +274,7 @@ "name": "Temperatura de incomodidad interior" }, "outdoor_discomfort_temperature": { - "name": "Temperatura exterior incómoda" + "name": "Temperatura de incomodidad exterior" } }, "select": { @@ -290,13 +290,13 @@ }, "button": { "boost_all_heating": { - "name": "Impulsar toda la calefacción" + "name": "Reforzar toda la calefacción" }, "cancel_all_heating_overrides": { "name": "Cancelar todas las anulaciones de calefacción" }, "boost_hot_water": { - "name": "Impulsar el agua caliente" + "name": "Reforzar el agua caliente" }, "cancel_hot_water_overrides": { "name": "Cancelar anulaciones de agua caliente" @@ -343,13 +343,13 @@ "name": "Identificar" }, "outlet": { - "name": "Outlet" + "name": "Toma de corriente" }, "away_mode_turns_off": { - "name": "El modo Ausente se apaga" + "name": "El modo Ausente apaga" }, "away_mode_closes": { - "name": "El modo Ausente se cierra" + "name": "El modo Ausente cierra" }, "passive_mode": { "name": "Modo pasivo" @@ -358,19 +358,19 @@ "name": "Respetar el confort de verano" }, "interacts_with_room_climate": { - "name": "Interactúa con el clima ambiental" + "name": "Interactúa con la climatización de la habitación" }, "humidity_interacts_with_room_climate": { - "name": "La humedad interactúa con el clima ambiental" + "name": "La humedad interactúa con la climatización de la habitación" }, "temperature_interacts_with_room_climate": { - "name": "La temperatura interactúa con el clima ambiental" + "name": "La temperatura interactúa con la climatización de la habitación" }, "illuminance_interacts_with_room_climate": { - "name": "La iluminancia interactúa con el clima ambiental" + "name": "La iluminancia interactúa con la climatización de la habitación" }, "sensor_interacts_with_room_climate": { - "name": "{sensor} interactúa con el clima ambiental" + "name": "{sensor} interactúa con la climatización de la habitación" }, "manual_heat": { "name": "Calefacción manual" @@ -453,7 +453,7 @@ "name": "Lectura/escritura de setpoint de agua caliente de caldera" }, "boiler_hw_setpoint_transfer_enable": { - "name": "Agua caliente de caldera transferencia de setpoint habilitada" + "name": "Transferencia de la consigna de agua caliente de la caldera habilitada" }, "central_heating_2_active": { "name": "Calefacción central 2 activa" @@ -491,7 +491,7 @@ "name": "Nube" }, "heating_operation_mode": { - "name": "Modo funcionamiento calefacción" + "name": "Modo de funcionamiento de la calefacción" }, "heating": { "name": "Calefacción", @@ -501,7 +501,7 @@ } }, "heating_channel": { - "name": "Canal calefacción {channel}", + "name": "Canal de calefacción {channel}", "state": { "off": "Apagado", "on": "Encendido" @@ -515,7 +515,7 @@ } }, "hot_water_operation_mode": { - "name": "Modo funcionamiento agua caliente" + "name": "Modo de funcionamiento del agua caliente" }, "target_temperature": { "name": "Temperatura objetivo" @@ -533,13 +533,13 @@ "name": "Estadísticas de llama" }, "boiler_ch_setpoint": { - "name": "Punto de ajuste de calefacción de caldera" + "name": "Consigna de calefacción de la caldera" }, "boiler_ch_setpoint_lower_bound": { - "name": "Caldera de calefacción Límite inferior del punto de consigna" + "name": "Límite inferior de la consigna de calefacción de la caldera" }, "boiler_ch_setpoint_upper_bound": { - "name": "Límite superior del punto de consigna de calefacción de caldera" + "name": "Límite superior de la consigna de calefacción de la caldera" }, "boiler_exhaust_temperature": { "name": "Temperatura de escape de la caldera" @@ -554,16 +554,16 @@ "name": "Límite superior del punto de consigna de agua caliente de la caldera" }, "ch1_flow_setpoint": { - "name": "Punto de ajuste de flujo CH1" + "name": "Consigna de caudal CH1" }, "ch2_flow_setpoint": { - "name": "Punto de ajuste de flujo de CH2" + "name": "Consigna de caudal CH2" }, "ch_flow_active_lower_setpoint": { - "name": "Punto de ajuste inferior activo de flujo de CH" + "name": "Consigna inferior activa del caudal de calefacción" }, "ch_flow_active_upper_setpoint": { - "name": "Punto de ajuste superior activo de flujo de CH" + "name": "Consigna superior activa del caudal de calefacción" }, "ch_pressure_bar": { "name": "Presión de CH" @@ -572,10 +572,10 @@ "name": "Estado de conexión" }, "coprocessor_update_status": { - "name": "OpenTherm estado de actualización del coprocesador" + "name": "Estado de actualización del coprocesador OpenTherm" }, "coprocessor_version": { - "name": "OpenTherm versión del coprocesador" + "name": "Versión del coprocesador OpenTherm" }, "delta_t": { "name": "Delta-T" @@ -611,7 +611,7 @@ "name": "Temperatura ambiente" }, "slave_status": { - "name": "OpenTherm estado esclavo" + "name": "Estado esclavo OpenTherm" }, "tracked_room_id": { "name": "ID de habitación rastreada" @@ -643,9 +643,9 @@ "trigger_type": { "started_heating": "{entity_name} inicia la calefacción", "stopped_heating": "{entity_name} deja de calentar", - "boosted": "{entity_name} se potencia", - "target_temperature_increased": "{entity_name} temperatura objetivo aumentada", - "target_temperature_decreased": "{entity_name} temperatura objetivo disminuida" + "boosted": "Se ha reforzado {entity_name}", + "target_temperature_increased": "Ha aumentado la temperatura objetivo de {entity_name}", + "target_temperature_decreased": "Ha disminuido la temperatura objetivo de {entity_name}" } } } diff --git a/custom_components/wiser/translations/fi.json b/custom_components/wiser/translations/fi.json new file mode 100644 index 00000000..970b9ba6 --- /dev/null +++ b/custom_components/wiser/translations/fi.json @@ -0,0 +1,652 @@ +{ + "config": { + "flow_title": "{name}", + "step": { + "user": { + "title": "Wiser Heat Hubin määritys", + "description": "Anna keskittimestä saatu IP-osoite ja salainen avain.", + "data": { + "host": "IP-osoite tai isäntänimi", + "port": "Portin numero", + "password": "Salainen avain" + } + }, + "zeroconf_confirm": { + "title": "Wiser Heat Hubin määritys ({name})", + "description": "Anna keskittimestä saatu salainen avain.", + "data": { + "host": "IP-osoite tai isäntänimi", + "port": "Portin numero", + "password": "Salainen avain" + } + } + }, + "abort": { + "already_in_progress": "Wiser Heat Hubin määritys on jo käynnissä.", + "already_configured": "Tämä laite on jo määritetty.", + "not_wiser_hub": "Löydetty laite ei ole Wiser Heat Hub." + }, + "error": { + "auth_failure": "Todennus Wiser-keskittimeen epäonnistui. Tarkista salainen avain ja yritä uudelleen.", + "timeout_error": "Yhteys Wiser-keskittimeen aikakatkaistiin. Tarkista IP-osoite ja yritä uudelleen.", + "timeout_error_discovery": "Yhteys Wiser-keskittimeen aikakatkaistiin. Tarkista, että keskitin on yhä verkossa, ja yritä uudelleen.", + "unknown": "Tuntematon virhe yhdistettäessä Wiser-keskittimeen. Tarkista lokit." + } + }, + "options": { + "step": { + "init": { + "title": "Wiser-integraation asetukset", + "description": "Valitse muutettavat parametrit", + "menu_options": { + "main_params": "Pääparametrit", + "automation_params": "Automaatioparametrit", + "opentherm_sensors": "OpenTherm-anturit", + "equipment_sensors": "Laiteanturit", + "ui_options": "Käyttöliittymän asetukset" + } + }, + "ui_options": { + "title": "Käyttöliittymän asetukset", + "data": { + "legacy_naming": "Vanha nimeämistapa", + "show_wiser_sidebar": "Näytä Wiser sivupalkissa" + }, + "data_description": { + "legacy_naming": "Sisällytä huoneiden nimet Wiser-laitteiden nimiin. Jos tämä on käytössä, entiteettitunnusten luominen uudelleen Home Assistantin oletusmuodolla kohdassa Asetukset → Järjestelmä → Entiteettitunnuksen muoto (Home Assistant 2026.8 ja uudemmat) kahdentaa alueiden nimet, kun alueen ja Wiser-huoneen nimet ovat samat. Tämän asetuksen muuttaminen ei nimeä nykyisiä entiteettitunnuksia uudelleen." + } + }, + "main_params": { + "title": "Wiser-integraation asetukset", + "description": "Pääparametrit", + "data": { + "host": "IP-osoite tai isäntänimi", + "port": "Portin numero", + "scan_interval": "Päivitysväli (s)", + "heating_boost_temp": "Lämmitystehostuksen oletuslämpötila (°C)", + "heating_boost_time": "Lämmitystehostuksen oletuskesto (min)", + "hotwater_boost_time": "Käyttövesitehostuksen oletuskesto (min)", + "setpoint_mode": "Asetusarvotila", + "restore_manual_temp_option": "Käytä tätä lämpötilaa, jos manuaalista lämpötilaa ei ole tallennettu" + } + }, + "automation_params": { + "title": "Wiser-integraation asetukset", + "description": "Ota sisäiset automaatiot käyttöön", + "sections": { + "automations_passive_mode": { + "name": "Passiivinen tila", + "description": "Ota passiivinen TRV-toiminto käyttöön. Jokainen huone on otettava erikseen käyttöön.", + "data": { + "automations_passive_mode": "Passiivinen tila", + "passive_mode_temperature_increments": "Passiivisen tilan lämpötilaportaat" + } + }, + "hotwater_climate": { + "name": "Käyttöveden ilmastointiohjaus", + "description": "Ota käyttöveden ilmastointiohjaus käyttöön. Katso lisätietoja wikistä.", + "data": { + "hotwater_climate": "Ota ilmastointientiteetti käyttöön", + "experimental_mode": "Ota kokeellinen toimintatila käyttöön", + "hotwater_auto_mode": "Käyttöveden automaattitila", + "hotwater_heat_mode": "Käyttöveden lämmitystila", + "hotwater_boost_mode": "Käyttöveden tehostustila", + "hotwater_sensor_entity_id": "Käyttöveden lämpötila-anturi" + } + } + } + }, + "equipment_sensors": { + "title": "Laiteanturit", + "description": "Määritä yksityiskohtaiset laitetietoentiteetit yhteensopiville laitteille.", + "data": { + "equipment_sensors": "Ota laitetietoanturit käyttöön" + }, + "data_description": { + "equipment_sensors": "Näytä lisäanturi, joka sisältää yksityiskohtaiset laiteominaisuudet jokaiselle yhteensopivalle älypistorasialle, PowerTagille ja lämmitystoimilaitteelle." + } + }, + "opentherm_sensors": { + "title": "OpenTherm-anturit", + "description": "Valitse havaittujen OpenTherm-ominaisuuksien luokka.", + "menu_options": { + "opentherm_readings": "Lukemat", + "opentherm_central_heating": "Keskuslämmitys", + "opentherm_hot_water": "Käyttövesi", + "opentherm_status": "Tila ja diagnostiikka" + } + }, + "opentherm_readings": { + "title": "OpenTherm-lukemat", + "description": "Valitse, mitkä havaitut OpenTherm-lukemat näytetään anturientiteetteinä.", + "data": { + "ch_flow_temperature": "Kattilan menoveden lämpötila", + "ch_pressure_bar": "Keskuslämmityksen paine", + "ch_return_temperature": "Kattilan paluuveden lämpötila", + "delta_t": "Delta-T", + "boiler_exhaust_temperature": "Kattilan savukaasun lämpötila", + "estimated_boiler_output": "Kattilan arvioitu teho", + "hw_flow_rate": "Käyttöveden virtausnopeus", + "hw_temperature": "Käyttöveden lämpötila", + "maximum_capacity_kw": "Kattilan enimmäisteho", + "minimum_modulation_level": "Modulaation vähimmäistaso", + "relative_modulation_level": "Suhteellinen modulaatiotaso", + "room_temperature": "Huonelämpötila" + } + }, + "opentherm_central_heating": { + "title": "OpenTherm-keskuslämmitys", + "description": "Valitse, mitkä havaitut keskuslämmityksen ominaisuudet näytetään entiteetteinä.", + "data": { + "boiler_ch_max_setpoint_read_write": "Kattilan keskuslämmityksen enimmäisasetusarvon luku/kirjoitus", + "boiler_ch_max_setpoint_transfer_enable": "Kattilan keskuslämmityksen enimmäisasetusarvon siirto käytössä", + "boiler_ch_setpoint": "Kattilan keskuslämmityksen asetusarvo", + "boiler_ch_setpoint_lower_bound": "Kattilan keskuslämmityksen asetusarvon alaraja", + "boiler_ch_setpoint_upper_bound": "Kattilan keskuslämmityksen asetusarvon yläraja", + "ch_flow_active_lower_setpoint": "Keskuslämmityksen menoveden aktiivinen ala-asetusarvo", + "ch_flow_active_upper_setpoint": "Keskuslämmityksen menoveden aktiivinen yläasetusarvo", + "ch1_flow_enabled": "Keskuslämmityspiirin 1 meno käytössä", + "ch1_flow_setpoint": "Keskuslämmityspiirin 1 menoveden asetusarvo", + "ch2_flow_enabled": "Keskuslämmityspiirin 2 meno käytössä", + "ch2_flow_setpoint": "Keskuslämmityspiirin 2 menoveden asetusarvo", + "room_setpoint": "Huoneen asetusarvo" + } + }, + "opentherm_hot_water": { + "title": "OpenTherm-käyttövesi", + "description": "Valitse, mitkä havaitut käyttöveden ominaisuudet näytetään entiteetteinä.", + "data": { + "boiler_hw_setpoint": "Kattilan käyttöveden asetusarvo", + "boiler_hw_setpoint_lower_bound": "Kattilan käyttöveden asetusarvon alaraja", + "boiler_hw_setpoint_read_write": "Kattilan käyttöveden asetusarvon luku/kirjoitus", + "boiler_hw_setpoint_transfer_enable": "Kattilan käyttöveden asetusarvon siirto käytössä", + "boiler_hw_setpoint_upper_bound": "Kattilan käyttöveden asetusarvon yläraja", + "hw_enabled": "Käyttövesi käytössä", + "hw_flow_setpoint": "Käyttöveden menoveden asetusarvo" + } + }, + "opentherm_status": { + "title": "OpenTherm-tila ja diagnostiikka", + "description": "Valitse, mitkä havaitut tila- ja diagnostiikkaominaisuudet näytetään anturientiteetteinä.", + "data": { + "boiler_fault": "Kattilavika", + "central_heating_active": "Keskuslämmitys aktiivinen", + "central_heating_2_active": "Keskuslämmitys 2 aktiivinen", + "connection_status": "Yhteyden tila", + "coprocessor_update_status": "OpenTherm-apuprosessorin päivitystila", + "coprocessor_version": "OpenTherm-apuprosessorin versio", + "cooling_active": "Jäähdytys aktiivinen", + "diagnostic_event": "Diagnostiikkatapahtuma", + "flame_active": "Liekki aktiivinen", + "flame_statistics": "Liekkitilastot", + "hot_water_active": "Käyttövesi aktiivinen", + "operating_mode": "Toimintatila", + "slave_status": "OpenTherm-orjalaitteen tila", + "tracked_room_id": "Seurattavan huoneen tunnus" + } + } + }, + "abort": { + "opentherm_not_available": "OpenTherm-tietoja ei ole saatavilla tälle Wiser-keskittimelle.", + "equipment_not_available": "Laitetietoja ei ole saatavilla tälle Wiser-keskittimelle." + } + }, + "services": { + "set_opentherm_parameter": { + "name": "Aseta OpenTherm-parametri", + "description": "Muuttaa tuettua OpenTherm-lämpötilaparametria Wiser-keskittimessä.", + "fields": { + "parameter": { + "name": "Parametri", + "description": "Muutettava OpenTherm-lämpötilaparametri. Tarvittava API-päätepiste valitaan automaattisesti." + }, + "temperature": { + "name": "Lämpötila", + "description": "Käytä kattilan ilmoittamissa rajoissa olevaa lämpötilaa." + }, + "hub": { + "name": "Wiser-keskitin", + "description": "Valitse keskitin vain, jos käytössä on useita Wiser-keskittimiä." + } + } + } + }, + "selector": { + "opentherm_parameter": { + "options": { + "chFlowActiveLowerSetpoint": "Keskuslämmityksen aktiivinen ala-asetusarvo", + "chFlowActiveUpperSetpoint": "Keskuslämmityksen aktiivinen yläasetusarvo", + "dhwFlowSetpoint": "Keskittimen käyttöveden menoveden asetusarvo", + "dhwSetpoint": "Kattilan käyttöveden asetusarvo", + "maxChSetpoint": "Kattilan keskuslämmityksen enimmäisasetusarvo" + } + } + }, + "exceptions": { + "opentherm_temperature_required": { + "message": "Anna OpenTherm-lämpötila." + }, + "opentherm_hub_not_found": { + "message": "Määritettyä Wiser-keskitintä ei löytynyt." + }, + "opentherm_hub_not_loaded": { + "message": "Määritettyä Wiser-keskitintä ei ole ladattu." + }, + "opentherm_hub_required": { + "message": "Valitse Wiser-keskitin, kun useampi kuin yksi keskitin on määritetty." + }, + "opentherm_not_supported": { + "message": "Tässä keskittimessä ei ole OpenTherm-toimintoa." + }, + "opentherm_invalid_parameter": { + "message": "OpenTherm-parametri tai arvo on virheellinen: {error}" + }, + "opentherm_write_failed": { + "message": "OpenTherm-parametria {parameter} ei voitu asettaa: {error}" + }, + "opentherm_confirmation_failed": { + "message": "OpenTherm-parametri {parameter} ei pysynyt arvossa {requested} °C yhden uusintayrityksen ja {window} sekunnin vahvistusjakson jälkeen. Wiser ilmoittaa {reported} °C. Uusia yrityksiä ei lähetetä." + }, + "opentherm_retry_failed": { + "message": "OpenTherm-parametri {parameter} ei pysynyt arvossa {requested} °C eikä uusintayritystä voitu lähettää: {error}. Wiser ilmoittaa {reported} °C. Uusia yrityksiä ei lähetetä." + }, + "opentherm_notification_title": { + "message": "Wiser OpenTherm -komento" + } + }, + "entity": { + "climate": { + "heating": { + "name": "Lämmitys" + }, + "floor_temperature": { + "name": "Lattialämpötila" + } + }, + "number": { + "away_mode_target_temperature": { + "name": "Poissa-tilan tavoitelämpötila" + }, + "floor_temperature_offset": { + "name": "Lattialämpötilan poikkeama" + }, + "indoor_discomfort_temperature": { + "name": "Sisätilojen epämukavuuslämpötila" + }, + "outdoor_discomfort_temperature": { + "name": "Ulkoilman epämukavuuslämpötila" + } + }, + "select": { + "mode": { + "name": "Tila" + }, + "power_on_behavior": { + "name": "Käynnistyskäyttäytyminen" + }, + "led_indicator": { + "name": "LED-merkkivalo" + } + }, + "button": { + "boost_all_heating": { + "name": "Tehosta kaikkea lämmitystä" + }, + "cancel_all_heating_overrides": { + "name": "Peruuta kaikki lämmityksen ohitukset" + }, + "boost_hot_water": { + "name": "Tehosta käyttövettä" + }, + "cancel_hot_water_overrides": { + "name": "Peruuta kaikki käyttöveden ohitukset" + }, + "toggle_hot_water": { + "name": "Vaihda käyttöveden tila" + }, + "moment": { + "name": "Hetki: {name}" + } + }, + "switch": { + "valve_protection": { + "name": "Venttiilin suojaus" + }, + "eco_mode": { + "name": "Säästötila" + }, + "away_mode_affects_hot_water": { + "name": "Poissa-tila vaikuttaa käyttöveteen" + }, + "comfort_mode": { + "name": "Mukavuustila" + }, + "away_mode": { + "name": "Poissa-tila" + }, + "daylight_saving": { + "name": "Kesäaika" + }, + "summer_comfort_enabled": { + "name": "Kesämukavuus käytössä" + }, + "window_detection": { + "name": "Ikkunantunnistus" + }, + "include_in_summer_comfort": { + "name": "Sisällytä kesämukavuuteen" + }, + "device_lock": { + "name": "Laitelukitus" + }, + "identify": { + "name": "Tunnista" + }, + "outlet": { + "name": "Pistorasia" + }, + "away_mode_turns_off": { + "name": "Poissa-tila sammuttaa" + }, + "away_mode_closes": { + "name": "Poissa-tila sulkee" + }, + "passive_mode": { + "name": "Passiivinen tila" + }, + "respect_summer_comfort": { + "name": "Noudata kesämukavuutta" + }, + "interacts_with_room_climate": { + "name": "Vaikuttaa huoneilmastoon" + }, + "humidity_interacts_with_room_climate": { + "name": "Ilmankosteus vaikuttaa huoneilmastoon" + }, + "temperature_interacts_with_room_climate": { + "name": "Lämpötila vaikuttaa huoneilmastoon" + }, + "illuminance_interacts_with_room_climate": { + "name": "Valaistusvoimakkuus vaikuttaa huoneilmastoon" + }, + "sensor_interacts_with_room_climate": { + "name": "{sensor} vaikuttaa huoneilmastoon" + }, + "manual_heat": { + "name": "Manuaalinen lämmitys" + }, + "hot_water": { + "name": "Käyttövesi" + } + }, + "binary_sensor": { + "summer_discomfort_prevention": { + "name": "Kesäajan epämukavuuden esto" + }, + "summer_comfort_available": { + "name": "Kesämukavuus saatavilla" + }, + "pcm_device_limit_reached": { + "name": "PCM-laiteraja saavutettu" + }, + "smoke_alarm": { + "name": "Palovaroitin" + }, + "heat_alarm": { + "name": "Lämpöhälytys" + }, + "tamper_alarm": { + "name": "Peukalointihälytys" + }, + "fault_warning": { + "name": "Vikavaroitus" + }, + "remote_alarm": { + "name": "Etähälytys" + }, + "battery_defect": { + "name": "Akkuvika" + }, + "controllable": { + "name": "Ohjattavissa" + }, + "pcm_mode": { + "name": "PCM-tila" + }, + "window_detection_active": { + "name": "Ikkunantunnistus aktiivinen" + }, + "is_dimmable": { + "name": "Himmennettävä" + }, + "is_led_indicator_supported": { + "name": "LED-merkkivaloa tuetaan" + }, + "is_output_mode_supported": { + "name": "Lähtötilaa tuetaan" + }, + "is_power_on_behaviour_supported": { + "name": "Käynnistyskäyttäytymistä tuetaan" + }, + "is_tilt_supported": { + "name": "Kallistusta tuetaan" + }, + "is_open": { + "name": "Auki" + }, + "is_closed": { + "name": "Suljettu" + }, + "active": { + "name": "Aktiivinen" + }, + "boiler_ch_max_setpoint_read_write": { + "name": "Kattilan keskuslämmityksen enimmäisasetusarvon luku/kirjoitus" + }, + "boiler_ch_max_setpoint_transfer_enable": { + "name": "Kattilan keskuslämmityksen enimmäisasetusarvon siirto käytössä" + }, + "boiler_fault": { + "name": "Kattilavika" + }, + "boiler_hw_setpoint_read_write": { + "name": "Kattilan käyttöveden asetusarvon luku/kirjoitus" + }, + "boiler_hw_setpoint_transfer_enable": { + "name": "Kattilan käyttöveden asetusarvon siirto käytössä" + }, + "central_heating_2_active": { + "name": "Keskuslämmitys 2 aktiivinen" + }, + "central_heating_active": { + "name": "Keskuslämmitys aktiivinen" + }, + "ch1_flow_enabled": { + "name": "Keskuslämmityspiirin 1 meno käytössä" + }, + "ch2_flow_enabled": { + "name": "Keskuslämmityspiirin 2 meno käytössä" + }, + "cooling_active": { + "name": "Jäähdytys aktiivinen" + }, + "diagnostic_event": { + "name": "Diagnostiikkatapahtuma" + }, + "flame_active": { + "name": "Liekki aktiivinen" + }, + "hot_water_active": { + "name": "Käyttövesi aktiivinen" + }, + "hw_enabled": { + "name": "Käyttövesi käytössä" + } + }, + "sensor": { + "signal": { + "name": "Signaali" + }, + "cloud": { + "name": "Pilvi" + }, + "heating_operation_mode": { + "name": "Lämmityksen toimintatila" + }, + "heating": { + "name": "Lämmitys", + "state": { + "off": "Pois", + "on": "Päällä" + } + }, + "heating_channel": { + "name": "Lämmityskanava {channel}", + "state": { + "off": "Pois", + "on": "Päällä" + } + }, + "hot_water": { + "name": "Käyttövesi", + "state": { + "off": "Pois", + "on": "Päällä" + } + }, + "hot_water_operation_mode": { + "name": "Käyttöveden toimintatila" + }, + "target_temperature": { + "name": "Tavoitelämpötila" + }, + "floor_temperature": { + "name": "Lattialämpötila" + }, + "boiler_flow_temperature": { + "name": "Kattilan menoveden lämpötila" + }, + "boiler_return_temperature": { + "name": "Kattilan paluuveden lämpötila" + }, + "flame_statistics": { + "name": "Liekkitilastot" + }, + "boiler_ch_setpoint": { + "name": "Kattilan keskuslämmityksen asetusarvo" + }, + "boiler_ch_setpoint_lower_bound": { + "name": "Kattilan keskuslämmityksen asetusarvon alaraja" + }, + "boiler_ch_setpoint_upper_bound": { + "name": "Kattilan keskuslämmityksen asetusarvon yläraja" + }, + "boiler_exhaust_temperature": { + "name": "Kattilan savukaasun lämpötila" + }, + "boiler_hw_setpoint": { + "name": "Kattilan käyttöveden asetusarvo" + }, + "boiler_hw_setpoint_lower_bound": { + "name": "Kattilan käyttöveden asetusarvon alaraja" + }, + "boiler_hw_setpoint_upper_bound": { + "name": "Kattilan käyttöveden asetusarvon yläraja" + }, + "ch1_flow_setpoint": { + "name": "Keskuslämmityspiirin 1 menoveden asetusarvo" + }, + "ch2_flow_setpoint": { + "name": "Keskuslämmityspiirin 2 menoveden asetusarvo" + }, + "ch_flow_active_lower_setpoint": { + "name": "Keskuslämmityksen menoveden aktiivinen ala-asetusarvo" + }, + "ch_flow_active_upper_setpoint": { + "name": "Keskuslämmityksen menoveden aktiivinen yläasetusarvo" + }, + "ch_pressure_bar": { + "name": "Keskuslämmityksen paine" + }, + "connection_status": { + "name": "Yhteyden tila" + }, + "coprocessor_update_status": { + "name": "OpenTherm-apuprosessorin päivitystila" + }, + "coprocessor_version": { + "name": "OpenTherm-apuprosessorin versio" + }, + "delta_t": { + "name": "Delta-T" + }, + "estimated_boiler_output": { + "name": "Kattilan arvioitu teho" + }, + "hw_flow_rate": { + "name": "Käyttöveden virtausnopeus" + }, + "hw_flow_setpoint": { + "name": "Käyttöveden menoveden asetusarvo" + }, + "hw_temperature": { + "name": "Käyttöveden lämpötila" + }, + "maximum_capacity_kw": { + "name": "Kattilan enimmäisteho" + }, + "minimum_modulation_level": { + "name": "Modulaation vähimmäistaso" + }, + "operating_mode": { + "name": "Toimintatila" + }, + "relative_modulation_level": { + "name": "Suhteellinen modulaatiotaso" + }, + "room_setpoint": { + "name": "Huoneen asetusarvo" + }, + "room_temperature": { + "name": "Huonelämpötila" + }, + "slave_status": { + "name": "OpenTherm-orjalaitteen tila" + }, + "tracked_room_id": { + "name": "Seurattavan huoneen tunnus" + }, + "heating_demand": { + "name": "Lämmitystarve" + }, + "heating_demand_channel": { + "name": "Lämmitystarvekanava {channel}" + }, + "hot_water_demand": { + "name": "Käyttöveden tarve" + }, + "total_energy": { + "name": "Kokonaisenergia" + }, + "energy_delivered": { + "name": "Toimitettu energia" + }, + "energy_received": { + "name": "Vastaanotettu energia" + }, + "equipment_power": { + "name": "Laitteisto" + } + } + }, + "device_automation": { + "trigger_type": { + "started_heating": "{entity_name} aloittaa lämmityksen", + "stopped_heating": "{entity_name} lopettaa lämmityksen", + "boosted": "{entity_name} on tehostettu", + "target_temperature_increased": "Entiteetin {entity_name} tavoitelämpötilaa nostettiin", + "target_temperature_decreased": "Entiteetin {entity_name} tavoitelämpötilaa laskettiin" + } + } +} + diff --git a/custom_components/wiser/translations/hu.json b/custom_components/wiser/translations/hu.json index e57a2b6c..bc91593a 100644 --- a/custom_components/wiser/translations/hu.json +++ b/custom_components/wiser/translations/hu.json @@ -330,22 +330,22 @@ "heating": { "name": "Fűtés", "state": { - "off": "[%key:common::state::off%]", - "on": "[%key:common::state::on%]" + "off": "Ki", + "on": "Be" } }, "heating_channel": { "name": "Fűtési csatorna {channel}", "state": { - "off": "[%key:common::state::off%]", - "on": "[%key:common::state::on%]" + "off": "Ki", + "on": "Be" } }, "hot_water": { "name": "Meleg víz", "state": { - "off": "[%key:common::state::off%]", - "on": "[%key:common::state::on%]" + "off": "Ki", + "on": "Be" } }, "hot_water_operation_mode": { "name": "Melegvíz üzemmód" }, @@ -400,4 +400,4 @@ "target_temperature_decreased": "{entity_name} célhőmérséklete csökkent" } } -} \ No newline at end of file +} diff --git a/custom_components/wiser/translations/nb.json b/custom_components/wiser/translations/nb.json new file mode 100644 index 00000000..36590ccb --- /dev/null +++ b/custom_components/wiser/translations/nb.json @@ -0,0 +1,652 @@ +{ + "config": { + "flow_title": "{name}", + "step": { + "user": { + "title": "Oppsett av Wiser Heat Hub", + "description": "Skriv inn IP-adressen og den hemmelige nøkkelen som ble hentet fra huben.", + "data": { + "host": "IP-adresse eller vertsnavn", + "port": "Portnummer", + "password": "Hemmelig nøkkel" + } + }, + "zeroconf_confirm": { + "title": "Oppsett av Wiser Heat Hub ({name})", + "description": "Skriv inn den hemmelige nøkkelen som ble hentet fra huben.", + "data": { + "host": "IP-adresse eller vertsnavn", + "port": "Portnummer", + "password": "Hemmelig nøkkel" + } + } + }, + "abort": { + "already_in_progress": "Konfigurasjon av Wiser Heat Hub pågår allerede.", + "already_configured": "Denne enheten er allerede konfigurert.", + "not_wiser_hub": "Den oppdagede enheten er ikke en Wiser Heat Hub." + }, + "error": { + "auth_failure": "Kan ikke autentisere mot Wiser-huben. Kontroller den hemmelige nøkkelen og prøv igjen.", + "timeout_error": "Tidsavbrudd ved tilkobling til Wiser-huben. Kontroller IP-adressen og prøv igjen.", + "timeout_error_discovery": "Tidsavbrudd ved tilkobling til Wiser-huben. Kontroller at huben fortsatt er tilkoblet, og prøv igjen.", + "unknown": "Ukjent feil ved tilkobling til Wiser-huben. Kontroller loggene." + } + }, + "options": { + "step": { + "init": { + "title": "Alternativer for Wiser-integrasjonen", + "description": "Velg parametere som skal endres", + "menu_options": { + "main_params": "Hovedparametere", + "automation_params": "Automatiseringsparametere", + "opentherm_sensors": "OpenTherm-sensorer", + "equipment_sensors": "Utstyrssensorer", + "ui_options": "Brukergrensesnittalternativer" + } + }, + "ui_options": { + "title": "Brukergrensesnittalternativer", + "data": { + "legacy_naming": "Eldre navngivning", + "show_wiser_sidebar": "Vis Wiser i sidepanelet" + }, + "data_description": { + "legacy_naming": "Ta med romnavn i navnene på Wiser-enheter. Hvis dette er aktivert, vil regenerering av entitets-ID-er i Home Assistant med standardformatet under Innstillinger → System → Entitets-ID-format (Home Assistant 2026.8 og nyere) duplisere områdenavn når området og Wiser-rommet har samme navn. Endring av dette valget gir ikke nytt navn til eksisterende entitets-ID-er." + } + }, + "main_params": { + "title": "Alternativer for Wiser-integrasjonen", + "description": "Hovedparametere", + "data": { + "host": "IP-adresse eller vertsnavn", + "port": "Portnummer", + "scan_interval": "Skanneintervall (sek.)", + "heating_boost_temp": "Standardtemperatur for varmeboost (°C)", + "heating_boost_time": "Standardvarighet for varmeboost (min.)", + "hotwater_boost_time": "Standardvarighet for varmtvannsboost (min.)", + "setpoint_mode": "Settpunktmodus", + "restore_manual_temp_option": "Bruk denne temperaturen hvis ingen manuell temperatur er lagret" + } + }, + "automation_params": { + "title": "Alternativer for Wiser-integrasjonen", + "description": "Aktiver innebygde automatiseringer", + "sections": { + "automations_passive_mode": { + "name": "Passiv modus", + "description": "Aktiver passiv TRV-funksjon. Hvert rom må aktiveres for at den skal fungere.", + "data": { + "automations_passive_mode": "Passiv modus", + "passive_mode_temperature_increments": "Temperaturtrinn for passiv modus" + } + }, + "hotwater_climate": { + "name": "Klimastyring av varmtvann", + "description": "Aktiver klimastyring av varmtvann. Se wikien for detaljer.", + "data": { + "hotwater_climate": "Aktiver klimaentiteten", + "experimental_mode": "Aktiver eksperimentell driftsmodus", + "hotwater_auto_mode": "Automatisk varmtvannsmodus", + "hotwater_heat_mode": "Varmtvannsoppvarmingsmodus", + "hotwater_boost_mode": "Varmtvannsboostmodus", + "hotwater_sensor_entity_id": "Varmtvannstemperatursensor" + } + } + } + }, + "equipment_sensors": { + "title": "Utstyrssensorer", + "description": "Konfigurer entiteter med detaljerte utstyrsdata for kompatible enheter.", + "data": { + "equipment_sensors": "Aktiver utstyrsdatasensorer" + }, + "data_description": { + "equipment_sensors": "Vis en ekstra sensor med detaljerte utstyrsattributter for hver kompatible smartplugg, PowerTag og varmeaktuator." + } + }, + "opentherm_sensors": { + "title": "OpenTherm-sensorer", + "description": "Velg en kategori med oppdagede OpenTherm-attributter.", + "menu_options": { + "opentherm_readings": "Avlesninger", + "opentherm_central_heating": "Sentralvarme", + "opentherm_hot_water": "Varmtvann", + "opentherm_status": "Status og diagnostikk" + } + }, + "opentherm_readings": { + "title": "OpenTherm-avlesninger", + "description": "Velg hvilke oppdagede OpenTherm-avlesninger som skal vises som sensorentiteter.", + "data": { + "ch_flow_temperature": "Kjelens turtemperatur", + "ch_pressure_bar": "Sentralvarmetrykk", + "ch_return_temperature": "Kjelens returtemperatur", + "delta_t": "Delta-T", + "boiler_exhaust_temperature": "Kjelens avgastemperatur", + "estimated_boiler_output": "Anslått kjeleeffekt", + "hw_flow_rate": "Varmtvannsstrøm", + "hw_temperature": "Varmtvannstemperatur", + "maximum_capacity_kw": "Maksimal kjelekapasitet", + "minimum_modulation_level": "Minste modulasjonsnivå", + "relative_modulation_level": "Relativt modulasjonsnivå", + "room_temperature": "Romtemperatur" + } + }, + "opentherm_central_heating": { + "title": "OpenTherm-sentralvarme", + "description": "Velg hvilke oppdagede sentralvarmeattributter som skal vises som entiteter.", + "data": { + "boiler_ch_max_setpoint_read_write": "Lesing/skriving av kjelens maksimale sentralvarmesettpunkt", + "boiler_ch_max_setpoint_transfer_enable": "Overføring av kjelens maksimale sentralvarmesettpunkt aktivert", + "boiler_ch_setpoint": "Kjelens sentralvarmesettpunkt", + "boiler_ch_setpoint_lower_bound": "Nedre grense for kjelens sentralvarmesettpunkt", + "boiler_ch_setpoint_upper_bound": "Øvre grense for kjelens sentralvarmesettpunkt", + "ch_flow_active_lower_setpoint": "Aktivt nedre settpunkt for sentralvarmetur", + "ch_flow_active_upper_setpoint": "Aktivt øvre settpunkt for sentralvarmetur", + "ch1_flow_enabled": "Sentralvarmekrets 1 tur aktivert", + "ch1_flow_setpoint": "Settpunkt for sentralvarmekrets 1 tur", + "ch2_flow_enabled": "Sentralvarmekrets 2 tur aktivert", + "ch2_flow_setpoint": "Settpunkt for sentralvarmekrets 2 tur", + "room_setpoint": "Romsettpunkt" + } + }, + "opentherm_hot_water": { + "title": "OpenTherm-varmtvann", + "description": "Velg hvilke oppdagede varmtvannsattributter som skal vises som entiteter.", + "data": { + "boiler_hw_setpoint": "Kjelens varmtvannssettpunkt", + "boiler_hw_setpoint_lower_bound": "Nedre grense for kjelens varmtvannssettpunkt", + "boiler_hw_setpoint_read_write": "Lesing/skriving av kjelens varmtvannssettpunkt", + "boiler_hw_setpoint_transfer_enable": "Overføring av kjelens varmtvannssettpunkt aktivert", + "boiler_hw_setpoint_upper_bound": "Øvre grense for kjelens varmtvannssettpunkt", + "hw_enabled": "Varmtvann aktivert", + "hw_flow_setpoint": "Settpunkt for varmtvannstur" + } + }, + "opentherm_status": { + "title": "OpenTherm-status og diagnostikk", + "description": "Velg hvilke oppdagede status- og diagnoseattributter som skal vises som sensorentiteter.", + "data": { + "boiler_fault": "Kjelfeil", + "central_heating_active": "Sentralvarme aktiv", + "central_heating_2_active": "Sentralvarme 2 aktiv", + "connection_status": "Tilkoblingsstatus", + "coprocessor_update_status": "Oppdateringsstatus for OpenTherm-koprosessor", + "coprocessor_version": "Versjon av OpenTherm-koprosessor", + "cooling_active": "Kjøling aktiv", + "diagnostic_event": "Diagnosehendelse", + "flame_active": "Flamme aktiv", + "flame_statistics": "Flammestatistikk", + "hot_water_active": "Varmtvann aktivt", + "operating_mode": "Driftsmodus", + "slave_status": "OpenTherm-slavestatus", + "tracked_room_id": "ID for sporet rom" + } + } + }, + "abort": { + "opentherm_not_available": "OpenTherm-data er ikke tilgjengelige for denne Wiser-huben.", + "equipment_not_available": "Utstyrsdata er ikke tilgjengelige for denne Wiser-huben." + } + }, + "services": { + "set_opentherm_parameter": { + "name": "Angi OpenTherm-parameter", + "description": "Endrer en støttet OpenTherm-temperaturparameter på Wiser-huben.", + "fields": { + "parameter": { + "name": "Parameter", + "description": "OpenTherm-temperaturparameteren som skal endres. Nødvendig API-endepunkt velges automatisk." + }, + "temperature": { + "name": "Temperatur", + "description": "Bruk en temperatur innenfor grensene som kjelen rapporterer." + }, + "hub": { + "name": "Wiser-hub", + "description": "Velg bare en hub når du har flere Wiser-huber." + } + } + } + }, + "selector": { + "opentherm_parameter": { + "options": { + "chFlowActiveLowerSetpoint": "Aktivt nedre sentralvarmesettpunkt", + "chFlowActiveUpperSetpoint": "Aktivt øvre sentralvarmesettpunkt", + "dhwFlowSetpoint": "Hubens settpunkt for varmtvannstur", + "dhwSetpoint": "Kjelens varmtvannssettpunkt", + "maxChSetpoint": "Kjelens maksimale sentralvarmesettpunkt" + } + } + }, + "exceptions": { + "opentherm_temperature_required": { + "message": "Angi en OpenTherm-temperatur." + }, + "opentherm_hub_not_found": { + "message": "Den angitte Wiser-huben ble ikke funnet." + }, + "opentherm_hub_not_loaded": { + "message": "Den angitte Wiser-huben er ikke lastet inn." + }, + "opentherm_hub_required": { + "message": "Velg en Wiser-hub når mer enn én hub er konfigurert." + }, + "opentherm_not_supported": { + "message": "Denne huben har ikke OpenTherm-funksjonalitet." + }, + "opentherm_invalid_parameter": { + "message": "OpenTherm-parameteren eller verdien er ugyldig: {error}" + }, + "opentherm_write_failed": { + "message": "Kan ikke angi OpenTherm-parameteren {parameter}: {error}" + }, + "opentherm_confirmation_failed": { + "message": "OpenTherm-parameteren {parameter} forble ikke på {requested} °C etter ett nytt forsøk og bekreftelsesvinduet på {window} sekunder. Wiser rapporterer {reported} °C. Ingen flere forsøk sendes." + }, + "opentherm_retry_failed": { + "message": "OpenTherm-parameteren {parameter} forble ikke på {requested} °C, og et nytt forsøk kunne ikke sendes: {error}. Wiser rapporterer {reported} °C. Ingen flere forsøk sendes." + }, + "opentherm_notification_title": { + "message": "Wiser OpenTherm-kommando" + } + }, + "entity": { + "climate": { + "heating": { + "name": "Oppvarming" + }, + "floor_temperature": { + "name": "Gulvtemperatur" + } + }, + "number": { + "away_mode_target_temperature": { + "name": "Måltemperatur for bortemodus" + }, + "floor_temperature_offset": { + "name": "Forskyvning av gulvtemperatur" + }, + "indoor_discomfort_temperature": { + "name": "Innendørs ubehagstemperatur" + }, + "outdoor_discomfort_temperature": { + "name": "Utendørs ubehagstemperatur" + } + }, + "select": { + "mode": { + "name": "Modus" + }, + "power_on_behavior": { + "name": "Oppstartsadferd" + }, + "led_indicator": { + "name": "LED-indikator" + } + }, + "button": { + "boost_all_heating": { + "name": "Boost all oppvarming" + }, + "cancel_all_heating_overrides": { + "name": "Avbryt alle overstyringer av oppvarming" + }, + "boost_hot_water": { + "name": "Boost varmtvann" + }, + "cancel_hot_water_overrides": { + "name": "Avbryt alle overstyringer av varmtvann" + }, + "toggle_hot_water": { + "name": "Slå varmtvann av/på" + }, + "moment": { + "name": "Øyeblikk: {name}" + } + }, + "switch": { + "valve_protection": { + "name": "Ventilbeskyttelse" + }, + "eco_mode": { + "name": "Økomodus" + }, + "away_mode_affects_hot_water": { + "name": "Bortemodus påvirker varmtvann" + }, + "comfort_mode": { + "name": "Komfortmodus" + }, + "away_mode": { + "name": "Bortemodus" + }, + "daylight_saving": { + "name": "Sommertid" + }, + "summer_comfort_enabled": { + "name": "Sommerkomfort aktivert" + }, + "window_detection": { + "name": "Vindusregistrering" + }, + "include_in_summer_comfort": { + "name": "Ta med i sommerkomfort" + }, + "device_lock": { + "name": "Enhetslås" + }, + "identify": { + "name": "Identifiser" + }, + "outlet": { + "name": "Stikkontakt" + }, + "away_mode_turns_off": { + "name": "Bortemodus slår av" + }, + "away_mode_closes": { + "name": "Bortemodus lukker" + }, + "passive_mode": { + "name": "Passiv modus" + }, + "respect_summer_comfort": { + "name": "Respekter sommerkomfort" + }, + "interacts_with_room_climate": { + "name": "Samhandler med romklima" + }, + "humidity_interacts_with_room_climate": { + "name": "Luftfuktighet samhandler med romklima" + }, + "temperature_interacts_with_room_climate": { + "name": "Temperatur samhandler med romklima" + }, + "illuminance_interacts_with_room_climate": { + "name": "Belysningsstyrke samhandler med romklima" + }, + "sensor_interacts_with_room_climate": { + "name": "{sensor} samhandler med romklima" + }, + "manual_heat": { + "name": "Manuell oppvarming" + }, + "hot_water": { + "name": "Varmtvann" + } + }, + "binary_sensor": { + "summer_discomfort_prevention": { + "name": "Forebygging av sommerubehag" + }, + "summer_comfort_available": { + "name": "Sommerkomfort tilgjengelig" + }, + "pcm_device_limit_reached": { + "name": "Grensen for PCM-enheter er nådd" + }, + "smoke_alarm": { + "name": "Røykalarm" + }, + "heat_alarm": { + "name": "Varmealarm" + }, + "tamper_alarm": { + "name": "Sabotasjealarm" + }, + "fault_warning": { + "name": "Feilvarsel" + }, + "remote_alarm": { + "name": "Fjernalarm" + }, + "battery_defect": { + "name": "Batterifeil" + }, + "controllable": { + "name": "Styrbar" + }, + "pcm_mode": { + "name": "PCM-modus" + }, + "window_detection_active": { + "name": "Vindusregistrering aktiv" + }, + "is_dimmable": { + "name": "Kan dimmes" + }, + "is_led_indicator_supported": { + "name": "LED-indikator støttes" + }, + "is_output_mode_supported": { + "name": "Utgangsmodus støttes" + }, + "is_power_on_behaviour_supported": { + "name": "Oppstartsadferd støttes" + }, + "is_tilt_supported": { + "name": "Vipping støttes" + }, + "is_open": { + "name": "Åpen" + }, + "is_closed": { + "name": "Lukket" + }, + "active": { + "name": "Aktiv" + }, + "boiler_ch_max_setpoint_read_write": { + "name": "Lesing/skriving av kjelens maksimale sentralvarmesettpunkt" + }, + "boiler_ch_max_setpoint_transfer_enable": { + "name": "Overføring av kjelens maksimale sentralvarmesettpunkt aktivert" + }, + "boiler_fault": { + "name": "Kjelfeil" + }, + "boiler_hw_setpoint_read_write": { + "name": "Lesing/skriving av kjelens varmtvannssettpunkt" + }, + "boiler_hw_setpoint_transfer_enable": { + "name": "Overføring av kjelens varmtvannssettpunkt aktivert" + }, + "central_heating_2_active": { + "name": "Sentralvarme 2 aktiv" + }, + "central_heating_active": { + "name": "Sentralvarme aktiv" + }, + "ch1_flow_enabled": { + "name": "Sentralvarmekrets 1 tur aktivert" + }, + "ch2_flow_enabled": { + "name": "Sentralvarmekrets 2 tur aktivert" + }, + "cooling_active": { + "name": "Kjøling aktiv" + }, + "diagnostic_event": { + "name": "Diagnosehendelse" + }, + "flame_active": { + "name": "Flamme aktiv" + }, + "hot_water_active": { + "name": "Varmtvann aktivt" + }, + "hw_enabled": { + "name": "Varmtvann aktivert" + } + }, + "sensor": { + "signal": { + "name": "Signal" + }, + "cloud": { + "name": "Sky" + }, + "heating_operation_mode": { + "name": "Driftsmodus for oppvarming" + }, + "heating": { + "name": "Oppvarming", + "state": { + "off": "Av", + "on": "På" + } + }, + "heating_channel": { + "name": "Varmekanal {channel}", + "state": { + "off": "Av", + "on": "På" + } + }, + "hot_water": { + "name": "Varmtvann", + "state": { + "off": "Av", + "on": "På" + } + }, + "hot_water_operation_mode": { + "name": "Driftsmodus for varmtvann" + }, + "target_temperature": { + "name": "Måltemperatur" + }, + "floor_temperature": { + "name": "Gulvtemperatur" + }, + "boiler_flow_temperature": { + "name": "Kjelens turtemperatur" + }, + "boiler_return_temperature": { + "name": "Kjelens returtemperatur" + }, + "flame_statistics": { + "name": "Flammestatistikk" + }, + "boiler_ch_setpoint": { + "name": "Kjelens sentralvarmesettpunkt" + }, + "boiler_ch_setpoint_lower_bound": { + "name": "Nedre grense for kjelens sentralvarmesettpunkt" + }, + "boiler_ch_setpoint_upper_bound": { + "name": "Øvre grense for kjelens sentralvarmesettpunkt" + }, + "boiler_exhaust_temperature": { + "name": "Kjelens avgastemperatur" + }, + "boiler_hw_setpoint": { + "name": "Kjelens varmtvannssettpunkt" + }, + "boiler_hw_setpoint_lower_bound": { + "name": "Nedre grense for kjelens varmtvannssettpunkt" + }, + "boiler_hw_setpoint_upper_bound": { + "name": "Øvre grense for kjelens varmtvannssettpunkt" + }, + "ch1_flow_setpoint": { + "name": "Settpunkt for sentralvarmekrets 1 tur" + }, + "ch2_flow_setpoint": { + "name": "Settpunkt for sentralvarmekrets 2 tur" + }, + "ch_flow_active_lower_setpoint": { + "name": "Aktivt nedre settpunkt for sentralvarmetur" + }, + "ch_flow_active_upper_setpoint": { + "name": "Aktivt øvre settpunkt for sentralvarmetur" + }, + "ch_pressure_bar": { + "name": "Sentralvarmetrykk" + }, + "connection_status": { + "name": "Tilkoblingsstatus" + }, + "coprocessor_update_status": { + "name": "Oppdateringsstatus for OpenTherm-koprosessor" + }, + "coprocessor_version": { + "name": "Versjon av OpenTherm-koprosessor" + }, + "delta_t": { + "name": "Delta-T" + }, + "estimated_boiler_output": { + "name": "Anslått kjeleeffekt" + }, + "hw_flow_rate": { + "name": "Varmtvannsstrøm" + }, + "hw_flow_setpoint": { + "name": "Settpunkt for varmtvannstur" + }, + "hw_temperature": { + "name": "Varmtvannstemperatur" + }, + "maximum_capacity_kw": { + "name": "Maksimal kjelekapasitet" + }, + "minimum_modulation_level": { + "name": "Minste modulasjonsnivå" + }, + "operating_mode": { + "name": "Driftsmodus" + }, + "relative_modulation_level": { + "name": "Relativt modulasjonsnivå" + }, + "room_setpoint": { + "name": "Romsettpunkt" + }, + "room_temperature": { + "name": "Romtemperatur" + }, + "slave_status": { + "name": "OpenTherm-slavestatus" + }, + "tracked_room_id": { + "name": "ID for sporet rom" + }, + "heating_demand": { + "name": "Varmebehov" + }, + "heating_demand_channel": { + "name": "Varmebehovskanal {channel}" + }, + "hot_water_demand": { + "name": "Varmtvannsbehov" + }, + "total_energy": { + "name": "Total energi" + }, + "energy_delivered": { + "name": "Levert energi" + }, + "energy_received": { + "name": "Mottatt energi" + }, + "equipment_power": { + "name": "Utstyr" + } + } + }, + "device_automation": { + "trigger_type": { + "started_heating": "{entity_name} starter oppvarming", + "stopped_heating": "{entity_name} stopper oppvarming", + "boosted": "{entity_name} er boostet", + "target_temperature_increased": "Måltemperaturen for {entity_name} ble økt", + "target_temperature_decreased": "Måltemperaturen for {entity_name} ble redusert" + } + } +} + diff --git a/custom_components/wiser/translations/nl.json b/custom_components/wiser/translations/nl.json index 3411cc80..64fd34c7 100644 --- a/custom_components/wiser/translations/nl.json +++ b/custom_components/wiser/translations/nl.json @@ -3,7 +3,7 @@ "flow_title": "{name}", "step": { "user": { - "title": "Wiser Installatie warmtehub", + "title": "Wiser Heat Hub instellen", "description": "Voer het IP-adres en de geheime sleutel in die u van de hub hebt verkregen.", "data": { "host": "IP-adres of hostnaam", @@ -12,8 +12,8 @@ } }, "zeroconf_confirm": { - "title": "Wiser Installatie warmtehub ({name})", - "description": "Voer in de geheime sleutel verkregen van de hub.", + "title": "Wiser Heat Hub instellen ({name})", + "description": "Voer de geheime sleutel in die u van de hub hebt verkregen.", "data": { "host": "IP-adres of hostnaam", "port": "Poortnummer", @@ -22,9 +22,9 @@ } }, "abort": { - "already_in_progress": "Wiser De configuratie van de warmtehub wordt al uitgevoerd.", + "already_in_progress": "De configuratie van de Wiser Heat Hub wordt al uitgevoerd.", "already_configured": "Dit apparaat is al geconfigureerd.", - "not_wiser_hub": "Het ontdekte apparaat is geen Wiser Warmtehub." + "not_wiser_hub": "Het ontdekte apparaat is geen Wiser Heat Hub." }, "error": { "auth_failure": "Kan niet verifiëren met de Wiser-hub. Controleer de geheime sleutel en probeer het opnieuw.", @@ -36,33 +36,33 @@ "options": { "step": { "init": { - "title": "Wiser Integratieopties", + "title": "Opties voor de Wiser-integratie", "description": "Selecteer parameters om te wijzigen", "menu_options": { "main_params": "Hoofdparameters", "automation_params": "Automatiseringsparameters", "opentherm_sensors": "OpenTherm-sensoren", "equipment_sensors": "Apparatuursensoren", - "ui_options": "UI-opties" + "ui_options": "Opties voor de gebruikersinterface" } }, "ui_options": { - "title": "UI-opties", + "title": "Opties voor de gebruikersinterface", "data": { "legacy_naming": "Oude naamgeving", "show_wiser_sidebar": "Toon Wiser in zijbalk" }, "data_description": { - "legacy_naming": "Neem kamernamen op in Wiser apparaatnamen. Indien ingeschakeld, zal het gebruik van Home Assistant om entiteits-ID's opnieuw te genereren met het standaardformaat in Instellingen → Systeem → Entiteits-ID-formaat (Home Assistant 2026.8 en later) gebiedsnamen dupliceren wanneer het gebied en de Wiser kamernamen overeenkomen. Als u deze optie wijzigt, worden de bestaande entiteit-ID's niet hernoemd." + "legacy_naming": "Neem kamernamen op in de namen van Wiser-apparaten. Indien ingeschakeld, worden gebiedsnamen gedupliceerd wanneer Home Assistant entiteits-ID's opnieuw genereert met de standaardindeling via Instellingen → Systeem → Indeling entiteits-ID (Home Assistant 2026.8 en later) en de namen van het gebied en de Wiser-kamer overeenkomen. Als u deze optie wijzigt, worden bestaande entiteits-ID's niet hernoemd." } }, "main_params": { - "title": "Wiser Integratieopties", + "title": "Opties voor de Wiser-integratie", "description": "Hoofdparameters", "data": { "host": "IP-adres of hostnaam", "port": "Poortnummer", - "scan_interval": "Scaninterval (sec)", + "scan_interval": "Update-interval (seconden)", "heating_boost_temp": "Standaard verwarmingsboosttemperatuur (°C)", "heating_boost_time": "Standaard verwarmingsboostduur (min.)", "hotwater_boost_time": "Standaard warmwaterboostduur (min.)", @@ -71,7 +71,7 @@ } }, "automation_params": { - "title": "Wiser Integratieopties", + "title": "Opties voor de Wiser-integratie", "description": "Ingebouwde automatiseringen inschakelen", "sections": { "automations_passive_mode": { @@ -79,7 +79,7 @@ "description": "Passieve TRV-mogelijkheden inschakelen. Elke kamer moet worden ingeschakeld om te kunnen functioneren.", "data": { "automations_passive_mode": "Passieve modus", - "passive_mode_temperature_increments": "Passieve modus Temperatuurverhogingen" + "passive_mode_temperature_increments": "Temperatuurstappen voor passieve modus" } }, "hotwater_climate": { @@ -87,10 +87,10 @@ "description": "Schakel klimaatregeling voor warm water in. Zie de wiki voor details.", "data": { "hotwater_climate": "Schakel de klimaatentiteit in", - "experimental_mode": "Schakel de experimentele werkmodus in", + "experimental_mode": "Experimentele bedrijfsmodus inschakelen", "hotwater_auto_mode": "Automatische modus voor warm water", "hotwater_heat_mode": "Modus voor warm water", - "hotwater_boost_mode": "Modus voor warm water boost", + "hotwater_boost_mode": "Boostmodus voor warm water", "hotwater_sensor_entity_id": "Warmwatertemperatuursensor" } } @@ -103,7 +103,7 @@ "equipment_sensors": "Schakel apparatuurgegevenssensoren in" }, "data_description": { - "equipment_sensors": "Stel een extra sensor bloot met gedetailleerde apparatuurkenmerken voor elke compatibele slimme stekker, PowerTag en verwarmingsactuator." + "equipment_sensors": "Maakt een extra sensor beschikbaar met gedetailleerde apparatuurkenmerken voor elke compatibele slimme stekker, PowerTag en verwarmingsactuator." } }, "opentherm_sensors": { @@ -124,7 +124,7 @@ "ch_pressure_bar": "CV-druk", "ch_return_temperature": "Ketelretourtemperatuur", "delta_t": "Delta-T", - "boiler_exhaust_temperature": "Ketelafvoertemperatuur", + "boiler_exhaust_temperature": "Rookgastemperatuur van de ketel", "estimated_boiler_output": "Geschat ketelvermogen", "hw_flow_rate": "Warmwaterdebiet", "hw_temperature": "Warmwatertemperatuur", @@ -138,18 +138,18 @@ "title": "OpenTherm centrale verwarming", "description": "Kies welke gedetecteerde kenmerken voor centrale verwarming als entiteiten worden weergegeven.", "data": { - "boiler_ch_max_setpoint_read_write": "Ketel CH maximum setpoint lezen/schrijven", - "boiler_ch_max_setpoint_transfer_enable": "Ketel CH maximum setpoint overdracht ingeschakeld", - "boiler_ch_setpoint": "Ketel CH setpoint", - "boiler_ch_setpoint_lower_bound": "Ketel CH setpoint ondergrens", - "boiler_ch_setpoint_upper_bound": "Ketel CH setpoint bovengrens", - "ch_flow_active_lower_setpoint": "CH-debiet actief onderste setpoint", - "ch_flow_active_upper_setpoint": "CH-debiet actief bovenste setpoint", + "boiler_ch_max_setpoint_read_write": "Maximale CV-instelwaarde ketel lezen/schrijven", + "boiler_ch_max_setpoint_transfer_enable": "Overdracht maximale CV-instelwaarde ketel ingeschakeld", + "boiler_ch_setpoint": "CV-instelwaarde ketel", + "boiler_ch_setpoint_lower_bound": "Ondergrens CV-instelwaarde ketel", + "boiler_ch_setpoint_upper_bound": "Bovengrens CV-instelwaarde ketel", + "ch_flow_active_lower_setpoint": "Actieve onderste CV-aanvoerinstelwaarde", + "ch_flow_active_upper_setpoint": "Actieve bovenste CV-aanvoerinstelwaarde", "ch1_flow_enabled": "CH1-debiet ingeschakeld", - "ch1_flow_setpoint": "CH1 debiet-setpoint", + "ch1_flow_setpoint": "CV1-aanvoerinstelwaarde", "ch2_flow_enabled": "CH2-debiet ingeschakeld", - "ch2_flow_setpoint": "CH2-debiet instelpunt", - "room_setpoint": "Instelpunt kamer" + "ch2_flow_setpoint": "CV2-aanvoerinstelwaarde", + "room_setpoint": "Kamerinstelwaarde" } }, "opentherm_hot_water": { @@ -161,7 +161,7 @@ "boiler_hw_setpoint_read_write": "Ketelwarmwaterinstelpunt lezen/schrijven", "boiler_hw_setpoint_transfer_enable": "Ketelwarmwaterinstelpuntoverdracht ingeschakeld", "boiler_hw_setpoint_upper_bound": "Ketelwarmwaterinstelpunt bovengrens", - "hw_enabled": "Heet water ingeschakeld", + "hw_enabled": "Warm water ingeschakeld", "hw_flow_setpoint": "Instelpunt warmwaterdebiet" } }, @@ -173,7 +173,7 @@ "central_heating_active": "Centrale verwarming actief", "central_heating_2_active": "Centrale verwarming 2 actief", "connection_status": "Verbindingsstatus", - "coprocessor_update_status": "OpenTherm Updatestatus coprocessor", + "coprocessor_update_status": "Updatestatus OpenTherm-coprocessor", "coprocessor_version": "OpenTherm coprocessorversie", "cooling_active": "Koeling actief", "diagnostic_event": "Diagnosegebeurtenis", @@ -182,13 +182,13 @@ "hot_water_active": "Warm water actief", "operating_mode": "Bedrijfsmodus", "slave_status": "OpenTherm slave-status", - "tracked_room_id": "Getraceerde kamer-ID" + "tracked_room_id": "ID van gevolgde kamer" } } }, "abort": { - "opentherm_not_available": "OpenTherm-gegevens zijn niet beschikbaar voor deze Wiser naaf.", - "equipment_not_available": "Er zijn geen uitrustingsgegevens beschikbaar voor deze Wiser-hub." + "opentherm_not_available": "OpenTherm-gegevens zijn niet beschikbaar voor deze Wiser-hub.", + "equipment_not_available": "Apparatuurgegevens zijn niet beschikbaar voor deze Wiser-hub." } }, "services": { @@ -198,15 +198,15 @@ "fields": { "parameter": { "name": "Parameter", - "description": "OpenTherm temperatuurparameter die moet worden gewijzigd. Het vereiste API-eindpunt wordt automatisch geselecteerd." + "description": "OpenTherm-temperatuurparameter die moet worden gewijzigd. Het vereiste API-eindpunt wordt automatisch geselecteerd." }, "temperature": { "name": "Temperatuur", "description": "Gebruik een temperatuur binnen de grenzen die door uw ketel worden gerapporteerd." }, "hub": { - "name": "Wiser hub", - "description": "Selecteer alleen een hub als u meerdere Wiser hubs heeft." + "name": "Wiser-hub", + "description": "Selecteer alleen een hub als u meerdere Wiser-hubs hebt." } } } @@ -242,16 +242,16 @@ "message": "De parameter of waarde OpenTherm is ongeldig: {error}" }, "opentherm_write_failed": { - "message": "Kan parameter OpenTherm niet instellen {parameter}: {error}" + "message": "Kan OpenTherm-parameter {parameter} niet instellen: {error}" }, "opentherm_confirmation_failed": { - "message": "OpenTherm-parameter {parameter} bleef niet op {requested} °C na één nieuwe poging en het {window}-tweede bevestigingsvenster. Wiser rapporteert {reported} °C. Er wordt geen nieuwe poging meer verzonden." + "message": "OpenTherm-parameter {parameter} bleef na één nieuwe poging en de bevestigingsperiode van {window} seconden niet op {requested} °C. Wiser rapporteert {reported} °C. Er worden geen verdere pogingen verzonden." }, "opentherm_retry_failed": { - "message": "OpenTherm-parameter {parameter} bleef niet op {requested} °C en de nieuwe poging kon niet worden verzonden: {error}. Wiser meldt {reported} °C. Er wordt geen nieuwe poging meer verzonden." + "message": "OpenTherm-parameter {parameter} bleef niet op {requested} °C en de nieuwe poging kon niet worden verzonden: {error}. Wiser rapporteert {reported} °C. Er worden geen verdere pogingen verzonden." }, "opentherm_notification_title": { - "message": "Wiser OpenTherm commando" + "message": "Wiser OpenTherm-opdracht" } }, "entity": { @@ -271,10 +271,10 @@ "name": "Offset vloertemperatuur" }, "indoor_discomfort_temperature": { - "name": "Ongemakkelijke temperatuur binnen" + "name": "Ongemakstemperatuur binnen" }, "outdoor_discomfort_temperature": { - "name": "Ongemakkelijke temperatuur buiten" + "name": "Ongemakstemperatuur buiten" } }, "select": { @@ -290,13 +290,13 @@ }, "button": { "boost_all_heating": { - "name": "Alle verwarming stimuleren" + "name": "Alle verwarming boosten" }, "cancel_all_heating_overrides": { "name": "Alle verwarmingsoverrides annuleren" }, "boost_hot_water": { - "name": "Warm water boost" + "name": "Warm water boosten" }, "cancel_hot_water_overrides": { "name": "Warmwateroverrides annuleren" @@ -343,19 +343,19 @@ "name": "Identificeren" }, "outlet": { - "name": "Outlet" + "name": "Stopcontact" }, "away_mode_turns_off": { - "name": "Afwezig-modus wordt uitgeschakeld" + "name": "Schakelt uit in afwezigheidsmodus" }, "away_mode_closes": { - "name": "Afwezig-modus sluit" + "name": "Sluit in afwezigheidsmodus" }, "passive_mode": { "name": "Passieve modus" }, "respect_summer_comfort": { - "name": "Respecteer het zomercomfort" + "name": "Zomercomfort respecteren" }, "interacts_with_room_climate": { "name": "Heeft invloed op het binnenklimaat" @@ -370,7 +370,7 @@ "name": "Verlichtingssterkte heeft invloed op het binnenklimaat" }, "sensor_interacts_with_room_climate": { - "name": "{sensor} interageert met het binnenklimaat" + "name": "{sensor} heeft invloed op het binnenklimaat" }, "manual_heat": { "name": "Handmatige verwarming" @@ -441,19 +441,19 @@ "name": "Actief" }, "boiler_ch_max_setpoint_read_write": { - "name": "Ketel CH maximaal setpoint lezen/schrijven" + "name": "Maximale CV-instelwaarde ketel lezen/schrijven" }, "boiler_ch_max_setpoint_transfer_enable": { - "name": "Ketel CV maximum setpoint overdracht ingeschakeld" + "name": "Overdracht maximale CV-instelwaarde ketel ingeschakeld" }, "boiler_fault": { - "name": "Ketel storing" + "name": "Ketelstoring" }, "boiler_hw_setpoint_read_write": { - "name": "Ketel warm water setpoint lezen/schrijven" + "name": "Warmwaterinstelwaarde ketel lezen/schrijven" }, "boiler_hw_setpoint_transfer_enable": { - "name": "Ketel warm water setpoint overdracht ingeschakeld" + "name": "Overdracht warmwaterinstelwaarde ketel ingeschakeld" }, "central_heating_2_active": { "name": "Centrale verwarming 2 actief" @@ -462,10 +462,10 @@ "name": "Centrale verwarming actief" }, "ch1_flow_enabled": { - "name": "CH1-stroom ingeschakeld" + "name": "CV1-aanvoer ingeschakeld" }, "ch2_flow_enabled": { - "name": "CH2-stroom ingeschakeld" + "name": "CV2-aanvoer ingeschakeld" }, "cooling_active": { "name": "Koeling actief" @@ -533,19 +533,19 @@ "name": "Vlamstatistieken" }, "boiler_ch_setpoint": { - "name": "Ketel CV-instelpunt" + "name": "CV-instelwaarde ketel" }, "boiler_ch_setpoint_lower_bound": { - "name": "Ketel CH-instelpunt ondergrens" + "name": "Ondergrens CV-instelwaarde ketel" }, "boiler_ch_setpoint_upper_bound": { - "name": "Ketel CV-instelpunt bovengrens" + "name": "Bovengrens CV-instelwaarde ketel" }, "boiler_exhaust_temperature": { - "name": "Ketelafvoertemperatuur" + "name": "Rookgastemperatuur van de ketel" }, "boiler_hw_setpoint": { - "name": "Ketel heet waterinstelpunt" + "name": "Warmwaterinstelwaarde ketel" }, "boiler_hw_setpoint_lower_bound": { "name": "Ketelwarmwaterinstelpunt ondergrens" @@ -554,25 +554,25 @@ "name": "Ketelwarmwaterinstelpunt bovengrens" }, "ch1_flow_setpoint": { - "name": "CH1 debietinstelpunt" + "name": "CV1-aanvoerinstelwaarde" }, "ch2_flow_setpoint": { - "name": "CH2 aanvoer setpoint" + "name": "CV2-aanvoerinstelwaarde" }, "ch_flow_active_lower_setpoint": { - "name": "CH aanvoer actief onderste setpoint" + "name": "Actieve onderste CV-aanvoerinstelwaarde" }, "ch_flow_active_upper_setpoint": { - "name": "CH aanvoer actief bovenste setpoint" + "name": "Actieve bovenste CV-aanvoerinstelwaarde" }, "ch_pressure_bar": { - "name": "CV druk" + "name": "CV-druk" }, "connection_status": { "name": "Verbindingsstatus" }, "coprocessor_update_status": { - "name": "OpenTherm updatestatus coprocessor" + "name": "Updatestatus OpenTherm-coprocessor" }, "coprocessor_version": { "name": "OpenTherm coprocessorversie" @@ -605,7 +605,7 @@ "name": "Relatief modulatieniveau" }, "room_setpoint": { - "name": "Gewenste ruimteruimte" + "name": "Kamerinstelwaarde" }, "room_temperature": { "name": "Kamertemperatuur" @@ -614,7 +614,7 @@ "name": "OpenTherm slave-status" }, "tracked_room_id": { - "name": "Getraceerde kamer-ID" + "name": "ID van gevolgde kamer" }, "heating_demand": { "name": "Verwarmingsvraag" @@ -643,9 +643,9 @@ "trigger_type": { "started_heating": "{entity_name} begint met verwarmen", "stopped_heating": "{entity_name} stopt met verwarmen", - "boosted": "{entity_name} wordt versterkt", - "target_temperature_increased": "{entity_name} doeltemperatuur verhoogd", - "target_temperature_decreased": "{entity_name} doeltemperatuur verlaagd" + "boosted": "{entity_name} wordt geboost", + "target_temperature_increased": "Doeltemperatuur van {entity_name} verhoogd", + "target_temperature_decreased": "Doeltemperatuur van {entity_name} verlaagd" } } } diff --git a/custom_components/wiser/translations/pt.json b/custom_components/wiser/translations/pt.json index 1f372de7..aba3c3b3 100644 --- a/custom_components/wiser/translations/pt.json +++ b/custom_components/wiser/translations/pt.json @@ -3,8 +3,8 @@ "flow_title": "{name}", "step": { "user": { - "title": "Wiser Configuração do hub de calor", - "description": "Insira o endereço IP e a chave secreta obtidas do hub.", + "title": "Configuração do Heat Hub Wiser", + "description": "Introduza o endereço IP e a chave secreta obtidos do hub.", "data": { "host": "Endereço IP ou nome de host", "port": "Número da porta", @@ -12,8 +12,8 @@ } }, "zeroconf_confirm": { - "title": "Wiser Configuração do hub de aquecimento ({name})", - "description": "Insira a chave secreta obtida do hub.", + "title": "Configuração do Heat Hub Wiser ({name})", + "description": "Introduza a chave secreta obtida do hub.", "data": { "host": "Endereço IP ou nome de host", "port": "Número da porta", @@ -22,61 +22,61 @@ } }, "abort": { - "already_in_progress": "Wiser A configuração do Heat Hub já está em andamento.", + "already_in_progress": "A configuração do Heat Hub Wiser já está em curso.", "already_configured": "Este dispositivo já está configurado.", "not_wiser_hub": "O dispositivo descoberto não é um Heat Hub Wiser." }, "error": { - "auth_failure": "Não é possível autenticar com o hub Wiser. Verifique a chave secreta e tente novamente.", - "timeout_error": "Tempo limite esgotado ao tentar conectar-se ao hub Wiser. Verifique o endereço IP e tente novamente.", - "timeout_error_discovery": "Tempo limite esgotado ao tentar conectar-se ao hub Wiser. Verifique se o seu hub ainda está online e tente novamente.", - "unknown": "Erro desconhecido ao conectar ao hub Wiser. Por favor, verifique os registros." + "auth_failure": "Não foi possível autenticar no hub Wiser. Verifique a chave secreta e tente novamente.", + "timeout_error": "O tempo limite foi excedido ao estabelecer ligação ao hub Wiser. Verifique o endereço IP e tente novamente.", + "timeout_error_discovery": "O tempo limite foi excedido ao estabelecer ligação ao hub Wiser. Verifique se o hub continua online e tente novamente.", + "unknown": "Ocorreu um erro desconhecido ao estabelecer ligação ao hub Wiser. Consulte os registos." } }, "options": { "step": { "init": { - "title": "Wiser Opções de integração", + "title": "Opções da integração Wiser", "description": "Selecione parâmetros para alterar", "menu_options": { "main_params": "Parâmetros principais", "automation_params": "Parâmetros de automação", "opentherm_sensors": "Sensores OpenTherm", "equipment_sensors": "Sensores de equipamento", - "ui_options": "Opções de UI" + "ui_options": "Opções da interface do utilizador" } }, "ui_options": { - "title": "Opções de UI", + "title": "Opções da interface do utilizador", "data": { "legacy_naming": "Nomenclatura legada", "show_wiser_sidebar": "Mostrar Wiser na barra lateral" }, "data_description": { - "legacy_naming": "Incluir espaço nomes em nomes de dispositivos Wiser. Se ativado, usar Home Assistant para regenerar IDs de entidade com o formato padrão em Configurações → Sistema → Formato de ID de entidade (Home Assistant 2026.8 e posterior) duplicará os nomes das áreas quando os nomes da área e da sala Wiser corresponderem. A alteração desta opção não renomeia os IDs de entidade existentes." + "legacy_naming": "Inclui os nomes das divisões nos nomes dos dispositivos Wiser. Se estiver ativado, ao utilizar o Home Assistant para regenerar os ID de entidade com o formato predefinido em Definições → Sistema → Formato do ID de entidade (Home Assistant 2026.8 e posterior), os nomes das áreas serão duplicados quando coincidirem com os nomes das divisões Wiser. Alterar esta opção não muda o nome dos ID de entidade existentes." } }, "main_params": { - "title": "Wiser Opções de integração", + "title": "Opções da integração Wiser", "description": "Parâmetros principais", "data": { "host": "Endereço IP ou nome do host", "port": "Número da porta", - "scan_interval": "Intervalo de varredura (seg)", + "scan_interval": "Intervalo de atualização (segundos)", "heating_boost_temp": "Temperatura padrão do reforço de aquecimento (°C)", "heating_boost_time": "Duração padrão do reforço de aquecimento (minutos)", "hotwater_boost_time": "Duração padrão do reforço de água quente (minutos)", - "setpoint_mode": "Modo de ponto de ajuste", - "restore_manual_temp_option": "Use esta temperatura se não A temperatura manual é armazenada" + "setpoint_mode": "Modo do valor de referência", + "restore_manual_temp_option": "Utilizar esta temperatura se não existir uma temperatura manual guardada" } }, "automation_params": { - "title": "Wiser Opções de integração", + "title": "Opções da integração Wiser", "description": "Habilitar automações integradas", "sections": { "automations_passive_mode": { "name": "Modo passivo", - "description": "Habilitar capacidade TRV passiva. Cada sala precisa ser habilitada para funcionar.", + "description": "Ativar a funcionalidade TRV passiva. É necessário ativá-la individualmente em cada divisão.", "data": { "automations_passive_mode": "Modo passivo", "passive_mode_temperature_increments": "Incrementos de temperatura no modo passivo" @@ -86,8 +86,8 @@ "name": "Controle climático de água quente", "description": "Ativa o controle climático de água quente. Veja o wiki para detalhes.", "data": { - "hotwater_climate": "Ativar a entidade climática", - "experimental_mode": "Ativar modo de trabalho experimental", + "hotwater_climate": "Ativar a entidade de climatização", + "experimental_mode": "Ativar o modo de funcionamento experimental", "hotwater_auto_mode": "Modo automático de água quente", "hotwater_heat_mode": "Modo de aquecimento de água quente", "hotwater_boost_mode": "Modo de reforço de água quente", @@ -103,7 +103,7 @@ "equipment_sensors": "Habilitar sensores de dados do equipamento" }, "data_description": { - "equipment_sensors": "Exponha um sensor adicional contendo atributos detalhados do equipamento para cada plugue inteligente, PowerTag e atuador de aquecimento compatível." + "equipment_sensors": "Disponibiliza um sensor adicional com atributos detalhados do equipamento para cada tomada inteligente, PowerTag e atuador de aquecimento compatível." } }, "opentherm_sensors": { @@ -118,7 +118,7 @@ }, "opentherm_readings": { "title": "Leituras OpenTherm", - "description": "Escolha qual as leituras OpenTherm detectadas são expostas como entidades de sensor.", + "description": "Escolha quais leituras OpenTherm detetadas são apresentadas como entidades de sensor.", "data": { "ch_flow_temperature": "Temperatura de fluxo da caldeira", "ch_pressure_bar": "Pressão CH", @@ -126,7 +126,7 @@ "delta_t": "Delta-T", "boiler_exhaust_temperature": "Temperatura de exaustão da caldeira", "estimated_boiler_output": "Potência estimada da caldeira", - "hw_flow_rate": "Vazão de água quente", + "hw_flow_rate": "Caudal de água quente", "hw_temperature": "Temperatura da água quente", "maximum_capacity_kw": "Capacidade máxima da caldeira", "minimum_modulation_level": "Nível mínimo de modulação", @@ -148,7 +148,7 @@ "ch1_flow_enabled": "Fluxo CH1 habilitado", "ch1_flow_setpoint": "Ponto de ajuste de fluxo CH1", "ch2_flow_enabled": "Fluxo CH2 habilitado", - "ch2_flow_setpoint": "Fluxo CH2 ponto de ajuste", + "ch2_flow_setpoint": "Valor de referência do fluxo CH2", "room_setpoint": "Ponto de ajuste da sala" } }, @@ -160,7 +160,7 @@ "boiler_hw_setpoint_lower_bound": "Limite inferior do ponto de ajuste de água quente da caldeira", "boiler_hw_setpoint_read_write": "Leitura/escrita do ponto de ajuste de água quente da caldeira", "boiler_hw_setpoint_transfer_enable": "Transferência do ponto de ajuste de água quente da caldeira habilitada", - "boiler_hw_setpoint_upper_bound": "Ponto de ajuste de água quente da caldeira limite superior", + "boiler_hw_setpoint_upper_bound": "Limite superior do valor de referência de água quente da caldeira", "hw_enabled": "Água quente habilitada", "hw_flow_setpoint": "Ponto de ajuste do fluxo de água quente" } @@ -170,35 +170,35 @@ "description": "Escolha quais status detectados e atributos de diagnóstico são expostos como entidades de sensor.", "data": { "boiler_fault": "Avaria na caldeira", - "central_heating_active": "Aquecimento central activo", - "central_heating_2_active": "Aquecimento central 2 activo", + "central_heating_active": "Aquecimento central ativo", + "central_heating_2_active": "Aquecimento central 2 ativo", "connection_status": "Estado da ligação", - "coprocessor_update_status": "OpenTherm Estado de actualização do coprocessador", - "coprocessor_version": "OpenTherm versão do coprocessador", - "cooling_active": "Resfriamento ativo", + "coprocessor_update_status": "Estado de atualização do coprocessador OpenTherm", + "coprocessor_version": "Versão do coprocessador OpenTherm", + "cooling_active": "Arrefecimento ativo", "diagnostic_event": "Evento de diagnóstico", "flame_active": "Chama ativa", "flame_statistics": "Estatísticas de chama", "hot_water_active": "Água quente ativa", "operating_mode": "Modo de operação", - "slave_status": "OpenTherm status escravo", - "tracked_room_id": "ID da sala rastreada" + "slave_status": "Estado do dispositivo secundário OpenTherm", + "tracked_room_id": "ID da divisão monitorizada" } } }, "abort": { - "opentherm_not_available": "OpenTherm Os dados não estão disponíveis para este Wiser centro.", + "opentherm_not_available": "Os dados OpenTherm não estão disponíveis para este hub Wiser.", "equipment_not_available": "Os dados do equipamento não estão disponíveis para este hub Wiser." } }, "services": { "set_opentherm_parameter": { "name": "Definir parâmetro OpenTherm", - "description": "Altera um parâmetro de temperatura OpenTherm compatível no hub Wiser. Parâmetro", + "description": "Altera um parâmetro de temperatura OpenTherm compatível no hub Wiser.", "fields": { "parameter": { - "name": "", - "description": "OpenTherm Parâmetro de temperatura a ser alterado. O endpoint de API necessário é selecionado automaticamente." + "name": "Parâmetro", + "description": "Parâmetro de temperatura OpenTherm a alterar. O endpoint da API necessário é selecionado automaticamente." }, "temperature": { "name": "Temperatura", @@ -245,13 +245,13 @@ "message": "Não é possível definir o parâmetro OpenTherm {parameter}: {error}" }, "opentherm_confirmation_failed": { - "message": "O parâmetro OpenTherm {parameter} não permaneceu em {requested} °C após uma nova tentativa e a janela de confirmação de segundo {window}. Wiser relata {reported} °C. Nenhuma nova tentativa será enviada." + "message": "O parâmetro OpenTherm {parameter} não permaneceu em {requested} °C após uma nova tentativa e o período de confirmação de {window} segundos. O Wiser indica {reported} °C. Não serão efetuadas mais tentativas." }, "opentherm_retry_failed": { - "message": "O parâmetro OpenTherm {parameter} não permaneceu em {requested} °C e sua nova tentativa não pôde ser enviada: {error}. Wiser relata {reported} °C. Nenhuma nova tentativa será enviada." + "message": "O parâmetro OpenTherm {parameter} não permaneceu em {requested} °C e não foi possível enviar a nova tentativa: {error}. O Wiser indica {reported} °C. Não serão efetuadas mais tentativas." }, "opentherm_notification_title": { - "message": "Wiser Comando OpenTherm" + "message": "Comando OpenTherm do Wiser" } }, "entity": { @@ -268,7 +268,7 @@ "name": "Temperatura alvo do modo ausente" }, "floor_temperature_offset": { - "name": "Deslocamento da temperatura do piso" + "name": "Compensação da temperatura do piso" }, "indoor_discomfort_temperature": { "name": "Temperatura de desconforto interno" @@ -290,13 +290,13 @@ }, "button": { "boost_all_heating": { - "name": "Aumentar todo o aquecimento" + "name": "Reforçar todo o aquecimento" }, "cancel_all_heating_overrides": { "name": "Cancelar todas as substituições de aquecimento" }, "boost_hot_water": { - "name": "Aumentar a água quente" + "name": "Reforçar a água quente" }, "cancel_hot_water_overrides": { "name": "Cancelar substituições de água quente" @@ -346,16 +346,16 @@ "name": "Tomada" }, "away_mode_turns_off": { - "name": "O modo ausente desliga" + "name": "Desliga no modo ausente" }, "away_mode_closes": { - "name": "O modo ausente fecha" + "name": "Fecha no modo ausente" }, "passive_mode": { "name": "Modo passivo" }, "respect_summer_comfort": { - "name": "Respeite o conforto do verão" + "name": "Respeitar o conforto de verão" }, "interacts_with_room_climate": { "name": "Interage com o clima ambiente" @@ -572,10 +572,10 @@ "name": "Status de conexão" }, "coprocessor_update_status": { - "name": "OpenTherm Status de atualização do coprocessador" + "name": "Estado de atualização do coprocessador OpenTherm" }, "coprocessor_version": { - "name": "OpenTherm versão do coprocessador" + "name": "Versão do coprocessador OpenTherm" }, "delta_t": { "name": "Delta-T" @@ -584,7 +584,7 @@ "name": "Saída estimada da caldeira" }, "hw_flow_rate": { - "name": "Taxa de fluxo de água quente" + "name": "Caudal de água quente" }, "hw_flow_setpoint": { "name": "Ponto de ajuste do fluxo de água quente" @@ -611,10 +611,10 @@ "name": "Temperatura ambiente" }, "slave_status": { - "name": "OpenTherm status escravo" + "name": "Estado do dispositivo secundário OpenTherm" }, "tracked_room_id": { - "name": "ID da sala rastreada" + "name": "ID da divisão monitorizada" }, "heating_demand": { "name": "Demanda de aquecimento" @@ -643,9 +643,9 @@ "trigger_type": { "started_heating": "{entity_name} inicia o aquecimento", "stopped_heating": "{entity_name} para de aquecer", - "boosted": "{entity_name} é aumentado", - "target_temperature_increased": "{entity_name} temperatura alvo aumentada", - "target_temperature_decreased": "A temperatura alvo do {entity_name} diminuiu" + "boosted": "{entity_name} é reforçado", + "target_temperature_increased": "A temperatura alvo de {entity_name} aumentou", + "target_temperature_decreased": "A temperatura alvo de {entity_name} diminuiu" } } } diff --git a/custom_components/wiser/translations/sv.json b/custom_components/wiser/translations/sv.json new file mode 100644 index 00000000..09799533 --- /dev/null +++ b/custom_components/wiser/translations/sv.json @@ -0,0 +1,652 @@ +{ + "config": { + "flow_title": "{name}", + "step": { + "user": { + "title": "Konfiguration av Wiser Heat Hub", + "description": "Ange IP-adressen och den hemliga nyckeln som hämtats från hubben.", + "data": { + "host": "IP-adress eller värdnamn", + "port": "Portnummer", + "password": "Hemlig nyckel" + } + }, + "zeroconf_confirm": { + "title": "Konfiguration av Wiser Heat Hub ({name})", + "description": "Ange den hemliga nyckeln som hämtats från hubben.", + "data": { + "host": "IP-adress eller värdnamn", + "port": "Portnummer", + "password": "Hemlig nyckel" + } + } + }, + "abort": { + "already_in_progress": "Konfiguration av Wiser Heat Hub pågår redan.", + "already_configured": "Den här enheten är redan konfigurerad.", + "not_wiser_hub": "Den identifierade enheten är inte en Wiser Heat Hub." + }, + "error": { + "auth_failure": "Det gick inte att autentisera mot Wiser-hubben. Kontrollera den hemliga nyckeln och försök igen.", + "timeout_error": "Tidsgränsen överskreds vid anslutning till Wiser-hubben. Kontrollera IP-adressen och försök igen.", + "timeout_error_discovery": "Tidsgränsen överskreds vid anslutning till Wiser-hubben. Kontrollera att hubben fortfarande är online och försök igen.", + "unknown": "Okänt fel vid anslutning till Wiser-hubben. Kontrollera loggarna." + } + }, + "options": { + "step": { + "init": { + "title": "Alternativ för Wiser-integrationen", + "description": "Välj parametrar som ska ändras", + "menu_options": { + "main_params": "Huvudparametrar", + "automation_params": "Automatiseringsparametrar", + "opentherm_sensors": "OpenTherm-sensorer", + "equipment_sensors": "Utrustningssensorer", + "ui_options": "Gränssnittsalternativ" + } + }, + "ui_options": { + "title": "Gränssnittsalternativ", + "data": { + "legacy_naming": "Äldre namngivning", + "show_wiser_sidebar": "Visa Wiser i sidopanelen" + }, + "data_description": { + "legacy_naming": "Inkludera rumsnamn i namn på Wiser-enheter. Om detta är aktiverat kommer återskapande av entitets-ID:n i Home Assistant med standardformatet under Inställningar → System → Format för entitets-ID (Home Assistant 2026.8 och senare) att duplicera områdesnamn när området och Wiser-rummet har samma namn. Ändring av detta alternativ byter inte namn på befintliga entitets-ID:n." + } + }, + "main_params": { + "title": "Alternativ för Wiser-integrationen", + "description": "Huvudparametrar", + "data": { + "host": "IP-adress eller värdnamn", + "port": "Portnummer", + "scan_interval": "Skanningsintervall (sek.)", + "heating_boost_temp": "Standardtemperatur för värmeboost (°C)", + "heating_boost_time": "Standardtid för värmeboost (min.)", + "hotwater_boost_time": "Standardtid för varmvattenboost (min.)", + "setpoint_mode": "Börvärdesläge", + "restore_manual_temp_option": "Använd denna temperatur om ingen manuell temperatur har sparats" + } + }, + "automation_params": { + "title": "Alternativ för Wiser-integrationen", + "description": "Aktivera inbyggda automatiseringar", + "sections": { + "automations_passive_mode": { + "name": "Passivt läge", + "description": "Aktivera passiv TRV-funktion. Varje rum måste aktiveras för att funktionen ska fungera.", + "data": { + "automations_passive_mode": "Passivt läge", + "passive_mode_temperature_increments": "Temperatursteg för passivt läge" + } + }, + "hotwater_climate": { + "name": "Klimatstyrning av varmvatten", + "description": "Aktivera klimatstyrning av varmvatten. Se wikin för mer information.", + "data": { + "hotwater_climate": "Aktivera klimatentiteten", + "experimental_mode": "Aktivera experimentellt driftläge", + "hotwater_auto_mode": "Automatiskt varmvattenläge", + "hotwater_heat_mode": "Varmvattenvärmeläge", + "hotwater_boost_mode": "Varmvattenboostläge", + "hotwater_sensor_entity_id": "Varmvattentemperatursensor" + } + } + } + }, + "equipment_sensors": { + "title": "Utrustningssensorer", + "description": "Konfigurera entiteter med detaljerade utrustningsdata för kompatibla enheter.", + "data": { + "equipment_sensors": "Aktivera sensorer för utrustningsdata" + }, + "data_description": { + "equipment_sensors": "Visa en extra sensor med detaljerade utrustningsattribut för varje kompatibelt smartuttag, PowerTag och värmeställdon." + } + }, + "opentherm_sensors": { + "title": "OpenTherm-sensorer", + "description": "Välj en kategori med identifierade OpenTherm-attribut.", + "menu_options": { + "opentherm_readings": "Avläsningar", + "opentherm_central_heating": "Centralvärme", + "opentherm_hot_water": "Varmvatten", + "opentherm_status": "Status och diagnostik" + } + }, + "opentherm_readings": { + "title": "OpenTherm-avläsningar", + "description": "Välj vilka identifierade OpenTherm-avläsningar som ska visas som sensorentiteter.", + "data": { + "ch_flow_temperature": "Pannans framledningstemperatur", + "ch_pressure_bar": "Centralvärmetryck", + "ch_return_temperature": "Pannans returtemperatur", + "delta_t": "Delta-T", + "boiler_exhaust_temperature": "Pannans avgastemperatur", + "estimated_boiler_output": "Beräknad panneffekt", + "hw_flow_rate": "Varmvattenflöde", + "hw_temperature": "Varmvattentemperatur", + "maximum_capacity_kw": "Maximal pannkapacitet", + "minimum_modulation_level": "Lägsta modulationsnivå", + "relative_modulation_level": "Relativ modulationsnivå", + "room_temperature": "Rumstemperatur" + } + }, + "opentherm_central_heating": { + "title": "OpenTherm-centralvärme", + "description": "Välj vilka identifierade centralvärmeattribut som ska visas som entiteter.", + "data": { + "boiler_ch_max_setpoint_read_write": "Läsning/skrivning av pannans maximala centralvärmebörvärde", + "boiler_ch_max_setpoint_transfer_enable": "Överföring av pannans maximala centralvärmebörvärde aktiverad", + "boiler_ch_setpoint": "Pannans centralvärmebörvärde", + "boiler_ch_setpoint_lower_bound": "Nedre gräns för pannans centralvärmebörvärde", + "boiler_ch_setpoint_upper_bound": "Övre gräns för pannans centralvärmebörvärde", + "ch_flow_active_lower_setpoint": "Aktivt nedre börvärde för centralvärmeframledning", + "ch_flow_active_upper_setpoint": "Aktivt övre börvärde för centralvärmeframledning", + "ch1_flow_enabled": "Centralvärmekrets 1 framledning aktiverad", + "ch1_flow_setpoint": "Börvärde för centralvärmekrets 1 framledning", + "ch2_flow_enabled": "Centralvärmekrets 2 framledning aktiverad", + "ch2_flow_setpoint": "Börvärde för centralvärmekrets 2 framledning", + "room_setpoint": "Rumsbörvärde" + } + }, + "opentherm_hot_water": { + "title": "OpenTherm-varmvatten", + "description": "Välj vilka identifierade varmvattenattribut som ska visas som entiteter.", + "data": { + "boiler_hw_setpoint": "Pannans varmvattenbörvärde", + "boiler_hw_setpoint_lower_bound": "Nedre gräns för pannans varmvattenbörvärde", + "boiler_hw_setpoint_read_write": "Läsning/skrivning av pannans varmvattenbörvärde", + "boiler_hw_setpoint_transfer_enable": "Överföring av pannans varmvattenbörvärde aktiverad", + "boiler_hw_setpoint_upper_bound": "Övre gräns för pannans varmvattenbörvärde", + "hw_enabled": "Varmvatten aktiverat", + "hw_flow_setpoint": "Börvärde för varmvattenframledning" + } + }, + "opentherm_status": { + "title": "OpenTherm-status och diagnostik", + "description": "Välj vilka identifierade status- och diagnostikattribut som ska visas som sensorentiteter.", + "data": { + "boiler_fault": "Pannfel", + "central_heating_active": "Centralvärme aktiv", + "central_heating_2_active": "Centralvärme 2 aktiv", + "connection_status": "Anslutningsstatus", + "coprocessor_update_status": "Uppdateringsstatus för OpenTherm-hjälpprocessor", + "coprocessor_version": "Version av OpenTherm-hjälpprocessor", + "cooling_active": "Kylning aktiv", + "diagnostic_event": "Diagnostikhändelse", + "flame_active": "Låga aktiv", + "flame_statistics": "Lågstatistik", + "hot_water_active": "Varmvatten aktivt", + "operating_mode": "Driftläge", + "slave_status": "OpenTherm-slavstatus", + "tracked_room_id": "ID för övervakat rum" + } + } + }, + "abort": { + "opentherm_not_available": "OpenTherm-data är inte tillgängliga för denna Wiser-hubb.", + "equipment_not_available": "Utrustningsdata är inte tillgängliga för denna Wiser-hubb." + } + }, + "services": { + "set_opentherm_parameter": { + "name": "Ställ in OpenTherm-parameter", + "description": "Ändrar en OpenTherm-temperaturparameter som stöds på Wiser-hubben.", + "fields": { + "parameter": { + "name": "Parameter", + "description": "OpenTherm-temperaturparametern som ska ändras. Nödvändig API-slutpunkt väljs automatiskt." + }, + "temperature": { + "name": "Temperatur", + "description": "Använd en temperatur inom de gränser som rapporteras av pannan." + }, + "hub": { + "name": "Wiser-hubb", + "description": "Välj endast en hubb om du har flera Wiser-hubbar." + } + } + } + }, + "selector": { + "opentherm_parameter": { + "options": { + "chFlowActiveLowerSetpoint": "Aktivt nedre centralvärmebörvärde", + "chFlowActiveUpperSetpoint": "Aktivt övre centralvärmebörvärde", + "dhwFlowSetpoint": "Hubbens börvärde för varmvattenframledning", + "dhwSetpoint": "Pannans varmvattenbörvärde", + "maxChSetpoint": "Pannans maximala centralvärmebörvärde" + } + } + }, + "exceptions": { + "opentherm_temperature_required": { + "message": "Ange en OpenTherm-temperatur." + }, + "opentherm_hub_not_found": { + "message": "Den angivna Wiser-hubben hittades inte." + }, + "opentherm_hub_not_loaded": { + "message": "Den angivna Wiser-hubben är inte inläst." + }, + "opentherm_hub_required": { + "message": "Välj en Wiser-hubb när fler än en hubb är konfigurerad." + }, + "opentherm_not_supported": { + "message": "Den här hubben har inte OpenTherm-funktionalitet." + }, + "opentherm_invalid_parameter": { + "message": "OpenTherm-parametern eller värdet är ogiltigt: {error}" + }, + "opentherm_write_failed": { + "message": "Det gick inte att ställa in OpenTherm-parametern {parameter}: {error}" + }, + "opentherm_confirmation_failed": { + "message": "OpenTherm-parametern {parameter} låg inte kvar på {requested} °C efter ett nytt försök och bekräftelseperioden på {window} sekunder. Wiser rapporterar {reported} °C. Inga fler försök skickas." + }, + "opentherm_retry_failed": { + "message": "OpenTherm-parametern {parameter} låg inte kvar på {requested} °C och ett nytt försök kunde inte skickas: {error}. Wiser rapporterar {reported} °C. Inga fler försök skickas." + }, + "opentherm_notification_title": { + "message": "Wiser OpenTherm-kommando" + } + }, + "entity": { + "climate": { + "heating": { + "name": "Uppvärmning" + }, + "floor_temperature": { + "name": "Golvtemperatur" + } + }, + "number": { + "away_mode_target_temperature": { + "name": "Måltemperatur för bortaläge" + }, + "floor_temperature_offset": { + "name": "Förskjutning av golvtemperatur" + }, + "indoor_discomfort_temperature": { + "name": "Obehagstemperatur inomhus" + }, + "outdoor_discomfort_temperature": { + "name": "Obehagstemperatur utomhus" + } + }, + "select": { + "mode": { + "name": "Läge" + }, + "power_on_behavior": { + "name": "Startbeteende" + }, + "led_indicator": { + "name": "LED-indikator" + } + }, + "button": { + "boost_all_heating": { + "name": "Boosta all uppvärmning" + }, + "cancel_all_heating_overrides": { + "name": "Avbryt alla åsidosättningar av uppvärmning" + }, + "boost_hot_water": { + "name": "Boosta varmvatten" + }, + "cancel_hot_water_overrides": { + "name": "Avbryt alla åsidosättningar av varmvatten" + }, + "toggle_hot_water": { + "name": "Växla varmvatten" + }, + "moment": { + "name": "Moment: {name}" + } + }, + "switch": { + "valve_protection": { + "name": "Ventilskydd" + }, + "eco_mode": { + "name": "Ekoläge" + }, + "away_mode_affects_hot_water": { + "name": "Bortaläge påverkar varmvatten" + }, + "comfort_mode": { + "name": "Komfortläge" + }, + "away_mode": { + "name": "Bortaläge" + }, + "daylight_saving": { + "name": "Sommartid" + }, + "summer_comfort_enabled": { + "name": "Sommarkomfort aktiverad" + }, + "window_detection": { + "name": "Fönsterdetektering" + }, + "include_in_summer_comfort": { + "name": "Inkludera i sommarkomfort" + }, + "device_lock": { + "name": "Enhetslås" + }, + "identify": { + "name": "Identifiera" + }, + "outlet": { + "name": "Eluttag" + }, + "away_mode_turns_off": { + "name": "Bortaläge stänger av" + }, + "away_mode_closes": { + "name": "Bortaläge stänger" + }, + "passive_mode": { + "name": "Passivt läge" + }, + "respect_summer_comfort": { + "name": "Respektera sommarkomfort" + }, + "interacts_with_room_climate": { + "name": "Samverkar med rumsklimatet" + }, + "humidity_interacts_with_room_climate": { + "name": "Luftfuktighet samverkar med rumsklimatet" + }, + "temperature_interacts_with_room_climate": { + "name": "Temperatur samverkar med rumsklimatet" + }, + "illuminance_interacts_with_room_climate": { + "name": "Ljusstyrka samverkar med rumsklimatet" + }, + "sensor_interacts_with_room_climate": { + "name": "{sensor} samverkar med rumsklimatet" + }, + "manual_heat": { + "name": "Manuell uppvärmning" + }, + "hot_water": { + "name": "Varmvatten" + } + }, + "binary_sensor": { + "summer_discomfort_prevention": { + "name": "Förebyggande av sommarobehag" + }, + "summer_comfort_available": { + "name": "Sommarkomfort tillgänglig" + }, + "pcm_device_limit_reached": { + "name": "Gränsen för PCM-enheter har nåtts" + }, + "smoke_alarm": { + "name": "Röklarm" + }, + "heat_alarm": { + "name": "Värmelarm" + }, + "tamper_alarm": { + "name": "Sabotagelarm" + }, + "fault_warning": { + "name": "Felvarning" + }, + "remote_alarm": { + "name": "Fjärrlarm" + }, + "battery_defect": { + "name": "Batterifel" + }, + "controllable": { + "name": "Styrbar" + }, + "pcm_mode": { + "name": "PCM-läge" + }, + "window_detection_active": { + "name": "Fönsterdetektering aktiv" + }, + "is_dimmable": { + "name": "Dimbar" + }, + "is_led_indicator_supported": { + "name": "LED-indikator stöds" + }, + "is_output_mode_supported": { + "name": "Utgångsläge stöds" + }, + "is_power_on_behaviour_supported": { + "name": "Startbeteende stöds" + }, + "is_tilt_supported": { + "name": "Lutning stöds" + }, + "is_open": { + "name": "Öppen" + }, + "is_closed": { + "name": "Stängd" + }, + "active": { + "name": "Aktiv" + }, + "boiler_ch_max_setpoint_read_write": { + "name": "Läsning/skrivning av pannans maximala centralvärmebörvärde" + }, + "boiler_ch_max_setpoint_transfer_enable": { + "name": "Överföring av pannans maximala centralvärmebörvärde aktiverad" + }, + "boiler_fault": { + "name": "Pannfel" + }, + "boiler_hw_setpoint_read_write": { + "name": "Läsning/skrivning av pannans varmvattenbörvärde" + }, + "boiler_hw_setpoint_transfer_enable": { + "name": "Överföring av pannans varmvattenbörvärde aktiverad" + }, + "central_heating_2_active": { + "name": "Centralvärme 2 aktiv" + }, + "central_heating_active": { + "name": "Centralvärme aktiv" + }, + "ch1_flow_enabled": { + "name": "Centralvärmekrets 1 framledning aktiverad" + }, + "ch2_flow_enabled": { + "name": "Centralvärmekrets 2 framledning aktiverad" + }, + "cooling_active": { + "name": "Kylning aktiv" + }, + "diagnostic_event": { + "name": "Diagnostikhändelse" + }, + "flame_active": { + "name": "Låga aktiv" + }, + "hot_water_active": { + "name": "Varmvatten aktivt" + }, + "hw_enabled": { + "name": "Varmvatten aktiverat" + } + }, + "sensor": { + "signal": { + "name": "Signal" + }, + "cloud": { + "name": "Moln" + }, + "heating_operation_mode": { + "name": "Driftläge för uppvärmning" + }, + "heating": { + "name": "Uppvärmning", + "state": { + "off": "Av", + "on": "På" + } + }, + "heating_channel": { + "name": "Värmekanal {channel}", + "state": { + "off": "Av", + "on": "På" + } + }, + "hot_water": { + "name": "Varmvatten", + "state": { + "off": "Av", + "on": "På" + } + }, + "hot_water_operation_mode": { + "name": "Driftläge för varmvatten" + }, + "target_temperature": { + "name": "Måltemperatur" + }, + "floor_temperature": { + "name": "Golvtemperatur" + }, + "boiler_flow_temperature": { + "name": "Pannans framledningstemperatur" + }, + "boiler_return_temperature": { + "name": "Pannans returtemperatur" + }, + "flame_statistics": { + "name": "Lågstatistik" + }, + "boiler_ch_setpoint": { + "name": "Pannans centralvärmebörvärde" + }, + "boiler_ch_setpoint_lower_bound": { + "name": "Nedre gräns för pannans centralvärmebörvärde" + }, + "boiler_ch_setpoint_upper_bound": { + "name": "Övre gräns för pannans centralvärmebörvärde" + }, + "boiler_exhaust_temperature": { + "name": "Pannans avgastemperatur" + }, + "boiler_hw_setpoint": { + "name": "Pannans varmvattenbörvärde" + }, + "boiler_hw_setpoint_lower_bound": { + "name": "Nedre gräns för pannans varmvattenbörvärde" + }, + "boiler_hw_setpoint_upper_bound": { + "name": "Övre gräns för pannans varmvattenbörvärde" + }, + "ch1_flow_setpoint": { + "name": "Börvärde för centralvärmekrets 1 framledning" + }, + "ch2_flow_setpoint": { + "name": "Börvärde för centralvärmekrets 2 framledning" + }, + "ch_flow_active_lower_setpoint": { + "name": "Aktivt nedre börvärde för centralvärmeframledning" + }, + "ch_flow_active_upper_setpoint": { + "name": "Aktivt övre börvärde för centralvärmeframledning" + }, + "ch_pressure_bar": { + "name": "Centralvärmetryck" + }, + "connection_status": { + "name": "Anslutningsstatus" + }, + "coprocessor_update_status": { + "name": "Uppdateringsstatus för OpenTherm-hjälpprocessor" + }, + "coprocessor_version": { + "name": "Version av OpenTherm-hjälpprocessor" + }, + "delta_t": { + "name": "Delta-T" + }, + "estimated_boiler_output": { + "name": "Beräknad panneffekt" + }, + "hw_flow_rate": { + "name": "Varmvattenflöde" + }, + "hw_flow_setpoint": { + "name": "Börvärde för varmvattenframledning" + }, + "hw_temperature": { + "name": "Varmvattentemperatur" + }, + "maximum_capacity_kw": { + "name": "Maximal pannkapacitet" + }, + "minimum_modulation_level": { + "name": "Lägsta modulationsnivå" + }, + "operating_mode": { + "name": "Driftläge" + }, + "relative_modulation_level": { + "name": "Relativ modulationsnivå" + }, + "room_setpoint": { + "name": "Rumsbörvärde" + }, + "room_temperature": { + "name": "Rumstemperatur" + }, + "slave_status": { + "name": "OpenTherm-slavstatus" + }, + "tracked_room_id": { + "name": "ID för övervakat rum" + }, + "heating_demand": { + "name": "Värmebehov" + }, + "heating_demand_channel": { + "name": "Värmebehovskanal {channel}" + }, + "hot_water_demand": { + "name": "Varmvattenbehov" + }, + "total_energy": { + "name": "Total energi" + }, + "energy_delivered": { + "name": "Levererad energi" + }, + "energy_received": { + "name": "Mottagen energi" + }, + "equipment_power": { + "name": "Utrustning" + } + } + }, + "device_automation": { + "trigger_type": { + "started_heating": "{entity_name} börjar värma", + "stopped_heating": "{entity_name} slutar värma", + "boosted": "{entity_name} är boostad", + "target_temperature_increased": "Måltemperaturen för {entity_name} höjdes", + "target_temperature_decreased": "Måltemperaturen för {entity_name} sänktes" + } + } +} + diff --git a/tests/test_entity_naming.py b/tests/test_entity_naming.py index 12a8c935..c72f3911 100644 --- a/tests/test_entity_naming.py +++ b/tests/test_entity_naming.py @@ -384,9 +384,7 @@ def test_custom_integration_translations_use_resolved_text(self) -> None: self.assertEqual( translations["entity"][domain][key]["name"], expected_name ) - for filename in ( - "translations/en.json", - "translations/de.json", - "translations/fr.json", + for translation in sorted( + (COMPONENT_PATH / "translations").glob("*.json") ): - self.assertNotIn("[%key:", (COMPONENT_PATH / filename).read_text()) + self.assertNotIn("[%key:", translation.read_text()) From 5cdcf8d2aa3ca5cf99808f158211e6856a332f21 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Tue, 13 Oct 2026 14:52:34 +0100 Subject: [PATCH 145/154] feat: expose smoke alarm operating states --- custom_components/wiser/binary_sensor.py | 21 ++++++ custom_components/wiser/strings.json | 3 + custom_components/wiser/translations/de.json | 3 + .../wiser/translations/en-GB.json | 3 + custom_components/wiser/translations/en.json | 3 + custom_components/wiser/translations/fr.json | 3 + tests/test_sensor.py | 64 ++++++++++++++++++- 7 files changed, 99 insertions(+), 1 deletion(-) diff --git a/custom_components/wiser/binary_sensor.py b/custom_components/wiser/binary_sensor.py index 122d9079..aed9aa42 100644 --- a/custom_components/wiser/binary_sensor.py +++ b/custom_components/wiser/binary_sensor.py @@ -172,6 +172,9 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie WiserFaultWarning(data, device.id, "Fault Warning"), WiserRemoteAlarm(data, device.id, "Remote Alarm"), WiserBatteryDefect(data, device.id, "Battery Defect"), + WiserACMains(data, device.id, "AC Mains"), + WiserTestMode(data, device.id, "Test Mode"), + WiserHushMode(data, device.id, "Hush Mode"), ] ) @@ -536,6 +539,24 @@ class WiserRemoteAlarm(BaseBinarySensor): """Smoke Alarm sensor.""" +class WiserACMains(BaseBinarySensor): + """Smoke alarm mains-power status sensor.""" + + _attr_device_class = BinarySensorDeviceClass.POWER + + +class WiserTestMode(BaseBinarySensor): + """Smoke alarm test-mode status sensor.""" + + _attr_icon = "mdi:test-tube" + + +class WiserHushMode(BaseBinarySensor): + """Smoke alarm hush-mode status sensor.""" + + _attr_icon = "mdi:volume-off" + + class WiserEquipment(BaseBinarySensor): """Binary sensor backed by optional equipment data.""" diff --git a/custom_components/wiser/strings.json b/custom_components/wiser/strings.json index 63bdb70d..a3a6bf71 100755 --- a/custom_components/wiser/strings.json +++ b/custom_components/wiser/strings.json @@ -298,6 +298,9 @@ "fault_warning": { "name": "Fault warning" }, "remote_alarm": { "name": "Remote alarm" }, "battery_defect": { "name": "Battery defect" }, + "ac_mains": { "name": "AC mains" }, + "test_mode": { "name": "Test mode" }, + "hush_mode": { "name": "Hush mode" }, "controllable": { "name": "Controllable" }, "pcm_mode": { "name": "PCM mode" }, "window_detection_active": { "name": "Window detection active" }, diff --git a/custom_components/wiser/translations/de.json b/custom_components/wiser/translations/de.json index b588177e..9f0240e1 100644 --- a/custom_components/wiser/translations/de.json +++ b/custom_components/wiser/translations/de.json @@ -296,6 +296,9 @@ "fault_warning": { "name": "Fehlerwarnung" }, "remote_alarm": { "name": "Fernalarm" }, "battery_defect": { "name": "Batteriedefekt" }, + "ac_mains": { "name": "Netzstrom" }, + "test_mode": { "name": "Testmodus" }, + "hush_mode": { "name": "Stummschaltungsmodus" }, "controllable": { "name": "Steuerbar" }, "pcm_mode": { "name": "PCM-Modus" }, "window_detection_active": { "name": "Fenstererkennung aktiv" }, diff --git a/custom_components/wiser/translations/en-GB.json b/custom_components/wiser/translations/en-GB.json index 3d798b57..1a01af67 100644 --- a/custom_components/wiser/translations/en-GB.json +++ b/custom_components/wiser/translations/en-GB.json @@ -296,6 +296,9 @@ "fault_warning": { "name": "Fault warning" }, "remote_alarm": { "name": "Remote alarm" }, "battery_defect": { "name": "Battery defect" }, + "ac_mains": { "name": "AC mains" }, + "test_mode": { "name": "Test mode" }, + "hush_mode": { "name": "Hush mode" }, "controllable": { "name": "Controllable" }, "pcm_mode": { "name": "PCM mode" }, "window_detection_active": { "name": "Window detection active" }, diff --git a/custom_components/wiser/translations/en.json b/custom_components/wiser/translations/en.json index 44a9f3a3..4cda820b 100755 --- a/custom_components/wiser/translations/en.json +++ b/custom_components/wiser/translations/en.json @@ -296,6 +296,9 @@ "fault_warning": { "name": "Fault warning" }, "remote_alarm": { "name": "Remote alarm" }, "battery_defect": { "name": "Battery defect" }, + "ac_mains": { "name": "AC mains" }, + "test_mode": { "name": "Test mode" }, + "hush_mode": { "name": "Hush mode" }, "controllable": { "name": "Controllable" }, "pcm_mode": { "name": "PCM mode" }, "window_detection_active": { "name": "Window detection active" }, diff --git a/custom_components/wiser/translations/fr.json b/custom_components/wiser/translations/fr.json index ac62d7e0..898ef989 100644 --- a/custom_components/wiser/translations/fr.json +++ b/custom_components/wiser/translations/fr.json @@ -296,6 +296,9 @@ "fault_warning": { "name": "Avertissement de défaut" }, "remote_alarm": { "name": "Alarme distante" }, "battery_defect": { "name": "Défaut de batterie" }, + "ac_mains": { "name": "Alimentation secteur" }, + "test_mode": { "name": "Mode test" }, + "hush_mode": { "name": "Mode silencieux" }, "controllable": { "name": "Contrôlable" }, "pcm_mode": { "name": "Mode PCM" }, "window_detection_active": { "name": "Détection de fenêtre active" }, diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 6951f418..b1994509 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -313,7 +313,13 @@ class BinarySensorEntity: assert spec and spec.loader module = importlib.util.module_from_spec(spec) sys.modules[spec.name] = module - spec.loader.exec_module(module) + # The classes exercised here precede WiserStateActive, whose structural + # pattern matching requires a newer Python than the lightweight local test + # runtime. Home Assistant itself runs a supported newer Python version. + source = BINARY_SENSOR_SOURCE_PATH.read_text(encoding="utf-8").split( + "class WiserStateActive", 1 + )[0] + exec(compile(source, BINARY_SENSOR_SOURCE_PATH, "exec"), module.__dict__) return module @@ -1429,6 +1435,62 @@ def test_capability_flag_is_a_diagnostic_entity(self): self.assertEqual(sensor._attr_entity_category, "diagnostic") +class WiserSmokeAlarmStatusSensorTest(unittest.TestCase): + """Tests for smoke-alarm status fields exposed by the API.""" + + @classmethod + def setUpClass(cls): + cls.binary_sensor_module = _load_binary_sensor_module() + + def setUp(self): + self.device = SimpleNamespace( + ac_mains=True, + test_mode=False, + hush_mode=True, + product_type="SmokeAlarmDevice", + firmware_version="1.0", + ) + self.data = SimpleNamespace( + last_update_success=True, + wiserhub=SimpleNamespace( + devices=SimpleNamespace(get_by_id=lambda _device_id: self.device), + rooms=SimpleNamespace(get_by_device_id=lambda _device_id: None), + system=SimpleNamespace(name="WiserHeat123456"), + ), + ) + + def test_reads_ac_mains_state(self): + sensor = self.binary_sensor_module.WiserACMains( + self.data, 7, "AC Mains" + ) + sensor.async_write_ha_state = Mock() + + self.assertTrue(sensor.is_on) + self.assertEqual(sensor._attr_device_class, "power") + + self.device.ac_mains = False + sensor._handle_coordinator_update() + + self.assertFalse(sensor.is_on) + sensor.async_write_ha_state.assert_called_once_with() + + def test_reads_test_mode_state(self): + sensor = self.binary_sensor_module.WiserTestMode( + self.data, 7, "Test Mode" + ) + + self.assertFalse(sensor.is_on) + self.assertEqual(sensor._attr_icon, "mdi:test-tube") + + def test_reads_hush_mode_state(self): + sensor = self.binary_sensor_module.WiserHushMode( + self.data, 7, "Hush Mode" + ) + + self.assertTrue(sensor.is_on) + self.assertEqual(sensor._attr_icon, "mdi:volume-off") + + class WiserEquipmentBinarySensorTest(unittest.TestCase): """Tests for binary sensors backed by optional equipment data.""" From 82256b3ada9291c10b47289b5b5718d69d711136 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 15 Oct 2026 14:23:09 +0100 Subject: [PATCH 146/154] feat: expose smoke alarm report count --- custom_components/wiser/sensor.py | 68 ++++++++++++++++--- custom_components/wiser/strings.json | 1 + custom_components/wiser/translations/de.json | 1 + .../wiser/translations/en-GB.json | 1 + custom_components/wiser/translations/en.json | 1 + custom_components/wiser/translations/fr.json | 1 + tests/test_sensor.py | 19 ++++++ 7 files changed, 84 insertions(+), 8 deletions(-) diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index 0cc8247d..81742248 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -401,15 +401,18 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie if room.roomstat_id: wiser_sensors.append(WiserLTSHumiditySensor(data, room.roomstat_id)) - # Add temp sensors for smoke alarms - wiser_sensors.extend( - WiserLTSTempSensor( - data, - device.id, - sensor_type="smokealarm_temp", + # Add smoke-alarm sensors + for device in data.wiserhub.devices.smokealarms.all: + wiser_sensors.extend( + [ + WiserLTSTempSensor( + data, + device.id, + sensor_type="smokealarm_temp", + ), + WiserSmokeAlarmReportCountSensor(data, device.id), + ] ) - for device in data.wiserhub.devices.smokealarms.all - ) # Add temp sensors for ITRVs _LOGGER.debug("Setting up smartvalve remperature sensors") @@ -630,6 +633,55 @@ def device_info(self): } +class WiserSmokeAlarmReportCountSensor(WiserSensor): + """Diagnostic count of reports received from a smoke alarm.""" + + _attr_entity_category = EntityCategory.DIAGNOSTIC + _attr_icon = "mdi:counter" + + def __init__(self, data, device_id=0) -> None: + """Initialize the report-count sensor.""" + super().__init__( + data, + device_id, + "report_count", + translation_key="report_count", + ) + self._device = self._data.wiserhub.devices.get_by_id(self._device_id) + self._state = self._device.report_count + + @callback + def _handle_coordinator_update(self) -> None: + """Refresh the report count.""" + super()._handle_coordinator_update() + self._device = self._data.wiserhub.devices.get_by_id(self._device_id) + self._state = self._device.report_count + self.async_write_ha_state() + + @property + def unique_id(self): + """Return a name-independent unique ID.""" + return get_physical_entity_unique_id( + self._data, + "sensor", + self._device_id, + "report_count", + ) + + @property + def device_info(self): + """Attach the entity to its physical smoke-alarm device.""" + return { + "name": get_device_name(self._data, self._device_id), + "identifiers": {(DOMAIN, get_identifier(self._data, self._device_id))}, + "manufacturer": MANUFACTURER, + "model": self._device.product_type, + "sw_version": self._device.firmware_version, + **get_device_area_info(self._data, self._device_id), + **get_hub_via_device_info(self._data), + } + + class WiserDeviceSignalSensor(WiserSensor): """Definition of Wiser Device Sensor.""" diff --git a/custom_components/wiser/strings.json b/custom_components/wiser/strings.json index a3a6bf71..90e70b75 100755 --- a/custom_components/wiser/strings.json +++ b/custom_components/wiser/strings.json @@ -329,6 +329,7 @@ }, "sensor": { "signal": { "name": "Signal" }, + "report_count": { "name": "Report count" }, "cloud": { "name": "Cloud" }, "heating_operation_mode": { "name": "Heating operation mode" }, "heating": { diff --git a/custom_components/wiser/translations/de.json b/custom_components/wiser/translations/de.json index 9f0240e1..7457c0a1 100644 --- a/custom_components/wiser/translations/de.json +++ b/custom_components/wiser/translations/de.json @@ -327,6 +327,7 @@ }, "sensor": { "signal": { "name": "Signal" }, + "report_count": { "name": "Berichtsanzahl" }, "cloud": { "name": "Cloud" }, "heating_operation_mode": { "name": "Heizungsbetriebsart" }, "heating": { diff --git a/custom_components/wiser/translations/en-GB.json b/custom_components/wiser/translations/en-GB.json index 1a01af67..9419f80e 100644 --- a/custom_components/wiser/translations/en-GB.json +++ b/custom_components/wiser/translations/en-GB.json @@ -327,6 +327,7 @@ }, "sensor": { "signal": { "name": "Signal" }, + "report_count": { "name": "Report count" }, "cloud": { "name": "Cloud" }, "heating_operation_mode": { "name": "Heating operation mode" }, "heating": { diff --git a/custom_components/wiser/translations/en.json b/custom_components/wiser/translations/en.json index 4cda820b..4d877e40 100755 --- a/custom_components/wiser/translations/en.json +++ b/custom_components/wiser/translations/en.json @@ -327,6 +327,7 @@ }, "sensor": { "signal": { "name": "Signal" }, + "report_count": { "name": "Report count" }, "cloud": { "name": "Cloud" }, "heating_operation_mode": { "name": "Heating operation mode" }, "heating": { diff --git a/custom_components/wiser/translations/fr.json b/custom_components/wiser/translations/fr.json index 898ef989..91dad6df 100644 --- a/custom_components/wiser/translations/fr.json +++ b/custom_components/wiser/translations/fr.json @@ -327,6 +327,7 @@ }, "sensor": { "signal": { "name": "Signal" }, + "report_count": { "name": "Nombre de rapports" }, "cloud": { "name": "Cloud" }, "heating_operation_mode": { "name": "Mode de fonctionnement du chauffage" }, "heating": { diff --git a/tests/test_sensor.py b/tests/test_sensor.py index b1994509..8c3dc4ac 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -1441,12 +1441,14 @@ class WiserSmokeAlarmStatusSensorTest(unittest.TestCase): @classmethod def setUpClass(cls): cls.binary_sensor_module = _load_binary_sensor_module() + cls.sensor_module = _load_sensor_module() def setUp(self): self.device = SimpleNamespace( ac_mains=True, test_mode=False, hush_mode=True, + report_count=42, product_type="SmokeAlarmDevice", firmware_version="1.0", ) @@ -1490,6 +1492,23 @@ def test_reads_hush_mode_state(self): self.assertTrue(sensor.is_on) self.assertEqual(sensor._attr_icon, "mdi:volume-off") + def test_reads_report_count_and_refreshes(self): + sensor = self.sensor_module.WiserSmokeAlarmReportCountSensor( + self.data, 7 + ) + sensor.async_write_ha_state = Mock() + + self.assertEqual(sensor.native_value, 42) + self.assertEqual(sensor._attr_entity_category, "diagnostic") + self.assertEqual(sensor._attr_icon, "mdi:counter") + self.assertEqual(sensor.unique_id, "physical-sensor-7-report_count") + + self.device.report_count = 43 + sensor._handle_coordinator_update() + + self.assertEqual(sensor.native_value, 43) + sensor.async_write_ha_state.assert_called_once_with() + class WiserEquipmentBinarySensorTest(unittest.TestCase): """Tests for binary sensors backed by optional equipment data.""" From a9fbf108e5a7ee5938c1958a3bbdddb4e0c6f833 Mon Sep 17 00:00:00 2001 From: Andrew Blackburn Date: Thu, 15 Oct 2026 17:26:11 +0100 Subject: [PATCH 147/154] feat: add scheduled setpoint sensors for rooms --- custom_components/wiser/climate.py | 3 +- custom_components/wiser/config_flow.py | 51 +++++++++++- custom_components/wiser/const.py | 2 + custom_components/wiser/helpers.py | 5 ++ custom_components/wiser/sensor.py | 78 +++++++++++++++++++ custom_components/wiser/strings.json | 11 +++ custom_components/wiser/translations/de.json | 11 +++ .../wiser/translations/en-GB.json | 11 +++ custom_components/wiser/translations/en.json | 11 +++ custom_components/wiser/translations/fr.json | 11 +++ tests/test_room_migration_orchestration.py | 2 +- tests/test_sensor.py | 68 ++++++++++++++++ tests/test_ui_options.py | 70 +++++++++++++++++ 13 files changed, 330 insertions(+), 4 deletions(-) diff --git a/custom_components/wiser/climate.py b/custom_components/wiser/climate.py index 3c347151..3799d00f 100755 --- a/custom_components/wiser/climate.py +++ b/custom_components/wiser/climate.py @@ -57,6 +57,7 @@ get_room_entity_unique_id, get_uuid_unique_id, hub_error_handler, + room_has_climate, ) from .schedules import WiserScheduleEntity from .temperature import room_target_temperature @@ -142,7 +143,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie wiser_rooms = [ WiserRoom(hass, coordinator, room.id) for room in coordinator.wiserhub.rooms.all - if len(room.devices) > 0 + if room_has_climate(room) ] async_add_entities(wiser_rooms, True) diff --git a/custom_components/wiser/config_flow.py b/custom_components/wiser/config_flow.py index c7bb2a95..668bd3cb 100755 --- a/custom_components/wiser/config_flow.py +++ b/custom_components/wiser/config_flow.py @@ -42,6 +42,7 @@ from homeassistant.helpers.service_info.zeroconf import ZeroconfServiceInfo from .const import ( + CONF_ADDITIONAL_SENSORS, CONF_AUTOMATIONS_HW_AUTO_MODE, CONF_AUTOMATIONS_HW_BOOST_MODE, CONF_AUTOMATIONS_HW_CLIMATE, @@ -50,6 +51,7 @@ CONF_AUTOMATIONS_HW_SENSOR_ENTITY_ID, CONF_AUTOMATIONS_PASSIVE, CONF_AUTOMATIONS_PASSIVE_TEMP_INCREMENT, + CONF_SCHEDULE_SETPOINT_ROOMS, CONF_EQUIPMENT_SENSORS, CONF_HEATING_BOOST_TEMP, CONF_HEATING_BOOST_TIME, @@ -91,6 +93,7 @@ opentherm_hot_water_limits, opentherm_is_detected, ) +from .helpers import room_has_climate _LOGGER = logging.getLogger(__name__) @@ -395,9 +398,24 @@ def all_devices(collection_name): for device in all_devices(collection_name) ) + def _rooms_without_climate(self): + """Return loaded Wiser rooms that do not create climate entities.""" + entry_data = self.hass.data.get(DOMAIN, {}).get(self.config_entry.entry_id) + if not entry_data: + return [] + return [ + room + for room in entry_data[DATA].wiserhub.rooms.all + if not room_has_climate(room) + ] + async def async_step_init(self, user_input=None): """Handle options flow.""" - menu_options = ["main_params", "automation_params", "ui_options"] + menu_options = [ + "main_params", + "automation_params", + "ui_options", + ] if self._opentherm() is not None: menu_options.append("opentherm") if self._equipment_available() or self.config_entry.options.get( @@ -736,6 +754,9 @@ async def async_step_automation_params(self, user_input=None): return self.async_create_entry(data=options) options = self.config_entry.options + additional_sensor_options = options.get(CONF_ADDITIONAL_SENSORS, {}) + if not isinstance(additional_sensor_options, dict): + additional_sensor_options = {} data_schema = { vol.Required(CONF_AUTOMATIONS_PASSIVE): section( @@ -841,12 +862,38 @@ async def async_step_automation_params(self, user_input=None): ), {"collapsed": True}, ), + vol.Required(CONF_ADDITIONAL_SENSORS): section( + vol.Schema( + { + vol.Optional( + CONF_SCHEDULE_SETPOINT_ROOMS, + default=[ + str(room_id) + for room_id in additional_sensor_options.get( + CONF_SCHEDULE_SETPOINT_ROOMS, [] + ) + ], + ): selector( + { + "select": { + "options": [ + {"value": str(room.id), "label": room.name} + for room in self._rooms_without_climate() + ], + "multiple": True, + "mode": SelectSelectorMode.DROPDOWN, + } + } + ), + } + ), + {"collapsed": True}, + ), } return self.async_show_form( step_id="automation_params", data_schema=vol.Schema(data_schema) ) - class CannotConnect(exceptions.HomeAssistantError): """Error to indicate we cannot connect.""" diff --git a/custom_components/wiser/const.py b/custom_components/wiser/const.py index f579d7c2..92fbf617 100755 --- a/custom_components/wiser/const.py +++ b/custom_components/wiser/const.py @@ -89,6 +89,7 @@ class HWCycleModes(StrEnum): SETPOINT_MODE_BOOST_AUTO = "boost auto mode only" # Custom Configs +CONF_ADDITIONAL_SENSORS = "additional_sensors" CONF_AUTOMATIONS_PASSIVE = "automations_passive_mode" CONF_AUTOMATIONS_PASSIVE_TEMP_INCREMENT = "passive_mode_temperature_increments" CONF_HEATING_BOOST_TEMP = "heating_boost_temp" @@ -121,6 +122,7 @@ class HWCycleModes(StrEnum): DEFAULT_OPENTHERM_HOT_WATER_PRESET_TEMP = 55.0 MAX_OPENTHERM_HOT_WATER_PRESETS = 10 OPENTHERM_HOT_WATER_DEFAULT_BOOSTS = (15, 30, 45) +CONF_SCHEDULE_SETPOINT_ROOMS = "schedule_setpoint_rooms" # Custom Attributes ATTR_OPENTHERM_ENDPOINT = "endpoint" diff --git a/custom_components/wiser/helpers.py b/custom_components/wiser/helpers.py index 29a759cc..8707e171 100644 --- a/custom_components/wiser/helpers.py +++ b/custom_components/wiser/helpers.py @@ -39,6 +39,11 @@ def active_wiser_rooms(data): ] +def room_has_climate(room): + """Return whether the integration creates a climate entity for a room.""" + return bool(room.devices) + + def get_hub_mac_suffix(data): """Return the last three octets of the physical hub MAC address.""" mac_address = data.wiserhub.system.network.mac_address diff --git a/custom_components/wiser/sensor.py b/custom_components/wiser/sensor.py index 81742248..e66ef12d 100755 --- a/custom_components/wiser/sensor.py +++ b/custom_components/wiser/sensor.py @@ -42,6 +42,8 @@ from aioWiserHeatAPI.wiserhub import TEMP_MINIMUM, TEMP_OFF from .const import ( + CONF_ADDITIONAL_SENSORS, + CONF_SCHEDULE_SETPOINT_ROOMS, CONF_EQUIPMENT_SENSORS, CONF_OPENTHERM_SENSORS, DATA, @@ -62,6 +64,7 @@ get_identifier, get_room_entity_unique_id, get_unique_id, + room_has_climate, ) from .opentherm import ( OPENTHERM_BINARY_SENSOR_KEYS, @@ -117,6 +120,16 @@ } +def _selected_room_scheduled_setpoint_sensors(data, selected_room_ids): + """Create scheduled setpoint sensors for selected rooms without climate.""" + selected_room_ids = {str(room_id) for room_id in selected_room_ids or ()} + return [ + WiserRoomScheduledSetpointSensor(data, room.id) + for room in data.wiserhub.rooms.all + if str(room.id) in selected_room_ids and not room_has_climate(room) + ] + + async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entities): """Initialize the entry.""" data = hass.data[DOMAIN][config_entry.entry_id][DATA] # Get Handler @@ -124,6 +137,14 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie equipment_sensors_enabled = config_entry.options.get( CONF_EQUIPMENT_SENSORS, False ) + additional_sensor_options = config_entry.options.get( + CONF_ADDITIONAL_SENSORS, {} + ) + if not isinstance(additional_sensor_options, dict): + additional_sensor_options = {} + schedule_setpoint_rooms = additional_sensor_options.get( + CONF_SCHEDULE_SETPOINT_ROOMS, [] + ) # Add signal sensors for all devices _LOGGER.debug("Setting up Device sensors") @@ -401,6 +422,10 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie if room.roomstat_id: wiser_sensors.append(WiserLTSHumiditySensor(data, room.roomstat_id)) + wiser_sensors.extend( + _selected_room_scheduled_setpoint_sensors(data, schedule_setpoint_rooms) + ) + # Add smoke-alarm sensors for device in data.wiserhub.devices.smokealarms.all: wiser_sensors.extend( @@ -1248,6 +1273,59 @@ def native_unit_of_measurement(self) -> str: return UnitOfEnergy.KILO_WATT_HOUR +class WiserRoomScheduledSetpointSensor(WiserSensor): + """Scheduled setpoint reported for a Wiser room without climate control.""" + + _attr_device_class = SensorDeviceClass.TEMPERATURE + _attr_state_class = SensorStateClass.MEASUREMENT + _attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS + _attr_translation_key = "current_schedule_temperature" + + def __init__(self, data, room_id: int) -> None: + """Initialize the scheduled setpoint sensor.""" + super().__init__( + data, + room_id, + "Current Schedule Temperature", + translation_key="current_schedule_temperature", + ) + self._update_state() + + def _update_state(self) -> None: + """Read the current ScheduledSetPoint value from the room.""" + room = self._data.wiserhub.rooms.get_by_id(self._device_id) + self._state = room.scheduled_target_temperature if room else None + + @property + def unique_id(self): + """Return a stable ID when the room is renamed.""" + return get_room_entity_unique_id( + self._data, self._device_id, "current_schedule_temperature" + ) + + @callback + def _handle_coordinator_update(self) -> None: + """Fetch the latest scheduled setpoint.""" + super()._handle_coordinator_update() + self._update_state() + self.async_write_ha_state() + + @property + def device_info(self): + """Attach the entity to its Wiser room device.""" + room = self._data.wiserhub.rooms.get_by_id(self._device_id) + return { + "name": get_device_name(self._data, self._device_id, "room"), + "identifiers": { + (DOMAIN, get_identifier(self._data, self._device_id, "room")) + }, + "manufacturer": MANUFACTURER, + "model": "Room", + "suggested_area": room.name, + **get_hub_via_device_info(self._data), + } + + class WiserLTSTempSensor(WiserSensor): """Sensor for long term stats for room temp and target temp""" diff --git a/custom_components/wiser/strings.json b/custom_components/wiser/strings.json index f5111ece..0cce5abc 100755 --- a/custom_components/wiser/strings.json +++ b/custom_components/wiser/strings.json @@ -94,6 +94,16 @@ "hotwater_boost_mode": "Hot Water Boost Mode", "hotwater_sensor_entity_id": "Hot Water Temperature Sensor" } + }, + "additional_sensors": { + "name": "Additional sensors", + "description": "Expose optional sensors for data reported by Wiser.", + "data": { + "schedule_setpoint_rooms": "Rooms without climate control" + }, + "data_description": { + "schedule_setpoint_rooms": "Select the Wiser rooms where a current schedule temperature sensor should be created." + } } } }, @@ -383,6 +393,7 @@ }, "hot_water_operation_mode": { "name": "Hot water operation mode" }, "target_temperature": { "name": "Target temperature" }, + "current_schedule_temperature": { "name": "Current schedule temperature" }, "floor_temperature": { "name": "Floor temperature" }, "boiler_flow_temperature": { "name": "Boiler flow temperature" }, "boiler_return_temperature": { "name": "Boiler return temperature" }, diff --git a/custom_components/wiser/translations/de.json b/custom_components/wiser/translations/de.json index 9a692514..b5ca7554 100644 --- a/custom_components/wiser/translations/de.json +++ b/custom_components/wiser/translations/de.json @@ -94,6 +94,16 @@ "hotwater_boost_mode": "Warmwasser-Boost-Modus", "hotwater_sensor_entity_id": "Warmwasser-Temperatursensor" } + }, + "additional_sensors": { + "name": "Zusätzliche Sensoren", + "description": "Optionale Sensoren für von Wiser gemeldete Daten bereitstellen.", + "data": { + "schedule_setpoint_rooms": "Räume ohne Klimasteuerung" + }, + "data_description": { + "schedule_setpoint_rooms": "Wählen Sie die Wiser-Räume aus, für die ein Sensor für die aktuelle Zeitplantemperatur erstellt werden soll." + } } } }, @@ -379,6 +389,7 @@ }, "hot_water_operation_mode": { "name": "Warmwasserbetriebsart" }, "target_temperature": { "name": "Zieltemperatur" }, + "current_schedule_temperature": { "name": "Aktuelle Zeitplantemperatur" }, "floor_temperature": { "name": "Fußbodentemperatur" }, "boiler_flow_temperature": { "name": "Kesselvorlauftemperatur" }, "boiler_return_temperature": { "name": "Kesselrücklauftemperatur" }, diff --git a/custom_components/wiser/translations/en-GB.json b/custom_components/wiser/translations/en-GB.json index 0b461649..f3727f58 100644 --- a/custom_components/wiser/translations/en-GB.json +++ b/custom_components/wiser/translations/en-GB.json @@ -94,6 +94,16 @@ "hotwater_boost_mode": "Hot Water Boost Mode", "hotwater_sensor_entity_id": "Hot Water Temperature Sensor" } + }, + "additional_sensors": { + "name": "Additional sensors", + "description": "Expose optional sensors for data reported by Wiser.", + "data": { + "schedule_setpoint_rooms": "Rooms without climate control" + }, + "data_description": { + "schedule_setpoint_rooms": "Select the Wiser rooms where a current schedule temperature sensor should be created." + } } } }, @@ -379,6 +389,7 @@ }, "hot_water_operation_mode": { "name": "Hot water operation mode" }, "target_temperature": { "name": "Target temperature" }, + "current_schedule_temperature": { "name": "Current schedule temperature" }, "floor_temperature": { "name": "Floor temperature" }, "boiler_flow_temperature": { "name": "Boiler flow temperature" }, "boiler_return_temperature": { "name": "Boiler return temperature" }, diff --git a/custom_components/wiser/translations/en.json b/custom_components/wiser/translations/en.json index 72c6156f..17d93c41 100755 --- a/custom_components/wiser/translations/en.json +++ b/custom_components/wiser/translations/en.json @@ -94,6 +94,16 @@ "hotwater_boost_mode": "Hot Water Boost Mode", "hotwater_sensor_entity_id": "Hot Water Temperature Sensor" } + }, + "additional_sensors": { + "name": "Additional sensors", + "description": "Expose optional sensors for data reported by Wiser.", + "data": { + "schedule_setpoint_rooms": "Rooms without climate control" + }, + "data_description": { + "schedule_setpoint_rooms": "Select the Wiser rooms where a current schedule temperature sensor should be created." + } } } }, @@ -379,6 +389,7 @@ }, "hot_water_operation_mode": { "name": "Hot water operation mode" }, "target_temperature": { "name": "Target temperature" }, + "current_schedule_temperature": { "name": "Current schedule temperature" }, "floor_temperature": { "name": "Floor temperature" }, "boiler_flow_temperature": { "name": "Boiler flow temperature" }, "boiler_return_temperature": { "name": "Boiler return temperature" }, diff --git a/custom_components/wiser/translations/fr.json b/custom_components/wiser/translations/fr.json index 5a17f3af..818fe24e 100644 --- a/custom_components/wiser/translations/fr.json +++ b/custom_components/wiser/translations/fr.json @@ -94,6 +94,16 @@ "hotwater_boost_mode": "Mode boost de l’eau chaude", "hotwater_sensor_entity_id": "Capteur de température de l’eau chaude" } + }, + "additional_sensors": { + "name": "Capteurs supplémentaires", + "description": "Exposer des capteurs facultatifs pour les données communiquées par Wiser.", + "data": { + "schedule_setpoint_rooms": "Pièces sans contrôle climatique" + }, + "data_description": { + "schedule_setpoint_rooms": "Sélectionnez les pièces Wiser pour lesquelles un capteur de température programmée actuelle doit être créé." + } } } }, @@ -379,6 +389,7 @@ }, "hot_water_operation_mode": { "name": "Mode de fonctionnement de l’eau chaude" }, "target_temperature": { "name": "Température cible" }, + "current_schedule_temperature": { "name": "Température programmée actuelle" }, "floor_temperature": { "name": "Température du sol" }, "boiler_flow_temperature": { "name": "Température de départ de la chaudière" }, "boiler_return_temperature": { "name": "Température de retour de la chaudière" }, diff --git a/tests/test_room_migration_orchestration.py b/tests/test_room_migration_orchestration.py index 44be180d..d665efb4 100644 --- a/tests/test_room_migration_orchestration.py +++ b/tests/test_room_migration_orchestration.py @@ -182,7 +182,7 @@ def setUpClass(cls) -> None: cls.wiser = _load_wiser_init() def setUp(self) -> None: - self.entry = SimpleNamespace(entry_id="entry-id") + self.entry = SimpleNamespace(entry_id="entry-id", options={}) self.room = SimpleNamespace(id=7, name="Lounge") self.coordinator = SimpleNamespace( wiserhub=SimpleNamespace( diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 8c3dc4ac..5493b0d2 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -92,6 +92,8 @@ def available(self): _module( "wiser.const", DATA="data", + CONF_ADDITIONAL_SENSORS="additional_sensors", + CONF_SCHEDULE_SETPOINT_ROOMS="schedule_setpoint_rooms", CONF_EQUIPMENT_SENSORS="equipment_sensors", CONF_OPENTHERM_SENSORS="opentherm_sensors", DOMAIN="wiser", @@ -123,6 +125,7 @@ def available(self): get_room_entity_unique_id=lambda *_args: "room-entity-id", get_unique_id=lambda *_args: "unique-id", get_uuid_unique_id=lambda unique_id: f"uuid-{unique_id}", + room_has_climate=lambda room: bool(room.devices), ) class WiserEntityMixin: pass @@ -613,6 +616,71 @@ def test_missing_property_sets_unknown_state(self) -> None: self.sensor.async_write_ha_state.assert_called_once_with() +class WiserRoomScheduledSetpointSensorTest(unittest.TestCase): + @classmethod + def setUpClass(cls) -> None: + cls.sensor_module = _load_sensor_module() + + @staticmethod + def _data(rooms): + rooms_by_id = {room.id: room for room in rooms} + return SimpleNamespace( + wiserhub=SimpleNamespace( + rooms=SimpleNamespace( + all=rooms, + get_by_id=rooms_by_id.get, + get_by_device_id=lambda _device_id: None, + ), + system=SimpleNamespace(name="WiserHeat123456"), + ) + ) + + def test_sensor_reports_room_scheduled_setpoint(self) -> None: + room = SimpleNamespace( + id=4, + name="Kitchen", + devices=[], + scheduled_target_temperature=19.5, + ) + sensor = self.sensor_module.WiserRoomScheduledSetpointSensor( + self._data([room]), room.id + ) + + self.assertEqual(sensor.native_value, 19.5) + self.assertEqual( + sensor._attr_translation_key, "current_schedule_temperature" + ) + self.assertEqual(sensor.unique_id, "room-entity-id") + self.assertEqual(sensor.device_info["manufacturer"], "Drayton") + self.assertEqual(sensor.device_info["model"], "Room") + self.assertEqual(sensor.device_info["suggested_area"], "Kitchen") + + def test_only_selected_rooms_without_climate_get_sensors(self) -> None: + empty = SimpleNamespace( + id=4, + name="Kitchen", + devices=[], + scheduled_target_temperature=19.5, + ) + occupied = SimpleNamespace( + id=5, + name="Lounge", + devices=[SimpleNamespace(id=10)], + scheduled_target_temperature=21, + ) + data = self._data([empty, occupied]) + + self.assertEqual( + self.sensor_module._selected_room_scheduled_setpoint_sensors(data, []), + [], + ) + sensors = self.sensor_module._selected_room_scheduled_setpoint_sensors( + data, [str(empty.id), str(occupied.id)] + ) + self.assertEqual(len(sensors), 1) + self.assertEqual(sensors[0]._device_id, empty.id) + + class WiserDeviceSignalSensorNameTest(unittest.TestCase): """Tests for controller and device signal sensor names.""" diff --git a/tests/test_ui_options.py b/tests/test_ui_options.py index fa31c179..f3c58f7f 100644 --- a/tests/test_ui_options.py +++ b/tests/test_ui_options.py @@ -68,8 +68,10 @@ def function_call_lines(filename, function_name): class UIOptionsTest(unittest.IsolatedAsyncioTestCase): def setUp(self): self.namespace = { + "CONF_ADDITIONAL_SENSORS": "additional_sensors", "CONF_LEGACY_NAMING": "legacy_naming", "CONF_EQUIPMENT_SENSORS": "equipment_sensors", + "CONF_SCHEDULE_SETPOINT_ROOMS": "schedule_setpoint_rooms", "CONF_OPENTHERM_EVER_CONNECTED": "opentherm_ever_connected", "CONF_OPENTHERM_HOT_WATER_CAPABLE": "opentherm_hot_water_capable", "CONF_OPENTHERM_HOT_WATER_CONTROL": "opentherm_hot_water_control", @@ -86,6 +88,7 @@ def setUp(self): "validate_input": AsyncMock(return_value={"title": "Wiser", "unique_id": "1"}), "MAJOR_VERSION": 2026, "MINOR_VERSION": 8, + "room_has_climate": lambda room: bool(room.devices), } def test_opentherm_detection_uses_live_or_remembered_connection(self): @@ -474,6 +477,73 @@ async def test_menu_available_without_opentherm(self): self.assertIn("ui_options", result["menu_options"]) self.assertNotIn("opentherm", result["menu_options"]) self.assertNotIn("equipment_sensors", result["menu_options"]) + self.assertNotIn("additional_sensors", result["menu_options"]) + + async def test_additional_sensors_is_section_in_automation_parameters(self): + source = (COMPONENT / "config_flow.py").read_text() + tree = ast.parse(source) + function = next( + node + for node in ast.walk(tree) + if isinstance(node, ast.AsyncFunctionDef) + and node.name == "async_step_automation_params" + ) + self.assertIn( + "vol.Required(CONF_ADDITIONAL_SENSORS)", ast.unparse(function) + ) + self.assertNotIn("async_step_additional_sensors", source) + + def test_room_choices_exclude_rooms_with_climate(self): + functions = load_functions( + "config_flow.py", {"_rooms_without_climate"}, self.namespace + ) + kitchen = SimpleNamespace(id=4, name="Kitchen", devices=[]) + lounge = SimpleNamespace(id=5, name="Lounge", devices=[object()]) + flow = SimpleNamespace( + hass=SimpleNamespace( + data={ + "wiser": { + "entry": { + "data": SimpleNamespace( + wiserhub=SimpleNamespace( + rooms=SimpleNamespace(all=[kitchen, lounge]) + ) + ) + } + } + } + ), + config_entry=SimpleNamespace(entry_id="entry"), + ) + + self.assertEqual(functions._rooms_without_climate(flow), [kitchen]) + + async def test_additional_sensor_section_preserves_other_options(self): + functions = load_functions( + "config_flow.py", {"async_step_automation_params"}, self.namespace + ) + flow = SimpleNamespace( + config_entry=SimpleNamespace(options={"scan_interval": 30}), + async_create_entry=lambda **kwargs: kwargs, + ) + + saved = await functions.async_step_automation_params( + flow, + { + "additional_sensors": { + "schedule_setpoint_rooms": ["4"] + } + }, + ) + self.assertEqual( + saved["data"], + { + "scan_interval": 30, + "additional_sensors": { + "schedule_setpoint_rooms": ["4"] + }, + }, + ) async def test_equipment_menu_is_below_opentherm(self): functions = load_functions( From bd87fbcabfcdc875a110bb1a31946f9afb323138 Mon Sep 17 00:00:00 2001 From: asantaga Date: Sun, 18 Oct 2026 19:31:34 +0100 Subject: [PATCH 148/154] fix: prepare 4.0.0 release - Keep equipment sensors enabled for installations upgrading from 3.x, which created them unconditionally before they became optional. - Complete the da, es, fi, hu, nb, nl, pt and sv flow translations with the OpenTherm menu, hot-water control and additional sensor strings. - Bump the manifest version to 4.0.0. Co-Authored-By: Claude Opus 5.5 --- custom_components/wiser/__init__.py | 3 + custom_components/wiser/manifest.json | 2 +- custom_components/wiser/translations/da.json | 36 +- custom_components/wiser/translations/es.json | 35 +- custom_components/wiser/translations/fi.json | 36 +- custom_components/wiser/translations/hu.json | 531 ++++++++++++++----- custom_components/wiser/translations/nb.json | 36 +- custom_components/wiser/translations/nl.json | 35 +- custom_components/wiser/translations/pt.json | 35 +- custom_components/wiser/translations/sv.json | 36 +- tests/test_room_migration_orchestration.py | 1 + tests/test_ui_options.py | 21 +- 12 files changed, 669 insertions(+), 138 deletions(-) diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index 94c1c480..766f5369 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -29,6 +29,7 @@ CONF_AUTOMATIONS_PASSIVE, CONF_AUTOMATIONS_PASSIVE_TEMP_INCREMENT, CONF_DEPRECATED_HW_TARGET_TEMP, + CONF_EQUIPMENT_SENSORS, CONF_LEGACY_NAMING, CONF_OPENTHERM_EVER_CONNECTED, CONF_OPENTHERM_HOT_WATER_CAPABLE, @@ -174,6 +175,8 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> if config_entry.minor_version < 5: # Keep room context visible for installations upgrading to UI options. new_options.setdefault(CONF_LEGACY_NAMING, True) + # Equipment sensors were always created before they became optional. + new_options.setdefault(CONF_EQUIPMENT_SENSORS, True) hass.config_entries.async_update_entry( config_entry, options=new_options, minor_version=5, version=1 diff --git a/custom_components/wiser/manifest.json b/custom_components/wiser/manifest.json index be87b184..99646a4d 100755 --- a/custom_components/wiser/manifest.json +++ b/custom_components/wiser/manifest.json @@ -19,7 +19,7 @@ "requirements": [ "aioWiserHeatAPI==1.7.3" ], - "version": "4.0.0-rc1", + "version": "4.0.0", "zeroconf": [ { "type": "_http._tcp.local.", diff --git a/custom_components/wiser/translations/da.json b/custom_components/wiser/translations/da.json index 89944715..99584bce 100644 --- a/custom_components/wiser/translations/da.json +++ b/custom_components/wiser/translations/da.json @@ -27,6 +27,7 @@ "not_wiser_hub": "Den fundne enhed er ikke en Wiser Heat Hub." }, "error": { + "invalid_hot_water_presets": "En eller flere varmtvandsforudindstillinger er ugyldige.", "auth_failure": "Godkendelse med Wiser-hubben mislykkedes. Kontrollér den hemmelige nøgle, og prøv igen.", "timeout_error": "Forbindelsen til Wiser-hubben fik timeout. Kontrollér IP-adressen, og prøv igen.", "timeout_error_discovery": "Forbindelsen til Wiser-hubben fik timeout. Kontrollér, at hubben stadig er online, og prøv igen.", @@ -41,7 +42,7 @@ "menu_options": { "main_params": "Hovedparametre", "automation_params": "Automatiseringsparametre", - "opentherm_sensors": "OpenTherm-sensorer", + "opentherm": "OpenTherm", "equipment_sensors": "Udstyrssensorer", "ui_options": "Brugerfladeindstillinger" } @@ -93,6 +94,16 @@ "hotwater_boost_mode": "Varmtvandsboosttilstand", "hotwater_sensor_entity_id": "Varmtvandstemperatursensor" } + }, + "additional_sensors": { + "name": "Yderligere sensorer", + "description": "Vis valgfrie sensorer for data rapporteret af Wiser.", + "data": { + "schedule_setpoint_rooms": "Rum uden klimastyring" + }, + "data_description": { + "schedule_setpoint_rooms": "Vælg de Wiser-rum, hvor der skal oprettes en sensor for den aktuelle skematemperatur." + } } } }, @@ -106,6 +117,14 @@ "equipment_sensors": "Vis en ekstra sensor med detaljerede udstyrsattributter for hvert kompatibelt smartstik, PowerTag og varmeaktuator." } }, + "opentherm": { + "title": "OpenTherm", + "description": "Konfigurer OpenTherm-funktioner.", + "menu_options": { + "opentherm_hot_water_control": "Styring af varmt vand", + "opentherm_sensors": "Sensorer" + } + }, "opentherm_sensors": { "title": "OpenTherm-sensorer", "description": "Vælg en kategori af registrerede OpenTherm-attributter.", @@ -116,6 +135,20 @@ "opentherm_status": "Status og diagnosticering" } }, + "opentherm_hot_water_control": { + "title": "OpenTherm-styring af varmt vand", + "description": "Styr eventuelt kedlens setpunkt for brugsvand via Wiser. Integrationen opretter et OpenTherm Hot Water-skema i Wiser Schedules-panelet. Fra bruger den laveste varmtvandstemperatur, som OpenTherm rapporterer.", + "data": { + "opentherm_hot_water_control": "Aktivér styring af varmt vand", + "opentherm_hot_water_manual_temperature": "Manuel temperatur", + "opentherm_hot_water_sensor_entity_id": "Valgfri ekstern temperatursensor.", + "opentherm_hot_water_presets": "Forudindstillinger" + }, + "data_description": { + "opentherm_hot_water_manual_temperature": "Temperatur, der bruges i manuel tilstand.", + "opentherm_hot_water_sensor_entity_id": "Valgfri temperatursensor, der bruges til den aktuelle vandtemperatur. OpenTherm bruges, når sensoren ikke er tilgængelig." + } + }, "opentherm_readings": { "title": "OpenTherm-målinger", "description": "Vælg, hvilke registrerede OpenTherm-målinger der vises som sensorentiteter.", @@ -649,4 +682,3 @@ } } } - diff --git a/custom_components/wiser/translations/es.json b/custom_components/wiser/translations/es.json index dd9a98be..7520dfe2 100644 --- a/custom_components/wiser/translations/es.json +++ b/custom_components/wiser/translations/es.json @@ -27,6 +27,7 @@ "not_wiser_hub": "El dispositivo descubierto no es un Heat Hub Wiser." }, "error": { + "invalid_hot_water_presets": "Uno o más preajustes de agua caliente no son válidos.", "auth_failure": "No se pudo autenticar con el hub Wiser. Compruebe la clave secreta y vuelva a intentarlo.", "timeout_error": "Se agotó el tiempo de espera al conectarse al hub Wiser. Compruebe la dirección IP y vuelva a intentarlo.", "timeout_error_discovery": "Se agotó el tiempo de espera al conectarse al hub Wiser. Compruebe que el hub siga en línea y vuelva a intentarlo.", @@ -41,7 +42,7 @@ "menu_options": { "main_params": "Parámetros principales", "automation_params": "Parámetros de automatización", - "opentherm_sensors": "OpenTherm sensores", + "opentherm": "OpenTherm", "equipment_sensors": "Sensores de equipo", "ui_options": "Opciones de la interfaz de usuario" } @@ -93,6 +94,16 @@ "hotwater_boost_mode": "Modo de refuerzo de agua caliente", "hotwater_sensor_entity_id": "Sensor de temperatura de agua caliente" } + }, + "additional_sensors": { + "name": "Sensores adicionales", + "description": "Exponga sensores opcionales para los datos informados por Wiser.", + "data": { + "schedule_setpoint_rooms": "Habitaciones sin control de climatización" + }, + "data_description": { + "schedule_setpoint_rooms": "Seleccione las habitaciones Wiser en las que se debe crear un sensor de temperatura de la programación actual." + } } } }, @@ -106,6 +117,14 @@ "equipment_sensors": "Expone un sensor adicional con atributos detallados del equipo para cada enchufe inteligente, PowerTag y actuador de calefacción compatible." } }, + "opentherm": { + "title": "OpenTherm", + "description": "Configure las funciones de OpenTherm.", + "menu_options": { + "opentherm_hot_water_control": "Control de agua caliente", + "opentherm_sensors": "Sensores" + } + }, "opentherm_sensors": { "title": "Sensores OpenTherm", "description": "Elija una categoría de atributos OpenTherm detectados.", @@ -116,6 +135,20 @@ "opentherm_status": "Estado y diagnóstico" } }, + "opentherm_hot_water_control": { + "title": "Control de agua caliente OpenTherm", + "description": "Controle opcionalmente la consigna de agua caliente sanitaria de la caldera a través de Wiser. La integración crea una programación OpenTherm Hot Water en el panel Wiser Schedules. Apagado usa la temperatura mínima de agua caliente informada por OpenTherm.", + "data": { + "opentherm_hot_water_control": "Habilitar el control de agua caliente", + "opentherm_hot_water_manual_temperature": "Temperatura manual", + "opentherm_hot_water_sensor_entity_id": "Sensor de temperatura externo opcional.", + "opentherm_hot_water_presets": "Preajustes" + }, + "data_description": { + "opentherm_hot_water_manual_temperature": "Temperatura utilizada por el modo manual.", + "opentherm_hot_water_sensor_entity_id": "Sensor de temperatura opcional utilizado para la temperatura actual del agua. Se utiliza OpenTherm cuando el sensor no está disponible." + } + }, "opentherm_readings": { "title": "Lecturas OpenTherm", "description": "Elija qué lecturas OpenTherm detectadas se muestran como entidades de sensor.", diff --git a/custom_components/wiser/translations/fi.json b/custom_components/wiser/translations/fi.json index 970b9ba6..7d66bad2 100644 --- a/custom_components/wiser/translations/fi.json +++ b/custom_components/wiser/translations/fi.json @@ -27,6 +27,7 @@ "not_wiser_hub": "Löydetty laite ei ole Wiser Heat Hub." }, "error": { + "invalid_hot_water_presets": "Yksi tai useampi käyttöveden esiasetus on virheellinen.", "auth_failure": "Todennus Wiser-keskittimeen epäonnistui. Tarkista salainen avain ja yritä uudelleen.", "timeout_error": "Yhteys Wiser-keskittimeen aikakatkaistiin. Tarkista IP-osoite ja yritä uudelleen.", "timeout_error_discovery": "Yhteys Wiser-keskittimeen aikakatkaistiin. Tarkista, että keskitin on yhä verkossa, ja yritä uudelleen.", @@ -41,7 +42,7 @@ "menu_options": { "main_params": "Pääparametrit", "automation_params": "Automaatioparametrit", - "opentherm_sensors": "OpenTherm-anturit", + "opentherm": "OpenTherm", "equipment_sensors": "Laiteanturit", "ui_options": "Käyttöliittymän asetukset" } @@ -93,6 +94,16 @@ "hotwater_boost_mode": "Käyttöveden tehostustila", "hotwater_sensor_entity_id": "Käyttöveden lämpötila-anturi" } + }, + "additional_sensors": { + "name": "Lisäanturit", + "description": "Tuo näkyviin valinnaisia antureita Wiserin ilmoittamille tiedoille.", + "data": { + "schedule_setpoint_rooms": "Huoneet ilman ilmastointiohjausta" + }, + "data_description": { + "schedule_setpoint_rooms": "Valitse Wiser-huoneet, joihin luodaan nykyisen aikataulun lämpötila-anturi." + } } } }, @@ -106,6 +117,14 @@ "equipment_sensors": "Näytä lisäanturi, joka sisältää yksityiskohtaiset laiteominaisuudet jokaiselle yhteensopivalle älypistorasialle, PowerTagille ja lämmitystoimilaitteelle." } }, + "opentherm": { + "title": "OpenTherm", + "description": "Määritä OpenTherm-ominaisuudet.", + "menu_options": { + "opentherm_hot_water_control": "Käyttöveden ohjaus", + "opentherm_sensors": "Anturit" + } + }, "opentherm_sensors": { "title": "OpenTherm-anturit", "description": "Valitse havaittujen OpenTherm-ominaisuuksien luokka.", @@ -116,6 +135,20 @@ "opentherm_status": "Tila ja diagnostiikka" } }, + "opentherm_hot_water_control": { + "title": "OpenTherm-käyttöveden ohjaus", + "description": "Ohjaa valinnaisesti kattilan käyttöveden asetusarvoa Wiserin kautta. Integraatio luo OpenTherm Hot Water -aikataulun Wiser Schedules -paneeliin. Pois-tila käyttää OpenThermin ilmoittamaa käyttöveden vähimmäislämpötilaa.", + "data": { + "opentherm_hot_water_control": "Ota käyttöveden ohjaus käyttöön", + "opentherm_hot_water_manual_temperature": "Manuaalinen lämpötila", + "opentherm_hot_water_sensor_entity_id": "Valinnainen ulkoinen lämpötila-anturi.", + "opentherm_hot_water_presets": "Esiasetukset" + }, + "data_description": { + "opentherm_hot_water_manual_temperature": "Manuaalitilassa käytettävä lämpötila.", + "opentherm_hot_water_sensor_entity_id": "Valinnainen lämpötila-anturi, jota käytetään nykyiselle veden lämpötilalle. OpenThermiä käytetään, kun anturi ei ole käytettävissä." + } + }, "opentherm_readings": { "title": "OpenTherm-lukemat", "description": "Valitse, mitkä havaitut OpenTherm-lukemat näytetään anturientiteetteinä.", @@ -649,4 +682,3 @@ } } } - diff --git a/custom_components/wiser/translations/hu.json b/custom_components/wiser/translations/hu.json index bc91593a..45296929 100644 --- a/custom_components/wiser/translations/hu.json +++ b/custom_components/wiser/translations/hu.json @@ -27,6 +27,7 @@ "not_wiser_hub": "A felismert eszköz nem Wiser fűtési központ." }, "error": { + "invalid_hot_water_presets": "Egy vagy több melegvíz-előbeállítás érvénytelen.", "auth_failure": "Nem sikerült hitelesíteni a Wiser központnál. Ellenőrizze a titkos kulcsot, majd próbálja újra.", "timeout_error": "Időtúllépés történt a Wiser központhoz való csatlakozáskor. Ellenőrizze az IP-címet, majd próbálja újra.", "timeout_error_discovery": "Időtúllépés történt a Wiser központhoz való csatlakozáskor. Ellenőrizze, hogy a központ továbbra is elérhető-e, majd próbálja újra.", @@ -41,7 +42,7 @@ "menu_options": { "main_params": "Fő paraméterek", "automation_params": "Automatizálási paraméterek", - "opentherm_sensors": "OpenTherm érzékelők", + "opentherm": "OpenTherm", "equipment_sensors": "Berendezésérzékelők", "ui_options": "Felhasználói felület beállításai" } @@ -93,6 +94,16 @@ "hotwater_boost_mode": "Melegvíz gyorsfelfűtési módja", "hotwater_sensor_entity_id": "Melegvíz-hőmérséklet érzékelője" } + }, + "additional_sensors": { + "name": "További érzékelők", + "description": "Opcionális érzékelők megjelenítése a Wiser által jelentett adatokhoz.", + "data": { + "schedule_setpoint_rooms": "Klímavezérlés nélküli helyiségek" + }, + "data_description": { + "schedule_setpoint_rooms": "Válassza ki azokat a Wiser helyiségeket, amelyekhez aktuális ütemezési hőmérséklet-érzékelőt kell létrehozni." + } } } }, @@ -106,6 +117,14 @@ "equipment_sensors": "További érzékelő megjelenítése részletes berendezésjellemzőkkel minden kompatibilis okoskonnektorhoz, PowerTag eszközhöz és fűtési szelepmozgatóhoz." } }, + "opentherm": { + "title": "OpenTherm", + "description": "OpenTherm funkciók beállítása.", + "menu_options": { + "opentherm_hot_water_control": "Melegvíz-vezérlés", + "opentherm_sensors": "Érzékelők" + } + }, "opentherm_sensors": { "title": "OpenTherm érzékelők", "description": "Válasszon kategóriát a felismert OpenTherm-attribútumok közül.", @@ -116,6 +135,20 @@ "opentherm_status": "Állapot és diagnosztika" } }, + "opentherm_hot_water_control": { + "title": "OpenTherm melegvíz-vezérlés", + "description": "A kazán használati melegvíz-alapjelének opcionális vezérlése a Wiseren keresztül. Az integráció létrehoz egy OpenTherm Hot Water ütemezést a Wiser Schedules panelen. A Ki állapot az OpenTherm által jelentett minimális melegvíz-hőmérsékletet használja.", + "data": { + "opentherm_hot_water_control": "Melegvíz-vezérlés engedélyezése", + "opentherm_hot_water_manual_temperature": "Kézi hőmérséklet", + "opentherm_hot_water_sensor_entity_id": "Opcionális külső hőmérséklet-érzékelő.", + "opentherm_hot_water_presets": "Előbeállítások" + }, + "data_description": { + "opentherm_hot_water_manual_temperature": "A kézi módban használt hőmérséklet.", + "opentherm_hot_water_sensor_entity_id": "Opcionális hőmérséklet-érzékelő az aktuális vízhőmérséklethez. Ha az érzékelő nem érhető el, az OpenTherm értéke kerül felhasználásra." + } + }, "opentherm_readings": { "title": "OpenTherm mért értékek", "description": "Válassza ki, mely felismert OpenTherm-mért értékek jelenjenek meg érzékelőentitásként.", @@ -223,16 +256,36 @@ } }, "exceptions": { - "opentherm_temperature_required": { "message": "Adjon meg egy OpenTherm-hőmérsékletet." }, - "opentherm_hub_not_found": { "message": "A megadott Wiser központ nem található." }, - "opentherm_hub_not_loaded": { "message": "A megadott Wiser központ nincs betöltve." }, - "opentherm_hub_required": { "message": "Ha több központ van konfigurálva, válasszon egy Wiser központot." }, - "opentherm_not_supported": { "message": "Ez a központ nem támogatja az OpenTherm funkciót." }, - "opentherm_invalid_parameter": { "message": "Érvénytelen OpenTherm-paraméter vagy érték: {error}" }, - "opentherm_write_failed": { "message": "Nem sikerült beállítani az OpenTherm-paramétert ({parameter}): {error}" }, - "opentherm_confirmation_failed": { "message": "Az OpenTherm-paraméter ({parameter}) egy újrapróbálkozás és a {window} másodperces ellenőrzési időablak után sem maradt a kért {requested} °C értéken. A Wiser által jelentett érték: {reported} °C. Nem történik további újrapróbálkozás." }, - "opentherm_retry_failed": { "message": "Az OpenTherm-paraméter ({parameter}) nem maradt a kért {requested} °C értéken, és az újrapróbálkozást nem sikerült elküldeni: {error}. A Wiser által jelentett érték: {reported} °C. Nem történik további újrapróbálkozás." }, - "opentherm_notification_title": { "message": "Wiser OpenTherm parancs" } + "opentherm_temperature_required": { + "message": "Adjon meg egy OpenTherm-hőmérsékletet." + }, + "opentherm_hub_not_found": { + "message": "A megadott Wiser központ nem található." + }, + "opentherm_hub_not_loaded": { + "message": "A megadott Wiser központ nincs betöltve." + }, + "opentherm_hub_required": { + "message": "Ha több központ van konfigurálva, válasszon egy Wiser központot." + }, + "opentherm_not_supported": { + "message": "Ez a központ nem támogatja az OpenTherm funkciót." + }, + "opentherm_invalid_parameter": { + "message": "Érvénytelen OpenTherm-paraméter vagy érték: {error}" + }, + "opentherm_write_failed": { + "message": "Nem sikerült beállítani az OpenTherm-paramétert ({parameter}): {error}" + }, + "opentherm_confirmation_failed": { + "message": "Az OpenTherm-paraméter ({parameter}) egy újrapróbálkozás és a {window} másodperces ellenőrzési időablak után sem maradt a kért {requested} °C értéken. A Wiser által jelentett érték: {reported} °C. Nem történik további újrapróbálkozás." + }, + "opentherm_retry_failed": { + "message": "Az OpenTherm-paraméter ({parameter}) nem maradt a kért {requested} °C értéken, és az újrapróbálkozást nem sikerült elküldeni: {error}. A Wiser által jelentett érték: {reported} °C. Nem történik további újrapróbálkozás." + }, + "opentherm_notification_title": { + "message": "Wiser OpenTherm parancs" + } }, "entity": { "climate": { @@ -244,89 +297,235 @@ } }, "number": { - "away_mode_target_temperature": { "name": "Távolléti mód célhőmérséklete" }, - "floor_temperature_offset": { "name": "Padlóhőmérséklet korrekciója" }, - "indoor_discomfort_temperature": { "name": "Beltéri diszkomfort-hőmérséklet" }, - "outdoor_discomfort_temperature": { "name": "Kültéri diszkomfort-hőmérséklet" } + "away_mode_target_temperature": { + "name": "Távolléti mód célhőmérséklete" + }, + "floor_temperature_offset": { + "name": "Padlóhőmérséklet korrekciója" + }, + "indoor_discomfort_temperature": { + "name": "Beltéri diszkomfort-hőmérséklet" + }, + "outdoor_discomfort_temperature": { + "name": "Kültéri diszkomfort-hőmérséklet" + } }, "select": { - "mode": { "name": "Mód" }, - "power_on_behavior": { "name": "Bekapcsolás utáni viselkedés" }, - "led_indicator": { "name": "LED-jelzőfény" } + "mode": { + "name": "Mód" + }, + "power_on_behavior": { + "name": "Bekapcsolás utáni viselkedés" + }, + "led_indicator": { + "name": "LED-jelzőfény" + } }, "button": { - "boost_all_heating": { "name": "Összes fűtés gyorsfelfűtése" }, - "cancel_all_heating_overrides": { "name": "Összes fűtési felülbírálás törlése" }, - "boost_hot_water": { "name": "Melegvíz gyorsfelfűtése" }, - "cancel_hot_water_overrides": { "name": "Melegvíz-felülbírálások törlése" }, - "toggle_hot_water": { "name": "Melegvíz be-/kikapcsolása" }, - "moment": { "name": "Pillanat: {name}" } + "boost_all_heating": { + "name": "Összes fűtés gyorsfelfűtése" + }, + "cancel_all_heating_overrides": { + "name": "Összes fűtési felülbírálás törlése" + }, + "boost_hot_water": { + "name": "Melegvíz gyorsfelfűtése" + }, + "cancel_hot_water_overrides": { + "name": "Melegvíz-felülbírálások törlése" + }, + "toggle_hot_water": { + "name": "Melegvíz be-/kikapcsolása" + }, + "moment": { + "name": "Pillanat: {name}" + } }, "switch": { - "valve_protection": { "name": "Szelepvédelem" }, - "eco_mode": { "name": "Takarékos mód" }, - "away_mode_affects_hot_water": { "name": "A távolléti mód a melegvízre is hatással van" }, - "comfort_mode": { "name": "Komfort mód" }, - "away_mode": { "name": "Távolléti mód" }, - "daylight_saving": { "name": "Nyári időszámítás" }, - "summer_comfort_enabled": { "name": "Nyári komfort engedélyezve" }, - "window_detection": { "name": "Ablaknyitás-érzékelés" }, - "include_in_summer_comfort": { "name": "Bevonás a nyári komfortba" }, - "device_lock": { "name": "Eszköz zárolása" }, - "identify": { "name": "Azonosítás" }, - "outlet": { "name": "Aljzat" }, - "away_mode_turns_off": { "name": "Távolléti módban kikapcsol" }, - "away_mode_closes": { "name": "Távolléti módban bezár" }, - "passive_mode": { "name": "Passzív mód" }, - "respect_summer_comfort": { "name": "Nyári komfort figyelembevétele" }, - "interacts_with_room_climate": { "name": "Hatással van a helyiség klímaszabályozására" }, - "humidity_interacts_with_room_climate": { "name": "A páratartalom hatással van a helyiség klímaszabályozására" }, - "temperature_interacts_with_room_climate": { "name": "A hőmérséklet hatással van a helyiség klímaszabályozására" }, - "illuminance_interacts_with_room_climate": { "name": "A megvilágítás hatással van a helyiség klímaszabályozására" }, - "sensor_interacts_with_room_climate": { "name": "A(z) {sensor} hatással van a helyiség klímaszabályozására" }, - "manual_heat": { "name": "Kézi fűtés" }, - "hot_water": { "name": "Meleg víz" } + "valve_protection": { + "name": "Szelepvédelem" + }, + "eco_mode": { + "name": "Takarékos mód" + }, + "away_mode_affects_hot_water": { + "name": "A távolléti mód a melegvízre is hatással van" + }, + "comfort_mode": { + "name": "Komfort mód" + }, + "away_mode": { + "name": "Távolléti mód" + }, + "daylight_saving": { + "name": "Nyári időszámítás" + }, + "summer_comfort_enabled": { + "name": "Nyári komfort engedélyezve" + }, + "window_detection": { + "name": "Ablaknyitás-érzékelés" + }, + "include_in_summer_comfort": { + "name": "Bevonás a nyári komfortba" + }, + "device_lock": { + "name": "Eszköz zárolása" + }, + "identify": { + "name": "Azonosítás" + }, + "outlet": { + "name": "Aljzat" + }, + "away_mode_turns_off": { + "name": "Távolléti módban kikapcsol" + }, + "away_mode_closes": { + "name": "Távolléti módban bezár" + }, + "passive_mode": { + "name": "Passzív mód" + }, + "respect_summer_comfort": { + "name": "Nyári komfort figyelembevétele" + }, + "interacts_with_room_climate": { + "name": "Hatással van a helyiség klímaszabályozására" + }, + "humidity_interacts_with_room_climate": { + "name": "A páratartalom hatással van a helyiség klímaszabályozására" + }, + "temperature_interacts_with_room_climate": { + "name": "A hőmérséklet hatással van a helyiség klímaszabályozására" + }, + "illuminance_interacts_with_room_climate": { + "name": "A megvilágítás hatással van a helyiség klímaszabályozására" + }, + "sensor_interacts_with_room_climate": { + "name": "A(z) {sensor} hatással van a helyiség klímaszabályozására" + }, + "manual_heat": { + "name": "Kézi fűtés" + }, + "hot_water": { + "name": "Meleg víz" + } }, "binary_sensor": { - "summer_discomfort_prevention": { "name": "Nyári túlmelegedés megelőzése" }, - "summer_comfort_available": { "name": "Nyári komfort elérhető" }, - "pcm_device_limit_reached": { "name": "Elérte a PCM-eszközök maximális számát" }, - "smoke_alarm": { "name": "Füstjelzés" }, - "heat_alarm": { "name": "Hőriasztás" }, - "tamper_alarm": { "name": "Szabotázsriasztás" }, - "fault_warning": { "name": "Hibajelzés" }, - "remote_alarm": { "name": "Távoli riasztás" }, - "battery_defect": { "name": "Akkumulátorhiba" }, - "controllable": { "name": "Vezérelhető" }, - "pcm_mode": { "name": "PCM mód" }, - "window_detection_active": { "name": "Ablaknyitás-érzékelés aktív" }, - "is_dimmable": { "name": "Fényerőszabályozható" }, - "is_led_indicator_supported": { "name": "LED-jelzőfény támogatott" }, - "is_output_mode_supported": { "name": "Kimeneti mód támogatott" }, - "is_power_on_behaviour_supported": { "name": "Bekapcsolás utáni viselkedés támogatott" }, - "is_tilt_supported": { "name": "Döntés támogatott" }, - "is_open": { "name": "Nyitva" }, - "is_closed": { "name": "Zárva" }, - "active": { "name": "Aktív" }, - "boiler_ch_max_setpoint_read_write": { "name": "Kazán központifűtés-maximális célértékének olvasása/írása" }, - "boiler_ch_max_setpoint_transfer_enable": { "name": "Kazán központifűtés-maximális célértékének átvitele engedélyezve" }, - "boiler_fault": { "name": "Kazánhiba" }, - "boiler_hw_setpoint_read_write": { "name": "Kazán melegvíz-célhőmérsékletének olvasása/írása" }, - "boiler_hw_setpoint_transfer_enable": { "name": "Kazán melegvíz-célhőmérsékletének átvitele engedélyezve" }, - "central_heating_2_active": { "name": "2. központi fűtési kör aktív" }, - "central_heating_active": { "name": "Központi fűtés aktív" }, - "ch1_flow_enabled": { "name": "1. fűtési kör előremenő ága engedélyezve" }, - "ch2_flow_enabled": { "name": "2. fűtési kör előremenő ága engedélyezve" }, - "cooling_active": { "name": "Hűtés aktív" }, - "diagnostic_event": { "name": "Diagnosztikai esemény" }, - "flame_active": { "name": "Láng aktív" }, - "hot_water_active": { "name": "Melegvíz-készítés aktív" }, - "hw_enabled": { "name": "Melegvíz-készítés engedélyezve" } + "summer_discomfort_prevention": { + "name": "Nyári túlmelegedés megelőzése" + }, + "summer_comfort_available": { + "name": "Nyári komfort elérhető" + }, + "pcm_device_limit_reached": { + "name": "Elérte a PCM-eszközök maximális számát" + }, + "smoke_alarm": { + "name": "Füstjelzés" + }, + "heat_alarm": { + "name": "Hőriasztás" + }, + "tamper_alarm": { + "name": "Szabotázsriasztás" + }, + "fault_warning": { + "name": "Hibajelzés" + }, + "remote_alarm": { + "name": "Távoli riasztás" + }, + "battery_defect": { + "name": "Akkumulátorhiba" + }, + "controllable": { + "name": "Vezérelhető" + }, + "pcm_mode": { + "name": "PCM mód" + }, + "window_detection_active": { + "name": "Ablaknyitás-érzékelés aktív" + }, + "is_dimmable": { + "name": "Fényerőszabályozható" + }, + "is_led_indicator_supported": { + "name": "LED-jelzőfény támogatott" + }, + "is_output_mode_supported": { + "name": "Kimeneti mód támogatott" + }, + "is_power_on_behaviour_supported": { + "name": "Bekapcsolás utáni viselkedés támogatott" + }, + "is_tilt_supported": { + "name": "Döntés támogatott" + }, + "is_open": { + "name": "Nyitva" + }, + "is_closed": { + "name": "Zárva" + }, + "active": { + "name": "Aktív" + }, + "boiler_ch_max_setpoint_read_write": { + "name": "Kazán központifűtés-maximális célértékének olvasása/írása" + }, + "boiler_ch_max_setpoint_transfer_enable": { + "name": "Kazán központifűtés-maximális célértékének átvitele engedélyezve" + }, + "boiler_fault": { + "name": "Kazánhiba" + }, + "boiler_hw_setpoint_read_write": { + "name": "Kazán melegvíz-célhőmérsékletének olvasása/írása" + }, + "boiler_hw_setpoint_transfer_enable": { + "name": "Kazán melegvíz-célhőmérsékletének átvitele engedélyezve" + }, + "central_heating_2_active": { + "name": "2. központi fűtési kör aktív" + }, + "central_heating_active": { + "name": "Központi fűtés aktív" + }, + "ch1_flow_enabled": { + "name": "1. fűtési kör előremenő ága engedélyezve" + }, + "ch2_flow_enabled": { + "name": "2. fűtési kör előremenő ága engedélyezve" + }, + "cooling_active": { + "name": "Hűtés aktív" + }, + "diagnostic_event": { + "name": "Diagnosztikai esemény" + }, + "flame_active": { + "name": "Láng aktív" + }, + "hot_water_active": { + "name": "Melegvíz-készítés aktív" + }, + "hw_enabled": { + "name": "Melegvíz-készítés engedélyezve" + } }, "sensor": { - "signal": { "name": "Jel" }, - "cloud": { "name": "Felhő" }, - "heating_operation_mode": { "name": "Fűtési üzemmód" }, + "signal": { + "name": "Jel" + }, + "cloud": { + "name": "Felhő" + }, + "heating_operation_mode": { + "name": "Fűtési üzemmód" + }, "heating": { "name": "Fűtés", "state": { @@ -348,47 +547,129 @@ "on": "Be" } }, - "hot_water_operation_mode": { "name": "Melegvíz üzemmód" }, - "target_temperature": { "name": "Célhőmérséklet" }, - "floor_temperature": { "name": "Padlóhőmérséklet" }, - "boiler_flow_temperature": { "name": "Kazán előremenő hőmérséklete" }, - "boiler_return_temperature": { "name": "Kazán visszatérő hőmérséklete" }, - "flame_statistics": { "name": "Lángstatisztika" }, - "boiler_ch_setpoint": { "name": "Kazán központifűtés-célértéke" }, - "boiler_ch_setpoint_lower_bound": { "name": "Kazán központifűtés-célértékének alsó határa" }, - "boiler_ch_setpoint_upper_bound": { "name": "Kazán központifűtés-célértékének felső határa" }, - "boiler_exhaust_temperature": { "name": "Kazán füstgázhőmérséklete" }, - "boiler_hw_setpoint": { "name": "Kazán melegvíz-célhőmérséklete" }, - "boiler_hw_setpoint_lower_bound": { "name": "Kazán melegvíz-célhőmérsékletének alsó határa" }, - "boiler_hw_setpoint_upper_bound": { "name": "Kazán melegvíz-célhőmérsékletének felső határa" }, - "ch1_flow_setpoint": { "name": "1. fűtési kör előremenő célértéke" }, - "ch2_flow_setpoint": { "name": "2. fűtési kör előremenő célértéke" }, - "ch_flow_active_lower_setpoint": { "name": "Központi fűtés előremenő aktív alsó célértéke" }, - "ch_flow_active_upper_setpoint": { "name": "Központi fűtés előremenő aktív felső célértéke" }, - "ch_pressure_bar": { "name": "Központi fűtés nyomása" }, - "connection_status": { "name": "Kapcsolat állapota" }, - "coprocessor_update_status": { "name": "OpenTherm koprocesszor frissítési állapota" }, - "coprocessor_version": { "name": "OpenTherm koprocesszor verziója" }, - "delta_t": { "name": "Hőmérséklet-különbség (ΔT)" }, - "estimated_boiler_output": { "name": "Kazán becsült teljesítménye" }, - "hw_flow_rate": { "name": "Melegvíz térfogatárama" }, - "hw_flow_setpoint": { "name": "Melegvíz előremenő célhőmérséklete" }, - "hw_temperature": { "name": "Melegvíz hőmérséklete" }, - "maximum_capacity_kw": { "name": "Kazán maximális teljesítménye" }, - "minimum_modulation_level": { "name": "Minimális modulációs szint" }, - "operating_mode": { "name": "Üzemmód" }, - "relative_modulation_level": { "name": "Relatív modulációs szint" }, - "room_setpoint": { "name": "Helyiség célhőmérséklete" }, - "room_temperature": { "name": "Helyiség hőmérséklete" }, - "slave_status": { "name": "OpenTherm alárendelt eszköz állapota" }, - "tracked_room_id": { "name": "Követett helyiség azonosítója" }, - "heating_demand": { "name": "Fűtési igény" }, - "heating_demand_channel": { "name": "Fűtési igény – {channel}. csatorna" }, - "hot_water_demand": { "name": "Melegvíz-igény" }, - "total_energy": { "name": "Összes energia" }, - "energy_delivered": { "name": "Leadott energia" }, - "energy_received": { "name": "Felvett energia" }, - "equipment_power": { "name": "Berendezés teljesítménye" } + "hot_water_operation_mode": { + "name": "Melegvíz üzemmód" + }, + "target_temperature": { + "name": "Célhőmérséklet" + }, + "floor_temperature": { + "name": "Padlóhőmérséklet" + }, + "boiler_flow_temperature": { + "name": "Kazán előremenő hőmérséklete" + }, + "boiler_return_temperature": { + "name": "Kazán visszatérő hőmérséklete" + }, + "flame_statistics": { + "name": "Lángstatisztika" + }, + "boiler_ch_setpoint": { + "name": "Kazán központifűtés-célértéke" + }, + "boiler_ch_setpoint_lower_bound": { + "name": "Kazán központifűtés-célértékének alsó határa" + }, + "boiler_ch_setpoint_upper_bound": { + "name": "Kazán központifűtés-célértékének felső határa" + }, + "boiler_exhaust_temperature": { + "name": "Kazán füstgázhőmérséklete" + }, + "boiler_hw_setpoint": { + "name": "Kazán melegvíz-célhőmérséklete" + }, + "boiler_hw_setpoint_lower_bound": { + "name": "Kazán melegvíz-célhőmérsékletének alsó határa" + }, + "boiler_hw_setpoint_upper_bound": { + "name": "Kazán melegvíz-célhőmérsékletének felső határa" + }, + "ch1_flow_setpoint": { + "name": "1. fűtési kör előremenő célértéke" + }, + "ch2_flow_setpoint": { + "name": "2. fűtési kör előremenő célértéke" + }, + "ch_flow_active_lower_setpoint": { + "name": "Központi fűtés előremenő aktív alsó célértéke" + }, + "ch_flow_active_upper_setpoint": { + "name": "Központi fűtés előremenő aktív felső célértéke" + }, + "ch_pressure_bar": { + "name": "Központi fűtés nyomása" + }, + "connection_status": { + "name": "Kapcsolat állapota" + }, + "coprocessor_update_status": { + "name": "OpenTherm koprocesszor frissítési állapota" + }, + "coprocessor_version": { + "name": "OpenTherm koprocesszor verziója" + }, + "delta_t": { + "name": "Hőmérséklet-különbség (ΔT)" + }, + "estimated_boiler_output": { + "name": "Kazán becsült teljesítménye" + }, + "hw_flow_rate": { + "name": "Melegvíz térfogatárama" + }, + "hw_flow_setpoint": { + "name": "Melegvíz előremenő célhőmérséklete" + }, + "hw_temperature": { + "name": "Melegvíz hőmérséklete" + }, + "maximum_capacity_kw": { + "name": "Kazán maximális teljesítménye" + }, + "minimum_modulation_level": { + "name": "Minimális modulációs szint" + }, + "operating_mode": { + "name": "Üzemmód" + }, + "relative_modulation_level": { + "name": "Relatív modulációs szint" + }, + "room_setpoint": { + "name": "Helyiség célhőmérséklete" + }, + "room_temperature": { + "name": "Helyiség hőmérséklete" + }, + "slave_status": { + "name": "OpenTherm alárendelt eszköz állapota" + }, + "tracked_room_id": { + "name": "Követett helyiség azonosítója" + }, + "heating_demand": { + "name": "Fűtési igény" + }, + "heating_demand_channel": { + "name": "Fűtési igény – {channel}. csatorna" + }, + "hot_water_demand": { + "name": "Melegvíz-igény" + }, + "total_energy": { + "name": "Összes energia" + }, + "energy_delivered": { + "name": "Leadott energia" + }, + "energy_received": { + "name": "Felvett energia" + }, + "equipment_power": { + "name": "Berendezés teljesítménye" + } } }, "device_automation": { diff --git a/custom_components/wiser/translations/nb.json b/custom_components/wiser/translations/nb.json index 36590ccb..42c4f021 100644 --- a/custom_components/wiser/translations/nb.json +++ b/custom_components/wiser/translations/nb.json @@ -27,6 +27,7 @@ "not_wiser_hub": "Den oppdagede enheten er ikke en Wiser Heat Hub." }, "error": { + "invalid_hot_water_presets": "En eller flere varmtvannsforhåndsinnstillinger er ugyldige.", "auth_failure": "Kan ikke autentisere mot Wiser-huben. Kontroller den hemmelige nøkkelen og prøv igjen.", "timeout_error": "Tidsavbrudd ved tilkobling til Wiser-huben. Kontroller IP-adressen og prøv igjen.", "timeout_error_discovery": "Tidsavbrudd ved tilkobling til Wiser-huben. Kontroller at huben fortsatt er tilkoblet, og prøv igjen.", @@ -41,7 +42,7 @@ "menu_options": { "main_params": "Hovedparametere", "automation_params": "Automatiseringsparametere", - "opentherm_sensors": "OpenTherm-sensorer", + "opentherm": "OpenTherm", "equipment_sensors": "Utstyrssensorer", "ui_options": "Brukergrensesnittalternativer" } @@ -93,6 +94,16 @@ "hotwater_boost_mode": "Varmtvannsboostmodus", "hotwater_sensor_entity_id": "Varmtvannstemperatursensor" } + }, + "additional_sensors": { + "name": "Ekstra sensorer", + "description": "Vis valgfrie sensorer for data rapportert av Wiser.", + "data": { + "schedule_setpoint_rooms": "Rom uten klimastyring" + }, + "data_description": { + "schedule_setpoint_rooms": "Velg Wiser-rommene der det skal opprettes en sensor for gjeldende tidsplantemperatur." + } } } }, @@ -106,6 +117,14 @@ "equipment_sensors": "Vis en ekstra sensor med detaljerte utstyrsattributter for hver kompatible smartplugg, PowerTag og varmeaktuator." } }, + "opentherm": { + "title": "OpenTherm", + "description": "Konfigurer OpenTherm-funksjoner.", + "menu_options": { + "opentherm_hot_water_control": "Varmtvannsstyring", + "opentherm_sensors": "Sensorer" + } + }, "opentherm_sensors": { "title": "OpenTherm-sensorer", "description": "Velg en kategori med oppdagede OpenTherm-attributter.", @@ -116,6 +135,20 @@ "opentherm_status": "Status og diagnostikk" } }, + "opentherm_hot_water_control": { + "title": "OpenTherm-varmtvannsstyring", + "description": "Styr eventuelt kjelens settpunkt for forbruksvann via Wiser. Integrasjonen oppretter en OpenTherm Hot Water-tidsplan i Wiser Schedules-panelet. Av bruker den laveste varmtvannstemperaturen som OpenTherm rapporterer.", + "data": { + "opentherm_hot_water_control": "Aktiver varmtvannsstyring", + "opentherm_hot_water_manual_temperature": "Manuell temperatur", + "opentherm_hot_water_sensor_entity_id": "Valgfri ekstern temperatursensor.", + "opentherm_hot_water_presets": "Forhåndsinnstillinger" + }, + "data_description": { + "opentherm_hot_water_manual_temperature": "Temperatur som brukes i manuell modus.", + "opentherm_hot_water_sensor_entity_id": "Valgfri temperatursensor som brukes for gjeldende vanntemperatur. OpenTherm brukes når sensoren ikke er tilgjengelig." + } + }, "opentherm_readings": { "title": "OpenTherm-avlesninger", "description": "Velg hvilke oppdagede OpenTherm-avlesninger som skal vises som sensorentiteter.", @@ -649,4 +682,3 @@ } } } - diff --git a/custom_components/wiser/translations/nl.json b/custom_components/wiser/translations/nl.json index 64fd34c7..adf77ab3 100644 --- a/custom_components/wiser/translations/nl.json +++ b/custom_components/wiser/translations/nl.json @@ -27,6 +27,7 @@ "not_wiser_hub": "Het ontdekte apparaat is geen Wiser Heat Hub." }, "error": { + "invalid_hot_water_presets": "Een of meer warmwatervoorinstellingen zijn ongeldig.", "auth_failure": "Kan niet verifiëren met de Wiser-hub. Controleer de geheime sleutel en probeer het opnieuw.", "timeout_error": "Er is een time-out opgetreden bij het verbinden met de Wiser-hub. Controleer het IP-adres en probeer het opnieuw.", "timeout_error_discovery": "Er is een time-out opgetreden bij het verbinden met de Wiser-hub. Controleer of uw hub nog steeds online is en probeer het opnieuw.", @@ -41,7 +42,7 @@ "menu_options": { "main_params": "Hoofdparameters", "automation_params": "Automatiseringsparameters", - "opentherm_sensors": "OpenTherm-sensoren", + "opentherm": "OpenTherm", "equipment_sensors": "Apparatuursensoren", "ui_options": "Opties voor de gebruikersinterface" } @@ -93,6 +94,16 @@ "hotwater_boost_mode": "Boostmodus voor warm water", "hotwater_sensor_entity_id": "Warmwatertemperatuursensor" } + }, + "additional_sensors": { + "name": "Extra sensoren", + "description": "Maak optionele sensoren beschikbaar voor gegevens die Wiser rapporteert.", + "data": { + "schedule_setpoint_rooms": "Ruimtes zonder klimaatregeling" + }, + "data_description": { + "schedule_setpoint_rooms": "Selecteer de Wiser-ruimtes waarvoor een sensor voor de huidige schematemperatuur moet worden aangemaakt." + } } } }, @@ -106,6 +117,14 @@ "equipment_sensors": "Maakt een extra sensor beschikbaar met gedetailleerde apparatuurkenmerken voor elke compatibele slimme stekker, PowerTag en verwarmingsactuator." } }, + "opentherm": { + "title": "OpenTherm", + "description": "Configureer OpenTherm-functies.", + "menu_options": { + "opentherm_hot_water_control": "Warmwaterregeling", + "opentherm_sensors": "Sensoren" + } + }, "opentherm_sensors": { "title": "OpenTherm-sensoren", "description": "Kies een categorie gedetecteerde OpenTherm-attributen.", @@ -116,6 +135,20 @@ "opentherm_status": "Status en diagnostiek" } }, + "opentherm_hot_water_control": { + "title": "OpenTherm-warmwaterregeling", + "description": "Regel optioneel het tapwater-setpoint van de ketel via Wiser. De integratie maakt een OpenTherm Hot Water-schema aan in het Wiser Schedules-paneel. Uit gebruikt de minimale warmwatertemperatuur die OpenTherm rapporteert.", + "data": { + "opentherm_hot_water_control": "Warmwaterregeling inschakelen", + "opentherm_hot_water_manual_temperature": "Handmatige temperatuur", + "opentherm_hot_water_sensor_entity_id": "Optionele externe temperatuursensor.", + "opentherm_hot_water_presets": "Voorinstellingen" + }, + "data_description": { + "opentherm_hot_water_manual_temperature": "Temperatuur die in de handmatige modus wordt gebruikt.", + "opentherm_hot_water_sensor_entity_id": "Optionele temperatuursensor voor de huidige watertemperatuur. OpenTherm wordt gebruikt wanneer de sensor niet beschikbaar is." + } + }, "opentherm_readings": { "title": "OpenTherm uitlezingen", "description": "Kies welke gedetecteerde OpenTherm-metingen worden weergegeven als sensorentiteiten.", diff --git a/custom_components/wiser/translations/pt.json b/custom_components/wiser/translations/pt.json index aba3c3b3..28aad363 100644 --- a/custom_components/wiser/translations/pt.json +++ b/custom_components/wiser/translations/pt.json @@ -27,6 +27,7 @@ "not_wiser_hub": "O dispositivo descoberto não é um Heat Hub Wiser." }, "error": { + "invalid_hot_water_presets": "Uma ou mais predefinições de água quente são inválidas.", "auth_failure": "Não foi possível autenticar no hub Wiser. Verifique a chave secreta e tente novamente.", "timeout_error": "O tempo limite foi excedido ao estabelecer ligação ao hub Wiser. Verifique o endereço IP e tente novamente.", "timeout_error_discovery": "O tempo limite foi excedido ao estabelecer ligação ao hub Wiser. Verifique se o hub continua online e tente novamente.", @@ -41,7 +42,7 @@ "menu_options": { "main_params": "Parâmetros principais", "automation_params": "Parâmetros de automação", - "opentherm_sensors": "Sensores OpenTherm", + "opentherm": "OpenTherm", "equipment_sensors": "Sensores de equipamento", "ui_options": "Opções da interface do utilizador" } @@ -93,6 +94,16 @@ "hotwater_boost_mode": "Modo de reforço de água quente", "hotwater_sensor_entity_id": "Sensor de temperatura de água quente" } + }, + "additional_sensors": { + "name": "Sensores adicionais", + "description": "Exponha sensores opcionais para os dados informados pelo Wiser.", + "data": { + "schedule_setpoint_rooms": "Divisões sem controle de climatização" + }, + "data_description": { + "schedule_setpoint_rooms": "Selecione as divisões Wiser onde deve ser criado um sensor de temperatura da programação atual." + } } } }, @@ -106,6 +117,14 @@ "equipment_sensors": "Disponibiliza um sensor adicional com atributos detalhados do equipamento para cada tomada inteligente, PowerTag e atuador de aquecimento compatível." } }, + "opentherm": { + "title": "OpenTherm", + "description": "Configure as funcionalidades OpenTherm.", + "menu_options": { + "opentherm_hot_water_control": "Controle de água quente", + "opentherm_sensors": "Sensores" + } + }, "opentherm_sensors": { "title": "Sensores OpenTherm", "description": "Escolha uma categoria de atributos OpenTherm detectados.", @@ -116,6 +135,20 @@ "opentherm_status": "Estado e diagnóstico" } }, + "opentherm_hot_water_control": { + "title": "Controle de água quente OpenTherm", + "description": "Controle opcionalmente o ponto de ajuste de água quente sanitária da caldeira através do Wiser. A integração cria uma programação OpenTherm Hot Water no painel Wiser Schedules. Desligado usa a temperatura mínima de água quente informada pelo OpenTherm.", + "data": { + "opentherm_hot_water_control": "Ativar o controle de água quente", + "opentherm_hot_water_manual_temperature": "Temperatura manual", + "opentherm_hot_water_sensor_entity_id": "Sensor de temperatura externo opcional.", + "opentherm_hot_water_presets": "Predefinições" + }, + "data_description": { + "opentherm_hot_water_manual_temperature": "Temperatura usada pelo modo manual.", + "opentherm_hot_water_sensor_entity_id": "Sensor de temperatura opcional usado para a temperatura atual da água. O OpenTherm é usado quando o sensor não está disponível." + } + }, "opentherm_readings": { "title": "Leituras OpenTherm", "description": "Escolha quais leituras OpenTherm detetadas são apresentadas como entidades de sensor.", diff --git a/custom_components/wiser/translations/sv.json b/custom_components/wiser/translations/sv.json index 09799533..66743fb3 100644 --- a/custom_components/wiser/translations/sv.json +++ b/custom_components/wiser/translations/sv.json @@ -27,6 +27,7 @@ "not_wiser_hub": "Den identifierade enheten är inte en Wiser Heat Hub." }, "error": { + "invalid_hot_water_presets": "En eller flera förinställningar för varmvatten är ogiltiga.", "auth_failure": "Det gick inte att autentisera mot Wiser-hubben. Kontrollera den hemliga nyckeln och försök igen.", "timeout_error": "Tidsgränsen överskreds vid anslutning till Wiser-hubben. Kontrollera IP-adressen och försök igen.", "timeout_error_discovery": "Tidsgränsen överskreds vid anslutning till Wiser-hubben. Kontrollera att hubben fortfarande är online och försök igen.", @@ -41,7 +42,7 @@ "menu_options": { "main_params": "Huvudparametrar", "automation_params": "Automatiseringsparametrar", - "opentherm_sensors": "OpenTherm-sensorer", + "opentherm": "OpenTherm", "equipment_sensors": "Utrustningssensorer", "ui_options": "Gränssnittsalternativ" } @@ -93,6 +94,16 @@ "hotwater_boost_mode": "Varmvattenboostläge", "hotwater_sensor_entity_id": "Varmvattentemperatursensor" } + }, + "additional_sensors": { + "name": "Ytterligare sensorer", + "description": "Visa valfria sensorer för data som rapporteras av Wiser.", + "data": { + "schedule_setpoint_rooms": "Rum utan klimatstyrning" + }, + "data_description": { + "schedule_setpoint_rooms": "Välj de Wiser-rum där en sensor för aktuell schematemperatur ska skapas." + } } } }, @@ -106,6 +117,14 @@ "equipment_sensors": "Visa en extra sensor med detaljerade utrustningsattribut för varje kompatibelt smartuttag, PowerTag och värmeställdon." } }, + "opentherm": { + "title": "OpenTherm", + "description": "Konfigurera OpenTherm-funktioner.", + "menu_options": { + "opentherm_hot_water_control": "Varmvattenstyrning", + "opentherm_sensors": "Sensorer" + } + }, "opentherm_sensors": { "title": "OpenTherm-sensorer", "description": "Välj en kategori med identifierade OpenTherm-attribut.", @@ -116,6 +135,20 @@ "opentherm_status": "Status och diagnostik" } }, + "opentherm_hot_water_control": { + "title": "OpenTherm-varmvattenstyrning", + "description": "Styr valfritt pannans börvärde för tappvarmvatten via Wiser. Integrationen skapar ett OpenTherm Hot Water-schema i Wiser Schedules-panelen. Av använder den lägsta varmvattentemperatur som OpenTherm rapporterar.", + "data": { + "opentherm_hot_water_control": "Aktivera varmvattenstyrning", + "opentherm_hot_water_manual_temperature": "Manuell temperatur", + "opentherm_hot_water_sensor_entity_id": "Valfri extern temperatursensor.", + "opentherm_hot_water_presets": "Förinställningar" + }, + "data_description": { + "opentherm_hot_water_manual_temperature": "Temperatur som används i manuellt läge.", + "opentherm_hot_water_sensor_entity_id": "Valfri temperatursensor som används för aktuell vattentemperatur. OpenTherm används när sensorn inte är tillgänglig." + } + }, "opentherm_readings": { "title": "OpenTherm-avläsningar", "description": "Välj vilka identifierade OpenTherm-avläsningar som ska visas som sensorentiteter.", @@ -649,4 +682,3 @@ } } } - diff --git a/tests/test_room_migration_orchestration.py b/tests/test_room_migration_orchestration.py index d665efb4..286082c1 100644 --- a/tests/test_room_migration_orchestration.py +++ b/tests/test_room_migration_orchestration.py @@ -58,6 +58,7 @@ def _load_wiser_init() -> ModuleType: "CONF_AUTOMATIONS_PASSIVE", "CONF_AUTOMATIONS_PASSIVE_TEMP_INCREMENT", "CONF_DEPRECATED_HW_TARGET_TEMP", + "CONF_EQUIPMENT_SENSORS", "CONF_LEGACY_NAMING", "CONF_OPENTHERM_EVER_CONNECTED", "CONF_OPENTHERM_HOT_WATER_CAPABLE", diff --git a/tests/test_ui_options.py b/tests/test_ui_options.py index f3c58f7f..41985632 100644 --- a/tests/test_ui_options.py +++ b/tests/test_ui_options.py @@ -461,10 +461,29 @@ async def test_migration_enables_legacy_and_preserves_other_options(self): saved = update.call_args.kwargs self.assertEqual( saved["options"], - options | {"legacy_naming": expected}, + options | {"legacy_naming": expected, "equipment_sensors": True}, ) self.assertEqual(saved["minor_version"], 5) + async def test_migration_keeps_equipment_sensors_for_upgrades(self): + functions = load_functions("__init__.py", {"async_migrate_entry"}, self.namespace) + for options, expected in (({}, True), + ({"equipment_sensors": False}, False)): + entry = SimpleNamespace(version=1, minor_version=4, options=options) + update = Mock() + hass = SimpleNamespace(config_entries=SimpleNamespace(async_update_entry=update)) + self.assertTrue(await functions.async_migrate_entry(hass, entry)) + saved = update.call_args.kwargs["options"] + self.assertIs(saved["equipment_sensors"], expected) + + async def test_migration_leaves_current_entries_equipment_option_unset(self): + functions = load_functions("__init__.py", {"async_migrate_entry"}, self.namespace) + entry = SimpleNamespace(version=1, minor_version=5, options={}) + update = Mock() + hass = SimpleNamespace(config_entries=SimpleNamespace(async_update_entry=update)) + self.assertTrue(await functions.async_migrate_entry(hass, entry)) + self.assertNotIn("equipment_sensors", update.call_args.kwargs["options"]) + async def test_menu_available_without_opentherm(self): functions = load_functions("config_flow.py", {"async_step_init"}, self.namespace) flow = SimpleNamespace( From 1cb788c5b778106655fa83fe9c6aa796c5aa899c Mon Sep 17 00:00:00 2001 From: asantaga Date: Sun, 18 Oct 2026 19:32:43 +0100 Subject: [PATCH 149/154] docs: complete 4.0.0 release notes - Add the changes merged since 4.0.0-rc1 to the changelog and link the remaining PRs and issues. - Expand the README's 4.0 highlights and breaking changes, including the unique ID migration, downgrade and equipment sensor notes, and drop the unsupported claim that Repairs guides device migration. - Move build instructions to CONTRIBUTING.md and correct its outdated description of missing card assets. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 30 +++++++++++++++++----- CONTRIBUTING.md | 29 ++++++++++++++++++---- README.md | 66 ++++++++++++++----------------------------------- 3 files changed, 66 insertions(+), 59 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6e6d701..fa85794d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,37 +4,55 @@ All notable changes to the Wiser Home Assistant integration, newest release firs For releases before v3.3.5, see the [Full Change Log](https://github.com/asantaga/wiserHomeAssistantPlatform/wiki/Full-Change-Log) on our wiki. -## v4.0.0-rc1 +## v4.0.0 ### Breaking changes - The device registry is restructured. The separate virtual controller device is merged into the physical hub device, and Wiser room devices move to stable identifiers. In both cases the old device is removed and its entities are reassigned to the surviving device. Entity IDs and history are preserved, but anything that targets a Wiser *device* rather than an entity - device-based automations and scripts, or dashboard cards pointing at a device - needs repointing - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693). - Entity unique IDs migrate to deterministic UUIDv5. The migration runs automatically on upgrade and renames registry entries in place, so entity IDs, history, and customisations are preserved. Every target is checked before any change is applied, so it cannot partially apply, but it aborts if it finds a unique ID collision - take a backup before upgrading - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693). +- Downgrading is not supported. Because unique IDs and device identifiers change, returning to a 3.x release means restoring the backup taken before upgrading, not just reinstalling the older version. ### Added -- Added optional Wiser-only OpenTherm domestic-hot-water control with a Home Assistant water-heater entity, configurable temperature and presets, an optional external current-temperature sensor, icon mode controls, and an integration-owned weekly schedule managed from the Wiser Schedules panel. Non-timed presets can be used in schedule periods; temporary boost presets remain manual actions. -- Manage frontend definitions in the integration's bundled `cards.json`, with independent card and panel installation, offline caching, and a generic panel-settings API. - +- Added Schneider Mureva EV Link charger entities - issue [#689](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/689), PR [#749](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/749). +- Added smoke alarm operating states and a report count sensor - PR [#744](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/744). +- Added scheduled setpoint sensors, showing the current schedule temperature for Wiser rooms without climate control. Rooms are chosen under **Additional sensors** in the automation options - issue [#738](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/738), PR [#746](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/746). +- Added optional Wiser-only OpenTherm domestic-hot-water control with a Home Assistant water-heater entity, configurable temperature and presets, an optional external current-temperature sensor, icon mode controls, and an integration-owned weekly schedule managed from the Wiser Schedules panel. Non-timed presets can be used in schedule periods; temporary boost presets remain manual actions - PR [#745](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/745). - Added configurable OpenTherm monitoring and controls, including relative modulation, a Delta-T sensor, expanded telemetry, and categorized diagnostics - PR [#697](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/697). +- Added OpenTherm room demand attributes - PR [#724](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/724). +- Added PowerTag Control equipment sensors - PR [#726](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/726). - Added a configurable Wiser Schedules sidebar panel - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). - Added a Wiser Zigbee sidebar panel with a custom sidebar icon - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). +- Added an integration-managed frontend registry (`cards.json`), so the Schedules and Zigbee cards and the sidebar panels install and update independently through Home Assistant update entities, with offline caching and a shared panel-settings API - PR [#709](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/709), PR [#719](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/719). - Added a Hot Water on/off switch entity - issue [#626](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/626), PR [#682](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/682). - Added a UFH controller measured-temperature sensor - issue [#628](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/628). - Added optimistic light state for instant UI feedback on toggles, kept stable across rapid repeated toggles - PR [#684](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/684). - Added British English translations and corrected the German, French, and English integration translations - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). +- Added Danish, Spanish, Finnish, Hungarian, Norwegian, Dutch, Portuguese, and Swedish translations - PR [#747](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/747). ### Changed - Entity naming now follows Home Assistant conventions, using `has_entity_name` so Home Assistant composes each displayed name from the device name plus the entity name. Existing entity IDs are not renamed. A new **Legacy naming** option controls whether Wiser room names are included in device names; it is switched on automatically for existing installations, so your device names stay as they are unless you turn it off. New installations on Home Assistant 2026.8 and later default it to off - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693), PR [#700](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/700). - Wiser devices are now placed in Home Assistant areas matching their Wiser room, creating the area if it does not exist. This applies only to devices that have no area yet, so any area you assigned manually is left untouched - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693), PR [#700](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/700). +- Equipment power and energy sensors are now optional, under **Equipment sensors** in the integration options. Existing installations upgrading from 3.x keep them switched on; new installations start with them off - PR [#726](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/726). +- Card and panel bundles are no longer stored in the source repository. Release packages include them, and each card or panel updates from its own repository through a Home Assistant update entity - PR [#716](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/716). - Sidebar panel visibility is now configured through the integration's UI options - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). - Card versions are now detected from the installed card bundles instead of being pinned in the integration, so card updates no longer need an integration release - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). -- OpenTherm hot-water temperature changes made in Auto mode now act as temporary overrides and are replaced by the next scheduled period. +- OpenTherm hot-water temperature changes made in Auto mode now act as temporary overrides and are replaced by the next scheduled period - PR [#745](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/745). ### Fixed - Fixed Wiser room renames and removals creating duplicate or orphaned devices and entities. Physical devices and logical rooms now use stable identifiers, existing registry records are migrated while retaining entity IDs and history, integration-managed area assignments follow room renames, user-selected areas remain unchanged, and deleted rooms are removed after confirmation - issue [#732](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/732). +- Fixed passive mode for underfloor heating rooms - issue [#641](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/641), PR [#742](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/742). +- Improved light and smart plug responsiveness: commands are no longer blocked by a hub refresh, stale confirmations are retried, obsolete ones are cancelled, and smart plug state updates immediately after a command - issue [#666](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/666), PR [#725](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/725). +- Fixed light and dual-relay channel names, using the device's own name and dropping the redundant channel name on single-channel lights - issue [#666](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/666). +- Fixed OpenTherm options and entities appearing on systems with a standard boiler - issue [#735](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/735), PR [#729](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/729). +- Fixed Hub V1 installations creating unsupported Hub V2 system sensors - PR [#731](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/731). +- Fixed HeatHub parent device compatibility - issue [#733](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/733), PR [#734](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/734). +- Fixed system binary sensors not updating - issue [#736](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/736), PR [#737](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/737). +- Fixed heating and hot-water circuit state normalisation - issue [#711](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/711), PR [#721](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/721). +- Fixed light capability entities being lost during unique ID migration - PR [#723](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/723). +- Fixed flame runtime statistics to count from local midnight - PR [#715](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/715). - Reintroduced the previous Power and Energy entities, corrected equipment data naming on v2 hubs, and added an active state for the window/door sensor - issue [#677](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/677), PR [#690](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/690). - Fixed multi-gang dimmer lights breaking select, binary_sensor, switch, and sensor entities - issue [#681](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/681), PR [#683](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/683). - Preserved light entities across the multi-gang unique_id migration - issue [#681](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/681), PR [#683](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/683). @@ -44,7 +62,7 @@ For releases before v3.3.5, see the [Full Change Log](https://github.com/asantag - Fixed the hot water switch to report against the hub as its parent device - PR [#704](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/704). - Fixed a Zigbee sidebar route conflict that could stop the integration setting up - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). - Fixed the boiler capacity and estimated boiler output sensors to use a gas burner icon - PR [#701](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/701). -- Fix for issue [#662](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/662) - PR [#680](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/680). +- Fixed room stat and iTRV battery values not always being reported correctly - issue [#662](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/662), PR [#680](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/680). ## v3.4.20 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 99d82a46..a7b0fce9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -116,10 +116,28 @@ python3 scripts/build.py --release --channel stable python3 scripts/build.py --release --channel dev ``` +The build downloads every card and panel declared in +`custom_components/wiser/frontend/cards.json` from its own GitHub repository. +Stable builds use stable frontend releases; prerelease builds use the most +recently published stable or prerelease release. In a running installation, +each frontend update entity follows the HACS **Pre-release** switch for this +integration; without that option it offers stable releases only. See +[Adding frontend cards and panels](docs/frontend-registry.md) for the registry +format and shared panel API. + The output is `dist/wiser.zip`, with `dist/card-releases.json` recording the -card releases and checksums included. Stable builds use stable card releases; -prerelease builds use the most recently published stable or prerelease of each -card. Missing or invalid card assets fail the build. +frontend artifacts and checksums included. If an individual card or panel +repository is temporarily unavailable, its bundle is omitted and the +integration still builds; its Home Assistant update entity can install it +later. Invalid local development bundles and an invalid bundled registry still +fail the build. + +For an integration-only test package that retains the registry but +deliberately omits every card and panel bundle: + +```sh +python3 scripts/build.py --channel dev --without-frontend +``` To see which card releases would be selected without downloading card bundles (the registry metadata is still fetched): @@ -128,8 +146,9 @@ To see which card releases would be selected without downloading card bundles python3 scripts/fetch_card_releases.py --channel dev --plan ``` -The **Publish** workflow runs the same build and attaches `wiser.zip` when a -release is published. +The **Publish** GitHub Actions workflow runs the same build and attaches +`wiser.zip` when an integration release is published. Preview runs provide a +downloadable **wiser-package** artifact without publishing a release. ## Licence diff --git a/README.md b/README.md index 38290780..ed21aaed 100755 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Wiser Home Assistant Integration v4.0.0-rc1 +# Wiser Home Assistant Integration v4.0.0 [![hacs_badge](https://img.shields.io/badge/HACS-Default-orange.svg?style=for-the-badge)](https://github.com/hacs/integration) [![downloads](https://shields.io/github/downloads/asantaga/wiserHomeAssistantPlatform/latest/total?style=for-the-badge)](https://github.com/asantaga/wiserHomeAssistantPlatform) @@ -20,29 +20,28 @@ For more information checkout the AMAZING community thread available on ## What's New in 4.0? -This is a big release with a lot of bug fixes and changes. -- Entity and device naming now follows new Home Assistant conventions, where devices are associated with areas. Existing installations keep their current names automatically via the Legacy naming option - turn it off to adopt the new names -- New Wiser devices are assigned to Home Assistant areas matching your Wiser rooms -- Configurable OpenTherm monitoring and controls -- Brand new UI for Wiser Schedules and Wiser Zigbee, including optional sidebar panels -- Multiple bug fixes +This is a **big** release with a lot of new features, bug fixes and changes. -Huge thanks to [@andyblac](https://github.com/andyblac) and [@lgo44](https://github.com/LGO44) for this release - -### Breaking changes in 4.0 +- Entity and device naming now follows Home Assistant conventions, with devices associated with areas. Existing installations keep their current names automatically through the **Legacy naming** option - turn it off to adopt the new names. New installations on Home Assistant 2026.8 and later use the new names by default +- Wiser devices are assigned to Home Assistant areas matching your Wiser rooms, and room renames in the Wiser app no longer create duplicate devices +- Configurable OpenTherm monitoring and controls, plus optional OpenTherm hot water control with its own schedule +- New device support, including the Schneider Mureva EV Link charger, smoke alarm operating states and scheduled setpoint sensors for rooms without heating control +- Brand new UI for Wiser Schedules and Wiser Zigbee, including optional sidebar panels. Cards and panels now update independently of the integration +- Translations for Danish, Spanish, Finnish, Hungarian, Norwegian, Dutch, Portuguese and Swedish +- Many bug fixes -**Please Take a backup before upgrading.** +See the [change log](CHANGELOG.md) for the full list of changes in this release. -- **The device registry is restructured.** The separate virtual controller device is merged into the physical hub device, and Wiser room devices move to stable identifiers. Entity IDs and history are preserved, but anything that targets a Wiser *device* rather than an entity - device-based automations and scripts, or dashboard cards pointing at a device - needs repointing. -- If a device has been used in an automation then Home Assistant repairs should catch this and guide the user through the migration +Huge thanks to [@andyblac](https://github.com/andyblac) and [@lgo44](https://github.com/LGO44) for this release -## What's New in 3.4? +### Breaking changes in 4.0 -- Added support for v2 hub -- Added support for many new v2 hub devices -- Climate entity for controlling hot water with external tank temp sensor +**Please take a backup before upgrading.** -See the [change log](CHANGELOG.md) for the full list of changes in this release. +- **The device registry is restructured.** The separate virtual controller device is merged into the physical hub device, and Wiser room devices move to stable identifiers. Entity IDs and history are preserved, but anything that targets a Wiser *device* rather than an entity - device-based automations and scripts, or dashboard cards pointing at a device - needs repointing. Check these after upgrading. +- **Entity unique IDs move to a new format.** This migration runs automatically and keeps your entity IDs and history. It is all-or-nothing: if it finds a conflict it stops without changing anything, and the integration will not load until it is resolved. +- **Downgrading is not supported.** To go back to 3.x, restore the backup you took before upgrading - reinstalling the older version on its own will not work. +- **Equipment power and energy sensors are now optional.** Existing installations keep them; new installations can enable them under **Equipment sensors** in the integration options. ## Installing @@ -56,36 +55,7 @@ Releases before v3.3.5 are listed on our wiki [here](https://github.com/asantaga ## Building -To build a stable release package, run: - -```sh -python3 scripts/build.py --release --channel stable -``` - -For a prerelease package, use `--channel dev` instead. The build downloads every -card and panel declared in `custom_components/wiser/frontend/cards.json` from -its own GitHub repository. Stable builds use stable frontend releases; -prerelease builds use the most recently published stable or prerelease release. -In a running installation, each frontend update entity follows the HACS -**Pre-release** switch for this integration; without that option it offers stable -releases only. See [Adding frontend cards and panels](docs/frontend-registry.md) -for the registry format and shared panel API. - -For an integration-only test package that retains the registry but deliberately -omits every card and panel bundle, run: - -```sh -python3 scripts/build.py --channel dev --without-frontend -``` - -The output is `dist/wiser.zip`. The accompanying `dist/card-releases.json` file -records the frontend artifacts included in the package. If an individual card -or panel repository is temporarily unavailable, its bundle is omitted and the -integration still builds; its Home Assistant update entity can install it later. -Invalid local development bundles and an invalid bundled registry still fail the -build. - -The **Publish** GitHub Actions workflow runs the same build and attaches `wiser.zip` when an integration release is published. Preview runs provide a downloadable **wiser-package** artifact without publishing a release. +See [Building a package](CONTRIBUTING.md#building-a-package) in the contributing guide. ## Contributing From 2cd1d937e6d3b2cdaa6865d92dd7ebdbbb050961 Mon Sep 17 00:00:00 2001 From: asantaga Date: Sun, 18 Oct 2026 19:54:50 +0100 Subject: [PATCH 150/154] revert: leave equipment sensors off by default on upgrade Equipment sensors are intentionally off by default in 4.0.0, including for installations upgrading from 3.x. Remove the migration default added in bd87fbc and document the change as breaking instead. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 2 +- README.md | 2 +- custom_components/wiser/__init__.py | 3 --- tests/test_room_migration_orchestration.py | 1 - tests/test_ui_options.py | 21 +-------------------- 5 files changed, 3 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa85794d..476ef529 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ For releases before v3.3.5, see the [Full Change Log](https://github.com/asantag - The device registry is restructured. The separate virtual controller device is merged into the physical hub device, and Wiser room devices move to stable identifiers. In both cases the old device is removed and its entities are reassigned to the surviving device. Entity IDs and history are preserved, but anything that targets a Wiser *device* rather than an entity - device-based automations and scripts, or dashboard cards pointing at a device - needs repointing - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693). - Entity unique IDs migrate to deterministic UUIDv5. The migration runs automatically on upgrade and renames registry entries in place, so entity IDs, history, and customisations are preserved. Every target is checked before any change is applied, so it cannot partially apply, but it aborts if it finds a unique ID collision - take a backup before upgrading - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693). - Downgrading is not supported. Because unique IDs and device identifiers change, returning to a 3.x release means restoring the backup taken before upgrading, not just reinstalling the older version. +- Equipment power and energy sensors are now optional and off by default, including for existing installations. To keep them, enable **Equipment sensors** in the integration options after upgrading - PR [#726](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/726). ### Added @@ -34,7 +35,6 @@ For releases before v3.3.5, see the [Full Change Log](https://github.com/asantag - Entity naming now follows Home Assistant conventions, using `has_entity_name` so Home Assistant composes each displayed name from the device name plus the entity name. Existing entity IDs are not renamed. A new **Legacy naming** option controls whether Wiser room names are included in device names; it is switched on automatically for existing installations, so your device names stay as they are unless you turn it off. New installations on Home Assistant 2026.8 and later default it to off - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693), PR [#700](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/700). - Wiser devices are now placed in Home Assistant areas matching their Wiser room, creating the area if it does not exist. This applies only to devices that have no area yet, so any area you assigned manually is left untouched - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693), PR [#700](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/700). -- Equipment power and energy sensors are now optional, under **Equipment sensors** in the integration options. Existing installations upgrading from 3.x keep them switched on; new installations start with them off - PR [#726](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/726). - Card and panel bundles are no longer stored in the source repository. Release packages include them, and each card or panel updates from its own repository through a Home Assistant update entity - PR [#716](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/716). - Sidebar panel visibility is now configured through the integration's UI options - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). - Card versions are now detected from the installed card bundles instead of being pinned in the integration, so card updates no longer need an integration release - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). diff --git a/README.md b/README.md index ed21aaed..3fa8c0ca 100755 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Huge thanks to [@andyblac](https://github.com/andyblac) and [@lgo44](https://git - **The device registry is restructured.** The separate virtual controller device is merged into the physical hub device, and Wiser room devices move to stable identifiers. Entity IDs and history are preserved, but anything that targets a Wiser *device* rather than an entity - device-based automations and scripts, or dashboard cards pointing at a device - needs repointing. Check these after upgrading. - **Entity unique IDs move to a new format.** This migration runs automatically and keeps your entity IDs and history. It is all-or-nothing: if it finds a conflict it stops without changing anything, and the integration will not load until it is resolved. - **Downgrading is not supported.** To go back to 3.x, restore the backup you took before upgrading - reinstalling the older version on its own will not work. -- **Equipment power and energy sensors are now optional.** Existing installations keep them; new installations can enable them under **Equipment sensors** in the integration options. +- **Equipment power and energy sensors are now off by default**, including for existing installations. If you use them, for example in the Energy dashboard, enable **Equipment sensors** in the integration options after upgrading. ## Installing diff --git a/custom_components/wiser/__init__.py b/custom_components/wiser/__init__.py index 766f5369..94c1c480 100755 --- a/custom_components/wiser/__init__.py +++ b/custom_components/wiser/__init__.py @@ -29,7 +29,6 @@ CONF_AUTOMATIONS_PASSIVE, CONF_AUTOMATIONS_PASSIVE_TEMP_INCREMENT, CONF_DEPRECATED_HW_TARGET_TEMP, - CONF_EQUIPMENT_SENSORS, CONF_LEGACY_NAMING, CONF_OPENTHERM_EVER_CONNECTED, CONF_OPENTHERM_HOT_WATER_CAPABLE, @@ -175,8 +174,6 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> if config_entry.minor_version < 5: # Keep room context visible for installations upgrading to UI options. new_options.setdefault(CONF_LEGACY_NAMING, True) - # Equipment sensors were always created before they became optional. - new_options.setdefault(CONF_EQUIPMENT_SENSORS, True) hass.config_entries.async_update_entry( config_entry, options=new_options, minor_version=5, version=1 diff --git a/tests/test_room_migration_orchestration.py b/tests/test_room_migration_orchestration.py index 286082c1..d665efb4 100644 --- a/tests/test_room_migration_orchestration.py +++ b/tests/test_room_migration_orchestration.py @@ -58,7 +58,6 @@ def _load_wiser_init() -> ModuleType: "CONF_AUTOMATIONS_PASSIVE", "CONF_AUTOMATIONS_PASSIVE_TEMP_INCREMENT", "CONF_DEPRECATED_HW_TARGET_TEMP", - "CONF_EQUIPMENT_SENSORS", "CONF_LEGACY_NAMING", "CONF_OPENTHERM_EVER_CONNECTED", "CONF_OPENTHERM_HOT_WATER_CAPABLE", diff --git a/tests/test_ui_options.py b/tests/test_ui_options.py index 41985632..f3c58f7f 100644 --- a/tests/test_ui_options.py +++ b/tests/test_ui_options.py @@ -461,29 +461,10 @@ async def test_migration_enables_legacy_and_preserves_other_options(self): saved = update.call_args.kwargs self.assertEqual( saved["options"], - options | {"legacy_naming": expected, "equipment_sensors": True}, + options | {"legacy_naming": expected}, ) self.assertEqual(saved["minor_version"], 5) - async def test_migration_keeps_equipment_sensors_for_upgrades(self): - functions = load_functions("__init__.py", {"async_migrate_entry"}, self.namespace) - for options, expected in (({}, True), - ({"equipment_sensors": False}, False)): - entry = SimpleNamespace(version=1, minor_version=4, options=options) - update = Mock() - hass = SimpleNamespace(config_entries=SimpleNamespace(async_update_entry=update)) - self.assertTrue(await functions.async_migrate_entry(hass, entry)) - saved = update.call_args.kwargs["options"] - self.assertIs(saved["equipment_sensors"], expected) - - async def test_migration_leaves_current_entries_equipment_option_unset(self): - functions = load_functions("__init__.py", {"async_migrate_entry"}, self.namespace) - entry = SimpleNamespace(version=1, minor_version=5, options={}) - update = Mock() - hass = SimpleNamespace(config_entries=SimpleNamespace(async_update_entry=update)) - self.assertTrue(await functions.async_migrate_entry(hass, entry)) - self.assertNotIn("equipment_sensors", update.call_args.kwargs["options"]) - async def test_menu_available_without_opentherm(self): functions = load_functions("config_flow.py", {"async_step_init"}, self.namespace) flow = SimpleNamespace( From c8066b004f63cedb79ff05d402eca5755822b851 Mon Sep 17 00:00:00 2001 From: asantaga Date: Sun, 18 Oct 2026 20:07:18 +0100 Subject: [PATCH 151/154] chore: finalise 4.0.0 version and README - Bump the integration VERSION constant from 4.0.0-rc1 to 4.0.0 so the hub signal sensor reports the release version. - Describe the unified Wiser sidebar panel, the new Wiser Controls card and Wiser Hub panel, and that the OpenTherm hot water schedule runs in Home Assistant. - Note that room climate demand attributes now require OpenTherm. Co-Authored-By: Claude Opus 5.5 --- README.md | 12 ++++++++---- custom_components/wiser/const.py | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 3fa8c0ca..3d0444d8 100755 --- a/README.md +++ b/README.md @@ -20,15 +20,18 @@ For more information checkout the AMAZING community thread available on ## What's New in 4.0? -This is a **big** release with a lot of new features, bug fixes and changes. +This is a **major** and **big** release with a lot of new features, bug fixes and changes. - Entity and device naming now follows Home Assistant conventions, with devices associated with areas. Existing installations keep their current names automatically through the **Legacy naming** option - turn it off to adopt the new names. New installations on Home Assistant 2026.8 and later use the new names by default - Wiser devices are assigned to Home Assistant areas matching your Wiser rooms, and room renames in the Wiser app no longer create duplicate devices -- Configurable OpenTherm monitoring and controls, plus optional OpenTherm hot water control with its own schedule +- Configurable OpenTherm monitoring and controls, plus optional OpenTherm hot water control with its own schedule. The hot water schedule is run by Home Assistant rather than the hub, so it does not change the boiler while Home Assistant is offline - New device support, including the Schneider Mureva EV Link charger, smoke alarm operating states and scheduled setpoint sensors for rooms without heating control -- Brand new UI for Wiser Schedules and Wiser Zigbee, including optional sidebar panels. Cards and panels now update independently of the integration +- Brand new **UI**: a single **Wiser** sidebar panel with tabs for Schedules, Zigbee, Controls and Hub. It is shown by default and can be hidden with **Show Wiser in sidebar** in the integration's UI options +- New **Wiser Controls card** for dashboards, covering heating, hot water, shutters, lights and smart plugs, alongside the updated Wiser Schedule and Wiser Zigbee cards +- New **Wiser Hub panel** with an overview, live controls, diagnostics and recent history for each hub +- Cards and panels now update independently of the integration, through Home Assistant update entities - Translations for Danish, Spanish, Finnish, Hungarian, Norwegian, Dutch, Portuguese and Swedish -- Many bug fixes +- Many bug fixes see change log See the [change log](CHANGELOG.md) for the full list of changes in this release. @@ -42,6 +45,7 @@ Huge thanks to [@andyblac](https://github.com/andyblac) and [@lgo44](https://git - **Entity unique IDs move to a new format.** This migration runs automatically and keeps your entity IDs and history. It is all-or-nothing: if it finds a conflict it stops without changing anything, and the integration will not load until it is resolved. - **Downgrading is not supported.** To go back to 3.x, restore the backup you took before upgrading - reinstalling the older version on its own will not work. - **Equipment power and energy sensors are now off by default**, including for existing installations. If you use them, for example in the Energy dashboard, enable **Equipment sensors** in the integration options after upgrading. +- **Room climate entities only report `percentage_demand` and `demand_type` when OpenTherm is enabled.** On systems without OpenTherm these attributes are no longer present, so update any templates or automations that use them. ## Installing diff --git a/custom_components/wiser/const.py b/custom_components/wiser/const.py index 92fbf617..3435121e 100755 --- a/custom_components/wiser/const.py +++ b/custom_components/wiser/const.py @@ -9,7 +9,7 @@ import json from pathlib import Path -VERSION = "4.0.0-rc1" +VERSION = "4.0.0" DOMAIN = "wiser" CONF_LEGACY_NAMING = "legacy_naming" DATA_WISER_CONFIG = "wiser_config" From 8eecb7ad93ab7d5cfdf52f210cf5c58e4d1269e0 Mon Sep 17 00:00:00 2001 From: asantaga Date: Sun, 18 Oct 2026 20:14:16 +0100 Subject: [PATCH 152/154] docs: describe unified Wiser panel, Controls card and Hub panel Replace the separate Schedules and Zigbee sidebar panel entries with the single Wiser sidebar panel, and add the Wiser Controls card and Wiser Hub panel shipped through the frontend registry. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 476ef529..12003076 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,9 +22,10 @@ For releases before v3.3.5, see the [Full Change Log](https://github.com/asantag - Added configurable OpenTherm monitoring and controls, including relative modulation, a Delta-T sensor, expanded telemetry, and categorized diagnostics - PR [#697](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/697). - Added OpenTherm room demand attributes - PR [#724](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/724). - Added PowerTag Control equipment sensors - PR [#726](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/726). -- Added a configurable Wiser Schedules sidebar panel - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). -- Added a Wiser Zigbee sidebar panel with a custom sidebar icon - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). -- Added an integration-managed frontend registry (`cards.json`), so the Schedules and Zigbee cards and the sidebar panels install and update independently through Home Assistant update entities, with offline caching and a shared panel-settings API - PR [#709](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/709), PR [#719](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/719). +- Added a single **Wiser** sidebar panel with a custom sidebar icon and tabs for Schedules, Zigbee, Controls and Hub. It is shown by default and can be hidden with **Show Wiser in sidebar** in the integration's UI options - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708), PR [#719](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/719). +- Added the **Wiser Controls card**, a dashboard card for heating, stored and OpenTherm hot water, shutters, lights, dimmers and smart plugs, with room controls, schedule information and bulk actions. It is also available as the Controls tab of the Wiser panel - PR [#719](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/719). +- Added the **Wiser Hub panel**, a Wiser panel tab giving an overview, live controls, diagnostics and recent history charts for each hub - PR [#719](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/719). +- Added an integration-managed frontend registry (`cards.json`), so the Schedule, Zigbee and Controls cards and the Wiser panel tabs install and update independently through Home Assistant update entities, with offline caching and a shared panel-settings API - PR [#709](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/709), PR [#719](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/719). - Added a Hot Water on/off switch entity - issue [#626](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/626), PR [#682](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/682). - Added a UFH controller measured-temperature sensor - issue [#628](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/628). - Added optimistic light state for instant UI feedback on toggles, kept stable across rapid repeated toggles - PR [#684](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/684). @@ -36,7 +37,6 @@ For releases before v3.3.5, see the [Full Change Log](https://github.com/asantag - Entity naming now follows Home Assistant conventions, using `has_entity_name` so Home Assistant composes each displayed name from the device name plus the entity name. Existing entity IDs are not renamed. A new **Legacy naming** option controls whether Wiser room names are included in device names; it is switched on automatically for existing installations, so your device names stay as they are unless you turn it off. New installations on Home Assistant 2026.8 and later default it to off - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693), PR [#700](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/700). - Wiser devices are now placed in Home Assistant areas matching their Wiser room, creating the area if it does not exist. This applies only to devices that have no area yet, so any area you assigned manually is left untouched - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693), PR [#700](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/700). - Card and panel bundles are no longer stored in the source repository. Release packages include them, and each card or panel updates from its own repository through a Home Assistant update entity - PR [#716](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/716). -- Sidebar panel visibility is now configured through the integration's UI options - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). - Card versions are now detected from the installed card bundles instead of being pinned in the integration, so card updates no longer need an integration release - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). - OpenTherm hot-water temperature changes made in Auto mode now act as temporary overrides and are replaced by the next scheduled period - PR [#745](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/745). From d7928d9ff1eceff89b82ee0c1f3b37bbf9e0e7b7 Mon Sep 17 00:00:00 2001 From: asantaga Date: Sun, 18 Oct 2026 20:42:13 +0100 Subject: [PATCH 153/154] fix: report room percentage_demand without OpenTherm percentage_demand is reported by rooms on standard relay systems too, so keep it outside the OpenTherm guard as it was in 3.4.x. demand_type and is_calling_for_heat remain OpenTherm-only. Co-Authored-By: Claude Opus 5.5 --- custom_components/wiser/climate.py | 2 +- tests/test_climate_attributes.py | 62 ++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 tests/test_climate_attributes.py diff --git a/custom_components/wiser/climate.py b/custom_components/wiser/climate.py index 3799d00f..2f7edef9 100755 --- a/custom_components/wiser/climate.py +++ b/custom_components/wiser/climate.py @@ -508,12 +508,12 @@ def extra_state_attributes(self): attrs["is_passive"] = self._room.is_passive_mode attrs["control_output_state"] = "On" if self._room.is_heating else "Off" attrs["heating_rate"] = self._room.heating_rate + attrs["percentage_demand"] = self._room.percentage_demand # OpenTherm opentherm = getattr(self._data.wiserhub.system, "opentherm", None) if opentherm is not None and opentherm.enabled: attrs["demand_type"] = self._room.demand_type - attrs["percentage_demand"] = self._room.percentage_demand if hasattr(self._room, "is_calling_for_heat"): attrs["is_calling_for_heat"] = self._room.is_calling_for_heat else: diff --git a/tests/test_climate_attributes.py b/tests/test_climate_attributes.py new file mode 100644 index 00000000..edf2a636 --- /dev/null +++ b/tests/test_climate_attributes.py @@ -0,0 +1,62 @@ +"""Regression tests for room climate state attributes.""" + +import ast +from pathlib import Path +import unittest + + +COMPONENT_PATH = Path(__file__).parents[1] / "custom_components/wiser" + + +def attribute_assignments(nodes): + """Return the attrs keys assigned by the given nodes.""" + return [ + target.slice.value + for node in nodes + if isinstance(node, ast.Assign) + for target in node.targets + if isinstance(target, ast.Subscript) + and isinstance(target.value, ast.Name) + and target.value.id == "attrs" + and isinstance(target.slice, ast.Constant) + ] + + +class RoomClimateAttributesTest(unittest.TestCase): + """Ensure only OpenTherm-specific room attributes need OpenTherm.""" + + def setUp(self) -> None: + tree = ast.parse((COMPONENT_PATH / "climate.py").read_text()) + wiser_room = next( + node + for node in tree.body + if isinstance(node, ast.ClassDef) and node.name == "WiserRoom" + ) + self.method = next( + node + for node in wiser_room.body + if isinstance(node, ast.FunctionDef) + and node.name == "extra_state_attributes" + ) + self.opentherm_guard = next( + node + for node in self.method.body + if isinstance(node, ast.If) and "opentherm" in ast.unparse(node.test) + ) + + def test_percentage_demand_is_reported_without_opentherm(self) -> None: + self.assertIn("percentage_demand", attribute_assignments(self.method.body)) + self.assertNotIn( + "percentage_demand", + attribute_assignments(ast.walk(self.opentherm_guard)), + ) + + def test_demand_type_is_reported_only_with_opentherm(self) -> None: + guarded = set(ast.walk(self.opentherm_guard)) + unguarded = [node for node in ast.walk(self.method) if node not in guarded] + self.assertIn("demand_type", attribute_assignments(guarded)) + self.assertNotIn("demand_type", attribute_assignments(unguarded)) + + +if __name__ == "__main__": + unittest.main() From 71e044fdab40d9dc1544a1085b2b84dd04e2c218 Mon Sep 17 00:00:00 2001 From: asantaga Date: Sun, 18 Oct 2026 20:42:13 +0100 Subject: [PATCH 154/154] docs: finalise 4.0.0 breaking changes and changelog - Fold fixes for features new in 4.0 into their Added, Changed or Breaking entries instead of listing them as Fixed. - Narrow the room demand breaking change to demand_type and describe is_calling_for_heat as the attribute #724 adds. - Document the circuit state sensors moving from On/Off to on/off. - Note that the version lives in both manifest.json and const.py. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 23 ++++++++--------------- CONTRIBUTING.md | 17 ++++++++++++----- README.md | 3 ++- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12003076..8b4ffe7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,10 +8,12 @@ For releases before v3.3.5, see the [Full Change Log](https://github.com/asantag ### Breaking changes -- The device registry is restructured. The separate virtual controller device is merged into the physical hub device, and Wiser room devices move to stable identifiers. In both cases the old device is removed and its entities are reassigned to the surviving device. Entity IDs and history are preserved, but anything that targets a Wiser *device* rather than an entity - device-based automations and scripts, or dashboard cards pointing at a device - needs repointing - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693). -- Entity unique IDs migrate to deterministic UUIDv5. The migration runs automatically on upgrade and renames registry entries in place, so entity IDs, history, and customisations are preserved. Every target is checked before any change is applied, so it cannot partially apply, but it aborts if it finds a unique ID collision - take a backup before upgrading - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693). +- The device registry is restructured. The separate virtual controller device is merged into the physical hub device, and Wiser room devices move to stable identifiers. In both cases the old device is removed and its entities are reassigned to the surviving device. Entity IDs and history are preserved, but anything that targets a Wiser *device* rather than an entity - device-based automations and scripts, or dashboard cards pointing at a device - needs repointing - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693), issue [#733](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/733), PR [#734](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/734). +- Entity unique IDs migrate to deterministic UUIDv5. The migration runs automatically on upgrade and renames registry entries in place, including light capability entities, so entity IDs, history, and customisations are preserved. Every target is checked before any change is applied, so it cannot partially apply, but it aborts if it finds a unique ID collision - take a backup before upgrading - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693), PR [#723](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/723). - Downgrading is not supported. Because unique IDs and device identifiers change, returning to a 3.x release means restoring the backup taken before upgrading, not just reinstalling the older version. - Equipment power and energy sensors are now optional and off by default, including for existing installations. To keep them, enable **Equipment sensors** in the integration options after upgrading - PR [#726](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/726). +- Room climate entities only report the `demand_type` attribute when OpenTherm is enabled. On systems without OpenTherm it is no longer present, so update any templates or automations that use it. `percentage_demand` is still reported on all systems - PR [#724](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/724). +- The Heating, Heating channel and Hot Water circuit state sensors now report the standard Home Assistant states `on` and `off` instead of `On` and `Off`, and show as unknown when the hub reports neither. The displayed state is unchanged, but templates and automations that compare against `On` or `Off` must use the lowercase values - issue [#711](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/711), PR [#721](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/721). ### Added @@ -19,14 +21,14 @@ For releases before v3.3.5, see the [Full Change Log](https://github.com/asantag - Added smoke alarm operating states and a report count sensor - PR [#744](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/744). - Added scheduled setpoint sensors, showing the current schedule temperature for Wiser rooms without climate control. Rooms are chosen under **Additional sensors** in the automation options - issue [#738](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/738), PR [#746](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/746). - Added optional Wiser-only OpenTherm domestic-hot-water control with a Home Assistant water-heater entity, configurable temperature and presets, an optional external current-temperature sensor, icon mode controls, and an integration-owned weekly schedule managed from the Wiser Schedules panel. Non-timed presets can be used in schedule periods; temporary boost presets remain manual actions - PR [#745](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/745). -- Added configurable OpenTherm monitoring and controls, including relative modulation, a Delta-T sensor, expanded telemetry, and categorized diagnostics - PR [#697](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/697). -- Added OpenTherm room demand attributes - PR [#724](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/724). +- Added configurable OpenTherm monitoring and controls, including relative modulation, a Delta-T sensor, daily flame runtime statistics counted from local midnight, boiler capacity and estimated boiler output sensors, expanded telemetry, and categorized diagnostics. OpenTherm options and entities only appear on systems with an OpenTherm boiler - PR [#697](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/697), PR [#701](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/701), PR [#715](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/715), issue [#735](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/735), PR [#729](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/729). +- Added an `is_calling_for_heat` attribute to room climate entities on OpenTherm systems - PR [#724](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/724). - Added PowerTag Control equipment sensors - PR [#726](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/726). - Added a single **Wiser** sidebar panel with a custom sidebar icon and tabs for Schedules, Zigbee, Controls and Hub. It is shown by default and can be hidden with **Show Wiser in sidebar** in the integration's UI options - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708), PR [#719](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/719). - Added the **Wiser Controls card**, a dashboard card for heating, stored and OpenTherm hot water, shutters, lights, dimmers and smart plugs, with room controls, schedule information and bulk actions. It is also available as the Controls tab of the Wiser panel - PR [#719](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/719). - Added the **Wiser Hub panel**, a Wiser panel tab giving an overview, live controls, diagnostics and recent history charts for each hub - PR [#719](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/719). - Added an integration-managed frontend registry (`cards.json`), so the Schedule, Zigbee and Controls cards and the Wiser panel tabs install and update independently through Home Assistant update entities, with offline caching and a shared panel-settings API - PR [#709](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/709), PR [#719](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/719). -- Added a Hot Water on/off switch entity - issue [#626](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/626), PR [#682](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/682). +- Added a Hot Water on/off switch entity, attached to the hub device - issue [#626](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/626), PR [#682](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/682), PR [#704](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/704). - Added a UFH controller measured-temperature sensor - issue [#628](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/628). - Added optimistic light state for instant UI feedback on toggles, kept stable across rapid repeated toggles - PR [#684](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/684). - Added British English translations and corrected the German, French, and English integration translations - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). @@ -34,7 +36,7 @@ For releases before v3.3.5, see the [Full Change Log](https://github.com/asantag ### Changed -- Entity naming now follows Home Assistant conventions, using `has_entity_name` so Home Assistant composes each displayed name from the device name plus the entity name. Existing entity IDs are not renamed. A new **Legacy naming** option controls whether Wiser room names are included in device names; it is switched on automatically for existing installations, so your device names stay as they are unless you turn it off. New installations on Home Assistant 2026.8 and later default it to off - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693), PR [#700](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/700). +- Entity naming now follows Home Assistant conventions, using `has_entity_name` so Home Assistant composes each displayed name from the device name plus the entity name. Existing entity IDs are not renamed. A new **Legacy naming** option controls whether Wiser room names are included in device names; it is switched on automatically for existing installations, so your device names stay as they are unless you turn it off. New installations on Home Assistant 2026.8 and later default it to off. Light and dual-relay channels are named from the physical device, and single-channel lights do not repeat a channel name - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693), PR [#700](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/700), issue [#666](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/666). - Wiser devices are now placed in Home Assistant areas matching their Wiser room, creating the area if it does not exist. This applies only to devices that have no area yet, so any area you assigned manually is left untouched - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693), PR [#700](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/700). - Card and panel bundles are no longer stored in the source repository. Release packages include them, and each card or panel updates from its own repository through a Home Assistant update entity - PR [#716](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/716). - Card versions are now detected from the installed card bundles instead of being pinned in the integration, so card updates no longer need an integration release - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). @@ -45,23 +47,14 @@ For releases before v3.3.5, see the [Full Change Log](https://github.com/asantag - Fixed Wiser room renames and removals creating duplicate or orphaned devices and entities. Physical devices and logical rooms now use stable identifiers, existing registry records are migrated while retaining entity IDs and history, integration-managed area assignments follow room renames, user-selected areas remain unchanged, and deleted rooms are removed after confirmation - issue [#732](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/732). - Fixed passive mode for underfloor heating rooms - issue [#641](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/641), PR [#742](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/742). - Improved light and smart plug responsiveness: commands are no longer blocked by a hub refresh, stale confirmations are retried, obsolete ones are cancelled, and smart plug state updates immediately after a command - issue [#666](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/666), PR [#725](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/725). -- Fixed light and dual-relay channel names, using the device's own name and dropping the redundant channel name on single-channel lights - issue [#666](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/666). -- Fixed OpenTherm options and entities appearing on systems with a standard boiler - issue [#735](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/735), PR [#729](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/729). - Fixed Hub V1 installations creating unsupported Hub V2 system sensors - PR [#731](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/731). -- Fixed HeatHub parent device compatibility - issue [#733](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/733), PR [#734](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/734). - Fixed system binary sensors not updating - issue [#736](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/736), PR [#737](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/737). -- Fixed heating and hot-water circuit state normalisation - issue [#711](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/711), PR [#721](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/721). -- Fixed light capability entities being lost during unique ID migration - PR [#723](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/723). -- Fixed flame runtime statistics to count from local midnight - PR [#715](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/715). - Reintroduced the previous Power and Energy entities, corrected equipment data naming on v2 hubs, and added an active state for the window/door sensor - issue [#677](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/677), PR [#690](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/690). - Fixed multi-gang dimmer lights breaking select, binary_sensor, switch, and sensor entities - issue [#681](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/681), PR [#683](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/683). - Preserved light entities across the multi-gang unique_id migration - issue [#681](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/681), PR [#683](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/683). - Fixed the device signal sensor to emit once per physical device instead of once per light channel on multi-gang dimmers - issue [#681](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/681), PR [#683](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/683). - Fixed the room **Window Detection Active** binary sensor being presented as a physical window sensor. It carried a `window` device class, so Home Assistant displayed it as Open/Closed as though it reported a real window, when it actually reports whether the room's window-detection feature is switched on. It now shows a plain on/off state. The underlying state values are unchanged, so automations that test for `on`/`off` keep working - only the displayed wording and icon change - PR [#703](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/703). - Fixed away mode and frost protection reporting distinct target temperatures, and the frost protection target now honours the configured value - PR [#693](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/693). -- Fixed the hot water switch to report against the hub as its parent device - PR [#704](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/704). -- Fixed a Zigbee sidebar route conflict that could stop the integration setting up - PR [#708](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/708). -- Fixed the boiler capacity and estimated boiler output sensors to use a gas burner icon - PR [#701](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/701). - Fixed room stat and iTRV battery values not always being reported correctly - issue [#662](https://github.com/asantaga/wiserHomeAssistantPlatform/issues/662), PR [#680](https://github.com/asantaga/wiserHomeAssistantPlatform/pull/680). ## v3.4.20 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a7b0fce9..4a7b5f8d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -100,11 +100,18 @@ surrounding code, which follows Home Assistant core conventions: ## Versioning -`version` in `custom_components/wiser/manifest.json` must stay parseable by HACS -and Home Assistant. Use `X.Y.Z` for releases, `X.Y.Z-rcN` for release -candidates, and `X.Y.ZbN` for beta builds on `dev`. Do not invent suffixes such -as `Dev` — HACS and Home Assistant reject them, and the integration will fail to -load with `does not have a valid version key`. +The version is set in two places, and both must be changed together: + +- `version` in `custom_components/wiser/manifest.json`, which HACS and Home + Assistant read. +- `VERSION` in `custom_components/wiser/const.py`, which the integration reports + itself, for example in the hub sensor's `integration_version` attribute. + +The version must stay parseable by HACS and Home Assistant. Use `X.Y.Z` for +releases, `X.Y.Z-rcN` for release candidates, and `X.Y.ZbN` for beta builds on +`dev`. Do not invent suffixes such as `Dev` — HACS and Home Assistant reject +them, and the integration will fail to load with `does not have a valid version +key`. ## Building a package diff --git a/README.md b/README.md index 3d0444d8..bf72d2d4 100755 --- a/README.md +++ b/README.md @@ -45,7 +45,8 @@ Huge thanks to [@andyblac](https://github.com/andyblac) and [@lgo44](https://git - **Entity unique IDs move to a new format.** This migration runs automatically and keeps your entity IDs and history. It is all-or-nothing: if it finds a conflict it stops without changing anything, and the integration will not load until it is resolved. - **Downgrading is not supported.** To go back to 3.x, restore the backup you took before upgrading - reinstalling the older version on its own will not work. - **Equipment power and energy sensors are now off by default**, including for existing installations. If you use them, for example in the Energy dashboard, enable **Equipment sensors** in the integration options after upgrading. -- **Room climate entities only report `percentage_demand` and `demand_type` when OpenTherm is enabled.** On systems without OpenTherm these attributes are no longer present, so update any templates or automations that use them. +- **Room climate entities only report `demand_type` when OpenTherm is enabled.** On systems without OpenTherm this attribute is no longer present, so update any templates or automations that use it. `percentage_demand` is still reported on all systems. +- **The Heating and Hot Water circuit state sensors now report `on`/`off` instead of `On`/`Off`.** The dashboard still shows On and Off, but templates and automations that compare against `On` or `Off` need updating to the lowercase values. ## Installing