import { css, LitElement } from 'lit';
import { customElement, property, query } from 'lit/decorators.js';
import { nothing, html } from 'lit/html.js';
import { createUUID } from './utils/UniqueId';
import { MonoTextComp } from './MonoTextComp';
import { fromOptionalConverter, spread } from './utils/LitHelper';
import { SpreadController } from './utils/SpreadController';
import { mask } from './utils/InputMask';
import { TailwindStylesController } from './utils/TailwindStylesController';
import { RoundedCorners } from './utils/CommonTypes';
export type InputMaskType = 'number' | 'date' | 'phone';
export type InputMode =
| 'none'
| 'text'
| 'decimal'
| 'numeric'
| 'tel'
| 'search'
| 'email'
| 'url';
@customElement('mono-textfield')
export class MonoTextFieldComp extends LitElement {
static styles = css`
::slotted(p:first-of-type) {
margin: 0;
}
`;
private __spreadController: SpreadController = new SpreadController(this);
private __stylesController: TailwindStylesController = new TailwindStylesController(
this,
);
@property({ type: String, reflect: true })
value: string = '';
@property({ type: String, reflect: true }) placeholder: string = '';
@property({ type: String, reflect: true }) id: string = createUUID();
@property({ type: String, reflect: true }) name: string = '';
@property({ type: String, reflect: true, converter: fromOptionalConverter })
error?: string;
@property({ type: Boolean, reflect: true }) disabled: boolean = false;
@property({ type: Boolean, reflect: true }) required: boolean = false;
@property({ type: String, reflect: true, attribute: 'mask-type' })
maskType?: InputMaskType;
@property({ type: String, reflect: true, attribute: 'inputmode' })
inputMode: InputMode = 'text';
@property({ type: String, reflect: true }) corners: RoundedCorners = 'none';
@query('input', true)
__inputEl!: HTMLInputElement;
@query('label', true)
__labelEl!: HTMLLabelElement;
@query('[id*="-errors"]', true)
__errorEl!: MonoTextComp;
__computMaskType() {
switch (this.maskType) {
case 'number':
// kind of a hack, need to update input mask
// but we aren't using it at the moment
return '99999999999999999999999999999999999999999999999999999999999';
case 'phone':
return '9999999999';
case 'date':
return '99/99/9999';
default:
return null;
}
}
private __onInput(_event: Event) {
const maskType = this.__computMaskType();
if (maskType) {
const newValue = mask(this.__inputEl.value, maskType);
this.__inputEl.value = newValue;
this.value = newValue;
} else {
this.value = this.__inputEl.value;
}
}
private __onChange(event: Event) {
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
const maskType = this.__computMaskType();
if (maskType) {
const newValue = mask(this.__inputEl.value, maskType);
this.__inputEl.value = newValue;
this.value = newValue;
} else {
this.value = this.__inputEl.value;
}
const changeEvent = new CustomEvent('change', {
detail: { value: this.value },
bubbles: true,
composed: true,
});
this.dispatchEvent(changeEvent);
}
private __hasError() {
return this.error && this.error.length > 0;
}
private __renderError(ariaDescribedBy: string) {
if (this.__hasError()) {
return html`