import {
html, unsafeCSS, type PropertyValues,
} from 'lit';
import { PieElement } from '@justeattakeaway/pie-webc-core/src/internals/PieElement';
import { property, query } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import { live } from 'lit/directives/live.js';
import throttle from 'lodash.throttle';
import '@justeattakeaway/pie-assistive-text';
import {
validPropertyValues, RtlMixin, FormControlMixin, wrapNativeEvent, type PIEInputElement,
safeCustomElement,
DelegatesFocusMixin,
} from '@justeattakeaway/pie-webc-core';
import styles from './textarea.scss?inline';
import {
type TextareaProps, defaultProps, sizes, resizeModes, statusTypes,
} from './defs';
// Valid values available to consumers
export * from './defs';
const componentSelector = 'pie-textarea';
const assistiveTextIdValue = 'assistive-text';
/**
* @tagname pie-textarea
* @event {InputEvent} input - when the textarea value is changed.
* @event {CustomEvent} change - when the textarea value is changed.
*/
@safeCustomElement('pie-textarea')
export class PieTextarea extends FormControlMixin(RtlMixin(DelegatesFocusMixin(PieElement))) implements TextareaProps, PIEInputElement {
@property({ type: String })
public value = defaultProps.value;
@property({ type: String })
public defaultValue: TextareaProps['defaultValue'];
@property({ type: Boolean, reflect: true })
public disabled = defaultProps.disabled;
@property({ type: String })
@validPropertyValues(componentSelector, sizes, defaultProps.size)
public size = defaultProps.size;
@property({ type: String })
@validPropertyValues(componentSelector, resizeModes, defaultProps.resize)
public resize = defaultProps.resize;
@property({ type: Boolean })
public readonly = defaultProps.readonly;
@property({ type: Boolean })
public autoFocus = defaultProps.autoFocus;
@property({ type: Boolean })
public required = defaultProps.required;
@property({ type: String })
@validPropertyValues(componentSelector, statusTypes, defaultProps.status)
public status = defaultProps.status;
@property({ type: String })
public assistiveText: TextareaProps['assistiveText'];
@property({ type: String, reflect: true })
public name: TextareaProps['name'];
@property({ type: String })
public autocomplete: TextareaProps['autocomplete'];
@property({ type: String })
public placeholder: TextareaProps['placeholder'];
@property({ type: Number })
public maxlength: TextareaProps['maxlength'];
@property({ type: Number })
public rows: TextareaProps['rows'];
@property({ type: Object })
public aria: TextareaProps['aria'];
@query('textarea')
private _textarea!: HTMLTextAreaElement;
@query('textarea')
public focusTarget!: HTMLElement;
private _abortController!: AbortController;
connectedCallback () {
super.connectedCallback();
this._abortController = new AbortController();
const { signal } = this._abortController;
window.addEventListener('resize', () => this.handleResize(), { signal });
}
public disconnectedCallback (): void {
super.disconnectedCallback();
this._abortController.abort();
}
protected firstUpdated (): void {
const { signal } = this._abortController;
this._textarea.addEventListener('keydown', this.handleKeyDown, { signal });
this._internals.setFormValue(this.value);
}
protected updated (changedProperties: PropertyValues) {
if (changedProperties.has('value')) {
this.handleInput(null, this.value);
}
if (this.resize === 'auto' && ((changedProperties.has('resize') || changedProperties.has('size')) || changedProperties.has('rows'))) {
this.handleResize();
}
if ((this.resize === 'manual' || this.resize === 'none') && ((changedProperties.has('rows') || changedProperties.has('size') || changedProperties.has('resize')))) {
this._textarea.style.height = '';
}
}
private _throttledResize = throttle(() => {
if (this.resize === 'auto') {
this._textarea.style.height = 'auto';
this._textarea.style.height = `${this._textarea.scrollHeight}px`;
}
}, 100);
/**
* (Read-only) returns a ValidityState with the validity states that this element is in.
* https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/validity
*/
public get validity (): ValidityState {
return (this._textarea as HTMLTextAreaElement).validity;
}
/**
* Called after the disabled state of the element changes,
* either because the disabled attribute of this element was added or removed;
* or because the disabled state changed on a