// Mockup https://www.figma.com/design/zsq2ahat30acTnumyy9aqC/00.Small-System?node-id=1235-18586&m=dev
import { LitElement, type TemplateResult, css, html, unsafeCSS } from "lit";
import { customElement, property } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
import "~icons/mingcute/search-3-line";
import ComponentStyle from "@styles/forms/ui/tems-input-field.scss?inline";
export type TemsInputFieldProps = {
disabled?: boolean;
field: Element;
icon?: TemplateResult;
label?: string;
name?: string;
size: "sm" | "md" | "lg";
status: string | undefined;
type: string;
value?: string;
};
@customElement("tems-input-field")
export class TemsInputField extends LitElement {
static styles = css`
${unsafeCSS(ComponentStyle)}
`;
@property({ attribute: "disabled", type: Boolean, reflect: true })
disabled: TemsInputFieldProps["disabled"];
@property({ type: Element })
field: TemsInputFieldProps["field"] = document.createElement("input");
@property({ attribute: false })
icon: TemsInputFieldProps["icon"];
@property({ attribute: "label", type: String, reflect: true })
label: TemsInputFieldProps["label"];
@property({ attribute: "name", type: String, reflect: true })
name: TemsInputFieldProps["name"] = "";
@property({ attribute: "size", type: String, reflect: true })
size: TemsInputFieldProps["size"] = "md";
@property({ attribute: "status", type: String, reflect: true })
status: TemsInputFieldProps["status"] = undefined;
@property({ attribute: "type", type: String, reflect: true })
type: TemsInputFieldProps["type"] = "text";
@property({ attribute: "value", type: String, reflect: true })
value: TemsInputFieldProps["value"];
defaultIcon: TemplateResult | symbol = html``;
_getSizeClasses() {
const allowedSizes = ["sm", "md", "lg"];
if (this.size && !allowedSizes.includes(this.size)) {
this.size = "md";
}
return {
sm: this.size === "sm",
md: this.size === "md",
lg: this.size === "lg",
};
}
private _timer: number | undefined;
_updateInputValue(e: Event) {
e.preventDefault();
if (this._timer) {
clearTimeout(this._timer);
}
this._timer = window.setTimeout(() => {
this.value = this.field.value;
this._timer = undefined;
this.dispatchEvent(
new CustomEvent("change", {
detail: {
value: this.value,
},
}),
);
}, 100);
}
_updateStatus() {
const status = this.status;
if (typeof status === "string") {
if (status === "true") {
this.field._isValid = true;
this.field.setCustomValidity("");
} else {
this.field._isValid = false;
this.field.setCustomValidity(
status === "false" ? "Invalid value" : status,
);
}
this.field.classList.add("report-validity");
} else {
this.field.classList.remove("report-validity");
}
this.field.reportValidity();
}
protected updated() {
this.field.setAttribute("type", this.type);
if (this.name) {
this.field.setAttribute("name", this.name);
} else {
this.field.removeAttribute("name");
}
if (this.label) {
this.field.setAttribute("placeholder", this.label);
} else {
this.field.removeAttribute("placeholder");
}
if (this.value) {
this.field.setAttribute("value", this.value);
this.field.value = this.value;
} else {
this.field.setAttribute("value", "");
this.field.value = "";
}
if (this.disabled) {
this.field.setAttribute("disabled", "true");
} else {
this.field.removeAttribute("disabled");
}
this._updateStatus();
this._adaptFieldOnUpdate();
}
protected firstUpdated() {
this.field.addEventListener("change", this._updateInputValue.bind(this));
}
_adaptFieldOnUpdate() {}
_renderInput() {
return html`${
this.icon ? html`${this.icon}` : this.defaultIcon
}${this.field}`;
}
render() {
return html``;
}
}