export class TextEdit extends HTMLElement { constructor() { super() this.attachShadow({mode: 'open'}) this.stackEl = document.createElement('div') this.stackEl.classList.add('stack') this.textEl = document.createElement('textarea') this.textEl.classList.add('text') this.textEl.setAttribute('spellcheck', 'false') this.textEl.rows = 1 this.stackEl.appendChild(this.textEl) this.shadowRoot.appendChild(this.stackEl) this.textEl.addEventListener('input', () => { this.stackEl.dataset.copy = this.textEl.value }) } connectedCallback() { // https://css-tricks.com/the-cleanest-trick-for-autogrowing-textareas/ const style = document.createElement('style') style.textContent = ` :host { display: flex; flex-direction: column; align-items: stretch; margin: 5px 0; } div.stack { display: grid; } div.stack::after { content: attr(data-copy) " "; visibility: hidden; overflow: hidden; } div.stack::after, div.stack > textarea { white-space: pre-wrap; border: 1px solid #888; padding: 3px; font: inherit; font-family: monospace; grid-area: 1 / 1 / 2 / 2; min-height: 1em; border-radius: 2px; resize: none; } ` this.shadowRoot.appendChild(style) } set value(value) { this.textEl.value = value this.stackEl.dataset.copy = this.textEl.value } get value() { return this.textEl.value } }