Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 54 additions & 100 deletions src/components/ha-area-picker.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,6 @@
import { mdiCheck, mdiClose, mdiMenuDown, mdiMenuUp } from "@mdi/js";
import "@polymer/paper-input/paper-input";
import "@polymer/paper-item/paper-item";
import "@polymer/paper-item/paper-item-body";
import "@polymer/paper-listbox/paper-listbox";
import "@vaadin/combo-box/theme/material/vaadin-combo-box-light";
import { UnsubscribeFunc } from "home-assistant-js-websocket";
import {
css,
CSSResultGroup,
html,
LitElement,
PropertyValues,
TemplateResult,
} from "lit";
import { ComboBoxLitRenderer, comboBoxRenderer } from "lit-vaadin-helpers";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { ComboBoxLitRenderer } from "lit-vaadin-helpers";
import { customElement, property, query, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import memoizeOne from "memoize-one";
Expand Down Expand Up @@ -41,38 +28,18 @@ import { SubscribeMixin } from "../mixins/subscribe-mixin";
import { PolymerChangedEvent } from "../polymer-types";
import { HomeAssistant } from "../types";
import type { HaDevicePickerDeviceFilterFunc } from "./device/ha-device-picker";
import type { HaComboBox } from "./ha-combo-box";
import "./ha-combo-box";
import "./ha-icon-button";
import "./ha-svg-icon";

const rowRenderer: ComboBoxLitRenderer<AreaRegistryEntry> = (
item
// eslint-disable-next-line lit/prefer-static-styles
) => html`<style>
paper-item {
padding: 0;
margin: -10px;
margin-left: 0;
}
#content {
display: flex;
align-items: center;
}
ha-svg-icon {
padding-left: 2px;
margin-right: -2px;
color: var(--secondary-text-color);
}
:host(:not([selected])) ha-svg-icon {
display: none;
}
:host([selected]) paper-item {
margin-left: 10px;
}
</style>
<ha-svg-icon .path=${mdiCheck}></ha-svg-icon>
<paper-item class=${classMap({ "add-new": item.area_id === "add_new" })}>
<paper-item-body two-line>${item.name}</paper-item-body>
</paper-item>`;
) => html`<mwc-list-item
class=${classMap({ "add-new": item.area_id === "add_new" })}
>
${item.name}
</mwc-list-item>`;

@customElement("ha-area-picker")
export class HaAreaPicker extends SubscribeMixin(LitElement) {
Expand Down Expand Up @@ -125,7 +92,9 @@ export class HaAreaPicker extends SubscribeMixin(LitElement) {

@state() private _opened?: boolean;

@query("vaadin-combo-box-light", true) public comboBox!: HTMLElement;
@query("ha-combo-box", true) public comboBox!: HaComboBox;

private _filter?: string;

private _init = false;

Expand All @@ -145,13 +114,13 @@ export class HaAreaPicker extends SubscribeMixin(LitElement) {

public open() {
this.updateComplete.then(() => {
(this.shadowRoot?.querySelector("vaadin-combo-box-light") as any)?.open();
this.comboBox?.open();
});
}

public focus() {
this.updateComplete.then(() => {
this.shadowRoot?.querySelector("paper-input")?.focus();
this.comboBox?.focus();
});
}

Expand Down Expand Up @@ -339,62 +308,55 @@ export class HaAreaPicker extends SubscribeMixin(LitElement) {
return html``;
}
return html`
<vaadin-combo-box-light
<ha-combo-box
.hass=${this.hass}
item-value-path="area_id"
item-id-path="area_id"
item-label-path="name"
.value=${this.value}
.disabled=${this.disabled}
${comboBoxRenderer(rowRenderer)}
.label=${this.label === undefined && this.hass
? this.hass.localize("ui.components.area-picker.area")
: this.label}
.placeholder=${this.placeholder
? this._area(this.placeholder)?.name
: undefined}
.renderer=${rowRenderer}
@filter-changed=${this._filterChanged}
@opened-changed=${this._openedChanged}
@value-changed=${this._areaChanged}
>
<paper-input
.label=${this.label === undefined && this.hass
? this.hass.localize("ui.components.area-picker.area")
: this.label}
.placeholder=${this.placeholder
? this._area(this.placeholder)?.name
: undefined}
.disabled=${this.disabled}
class="input"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
spellcheck="false"
>
${this.value
? html`
<ha-icon-button
.label=${this.hass.localize(
"ui.components.area-picker.clear"
)}
.path=${mdiClose}
slot="suffix"
class="clear-button"
@click=${this._clearValue}
></ha-icon-button>
`
: ""}

<ha-icon-button
.label=${this.hass.localize("ui.components.area-picker.toggle")}
.path=${this._opened ? mdiMenuUp : mdiMenuDown}
slot="suffix"
class="toggle-button"
></ha-icon-button>
</paper-input>
</vaadin-combo-box-light>
</ha-combo-box>
`;
}

private _area = memoizeOne((areaId: string): AreaRegistryEntry | undefined =>
this._areas?.find((area) => area.area_id === areaId)
);

private _clearValue(ev: Event) {
ev.stopPropagation();
this._setValue("");
private _filterChanged(ev: CustomEvent): void {
this._filter = ev.detail.value;
if (!this._filter) {
this.comboBox.filteredItems = this.comboBox.items;
return;
}
// @ts-ignore
if (!this.noAdd && this.comboBox._comboBox.filteredItems?.length === 0) {
this.comboBox.filteredItems = [
{
area_id: "add_new_suggestion",
name: this.hass.localize(
"ui.components.area-picker.add_new_sugestion",
{ name: this._filter }
),
picture: null,
},
];
} else {
this.comboBox.filteredItems = this.comboBox.items?.filter((item) =>
item.name.toLowerCase().includes(this._filter!.toLowerCase())
);
}
}

private get _value() {
Expand All @@ -406,9 +368,10 @@ export class HaAreaPicker extends SubscribeMixin(LitElement) {
}

private _areaChanged(ev: PolymerChangedEvent<string>) {
ev.stopPropagation();
const newValue = ev.detail.value;

if (newValue !== "add_new") {
if (!["add_new_suggestion", "add_new"].includes(newValue)) {
if (newValue !== this._value) {
this._setValue(newValue);
}
Expand All @@ -425,6 +388,8 @@ export class HaAreaPicker extends SubscribeMixin(LitElement) {
inputLabel: this.hass.localize(
"ui.components.area-picker.add_dialog.name"
),
defaultValue:
newValue === "add_new_suggestion" ? this._filter : undefined,
confirm: async (name) => {
if (!name) {
return;
Expand All @@ -445,6 +410,8 @@ export class HaAreaPicker extends SubscribeMixin(LitElement) {
this.entityFilter,
this.noAdd
);
await this.updateComplete;
await this.comboBox.updateComplete;
this._setValue(area.area_id);
} catch (err: any) {
showAlertDialog(this, {
Expand All @@ -465,19 +432,6 @@ export class HaAreaPicker extends SubscribeMixin(LitElement) {
fireEvent(this, "change");
}, 0);
}

static get styles(): CSSResultGroup {
return css`
paper-input > ha-icon-button {
--mdc-icon-button-size: 24px;
padding: 2px;
color: var(--secondary-text-color);
}
[hidden] {
display: none;
}
`;
}
}

declare global {
Expand Down
4 changes: 2 additions & 2 deletions src/components/ha-combo-box.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ export class HaComboBox extends LitElement {

@property() public value?: string;

@property() public items?: [];
@property() public items?: any[];

@property() public filteredItems?: [];
@property() public filteredItems?: any[];

@property({ attribute: "allow-custom-value", type: Boolean })
public allowCustomValue?: boolean;
Expand Down
1 change: 1 addition & 0 deletions src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@
"clear": "Clear",
"show_areas": "Show areas",
"area": "Area",
"add_new_sugestion": "Add new area ''{name}''",
"add_new": "Add new area…",
"no_areas": "You don't have any areas",
"no_match": "No matching areas found",
Expand Down