revert textarea component to conenteditable

This commit is contained in:
Chris Kruining 2025-03-03 10:57:10 +01:00
parent 925ea142fb
commit c6c7240fee
No known key found for this signature in database
GPG key ID: EB894A3560CCCAD2
3 changed files with 30 additions and 11 deletions

View file

@ -1,8 +1,8 @@
import { createEffect, createSignal, on } from 'solid-js'; import { createEffect, createSignal, on, onMount } from 'solid-js';
import { getTextNodes } from '@solid-primitives/selection'; import { createSelection, getTextNodes } from '@solid-primitives/selection';
import { createEditContext } from '~/features/editor';
import { createSource } from '~/features/source'; import { createSource } from '~/features/source';
import css from './textarea.module.css'; import css from './textarea.module.css';
import { debounce } from '@solid-primitives/scheduled';
interface TextareaProps { interface TextareaProps {
class?: string; class?: string;
@ -16,13 +16,31 @@ interface TextareaProps {
} }
export function Textarea(props: TextareaProps) { export function Textarea(props: TextareaProps) {
const [selection, setSelection] = createSelection();
const [editorRef, setEditorRef] = createSignal<HTMLElement>(); const [editorRef, setEditorRef] = createSignal<HTMLElement>();
const source = createSource(() => props.value); const source = createSource(() => props.value);
const [text] = createEditContext(editorRef, () => source.out);
createEffect(() => { const mutate = debounce(() => {
source.out = text(); const [, start, end] = selection();
const ref = editorRef();
if (ref) {
source.out = ref.innerHTML;
ref.style.height = `1px`;
ref.style.height = `${2 + ref.scrollHeight}px`;
setSelection([ref, start, end]);
}
}, 300);
onMount(() => {
new MutationObserver(mutate).observe(editorRef()!, {
subtree: true,
childList: true,
characterData: true,
});
}); });
createEffect(() => { createEffect(() => {
@ -42,12 +60,13 @@ export function Textarea(props: TextareaProps) {
})); }));
return <div return <div
contentEditable
ref={setEditorRef} ref={setEditorRef}
class={`${css.textarea} ${props.class}`} class={`${css.textarea} ${props.class}`}
title={props.title ?? ''} title={props.title ?? ''}
dir="auto" dir="auto"
lang={props.lang} lang={props.lang}
innerHTML={text()} innerHTML={source.out}
data-placeholder={props.placeholder ?? ''} data-placeholder={props.placeholder ?? ''}
on:keydown={e => e.stopPropagation()} on:keydown={e => e.stopPropagation()}
on:pointerdown={e => e.stopPropagation()} on:pointerdown={e => e.stopPropagation()}

View file

@ -103,7 +103,7 @@ export function createSource(value: Accessor<string>): Source {
}); });
createEffect(() => { createEffect(() => {
setStore('metadata', 'queryResults', findMatches(store.plain, store.query).toArray()); setStore('metadata', 'queryResults', findMatches(store.plain, store.query));
}); });
return src; return src;

View file

@ -37,11 +37,11 @@ export default function Formatter(props: {}) {
return <div class={css.root}> return <div class={css.root}>
<textarea oninput={onInput} title="markdown">{value()}</textarea> <textarea oninput={onInput} title="markdown">{value()}</textarea>
<Editor value={value()} oninput={setValue}> {/* <Editor value={value()} oninput={setValue}>
<SearchAndReplace /> <SearchAndReplace />
</Editor> </Editor> */}
{/* <Textarea class={css.textarea} title="html" value={value()} oninput={setValue} lang="en-GB" /> */} <Textarea class={css.textarea} title="html" value={value()} oninput={setValue} lang="en-GB" />
</div>; </div>;
} }