diff --git a/src/components/ha-filter-devices.ts b/src/components/ha-filter-devices.ts
index 4b9f2bebc443..de5f5d9c7850 100644
--- a/src/components/ha-filter-devices.ts
+++ b/src/components/ha-filter-devices.ts
@@ -13,10 +13,11 @@ import { stringCompare } from "../common/string/compare";
import { computeDeviceName } from "../data/device_registry";
import { findRelated, RelatedResult } from "../data/search";
import { haStyleScrollbar } from "../resources/styles";
+import { loadVirtualizer } from "../resources/virtualizer";
import type { HomeAssistant } from "../types";
-import "./ha-expansion-panel";
import "./ha-check-list-item";
-import { loadVirtualizer } from "../resources/virtualizer";
+import "./ha-expansion-panel";
+import "./search-input-outlined";
@customElement("ha-filter-devices")
export class HaFilterDevices extends LitElement {
@@ -32,6 +33,8 @@ export class HaFilterDevices extends LitElement {
@state() private _shouldRender = false;
+ @state() private _filter?: string;
+
public willUpdate(properties: PropertyValues) {
super.willUpdate(properties);
@@ -55,15 +58,25 @@ export class HaFilterDevices extends LitElement {
: nothing}
${this._shouldRender
- ? html`
-
-
- `
+
+
+
+
+ `
: nothing}
`;
@@ -72,12 +85,14 @@ export class HaFilterDevices extends LitElement {
private _keyFunction = (device) => device?.id;
private _renderItem = (device) =>
- html`
- ${computeDeviceName(device, this.hass)}
- `;
+ !device
+ ? nothing
+ : html`
+ ${computeDeviceName(device, this.hass)}
+ `;
private _handleItemClick(ev) {
const listItem = ev.target.closest("ha-check-list-item");
@@ -99,7 +114,7 @@ export class HaFilterDevices extends LitElement {
setTimeout(() => {
if (!this.expanded) return;
this.renderRoot.querySelector("mwc-list")!.style.height =
- `${this.clientHeight - 49}px`;
+ `${this.clientHeight - 49 - 32}px`; // 32px is the height of the search input
}, 300);
}
}
@@ -112,16 +127,28 @@ export class HaFilterDevices extends LitElement {
this.expanded = ev.detail.expanded;
}
- private _devices = memoizeOne((devices: HomeAssistant["devices"], _value) => {
- const values = Object.values(devices);
- return values.sort((a, b) =>
- stringCompare(
- a.name_by_user || a.name || "",
- b.name_by_user || b.name || "",
- this.hass.locale.language
- )
- );
- });
+ private _handleSearchChange(ev: CustomEvent) {
+ this._filter = ev.detail.value.toLowerCase();
+ }
+
+ private _devices = memoizeOne(
+ (devices: HomeAssistant["devices"], filter: string, _value) => {
+ const values = Object.values(devices);
+ return values
+ .filter(
+ (device) =>
+ !filter ||
+ computeDeviceName(device, this.hass).toLowerCase().includes(filter)
+ )
+ .sort((a, b) =>
+ stringCompare(
+ computeDeviceName(a, this.hass),
+ computeDeviceName(b, this.hass),
+ this.hass.locale.language
+ )
+ );
+ }
+ );
private async _findRelated() {
const relatedPromises: Promise[] = [];
@@ -197,6 +224,10 @@ export class HaFilterDevices extends LitElement {
ha-check-list-item {
width: 100%;
}
+ search-input-outlined {
+ display: block;
+ padding: 0 8px;
+ }
`,
];
}
diff --git a/src/components/ha-filter-entities.ts b/src/components/ha-filter-entities.ts
index 2cffd9945612..15d9b2f39154 100644
--- a/src/components/ha-filter-entities.ts
+++ b/src/components/ha-filter-entities.ts
@@ -14,10 +14,11 @@ import { computeStateName } from "../common/entity/compute_state_name";
import { stringCompare } from "../common/string/compare";
import { findRelated, RelatedResult } from "../data/search";
import { haStyleScrollbar } from "../resources/styles";
+import { loadVirtualizer } from "../resources/virtualizer";
import type { HomeAssistant } from "../types";
-import "./ha-state-icon";
import "./ha-check-list-item";
-import { loadVirtualizer } from "../resources/virtualizer";
+import "./ha-state-icon";
+import "./search-input-outlined";
@customElement("ha-filter-entities")
export class HaFilterEntities extends LitElement {
@@ -33,6 +34,8 @@ export class HaFilterEntities extends LitElement {
@state() private _shouldRender = false;
+ @state() private _filter?: string;
+
public willUpdate(properties: PropertyValues) {
super.willUpdate(properties);
@@ -57,11 +60,18 @@ export class HaFilterEntities extends LitElement {
${this._shouldRender
? html`
+
+
{
if (!this.expanded) return;
this.renderRoot.querySelector("mwc-list")!.style.height =
- `${this.clientHeight - 49}px`;
+ `${this.clientHeight - 49 - 32}px`; // 32px is the height of the search input
}, 300);
}
}
@@ -89,18 +99,20 @@ export class HaFilterEntities extends LitElement {
private _keyFunction = (entity) => entity?.entity_id;
private _renderItem = (entity) =>
- html`
-
- ${computeStateName(entity)}
- `;
+ !entity
+ ? nothing
+ : html`
+
+ ${computeStateName(entity)}
+ `;
private _handleItemClick(ev) {
const listItem = ev.target.closest("ha-check-list-item");
@@ -125,12 +137,27 @@ export class HaFilterEntities extends LitElement {
this.expanded = ev.detail.expanded;
}
+ private _handleSearchChange(ev: CustomEvent) {
+ this._filter = ev.detail.value.toLowerCase();
+ }
+
private _entities = memoizeOne(
- (states: HomeAssistant["states"], type: this["type"], _value) => {
+ (
+ states: HomeAssistant["states"],
+ type: this["type"],
+ filter: string,
+ _value
+ ) => {
const values = Object.values(states);
return values
.filter(
- (entityState) => !type || computeStateDomain(entityState) !== type
+ (entityState) =>
+ (!type || computeStateDomain(entityState) !== type) &&
+ (!filter ||
+ entityState.entity_id.toLowerCase().includes(filter) ||
+ entityState.attributes.friendly_name
+ ?.toLowerCase()
+ .includes(filter))
)
.sort((a, b) =>
stringCompare(
@@ -216,6 +243,10 @@ export class HaFilterEntities extends LitElement {
--mdc-list-item-graphic-margin: 16px;
width: 100%;
}
+ search-input-outlined {
+ display: block;
+ padding: 0 8px;
+ }
`,
];
}