/** * TBD * * @module */ import { Connect } from "../uwc-input"; import { create, createEventRegistrar, dispatch, text, } from "@hesxenon/prelude/Dom.js"; import { backup } from "../../utils/ElementBackup"; import { Events } from "../events"; import * as Root from "../parts/root"; const stringValue = (input: UwcInputElement) => { return input.value?.toString() ?? ""; }; const initializeInput: Connect = (input, opts) => { backup(input, opts.disconnect); input.value = stringValue(input); }; const syncFormData: Connect = (input) => { dispatch(input, { type: Events.formValuesChanged, detail: [stringValue(input)], }); }; const validate: Connect = (input) => { dispatch(input, { type: Events.validityStateChanged, detail: { valueMissing: input.required && !input.value, tooShort: input.minlength != null && stringValue(input).length < input.minlength, tooLong: input.maxlength != null && stringValue(input).length > input.maxlength, }, }); }; /** * @internal */ export const connectTextarea: Connect = (input, opts) => { const content = create("div", { contentEditable: "true" }); const placeholder = create("div", { part: "placeholder" }, [ text(input.placeholder ?? ""), ]); const on = createEventRegistrar(input, opts.disconnect); const initial = input.value; let snapshot = stringValue(input); content.addEventListener("mousedown", (e) => { if (input.disabled) { e.preventDefault(); } }); let preventFocus = false; on("mousedown", (e) => { preventFocus = e.defaultPrevented; if (preventFocus) { return; } if (!e.composedPath().includes(Root.getFor(input))) { // otherwise a mousedown would remove the focus as soon as it reaches the document e.preventDefault(); } content.focus(); }); on("click", (e) => { if (!e.isTrusted) { // TODO: workaround for https://github.com/testing-library/user-event/issues/1237 e.preventDefault(); } if (!preventFocus) { content.focus(); } }); on("focusin", () => { snapshot = stringValue(input); }); on("focusout", () => { if (stringValue(input) !== snapshot) { dispatch(input, { type: "change" }); } }); on("input", () => { input.value = content.innerText; }); on(Events.valueChanged, () => { if (input.value === "\n") { input.value = ""; } if (content.innerText !== input.value) { content.innerText = input.value?.toString() ?? ""; syncFormData(input, opts); } }); on([Events.nameChanged, Events.formAssociated], () => syncFormData(input, opts), ); on(Events.placeholderChanged, () => { placeholder.innerText = input.placeholder ?? ""; }); on( [ Events.formValuesChanged, Events.minlengthChanged, Events.maxlengthChanged, Events.requiredChanged, ], () => validate(input, opts), ); on(Events.formReset, () => { input.value = initial; }); on(Events.clear, () => { input.value = ""; }); Root.replaceChildren(input, [content, placeholder]); initializeInput(input, opts); syncFormData(input, opts); };