mirror of
https://github.com/usememos/memos.git
synced 2024-12-26 07:01:17 +08:00
feat: impl list syntax auto complete to editor
This commit is contained in:
parent
436a6cb084
commit
6d10251cbd
4 changed files with 137 additions and 89 deletions
|
@ -1,8 +1,10 @@
|
|||
import classNames from "classnames";
|
||||
import { forwardRef, ReactNode, useCallback, useEffect, useImperativeHandle, useRef } from "react";
|
||||
import { useAutoComplete } from "../hooks";
|
||||
import TagSuggestions from "./TagSuggestions";
|
||||
|
||||
export interface EditorRefActions {
|
||||
getEditor: () => HTMLTextAreaElement | null;
|
||||
focus: FunctionType;
|
||||
scrollToCursor: FunctionType;
|
||||
insertText: (text: string, prefix?: string, suffix?: string) => void;
|
||||
|
@ -43,16 +45,10 @@ const Editor = forwardRef(function Editor(props: Props, ref: React.ForwardedRef<
|
|||
}
|
||||
}, [editorRef.current?.value]);
|
||||
|
||||
const updateEditorHeight = () => {
|
||||
if (editorRef.current) {
|
||||
editorRef.current.style.height = "auto";
|
||||
editorRef.current.style.height = (editorRef.current.scrollHeight ?? 0) + "px";
|
||||
}
|
||||
};
|
||||
|
||||
useImperativeHandle(
|
||||
ref,
|
||||
() => ({
|
||||
const editorActions = {
|
||||
getEditor: () => {
|
||||
return editorRef.current;
|
||||
},
|
||||
focus: () => {
|
||||
editorRef.current?.focus();
|
||||
},
|
||||
|
@ -135,9 +131,18 @@ const Editor = forwardRef(function Editor(props: Props, ref: React.ForwardedRef<
|
|||
updateEditorHeight();
|
||||
}
|
||||
},
|
||||
}),
|
||||
[],
|
||||
);
|
||||
};
|
||||
|
||||
useAutoComplete(editorActions);
|
||||
|
||||
useImperativeHandle(ref, () => editorActions, []);
|
||||
|
||||
const updateEditorHeight = () => {
|
||||
if (editorRef.current) {
|
||||
editorRef.current.style.height = "auto";
|
||||
editorRef.current.style.height = (editorRef.current.scrollHeight ?? 0) + "px";
|
||||
}
|
||||
};
|
||||
|
||||
const handleEditorInput = useCallback(() => {
|
||||
handleContentChangeCallback(editorRef.current?.value ?? "");
|
||||
|
|
3
web/src/components/MemoEditor/hooks/index.ts
Normal file
3
web/src/components/MemoEditor/hooks/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
import useAutoComplete from "./useAutoComplete";
|
||||
|
||||
export { useAutoComplete };
|
40
web/src/components/MemoEditor/hooks/useAutoComplete.ts
Normal file
40
web/src/components/MemoEditor/hooks/useAutoComplete.ts
Normal file
|
@ -0,0 +1,40 @@
|
|||
import { last } from "lodash-es";
|
||||
import { useEffect } from "react";
|
||||
import { NodeType, OrderedListNode, TaskListNode, UnorderedListNode } from "@/types/node";
|
||||
import { EditorRefActions } from "../Editor";
|
||||
|
||||
const useAutoComplete = (actions: EditorRefActions) => {
|
||||
useEffect(() => {
|
||||
const editor = actions.getEditor();
|
||||
if (!editor) return;
|
||||
|
||||
editor.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Enter") {
|
||||
const cursorPosition = actions.getCursorPosition();
|
||||
const prevContent = actions.getContent().substring(0, cursorPosition);
|
||||
const lastNode = last(window.parse(prevContent));
|
||||
if (!lastNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
let insertText = "";
|
||||
if (lastNode.type === NodeType.TASK_LIST) {
|
||||
const { complete } = lastNode.value as TaskListNode;
|
||||
insertText = complete ? "- [x] " : "- [ ] ";
|
||||
} else if (lastNode.type === NodeType.UNORDERED_LIST) {
|
||||
const { symbol } = lastNode.value as UnorderedListNode;
|
||||
insertText = `${symbol} `;
|
||||
} else if (lastNode.type === NodeType.ORDERED_LIST) {
|
||||
const { number } = lastNode.value as OrderedListNode;
|
||||
insertText = `${Number(number) + 1}. `;
|
||||
}
|
||||
if (insertText) {
|
||||
actions.insertText(`\n${insertText}`);
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
};
|
||||
|
||||
export default useAutoComplete;
|
Loading…
Reference in a new issue