import '../templating.js'; import { attr, css, element, html, listen, query } from '@joist/element'; import { effect } from '@joist/observable'; import { bind } from '@joist/templating'; declare global { interface HTMLElementTagNameMap { 'usa-textarea': USATextareaElement; } } @element({ tagName: 'usa-textarea', shadowDom: [ css` * { box-sizing: border-box; } :host { font-size: 1.06rem; line-height: 1.3; display: flex; flex-direction: column; font-weight: 400; margin-bottom: 1.5rem; max-width: 30rem; position: relative; height: 9lh; gap: 0.5rem; } textarea { font-family: inherit; font-size: inherit; border-radius: 0; color: #1b1b1b; display: block; padding: 0.5rem; border-width: 1px; border-color: #5c5c5c; border-style: solid; background-color: #fff; -webkit-appearance: none; -moz-appearance: none; appearance: none; width: 100%; resize: none; flex-grow: 1; } textarea:not(:disabled):focus { outline: 0.25rem solid #2491ff; outline-offset: 0; } textarea:disabled { background-color: #fff; border-color: #757575; color: #757575; } `, html` `, ], }) export class USATextareaElement extends HTMLElement { static formAssociated = true; @attr() @bind() accessor name = ''; @attr() @bind() accessor disabled = false; @attr() @bind() accessor autocomplete: AutoFill = 'on'; @attr() @bind() accessor placeholder = ''; @attr() @bind() accessor required = false; @attr() @bind() accessor autofocus = false; @attr({ reflect: false, }) @bind() accessor value = ''; #internals = this.attachInternals(); #input = query('textarea'); formAssociatedCallback() { this.#syncFormState(); } @effect() onChange() { this.#syncFormState(); } @listen('input') onInputChange(e: Event) { e.stopPropagation(); this.value = this.#input().value; this.dispatchEvent(new Event('input', { bubbles: true })); } async #syncFormState() { const input = this.#input(); this.#internals.setFormValue(this.value); this.#internals.setValidity({}); await Promise.resolve(); if (input.validationMessage) { this.#internals.setValidity({ customError: true }, input.validationMessage, input); } } }