UNPKG

@oslokommune/punkt-elements

Version:

Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo

121 lines (111 loc) 4.2 kB
import { html, PropertyValues } from 'lit' import { ifDefined } from 'lit/directives/if-defined.js' import { customElement, property, state } from 'lit/decorators.js' import { Ref, createRef, ref } from 'lit/directives/ref.js' import { classMap } from 'lit/directives/class-map.js' import { live } from 'lit/directives/live.js' import { PktInputElement } from '@/base-elements/input-element' import { PktSlotController } from '@/controllers/pkt-slot-controller' import '@/components/input-wrapper' import '@/components/icon' @customElement('pkt-textarea') export class PktTextarea extends PktInputElement { private inputRef: Ref<HTMLTextAreaElement> = createRef() private helptextSlot: Ref<HTMLElement> = createRef() @property({ type: String, reflect: true }) value: string = '' @property({ type: String }) autocomplete: string = 'off' @property({ type: Number }) rows: number | null = null @state() counterCurrent = 0 constructor() { super() this.slotController = new PktSlotController(this, this.helptextSlot) } attributeChangedCallback(name: string, _old: string | null, value: string | null): void { if (name === 'value' && this.value !== _old) { this.counterCurrent = value ? value.length : 0 this.valueChanged(value, _old) } super.attributeChangedCallback(name, _old, value) } updated(changedProperties: PropertyValues) { super.updated(changedProperties) if (changedProperties.has('value')) { this.counterCurrent = this.value?.length || 0 this.valueChanged(this.value, changedProperties.get('value')) } if (changedProperties.has('id')) { !this.name && this.id && (this.name = this.id) } } render() { const inputClasses = classMap({ 'pkt-input': true, 'pkt-input--fullwidth': this.fullwidth, 'pkt-input--counter-error': this.counter && this.counterMaxLength && this.value.length && this.value.length > this.counterMaxLength, }) const labelledBy = this.ariaLabelledby || `${this.id}-input-label` return html`<pkt-input-wrapper label=${this.label} ?counter=${this.counter} ?disabled=${this.disabled} ?hasError=${this.hasError} ?inline=${this.inline} ?optionalTag=${this.optionalTag} ?required=${this.required} ?requiredTag=${this.requiredTag} ?useWrapper=${this.useWrapper} .ariaDescribedBy=${this.ariaDescribedBy} .counterCurrent=${this.counterCurrent} .counterMaxLength=${this.counterMaxLength} .errorMessage=${this.errorMessage} .forId="${this.id + '-input'}" .helptext=${this.helptext} .helptextDropdown=${this.helptextDropdown} .helptextDropdownButton=${this.helptextDropdownButton} .optionalText=${this.optionalText} .requiredText=${this.requiredText} .tagText=${this.tagText} class="pkt-textarea" > <div class="pkt-contents" ${ref(this.helptextSlot)} name="helptext" slot="helptext"></div> <textarea ${ref(this.inputRef)} class=${inputClasses} id=${this.id + '-input'} name=${(this.name || this.id) + '-input'} placeholder=${ifDefined(this.placeholder)} .value=${live(this.value)} minlength=${ifDefined(this.minlength)} maxlength=${ifDefined(this.maxlength)} ?readonly=${this.readonly} autocomplete=${this.autocomplete} aria-labelledby=${labelledBy} aria-invalid=${this.hasError} aria-errormessage=${`${this.id}-error`} rows=${this.rows} ?disabled=${this.disabled} @input=${(e: InputEvent) => { this.value = (e.target as HTMLInputElement).value this.onInput() e.stopImmediatePropagation() }} @change=${(e: Event) => { e.stopImmediatePropagation() }} @focus=${(e: FocusEvent) => { this.onFocus() e.stopImmediatePropagation() }} @blur=${(e: FocusEvent) => { this.value = (e.target as HTMLInputElement).value this.onBlur() e.stopImmediatePropagation() }} ></textarea> </pkt-input-wrapper>` } }