diff --git a/src/panels/developer-tools/state/developer-tools-state.js b/src/panels/developer-tools/state/developer-tools-state.js
deleted file mode 100644
index bddf382e5b..0000000000
--- a/src/panels/developer-tools/state/developer-tools-state.js
+++ /dev/null
@@ -1,699 +0,0 @@
-import { addHours } from "date-fns/esm";
-import "@material/mwc-button";
-import {
- mdiClipboardTextMultipleOutline,
- mdiInformationOutline,
- mdiRefresh,
-} from "@mdi/js";
-import { html } from "@polymer/polymer/lib/utils/html-tag";
-/* eslint-plugin-disable lit */
-import { PolymerElement } from "@polymer/polymer/polymer-element";
-import { dump, load } from "js-yaml";
-import { formatDateTimeWithSeconds } from "../../../common/datetime/format_date_time";
-import { computeRTL } from "../../../common/util/compute_rtl";
-import { escapeRegExp } from "../../../common/string/escape_regexp";
-import { copyToClipboard } from "../../../common/util/copy-clipboard";
-import "../../../components/entity/ha-entity-picker";
-import "../../../components/ha-code-editor";
-import "../../../components/ha-icon-button";
-import "../../../components/ha-svg-icon";
-import "../../../components/ha-checkbox";
-import "../../../components/ha-tip";
-import "../../../components/ha-alert";
-import "../../../components/search-input";
-import "../../../components/ha-expansion-panel";
-import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box";
-import { EventsMixin } from "../../../mixins/events-mixin";
-import LocalizeMixin from "../../../mixins/localize-mixin";
-import "../../../styles/polymer-ha-style";
-
-const ERROR_SENTINEL = {};
-/*
- * @appliesMixin EventsMixin
- * @appliesMixin LocalizeMixin
- */
-class HaPanelDevState extends EventsMixin(LocalizeMixin(PolymerElement)) {
- static get template() {
- return html`
-
-
- [[localize('ui.panel.developer-tools.tabs.states.current_entities')]]
-
-
-
- [[localize('ui.panel.developer-tools.tabs.states.description1')]]
- [[localize('ui.panel.developer-tools.tabs.states.description2')]]
-
-
- [[_error]]
-
-
-
-
-
-
- [[localize('ui.panel.developer-tools.tabs.states.entity')]] |
- [[localize('ui.panel.developer-tools.tabs.states.state')]] |
-
- [[localize('ui.panel.developer-tools.tabs.states.attributes')]]
-
- |
-
-
-
-
- |
-
-
- |
-
-
- |
-
-
-
- [[localize('ui.panel.developer-tools.tabs.states.no_entities')]]
- |
-
-
-
-
-
-
-
-
-
- [[entity.attributes.friendly_name]]
-
-
-
- |
- [[entity.state]] |
-
- [[attributeString(entity)]] |
-
-
-
-
-
- `;
- }
-
- static get properties() {
- return {
- hass: {
- type: Object,
- },
-
- parsedJSON: {
- type: Object,
- computed: "_computeParsedStateAttributes(_stateAttributes)",
- },
-
- validJSON: {
- type: Boolean,
- computed: "_computeValidJSON(parsedJSON)",
- },
-
- _error: {
- type: String,
- value: "",
- },
-
- _entityId: {
- type: String,
- value: "",
- },
-
- _entityFilter: {
- type: String,
- value: "",
- },
-
- _stateFilter: {
- type: String,
- value: "",
- },
-
- _attributeFilter: {
- type: String,
- value: "",
- },
-
- _entity: {
- type: Object,
- },
-
- _state: {
- type: String,
- value: "",
- },
-
- _stateAttributes: {
- type: String,
- value: "",
- },
-
- _showAttributes: {
- type: Boolean,
- value: JSON.parse(
- localStorage.getItem("devToolsShowAttributes") || true
- ),
- },
-
- _entities: {
- type: Array,
- computed:
- "computeEntities(hass, _entityFilter, _stateFilter, _attributeFilter)",
- },
-
- _expanded: {
- type: Boolean,
- value: false,
- },
-
- narrow: {
- type: Boolean,
- reflectToAttribute: true,
- },
-
- rtl: {
- reflectToAttribute: true,
- computed: "_computeRTL(hass)",
- },
- };
- }
-
- copyEntity(ev) {
- ev.preventDefault();
- copyToClipboard(ev.model.entity.entity_id);
- }
-
- entitySelected(ev) {
- const state = ev.model.entity;
- this._entityId = state.entity_id;
- this._entity = state;
- this._state = state.state;
- this._stateAttributes = dump(state.attributes);
- this._expanded = true;
- ev.preventDefault();
- }
-
- entityIdChanged() {
- if (!this._entityId) {
- this._entity = undefined;
- this._state = "";
- this._stateAttributes = "";
- return;
- }
- const state = this.hass.states[this._entityId];
- if (!state) {
- return;
- }
- this._entity = state;
- this._state = state.state;
- this._stateAttributes = dump(state.attributes);
- this._expanded = true;
- }
-
- stateChanged(ev) {
- this._state = ev.target.value;
- }
-
- _entityFilterChanged(ev) {
- this._entityFilter = ev.detail.value;
- }
-
- _stateFilterChanged(ev) {
- this._stateFilter = ev.detail.value;
- }
-
- _attributeFilterChanged(ev) {
- this._attributeFilter = ev.detail.value;
- }
-
- _getHistoryURL(entityId, inputDate) {
- const date = new Date(inputDate);
- const hourBefore = addHours(date, -1).toISOString();
- return `/history?entity_id=${entityId}&start_date=${hourBefore}`;
- }
-
- historyFromLastChanged(entity) {
- return this._getHistoryURL(entity.entity_id, entity.last_changed);
- }
-
- historyFromLastUpdated(entity) {
- return this._getHistoryURL(entity.entity_id, entity.last_updated);
- }
-
- expandedChanged(ev) {
- this._expanded = ev.detail.expanded;
- }
-
- entityMoreInfo(ev) {
- ev.preventDefault();
- this.fire("hass-more-info", { entityId: ev.model.entity.entity_id });
- }
-
- async handleSetState() {
- this._error = "";
- if (!this._entityId) {
- showAlertDialog(this, {
- text: this.hass.localize(
- "ui.panel.developer-tools.tabs.states.alert_entity_field"
- ),
- });
- return;
- }
- try {
- await this.hass.callApi("POST", "states/" + this._entityId, {
- state: this._state,
- attributes: this.parsedJSON,
- });
- } catch (e) {
- this._error = e.body?.message || "Unknown error";
- }
- }
-
- informationOutlineIcon() {
- return mdiInformationOutline;
- }
-
- clipboardOutlineIcon() {
- return mdiClipboardTextMultipleOutline;
- }
-
- refreshIcon() {
- return mdiRefresh;
- }
-
- computeEntities(hass, _entityFilter, _stateFilter, _attributeFilter) {
- const entityFilterRegExp =
- _entityFilter &&
- RegExp(escapeRegExp(_entityFilter).replace(/\\\*/g, ".*"), "i");
-
- const stateFilterRegExp =
- _stateFilter &&
- RegExp(escapeRegExp(_stateFilter).replace(/\\\*/g, ".*"), "i");
-
- let keyFilterRegExp;
- let valueFilterRegExp;
- let multiMode = false;
-
- if (_attributeFilter) {
- const colonIndex = _attributeFilter.indexOf(":");
- multiMode = colonIndex !== -1;
-
- const keyFilter = multiMode
- ? _attributeFilter.substring(0, colonIndex).trim()
- : _attributeFilter;
- const valueFilter = multiMode
- ? _attributeFilter.substring(colonIndex + 1).trim()
- : _attributeFilter;
-
- keyFilterRegExp = RegExp(
- escapeRegExp(keyFilter).replace(/\\\*/g, ".*"),
- "i"
- );
- valueFilterRegExp = multiMode
- ? RegExp(escapeRegExp(valueFilter).replace(/\\\*/g, ".*"), "i")
- : keyFilterRegExp;
- }
-
- return Object.values(hass.states)
- .filter((value) => {
- if (
- entityFilterRegExp &&
- !entityFilterRegExp.test(value.entity_id) &&
- (value.attributes.friendly_name === undefined ||
- !entityFilterRegExp.test(value.attributes.friendly_name))
- ) {
- return false;
- }
-
- if (stateFilterRegExp && !stateFilterRegExp.test(value.state)) {
- return false;
- }
-
- if (keyFilterRegExp && valueFilterRegExp) {
- for (const [key, attributeValue] of Object.entries(
- value.attributes
- )) {
- const match = keyFilterRegExp.test(key);
- if (match && !multiMode) {
- return true; // in single mode we're already satisfied with this match
- }
- if (!match && multiMode) {
- continue;
- }
-
- if (
- attributeValue !== undefined &&
- valueFilterRegExp.test(JSON.stringify(attributeValue))
- ) {
- return true;
- }
- }
-
- // there are no attributes where the key and/or value can be matched
- return false;
- }
-
- return true;
- })
- .sort((entityA, entityB) => {
- if (entityA.entity_id < entityB.entity_id) {
- return -1;
- }
- if (entityA.entity_id > entityB.entity_id) {
- return 1;
- }
- return 0;
- });
- }
-
- computeShowEntitiesPlaceholder(_entities) {
- return _entities.length === 0;
- }
-
- computeShowAttributes(narrow, _showAttributes) {
- return !narrow && _showAttributes;
- }
-
- attributeString(entity) {
- let output = "";
- let i;
- let keys;
- let key;
- let value;
-
- for (i = 0, keys = Object.keys(entity.attributes); i < keys.length; i++) {
- key = keys[i];
- value = this.formatAttributeValue(entity.attributes[key]);
- output += `${key}: ${value}\n`;
- }
- return output;
- }
-
- lastChangedString(entity) {
- return formatDateTimeWithSeconds(
- new Date(entity.last_changed),
- this.hass.locale,
- this.hass.config
- );
- }
-
- lastUpdatedString(entity) {
- return formatDateTimeWithSeconds(
- new Date(entity.last_updated),
- this.hass.locale,
- this.hass.config
- );
- }
-
- formatAttributeValue(value) {
- if (
- (Array.isArray(value) && value.some((val) => val instanceof Object)) ||
- (!Array.isArray(value) && value instanceof Object)
- ) {
- return `\n${dump(value)}`;
- }
- return Array.isArray(value) ? value.join(", ") : value;
- }
-
- saveAttributeCheckboxState(ev) {
- this._showAttributes = ev.target.checked;
- try {
- localStorage.setItem("devToolsShowAttributes", ev.target.checked);
- } catch (e) {
- // Catch for Safari private mode
- }
- }
-
- _computeParsedStateAttributes(stateAttributes) {
- try {
- return stateAttributes.trim() ? load(stateAttributes) : {};
- } catch (err) {
- return ERROR_SENTINEL;
- }
- }
-
- _computeValidJSON(parsedJSON) {
- return parsedJSON !== ERROR_SENTINEL;
- }
-
- _yamlChanged(ev) {
- this._stateAttributes = ev.detail.value;
- }
-
- _computeRTL(hass) {
- return computeRTL(hass);
- }
-}
-
-customElements.define("developer-tools-state", HaPanelDevState);
diff --git a/src/panels/developer-tools/state/developer-tools-state.ts b/src/panels/developer-tools/state/developer-tools-state.ts
new file mode 100644
index 0000000000..8a77150e45
--- /dev/null
+++ b/src/panels/developer-tools/state/developer-tools-state.ts
@@ -0,0 +1,708 @@
+import { addHours } from "date-fns/esm";
+import "@material/mwc-button";
+import {
+ mdiClipboardTextMultipleOutline,
+ mdiInformationOutline,
+ mdiRefresh,
+} from "@mdi/js";
+import { CSSResultGroup, LitElement, css, html, nothing } from "lit";
+import { customElement, property, state } from "lit/decorators";
+import {
+ HassEntities,
+ HassEntity,
+ HassEntityAttributeBase,
+} from "home-assistant-js-websocket";
+import memoizeOne from "memoize-one";
+import { formatDateTimeWithSeconds } from "../../../common/datetime/format_date_time";
+import { computeRTL } from "../../../common/util/compute_rtl";
+import { escapeRegExp } from "../../../common/string/escape_regexp";
+import { copyToClipboard } from "../../../common/util/copy-clipboard";
+import "../../../components/entity/ha-entity-picker";
+import "../../../components/ha-yaml-editor";
+import "../../../components/ha-icon-button";
+import "../../../components/ha-svg-icon";
+import "../../../components/ha-checkbox";
+import "../../../components/ha-tip";
+import "../../../components/ha-alert";
+import "../../../components/search-input";
+import "../../../components/ha-expansion-panel";
+import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box";
+import { haStyle } from "../../../resources/styles";
+import { HomeAssistant } from "../../../types";
+import { fireEvent } from "../../../common/dom/fire_event";
+import { toggleAttribute } from "../../../common/dom/toggle_attribute";
+import { storage } from "../../../common/decorators/storage";
+
+@customElement("developer-tools-state")
+class HaPanelDevState extends LitElement {
+ @property({ attribute: false }) public hass!: HomeAssistant;
+
+ @state() private _error: string = "";
+
+ @state() private _entityId: string = "";
+
+ @state() private _entityFilter: string = "";
+
+ @state() private _stateFilter: string = "";
+
+ @state() private _attributeFilter: string = "";
+
+ @state() private _entity?: HassEntity;
+
+ @state() private _state: string = "";
+
+ @state() private _stateAttributes: HassEntityAttributeBase & {
+ [key: string]: any;
+ } = {};
+
+ @state() private _expanded = false;
+
+ @state() private _validJSON: boolean = true;
+
+ @storage({
+ key: "devToolsShowAttributes",
+ state: true,
+ })
+ private _showAttributes = true;
+
+ @property({ type: Boolean, reflect: true }) public narrow = false;
+
+ @property({ type: Boolean, reflect: true }) public rtl = false;
+
+ private _filteredEntities = memoizeOne(
+ (
+ entityFilter: string,
+ stateFilter: string,
+ attributeFilter: string,
+ states: HassEntities
+ ): HassEntity[] =>
+ this._applyFiltersOnEntities(
+ entityFilter,
+ stateFilter,
+ attributeFilter,
+ states
+ )
+ );
+
+ protected render() {
+ const entities = this._filteredEntities(
+ this._entityFilter,
+ this._stateFilter,
+ this._attributeFilter,
+ this.hass.states
+ );
+ const showAttributes = !this.narrow && this._showAttributes;
+
+ return html`
+
+ ${this.hass.localize(
+ "ui.panel.developer-tools.tabs.states.current_entities"
+ )}
+
+
+
+ ${this.hass.localize(
+ "ui.panel.developer-tools.tabs.states.description1"
+ )}
+ ${this.hass.localize(
+ "ui.panel.developer-tools.tabs.states.description2"
+ )}
+
+ ${this._error
+ ? html`${this._error}}`
+ : nothing}
+
+
+
+
+
+
+ ${this.hass.localize(
+ "ui.panel.developer-tools.tabs.states.entity"
+ )}
+ |
+
+ ${this.hass.localize(
+ "ui.panel.developer-tools.tabs.states.state"
+ )}
+ |
+ ${!this.narrow
+ ? html`
+ ${this.hass.localize(
+ "ui.panel.developer-tools.tabs.states.attributes"
+ )}
+
+ | `
+ : nothing}
+
+
+
+
+ |
+
+
+ |
+ ${showAttributes
+ ? html`
+
+ | `
+ : nothing}
+
+ ${entities.length === 0
+ ? html`
+
+ ${this.hass.localize(
+ "ui.panel.developer-tools.tabs.states.no_entities"
+ )}
+ |
+
`
+ : nothing}
+ ${entities.map(
+ (entity) =>
+ html`
+
+
+
+
+
+
+ ${entity.attributes.friendly_name}
+
+
+
+ |
+ ${entity.state} |
+ ${showAttributes
+ ? html`${this._attributeString(entity)} | `
+ : nothing}
+
`
+ )}
+
+
+ `;
+ }
+
+ protected updated(changedProps) {
+ super.updated(changedProps);
+ const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
+ if (!oldHass || oldHass.locale !== this.hass.locale) {
+ toggleAttribute(this, "rtl", computeRTL(this.hass));
+ }
+ }
+
+ private _copyEntity(ev) {
+ ev.preventDefault();
+ const entity = (ev.currentTarget! as any).entity;
+ copyToClipboard(entity.entity_id);
+ }
+
+ private _entitySelected(ev) {
+ const entityState: HassEntity = (ev.currentTarget! as any).entity;
+ this._entityId = entityState.entity_id;
+ this._entity = entityState;
+ this._state = entityState.state;
+ this._stateAttributes = entityState.attributes;
+ this._expanded = true;
+ ev.preventDefault();
+ }
+
+ private _entityIdChanged() {
+ if (!this._entityId) {
+ this._entity = undefined;
+ this._state = "";
+ this._stateAttributes = {};
+ return;
+ }
+ const entityState = this.hass.states[this._entityId];
+ if (!entityState) {
+ return;
+ }
+ this._entity = entityState;
+ this._state = entityState.state;
+ this._stateAttributes = entityState.attributes;
+ this._expanded = true;
+ }
+
+ private _stateChanged(ev) {
+ this._state = ev.target.value;
+ }
+
+ private _entityFilterChanged(ev) {
+ this._entityFilter = ev.detail.value;
+ }
+
+ private _stateFilterChanged(ev) {
+ this._stateFilter = ev.detail.value;
+ }
+
+ private _attributeFilterChanged(ev) {
+ this._attributeFilter = ev.detail.value;
+ }
+
+ private _getHistoryURL(entityId, inputDate) {
+ const date = new Date(inputDate);
+ const hourBefore = addHours(date, -1).toISOString();
+ return `/history?entity_id=${entityId}&start_date=${hourBefore}`;
+ }
+
+ private _historyFromLastChanged(entity) {
+ return this._getHistoryURL(entity.entity_id, entity.last_changed);
+ }
+
+ private _historyFromLastUpdated(entity) {
+ return this._getHistoryURL(entity.entity_id, entity.last_updated);
+ }
+
+ private _expandedChanged(ev) {
+ this._expanded = ev.detail.expanded;
+ }
+
+ private _entityMoreInfo(ev) {
+ ev.preventDefault();
+ const entity = (ev.currentTarget! as any).entity;
+ fireEvent(this, "hass-more-info", { entityId: entity.entity_id });
+ }
+
+ private async _handleSetState() {
+ this._error = "";
+ if (!this._entityId) {
+ showAlertDialog(this, {
+ text: this.hass.localize(
+ "ui.panel.developer-tools.tabs.states.alert_entity_field"
+ ),
+ });
+ return;
+ }
+ try {
+ await this.hass.callApi("POST", "states/" + this._entityId, {
+ state: this._state,
+ attributes: this._stateAttributes,
+ });
+ } catch (e: any) {
+ this._error = e.body?.message || "Unknown error";
+ }
+ }
+
+ private _applyFiltersOnEntities(
+ entityFilter: string,
+ stateFilter: string,
+ attributeFilter: string,
+ states: HassEntities
+ ) {
+ const entityFilterRegExp =
+ entityFilter &&
+ RegExp(escapeRegExp(entityFilter).replace(/\\\*/g, ".*"), "i");
+
+ const stateFilterRegExp =
+ stateFilter &&
+ RegExp(escapeRegExp(stateFilter).replace(/\\\*/g, ".*"), "i");
+
+ let keyFilterRegExp;
+ let valueFilterRegExp;
+ let multiMode = false;
+
+ if (attributeFilter) {
+ const colonIndex = attributeFilter.indexOf(":");
+ multiMode = colonIndex !== -1;
+
+ const keyFilter = multiMode
+ ? attributeFilter.substring(0, colonIndex).trim()
+ : attributeFilter;
+ const valueFilter = multiMode
+ ? attributeFilter.substring(colonIndex + 1).trim()
+ : attributeFilter;
+
+ keyFilterRegExp = RegExp(
+ escapeRegExp(keyFilter).replace(/\\\*/g, ".*"),
+ "i"
+ );
+ valueFilterRegExp = multiMode
+ ? RegExp(escapeRegExp(valueFilter).replace(/\\\*/g, ".*"), "i")
+ : keyFilterRegExp;
+ }
+
+ return Object.values(states)
+ .filter((value) => {
+ if (
+ entityFilterRegExp &&
+ !entityFilterRegExp.test(value.entity_id) &&
+ (value.attributes.friendly_name === undefined ||
+ !entityFilterRegExp.test(value.attributes.friendly_name))
+ ) {
+ return false;
+ }
+
+ if (stateFilterRegExp && !stateFilterRegExp.test(value.state)) {
+ return false;
+ }
+
+ if (keyFilterRegExp && valueFilterRegExp) {
+ for (const [key, attributeValue] of Object.entries(
+ value.attributes
+ )) {
+ const match = keyFilterRegExp.test(key);
+ if (match && !multiMode) {
+ return true; // in single mode we're already satisfied with this match
+ }
+ if (!match && multiMode) {
+ continue;
+ }
+
+ if (
+ attributeValue !== undefined &&
+ valueFilterRegExp.test(JSON.stringify(attributeValue))
+ ) {
+ return true;
+ }
+ }
+
+ // there are no attributes where the key and/or value can be matched
+ return false;
+ }
+
+ return true;
+ })
+ .sort((entityA, entityB) => {
+ if (entityA.entity_id < entityB.entity_id) {
+ return -1;
+ }
+ if (entityA.entity_id > entityB.entity_id) {
+ return 1;
+ }
+ return 0;
+ });
+ }
+
+ private _attributeString(entity) {
+ const output = "";
+
+ if (entity && entity.attributes) {
+ return Object.keys(entity.attributes).map(
+ (key) => `${key}: ${entity.attributes[key]}\n`
+ );
+ }
+
+ return output;
+ }
+
+ private _lastChangedString(entity) {
+ return formatDateTimeWithSeconds(
+ new Date(entity.last_changed),
+ this.hass.locale,
+ this.hass.config
+ );
+ }
+
+ private _lastUpdatedString(entity) {
+ return formatDateTimeWithSeconds(
+ new Date(entity.last_updated),
+ this.hass.locale,
+ this.hass.config
+ );
+ }
+
+ private _saveAttributeCheckboxState(ev) {
+ this._showAttributes = ev.target.checked;
+ }
+
+ private _yamlChanged(ev) {
+ this._stateAttributes = ev.detail.value;
+ this._validJSON = ev.detail.isValid;
+ }
+
+ static get styles(): CSSResultGroup {
+ return [
+ haStyle,
+ css`
+ :host {
+ -ms-user-select: initial;
+ -webkit-user-select: initial;
+ -moz-user-select: initial;
+ display: block;
+ padding: 16px;
+ padding: max(16px, env(safe-area-inset-top))
+ max(16px, env(safe-area-inset-right))
+ max(16px, env(safe-area-inset-bottom))
+ max(16px, env(safe-area-inset-left));
+ }
+
+ ha-textfield {
+ display: block;
+ }
+
+ .state-input {
+ margin-top: 16px;
+ }
+
+ ha-expansion-panel {
+ margin: 0 8px 16px;
+ }
+
+ .inputs {
+ width: 100%;
+ max-width: 800px;
+ }
+
+ .info {
+ padding: 0 16px;
+ }
+
+ .button-row {
+ display: flex;
+ margin-top: 8px;
+ align-items: center;
+ }
+
+ .table-wrapper {
+ width: 100%;
+ overflow: auto;
+ }
+
+ .entities th {
+ padding: 0 8px;
+ text-align: left;
+ font-size: var(
+ --paper-input-container-shared-input-style_-_font-size
+ );
+ }
+
+ .filters th {
+ padding: 0;
+ }
+
+ .filters search-input {
+ display: block;
+ --mdc-text-field-fill-color: transparent;
+ }
+ ha-tip {
+ display: flex;
+ padding: 8px 0;
+ text-align: left;
+ }
+
+ th.attributes {
+ position: relative;
+ }
+
+ th.attributes ha-checkbox {
+ position: absolute;
+ bottom: -8px;
+ }
+
+ :host([rtl]) .entities th {
+ text-align: right;
+ direction: rtl;
+ }
+
+ :host([rtl]) .filters {
+ direction: rtl;
+ }
+
+ .entities tr {
+ vertical-align: top;
+ direction: ltr;
+ }
+
+ .entities tr:nth-child(odd) {
+ background-color: var(--table-row-background-color, #fff);
+ }
+
+ .entities tr:nth-child(even) {
+ background-color: var(--table-row-alternative-background-color, #eee);
+ }
+ .entities td {
+ padding: 4px;
+ min-width: 200px;
+ word-break: break-word;
+ }
+ .entities ha-svg-icon {
+ --mdc-icon-size: 20px;
+ padding: 4px;
+ cursor: pointer;
+ flex-shrink: 0;
+ margin-right: 8px;
+ }
+ .entities td:nth-child(1) {
+ min-width: 300px;
+ width: 30%;
+ }
+ .entities td:nth-child(3) {
+ white-space: pre-wrap;
+ word-break: break-word;
+ }
+
+ .entities a {
+ color: var(--primary-color);
+ }
+
+ .entities .id-name-container {
+ display: flex;
+ flex-direction: column;
+ }
+ .entities .id-name-row {
+ display: flex;
+ align-items: center;
+ }
+
+ :host([narrow]) .state-wrapper {
+ flex-direction: column;
+ }
+
+ :host([narrow]) .info {
+ padding: 0;
+ }
+
+ .flex-horizontal {
+ display: flex;
+ flex-direction: row;
+ }
+ `,
+ ];
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "developer-tools-state": HaPanelDevState;
+ }
+}