import { type HandlerEvent, htmlSlot, styles } from "@godown/element"; import { type TemplateResult, css, html } from "lit"; import { property, query } from "lit/decorators.js"; import { omit } from "sharekit"; import { GlobalStyle } from "./global-style.js"; import { ringTypeAttribute, type RingType } from "./ring.js"; const inputStyle = css` :host([disabled]) { cursor: not-allowed; filter: brightness(0.85); } input:disabled { cursor: inherit; } input::-ms-reveal, input::-ms-clear { display: none; } `; @styles(inputStyle) class SuperInput extends GlobalStyle { autofocus = false; @property() autocomplete: string | boolean; @property({ attribute: ringTypeAttribute }) ringType: RingType = "border"; @property({ type: Boolean, reflect: true }) disabled = false; @property({ reflect: true }) placeholder: string; @property({ reflect: true }) name: string; @property() value: V; get observedRecord(): Record { return omit(super.observedRecord, "default", "value"); } /** * default property records the default or initial value and is used to reset the input. */ @property() default: any; @query("[part=input]") protected _input: HTMLInputElement; /** * Returns true when the input is compositing. */ compositing = false; set defaultValue(value: typeof this.default) { this.default = value; } get defaultValue() { return this.default; } protected makeId: string = Math.random().toString(36).slice(1); namevalue(): [string, any] { return [this.name, this.value]; } nameValue: () => [string, any] = this.namevalue; reset(): void { this.value = this.default; this._input.value = this.default; } protected _handleInput(e: HandlerEvent): void { e.stopPropagation(); if (this.compositing) { return; } (this.value as string) = e.target.value?.trim(); this.dispatchCustomEvent("input", this.value, { bubbles: true }); } protected _handleChange(e: HandlerEvent): void { this.dispatchCustomEvent("change", this.value); } connectedCallback(): void { super.connectedCallback(); this._connectedInit(); } protected _connectedInit(): void { this.default ??= this.value || ""; this.value ??= this.default; } protected _compositionInit(): void { if (this._input) { this.events.add(this._input, "compositionstart", () => (this.compositing = true)); this.events.add(this._input, "compositionend", (e: HandlerEvent) => { this.compositing = false; this._handleInput(e); }); } } focus(options?: FocusOptions): void { this._input?.focus(options); } protected firstUpdated(): void { this._compositionInit(); } protected _renderPrefix(): TemplateResult<1> { return html` ${htmlSlot("prefix")} `; } protected _renderSuffix(): TemplateResult<1> { return html` ${htmlSlot("suffix")} `; } } export default SuperInput; export { SuperInput };