import { mdiEye, mdiEyeOff } from "@mdi/js"; import { css, CSSResultGroup, html, LitElement, PropertyValues, TemplateResult, } from "lit"; import { customElement, property, query, state } from "lit/decorators"; import { fireEvent } from "../../common/dom/fire_event"; import "../ha-icon-button"; import "../ha-textfield"; import type { HaTextField } from "../ha-textfield"; import type { HaFormElement, HaFormStringData, HaFormStringSchema, } from "./types"; const MASKED_FIELDS = ["password", "secret", "token"]; @customElement("ha-form-string") export class HaFormString extends LitElement implements HaFormElement { @property() public schema!: HaFormStringSchema; @property() public data!: HaFormStringData; @property() public label!: string; @property() public helper?: string; @property({ type: Boolean }) public disabled = false; @state() private _unmaskedPassword = false; @query("ha-textfield") private _input?: HaTextField; public focus(): void { if (this._input) { this._input.focus(); } } protected render(): TemplateResult { const isPassword = MASKED_FIELDS.some((field) => this.schema.name.includes(field) ); return html` ` : this.schema.description?.suffix} .validationMessage=${this.schema.required ? "Required" : undefined} @input=${this._valueChanged} > ${isPassword ? html`` : ""} `; } protected updated(changedProps: PropertyValues): void { if (changedProps.has("schema")) { this.toggleAttribute("own-margin", !!this.schema.required); } } private _toggleUnmaskedPassword(): void { this._unmaskedPassword = !this._unmaskedPassword; } private _valueChanged(ev: Event): void { let value: string | undefined = (ev.target as HaTextField).value; if (this.data === value) { return; } if (value === "" && !this.schema.required) { value = undefined; } fireEvent(this, "value-changed", { value, }); } private get _stringType(): string { if (this.schema.format) { if (["email", "url"].includes(this.schema.format)) { return this.schema.format; } if (this.schema.format === "fqdnurl") { return "url"; } } return "text"; } static get styles(): CSSResultGroup { return css` :host { display: block; position: relative; } :host([own-margin]) { margin-bottom: 5px; } ha-textfield { display: block; } ha-icon-button { position: absolute; top: 1em; right: 12px; --mdc-icon-button-size: 24px; color: var(--secondary-text-color); } ha-icon-button { inset-inline-start: initial; inset-inline-end: 12px; direction: var(--direction); } `; } } declare global { interface HTMLElementTagNameMap { "ha-form-string": HaFormString; } }