refactor[wip]: rich text editor state handling

Create dedicated RichTextEditState class, make editor configuration more
flexible, and modify schema to support multiple text blocks. Add keyboard
submission options.
This commit is contained in:
Shibo Lyu 2025-04-02 02:07:52 +08:00
parent cd6a8e392e
commit 48f4721e5b
3 changed files with 55 additions and 5 deletions

View file

@ -0,0 +1,25 @@
import { DOMParser, Node, Schema } from 'prosemirror-model';
import type { EditorState } from 'prosemirror-state';
import { createEditorState, type EditorConfiguration } from './editorState';
export class RichTextEditState {
state: EditorState;
doc: Node | undefined = $state();
plainText = $state('');
constructor(
config: EditorConfiguration,
schema?: Schema,
initialNodeOrPlainText?: Node | string
) {
if (initialNodeOrPlainText) {
if (typeof initialNodeOrPlainText === 'string') {
this.plainText = initialNodeOrPlainText;
} else {
this.doc = initialNodeOrPlainText;
}
}
this.state = createEditorState(config, schema);
}
}

View file

@ -1,13 +1,38 @@
import { EditorState } from 'prosemirror-state';
import { EditorState, type Command } from 'prosemirror-state';
import { history, undo, redo } from 'prosemirror-history';
import { keymap } from 'prosemirror-keymap';
import { baseKeymap } from 'prosemirror-commands';
import type { Schema } from 'prosemirror-model';
import { messageSchema } from './schema';
export function createMessageEditorState() {
export type EditorConfiguration = {
keyboardSubmitMethod?: 'enter' | 'shiftEnter' | undefined;
onKeyboardSubmit?: () => void;
};
export function createEditorState(
{ keyboardSubmitMethod, onKeyboardSubmit }: EditorConfiguration,
schema: Schema = messageSchema
) {
const submitCommand: Command = () => {
onKeyboardSubmit?.();
return true;
};
const newlineCommand: Command = baseKeymap.Enter;
const submitOrNewlineKeyMap: Record<string, Command> = {};
if (keyboardSubmitMethod === 'enter') {
submitOrNewlineKeyMap['Enter'] = submitCommand;
submitOrNewlineKeyMap['Shift-Enter'] = newlineCommand;
} else if (keyboardSubmitMethod === 'shiftEnter') {
submitOrNewlineKeyMap['Enter'] = newlineCommand;
submitOrNewlineKeyMap['Shift-Enter'] = submitCommand;
}
const state = EditorState.create({
schema: messageSchema,
schema,
plugins: [
history(),
keymap({
@ -15,7 +40,7 @@ export function createMessageEditorState() {
'Mod-y': redo,
'Mod-Shift-z': redo
}),
keymap(baseKeymap)
keymap({ ...baseKeymap, ...submitOrNewlineKeyMap })
]
});

View file

@ -3,7 +3,7 @@ import { nodes as basicNodes, marks as basicMarks } from 'prosemirror-schema-bas
export const messageSchema = new Schema({
nodes: {
doc: { content: 'block' }, // For now we only support a single block
doc: { content: 'block+' },
paragragh: {
content: 'inline*'
},