From 1cc0a9e33bbc0f7e4cb61613595d4c1808230f0d Mon Sep 17 00:00:00 2001 From: nathan Date: Tue, 6 Aug 2024 08:41:11 -0600 Subject: [PATCH] Et2Textbox: Also accept RegExp as validator Previously only accepted string --- api/js/etemplate/Et2Textbox/Et2Textbox.ts | 184 +++++++++++++++++++--- 1 file changed, 166 insertions(+), 18 deletions(-) diff --git a/api/js/etemplate/Et2Textbox/Et2Textbox.ts b/api/js/etemplate/Et2Textbox/Et2Textbox.ts index d53c1912d7..2add3f2433 100644 --- a/api/js/etemplate/Et2Textbox/Et2Textbox.ts +++ b/api/js/etemplate/Et2Textbox/Et2Textbox.ts @@ -9,12 +9,16 @@ */ -import {css, PropertyValues} from "lit"; +import {css, html, nothing, PropertyValues} from "lit"; +import {customElement} from "lit/decorators/custom-element.js"; +import {property} from "lit/decorators/property.js"; import {Regex} from "../Validators/Regex"; -import {SlInput} from "@shoelace-style/shoelace"; import shoelace from "../Styles/shoelace"; import {Et2InputWidget} from "../Et2InputWidget/Et2InputWidget"; +import IMask, {InputMask} from "imask"; +import {SlInput} from "@shoelace-style/shoelace"; +@customElement("et2-textbox") export class Et2Textbox extends Et2InputWidget(SlInput) { @@ -42,19 +46,37 @@ export class Et2Textbox extends Et2InputWidget(SlInput) ]; } - static get properties() - { - return { - ...super.properties, - /** - * Perl regular expression eg. '/^[0-9][a-f]{4}$/i' - * - * Not to be confused with this.validators, which is a list of validators for this widget - */ - validator: String, - onkeypress: Function, - } - } + @property() + value = ""; + + /** + * Placeholder text to show as a hint when the input is empty. + */ + @property() + placeholder; + + /** + * Mask the input to enforce format. The mask is enforced as the user types, preventing invalid input. + */ + @property() + mask; + + /** + * Disables the input. It is still visible. + * @type {boolean} + */ + @property({type: Boolean}) + disabled = false; + + @property({type: Function}) + onkeypress; + + private __validator : any; + private _mask : InputMask; + protected _value : string = ""; + + inputMode = "text"; + static get translate() { @@ -73,6 +95,20 @@ export class Et2Textbox extends Et2InputWidget(SlInput) super.connectedCallback(); } + disconnectedCallback() + { + super.disconnectedCallback(); + this.removeEventListener("focus", this.handleFocus); + } + + firstUpdated() + { + if(this.maskOptions.mask) + { + this.updateMask(); + } + } + /** @param changedProperties */ updated(changedProperties : PropertyValues) { @@ -83,8 +119,13 @@ export class Et2Textbox extends Et2InputWidget(SlInput) this.validators = (this.validators || []).filter((validator) => !(validator instanceof Regex)) this.validators.push(new Regex(this.validator)); } + if(changedProperties.has('mask')) + { + this.updateMask(); + } } + @property() get validator() { return this.__validator; @@ -112,7 +153,114 @@ export class Et2Textbox extends Et2InputWidget(SlInput) this.requestUpdate("validator"); } } -} -// @ts-ignore TypeScript is not recognizing that Et2Textbox is a LitElement -customElements.define("et2-textbox", Et2Textbox); \ No newline at end of file + /** + * Get the options for masking. + * Can be overridden by subclass for additional options. + * + * @see https://imask.js.org/guide.html#masked + */ + protected get maskOptions() + { + return { + mask: this.mask, + lazy: this.placeholder ? true : false, + autofix: true, + eager: "append", + overwrite: "shift" + } + } + + protected updateMask() + { + const input = this.shadowRoot.querySelector("input") + if(!this._mask) + { + this._mask = IMask(input, this.maskOptions); + this.addEventListener("focus", this.handleFocus) + window.setTimeout(() => + { + this._mask.updateControl(); + }, 1); + } + else + { + this._mask.updateOptions(this.maskOptions); + } + + if(this._mask) + { + this.updateMaskValue(); + } + } + + protected updateMaskValue() + { + this._mask.unmaskedValue = "" + this.value; + this._mask.updateValue(); + this.updateComplete.then(() => + { + this._mask.updateControl(); + }); + } + + protected handleFocus(event) + { + if(this._mask) + { + // this._mask.updateValue(); + } + } + + protected _inputTemplate() + { + return html` + + { + if(this.__mask) + { + this.__mask.updateCursor(this.__mask.cursorPos) + } + }} + > + + + + `; + } + + /* + render() + { + const labelTemplate = this._labelTemplate(); + const helpTemplate = this._helpTextTemplate(); + + return html` +
+ ${labelTemplate} +
+ ${this._inputTemplate()} +
+ ${helpTemplate} +
+ `; + } + + */ +}