diff --git a/src/components/ha-aliases-editor.ts b/src/components/ha-aliases-editor.ts
index 0e75247748..6109a3358b 100644
--- a/src/components/ha-aliases-editor.ts
+++ b/src/components/ha-aliases-editor.ts
@@ -2,7 +2,7 @@ import { LitElement, html, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import { fireEvent } from "../common/dom/fire_event";
import type { HomeAssistant } from "../types";
-import "./ha-multi-textfield";
+import "./input/ha-input-multi";
@customElement("ha-aliases-editor")
class AliasesEditor extends LitElement {
@@ -20,7 +20,7 @@ class AliasesEditor extends LitElement {
}
return html`
-
-
+
`;
}
diff --git a/src/components/ha-selector/ha-selector-text.ts b/src/components/ha-selector/ha-selector-text.ts
index b4b604ec32..cf3851f89b 100644
--- a/src/components/ha-selector/ha-selector-text.ts
+++ b/src/components/ha-selector/ha-selector-text.ts
@@ -1,14 +1,12 @@
-import { mdiEye, mdiEyeOff } from "@mdi/js";
-import { LitElement, css, html } from "lit";
-import { customElement, property, query, state } from "lit/decorators";
+import { LitElement, css, html, nothing } from "lit";
+import { customElement, property, query } from "lit/decorators";
import { ensureArray } from "../../common/array/ensure-array";
import { fireEvent } from "../../common/dom/fire_event";
import type { StringSelector } from "../../data/selector";
-import type { HomeAssistant } from "../../types";
-import "../ha-icon-button";
-import "../ha-multi-textfield";
+import type { HomeAssistant, ValueChangedEvent } from "../../types";
import "../ha-textarea";
-import "../ha-textfield";
+import "../input/ha-input";
+import "../input/ha-input-multi";
@customElement("ha-selector-text")
export class HaTextSelector extends LitElement {
@@ -30,9 +28,7 @@ export class HaTextSelector extends LitElement {
@property({ type: Boolean }) public required = true;
- @state() private _unmaskedPassword = false;
-
- @query("ha-textfield, ha-textarea") private _input?: HTMLInputElement;
+ @query("ha-input, ha-textarea") private _input?: HTMLInputElement;
public async focus() {
await this.updateComplete;
@@ -49,8 +45,7 @@ export class HaTextSelector extends LitElement {
protected render() {
if (this.selector.text?.multiple) {
return html`
-
-
+
`;
}
if (this.selector.text?.multiline) {
@@ -81,45 +76,34 @@ export class HaTextSelector extends LitElement {
autogrow
>`;
}
- return html``
- : this.selector.text?.suffix}
- .required=${this.required}
- .autocomplete=${this.selector.text?.autocomplete}
- >
- ${this.selector.text?.type === "password"
- ? html``
- : ""}`;
+ return html`
+ ${this.selector.text?.prefix
+ ? html`${this.selector.text.prefix}`
+ : nothing}
+ ${this.selector.text?.suffix
+ ? html`${this.selector.text.suffix}`
+ : nothing}
+ `;
}
- private _toggleUnmaskedPassword(): void {
- this._unmaskedPassword = !this._unmaskedPassword;
- }
-
- private _handleChange(ev) {
+ private _handleChange(ev: ValueChangedEvent | InputEvent) {
ev.stopPropagation();
- let value = ev.detail?.value ?? ev.target.value;
+ let value: string | undefined =
+ (ev as ValueChangedEvent).detail?.value ??
+ (ev.target as HTMLInputElement).value;
if (this.value === value) {
return;
}
@@ -139,20 +123,9 @@ export class HaTextSelector extends LitElement {
position: relative;
}
ha-textarea,
- ha-textfield {
+ ha-input {
width: 100%;
}
- ha-icon-button {
- position: absolute;
- top: 8px;
- right: 8px;
- inset-inline-start: initial;
- inset-inline-end: 8px;
- --ha-icon-button-size: 40px;
- --mdc-icon-size: 20px;
- color: var(--secondary-text-color);
- direction: var(--direction);
- }
`;
}
diff --git a/src/components/input/ha-input-copy.ts b/src/components/input/ha-input-copy.ts
index fdb697557c..76c8940f15 100644
--- a/src/components/input/ha-input-copy.ts
+++ b/src/components/input/ha-input-copy.ts
@@ -1,7 +1,7 @@
+import { consume, type ContextType } from "@lit/context";
import { mdiContentCopy, mdiEye, mdiEyeOff } from "@mdi/js";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
-import { consume, type ContextType } from "@lit/context";
import { copyToClipboard } from "../../common/util/copy-clipboard";
import { localizeContext } from "../../data/context";
import { showToast } from "../../util/toast";
diff --git a/src/components/ha-multi-textfield.ts b/src/components/input/ha-input-multi.ts
similarity index 78%
rename from src/components/ha-multi-textfield.ts
rename to src/components/input/ha-input-multi.ts
index 9670093e53..7f0e76ffd2 100644
--- a/src/components/ha-multi-textfield.ts
+++ b/src/components/input/ha-input-multi.ts
@@ -1,22 +1,21 @@
+import { consume, type ContextType } from "@lit/context";
import { mdiDeleteOutline, mdiDragHorizontalVariant, mdiPlus } from "@mdi/js";
import type { CSSResultGroup } from "lit";
import { LitElement, css, html, nothing } from "lit";
-import { customElement, property } from "lit/decorators";
+import { customElement, property, state } from "lit/decorators";
import { repeat } from "lit/directives/repeat";
-import { fireEvent } from "../common/dom/fire_event";
-import { haStyle } from "../resources/styles";
-import type { HomeAssistant } from "../types";
-import "./ha-button";
-import "./ha-icon-button";
-import "./ha-input-helper-text";
-import "./ha-sortable";
-import "./ha-textfield";
-import type { HaTextField } from "./ha-textfield";
-
-@customElement("ha-multi-textfield")
-class HaMultiTextField extends LitElement {
- @property({ attribute: false }) public hass?: HomeAssistant;
+import { fireEvent } from "../../common/dom/fire_event";
+import { localizeContext } from "../../data/context";
+import { haStyle } from "../../resources/styles";
+import "../ha-button";
+import "../ha-icon-button";
+import "../ha-input-helper-text";
+import "../ha-sortable";
+import "./ha-input";
+import type { HaInput, InputType } from "./ha-input";
+@customElement("ha-input-multi")
+class HaInputMulti extends LitElement {
@property({ attribute: false }) public value?: string[];
@property({ type: Boolean }) public disabled = false;
@@ -25,7 +24,7 @@ class HaMultiTextField extends LitElement {
@property({ attribute: false }) public helper?: string;
- @property({ attribute: false }) public inputType?: string;
+ @property({ attribute: false }) public inputType?: InputType;
@property({ attribute: false }) public inputSuffix?: string;
@@ -47,6 +46,10 @@ class HaMultiTextField extends LitElement {
@property({ type: Boolean, attribute: "update-on-blur" })
public updateOnBlur = false;
+ @state()
+ @consume({ context: localizeContext, subscribe: true })
+ private localize?: ContextType;
+
protected render() {
return html`
-
+ >
+ ${this.inputPrefix
+ ? html`${this.inputPrefix}`
+ : nothing}
+ ${this.inputSuffix
+ ? html`${this.inputSuffix}`
+ : nothing}
+
${this.addLabel ??
(this.label
- ? this.hass?.localize("ui.components.multi-textfield.add_item", {
+ ? this.localize?.("ui.components.multi-textfield.add_item", {
item: this.label,
})
- : this.hass?.localize("ui.common.add")) ??
+ : this.localize?.("ui.common.add")) ??
"Add"}
@@ -138,8 +146,8 @@ class HaMultiTextField extends LitElement {
const items = [...this._items, ""];
this._fireChanged(items);
await this.updateComplete;
- const field = this.shadowRoot?.querySelector(`ha-textfield[data-last]`) as
- | HaTextField
+ const field = this.shadowRoot?.querySelector(`ha-input[data-last]`) as
+ | HaInput
| undefined;
field?.focus();
}
@@ -191,9 +199,7 @@ class HaMultiTextField extends LitElement {
css`
.row {
margin-bottom: 8px;
- }
- ha-textfield {
- display: block;
+ --ha-input-padding-bottom: 0;
}
ha-icon-button {
display: block;
@@ -210,6 +216,6 @@ class HaMultiTextField extends LitElement {
declare global {
interface HTMLElementTagNameMap {
- "ha-multi-textfield": HaMultiTextField;
+ "ha-input-multi": HaInputMulti;
}
}