import { TextFieldBase } from "@material/mwc-textfield/mwc-textfield-base"; import { styles } from "@material/mwc-textfield/mwc-textfield.css"; import { TemplateResult, html, PropertyValues, css } from "lit"; import { customElement, property } from "lit/decorators"; @customElement("ha-textfield") export class HaTextField extends TextFieldBase { @property({ type: Boolean }) public invalid?: boolean; @property({ attribute: "error-message" }) public errorMessage?: string; // @ts-ignore @property({ type: Boolean }) public icon?: boolean; // @ts-ignore @property({ type: Boolean }) public iconTrailing?: boolean; override updated(changedProperties: PropertyValues) { super.updated(changedProperties); if ( (changedProperties.has("invalid") && (this.invalid || changedProperties.get("invalid") !== undefined)) || changedProperties.has("errorMessage") ) { this.setCustomValidity( this.invalid ? this.errorMessage || "Invalid" : "" ); this.reportValidity(); } } protected override renderIcon( _icon: string, isTrailingIcon = false ): TemplateResult { const type = isTrailingIcon ? "trailing" : "leading"; return html` `; } static override styles = [ styles, css` .mdc-text-field__input { width: var(--ha-textfield-input-width, 100%); } .mdc-text-field:not(.mdc-text-field--with-leading-icon) { padding: var(--text-field-padding, 0px 16px); } .mdc-text-field__affix--suffix { padding-left: var(--text-field-suffix-padding-left, 12px); padding-right: var(--text-field-suffix-padding-right, 0px); padding-inline-start: var(--text-field-suffix-padding-left, 12px); padding-inline-end: var(--text-field-suffix-padding-right, 0px); direction: var(--direction); } .mdc-text-field--with-leading-icon { padding-inline-start: var(--text-field-suffix-padding-left, 0px); padding-inline-end: var(--text-field-suffix-padding-right, 16px); direction: var(--direction); } .mdc-text-field:not(.mdc-text-field--disabled) .mdc-text-field__affix--suffix { color: var(--secondary-text-color); } .mdc-text-field__icon { color: var(--secondary-text-color); } .mdc-text-field__icon--leading { margin-inline-start: 16px; margin-inline-end: 8px; direction: var(--direction); } input { text-align: var(--text-field-text-align, start); } /* Chrome, Safari, Edge, Opera */ :host([no-spinner]) input::-webkit-outer-spin-button, :host([no-spinner]) input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; } /* Firefox */ :host([no-spinner]) input[type="number"] { -moz-appearance: textfield; } .mdc-text-field__ripple { overflow: hidden; } .mdc-text-field { overflow: var(--text-field-overflow); } .mdc-floating-label { inset-inline-start: 16px !important; inset-inline-end: initial !important; transform-origin: var(--float-start); direction: var(--direction); transform-origin: var(--float-start); } .mdc-text-field--with-leading-icon.mdc-text-field--filled .mdc-floating-label { max-width: calc(100% - 48px); inset-inline-start: 48px !important; inset-inline-end: initial !important; direction: var(--direction); } .mdc-text-field__input[type="number"] { direction: var(--direction); } `, // safari workaround - must be explicit document.dir === "rtl" ? css` .mdc-text-field__affix--suffix, .mdc-text-field--with-leading-icon, .mdc-text-field__icon--leading, .mdc-floating-label, .mdc-text-field--with-leading-icon.mdc-text-field--filled .mdc-floating-label, .mdc-text-field__input[type="number"] { direction: rtl; } ` : css``, ]; } declare global { interface HTMLElementTagNameMap { "ha-textfield": HaTextField; } }