mirror of
https://github.com/home-assistant/frontend.git
synced 2025-11-09 10:59:50 +00:00
* Update dependency typescript to v5.9.2 * fix types --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
247 lines
7.4 KiB
TypeScript
247 lines
7.4 KiB
TypeScript
import { TextFieldBase } from "@material/mwc-textfield/mwc-textfield-base";
|
|
import { styles } from "@material/mwc-textfield/mwc-textfield.css";
|
|
import type { TemplateResult, PropertyValues } from "lit";
|
|
import { html, css } from "lit";
|
|
import { customElement, property, query } from "lit/decorators";
|
|
import { mainWindow } from "../common/dom/get_main_window";
|
|
|
|
@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 = false;
|
|
|
|
// @ts-ignore
|
|
// eslint-disable-next-line lit/attribute-names
|
|
@property({ type: Boolean }) public iconTrailing = false;
|
|
|
|
@property() public autocomplete?: string;
|
|
|
|
@property({ type: Boolean }) public autocorrect = true;
|
|
|
|
@property({ attribute: "input-spellcheck" })
|
|
public inputSpellcheck?: string;
|
|
|
|
@query("input") public formElement!: HTMLInputElement;
|
|
|
|
override updated(changedProperties: PropertyValues) {
|
|
super.updated(changedProperties);
|
|
if (
|
|
changedProperties.has("invalid") ||
|
|
changedProperties.has("errorMessage")
|
|
) {
|
|
this.setCustomValidity(
|
|
this.invalid
|
|
? this.errorMessage || this.validationMessage || "Invalid"
|
|
: ""
|
|
);
|
|
if (
|
|
this.invalid ||
|
|
this.validateOnInitialRender ||
|
|
(changedProperties.has("invalid") &&
|
|
changedProperties.get("invalid") !== undefined)
|
|
) {
|
|
// Only report validity if the field is invalid or the invalid state has changed from
|
|
// true to false to prevent setting empty required fields to invalid on first render
|
|
this.reportValidity();
|
|
}
|
|
}
|
|
if (changedProperties.has("autocomplete")) {
|
|
if (this.autocomplete) {
|
|
this.formElement.setAttribute("autocomplete", this.autocomplete);
|
|
} else {
|
|
this.formElement.removeAttribute("autocomplete");
|
|
}
|
|
}
|
|
if (changedProperties.has("autocorrect")) {
|
|
if (this.autocorrect === false) {
|
|
this.formElement.setAttribute("autocorrect", "off");
|
|
} else {
|
|
this.formElement.removeAttribute("autocorrect");
|
|
}
|
|
}
|
|
if (changedProperties.has("inputSpellcheck")) {
|
|
if (this.inputSpellcheck) {
|
|
this.formElement.setAttribute("spellcheck", this.inputSpellcheck);
|
|
} else {
|
|
this.formElement.removeAttribute("spellcheck");
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override renderIcon(
|
|
_icon: string,
|
|
isTrailingIcon = false
|
|
): TemplateResult {
|
|
const type = isTrailingIcon ? "trailing" : "leading";
|
|
|
|
return html`
|
|
<span
|
|
class="mdc-text-field__icon mdc-text-field__icon--${type}"
|
|
tabindex=${isTrailingIcon ? 1 : -1}
|
|
>
|
|
<slot name="${type}Icon"></slot>
|
|
</span>
|
|
`;
|
|
}
|
|
|
|
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: ltr;
|
|
}
|
|
.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--with-leading-icon.mdc-text-field--with-trailing-icon {
|
|
padding-left: var(--text-field-suffix-padding-left, 0px);
|
|
padding-right: var(--text-field-suffix-padding-right, 0px);
|
|
padding-inline-start: var(--text-field-suffix-padding-left, 0px);
|
|
padding-inline-end: var(--text-field-suffix-padding-right, 0px);
|
|
}
|
|
.mdc-text-field:not(.mdc-text-field--disabled)
|
|
.mdc-text-field__affix--suffix {
|
|
color: var(--secondary-text-color);
|
|
}
|
|
|
|
.mdc-text-field:not(.mdc-text-field--disabled) .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);
|
|
}
|
|
|
|
.mdc-text-field__icon--trailing {
|
|
padding: var(--textfield-icon-trailing-padding, 12px);
|
|
}
|
|
|
|
.mdc-floating-label:not(.mdc-floating-label--float-above) {
|
|
max-width: calc(100% - 16px);
|
|
}
|
|
|
|
.mdc-floating-label--float-above {
|
|
max-width: calc((100% - 16px) / 0.75);
|
|
transition: none;
|
|
}
|
|
|
|
input {
|
|
text-align: var(--text-field-text-align, start);
|
|
}
|
|
|
|
input[type="color"] {
|
|
height: 20px;
|
|
}
|
|
|
|
/* Edge, hide reveal password icon */
|
|
::-ms-reveal {
|
|
display: none;
|
|
}
|
|
|
|
/* 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;
|
|
}
|
|
|
|
input[type="color"]::-webkit-color-swatch-wrapper {
|
|
padding: 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 {
|
|
padding-inline-end: 16px;
|
|
padding-inline-start: initial;
|
|
inset-inline-start: 16px !important;
|
|
inset-inline-end: initial !important;
|
|
transform-origin: var(--float-start);
|
|
direction: var(--direction);
|
|
text-align: var(--float-start);
|
|
box-sizing: border-box;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.mdc-text-field--with-leading-icon.mdc-text-field--filled
|
|
.mdc-floating-label {
|
|
max-width: calc(
|
|
100% - 48px - var(--text-field-suffix-padding-left, 0px)
|
|
);
|
|
inset-inline-start: calc(
|
|
48px + var(--text-field-suffix-padding-left, 0px)
|
|
) !important;
|
|
inset-inline-end: initial !important;
|
|
direction: var(--direction);
|
|
}
|
|
|
|
.mdc-text-field__input[type="number"] {
|
|
direction: var(--direction);
|
|
}
|
|
.mdc-text-field__affix--prefix {
|
|
padding-right: var(--text-field-prefix-padding-right, 2px);
|
|
padding-inline-end: var(--text-field-prefix-padding-right, 2px);
|
|
padding-inline-start: initial;
|
|
}
|
|
|
|
.mdc-text-field:not(.mdc-text-field--disabled)
|
|
.mdc-text-field__affix--prefix {
|
|
color: var(--mdc-text-field-label-ink-color);
|
|
}
|
|
#helper-text ha-markdown {
|
|
display: inline-block;
|
|
}
|
|
`,
|
|
// safari workaround - must be explicit
|
|
mainWindow.document.dir === "rtl"
|
|
? css`
|
|
.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;
|
|
--direction: rtl;
|
|
}
|
|
`
|
|
: css``,
|
|
];
|
|
}
|
|
|
|
declare global {
|
|
interface HTMLElementTagNameMap {
|
|
"ha-textfield": HaTextField;
|
|
}
|
|
}
|