UNPKG

web-ui-pack

Version:
141 lines (140 loc) 4.44 kB
import WUPBaseElement from "../baseElement"; import { WUPcssScrollSmall } from "../styles"; let isFirst = true; export default class WUPTextareaInput extends HTMLElement { #ctr = this.constructor; static $use() { } static get $style() { return `:host { display: inline-block; ${""} cursor: text; white-space: pre-wrap; word-break: break-word; overflow-wrap: break-word; overflow: auto; margin: 0; padding: 0; } ${WUPcssScrollSmall(":host")}`; } constructor() { super(); if (isFirst) { WUPBaseElement.$refStyle.append(this.#ctr.$style.replace(/:host/g, `${this.tagName}`)); isFirst = false; } } $options = {}; #isInit = true; connectedCallback() { if (this.#isInit) { this.setAttribute("contenteditable", "true"); this.setAttribute("role", "textbox"); this.setAttribute("aria-multiline", "true"); this.#isInit = false; this.oninput = () => { this._cached = undefined; }; } } select() { const range = document.createRange(); range.selectNodeContents(this); const sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(range); } get readOnly() { return this.hasAttribute("aria-readonly"); } set readOnly(v) { WUPBaseElement.prototype.setAttr.call(this, "aria-readonly", v); } _cached; get value() { if (this._cached == null) { this._cached = this.innerHTML .replace(/<div><br><\/div>/g, "\n") .replace(/<br>|<div>/g, "\n") .replace(/<\/div>/g, "") .replace(/^&nbsp;/, ""); } return this._cached; } set value(v) { this._cached = undefined; this.innerHTML = v; } setSelectionRange(start, end) { this.selection = { start: start || 0, end: end || 0 }; } get selectionStart() { return this.selection?.start ?? null; } set selectionStart(v) { this.selection = { start: v || 0, end: this.selection?.end }; } get selectionEnd() { return this.selection?.end ?? null; } set selectionEnd(v) { this.selection = { start: this.selection?.start, end: v || 0 }; } get selection() { if (document.activeElement !== this) { return null; } const sel = window.getSelection(); if (!sel || sel.rangeCount < 1) { return null; } const range = sel.getRangeAt(0); const pre = range.cloneRange(); pre.selectNodeContents(this); pre.setEnd(range.startContainer, range.startOffset); const start = pre.toString().length; return { start, end: start + range.toString().length, }; } set selection(sel) { if (document.activeElement !== this) { return; } let charIndex = 0; const range = document.createRange(); range.setStart(this, 0); range.collapse(true); const nodeStack = [this]; let node; let foundStart = false; let stop = false; if (sel) { while (!stop && (node = nodeStack.pop())) { if (node.nodeType === Node.TEXT_NODE) { const nextCharIndex = charIndex + node.length; if (!foundStart && sel.start >= charIndex && sel.start <= nextCharIndex) { range.setStart(node, sel.start - charIndex); foundStart = true; } if (foundStart && sel.end >= charIndex && sel.end <= nextCharIndex) { range.setEnd(node, sel.end - charIndex); stop = true; } charIndex = nextCharIndex; } else { let i = node.childNodes.length; while (i--) { nodeStack.push(node.childNodes[i]); } } } } const s = window.getSelection(); s.removeAllRanges(); s.addRange(range); } } customElements.define("wup-areainput", WUPTextareaInput);