Fix newlines in the contenteditable
This commit is contained in:
parent
a605c95890
commit
360bb1d714
|
|
@ -2,9 +2,17 @@
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.root {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
outline: none;
|
||||||
|
word-wrap: break-word;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
.root:empty::before {
|
.root:empty::before {
|
||||||
content: attr(data-placeholder);
|
content: attr(data-placeholder);
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
@ -70,7 +70,7 @@ export const ContentEditable = ({ value, placeholder, autoLines, onInput, class:
|
||||||
}, [value]);
|
}, [value]);
|
||||||
|
|
||||||
const handleKeyDown: JSX.KeyboardEventHandler<HTMLDivElement> = (e) => {
|
const handleKeyDown: JSX.KeyboardEventHandler<HTMLDivElement> = (e) => {
|
||||||
if (e.key !== 'Enter') return;
|
if (e.key !== 'Enter' || !ref.current) return;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const sel = window.getSelection();
|
const sel = window.getSelection();
|
||||||
|
|
@ -79,7 +79,10 @@ export const ContentEditable = ({ value, placeholder, autoLines, onInput, class:
|
||||||
const range = sel.getRangeAt(0);
|
const range = sel.getRangeAt(0);
|
||||||
range.deleteContents();
|
range.deleteContents();
|
||||||
|
|
||||||
const newline = document.createTextNode('\n');
|
const endsWithNewline = ref.current.textContent?.endsWith('\n');
|
||||||
|
const caretAtEnd = getCaretOffset(ref.current) === ref.current.textContent.length;
|
||||||
|
|
||||||
|
const newline = document.createTextNode('\n'.repeat((endsWithNewline || !caretAtEnd) ? 1 : 2));
|
||||||
range.insertNode(newline);
|
range.insertNode(newline);
|
||||||
range.setStartAfter(newline);
|
range.setStartAfter(newline);
|
||||||
range.collapse(true);
|
range.collapse(true);
|
||||||
|
|
@ -87,11 +90,15 @@ export const ContentEditable = ({ value, placeholder, autoLines, onInput, class:
|
||||||
sel.removeAllRanges();
|
sel.removeAllRanges();
|
||||||
sel.addRange(range);
|
sel.addRange(range);
|
||||||
|
|
||||||
|
(ref.current as any).value = ref.current.textContent;
|
||||||
ref.current?.dispatchEvent(new InputEvent('input', { bubbles: true }));
|
ref.current?.dispatchEvent(new InputEvent('input', { bubbles: true }));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleInput: JSX.EventHandler<JSX.TargetedInputEvent<HTMLDivElement>> = (e) => {
|
const handleInput: JSX.EventHandler<JSX.TargetedInputEvent<HTMLDivElement>> = (e) => {
|
||||||
if (autoLines && ref.current) resizeToContent(ref.current);
|
if (autoLines && ref.current) resizeToContent(ref.current);
|
||||||
|
if (ref.current) {
|
||||||
|
(ref.current as any).value = ref.current.textContent;
|
||||||
|
}
|
||||||
onInput?.(e);
|
onInput?.(e);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,12 +33,7 @@
|
||||||
line-height: 1.9;
|
line-height: 1.9;
|
||||||
color: var(--textColor);
|
color: var(--textColor);
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border: none;
|
|
||||||
outline: none;
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
white-space: pre-wrap;
|
|
||||||
word-wrap: break-word;
|
|
||||||
overflow-wrap: break-word;
|
|
||||||
|
|
||||||
&::placeholder {
|
&::placeholder {
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import clsx from "clsx";
|
||||||
import { CharacterEditor } from "./character-editor";
|
import { CharacterEditor } from "./character-editor";
|
||||||
import { LocationEditor } from "./location-editor";
|
import { LocationEditor } from "./location-editor";
|
||||||
import { ChaptersEditor } from "./chapters-editor";
|
import { ChaptersEditor } from "./chapters-editor";
|
||||||
|
import { useInputCallback } from "@common/hooks/useInputCallback";
|
||||||
|
|
||||||
const TABS: { id: Tab; label: string }[] = [
|
const TABS: { id: Tab; label: string }[] = [
|
||||||
{ id: "story", label: "Story" },
|
{ id: "story", label: "Story" },
|
||||||
|
|
@ -23,23 +24,21 @@ export const Editor = () => {
|
||||||
return <div class={styles.editor} />;
|
return <div class={styles.editor} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleInput = (e: Event) => {
|
const handleInput = useInputCallback((text: string) => {
|
||||||
const text = (e.target as HTMLElement).textContent || '';
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'EDIT_STORY',
|
type: 'EDIT_STORY',
|
||||||
id: currentStory.id,
|
id: currentStory.id,
|
||||||
text,
|
text,
|
||||||
});
|
});
|
||||||
};
|
}, []);
|
||||||
|
|
||||||
const handleLoreInput = (e: Event) => {
|
const handleLoreInput = useInputCallback((lore: string) => {
|
||||||
const lore = (e.target as HTMLElement).textContent || '';
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'EDIT_LORE',
|
type: 'EDIT_LORE',
|
||||||
id: currentStory.id,
|
id: currentStory.id,
|
||||||
lore,
|
lore,
|
||||||
});
|
});
|
||||||
};
|
}, []);
|
||||||
|
|
||||||
const handleTabChange = (tab: Tab) => {
|
const handleTabChange = (tab: Tab) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue