diff --git a/web/src/components/MemoEditor.tsx b/web/src/components/MemoEditor.tsx index 9d8560bb..9da0d341 100644 --- a/web/src/components/MemoEditor.tsx +++ b/web/src/components/MemoEditor.tsx @@ -8,44 +8,11 @@ import toastHelper from "./Toast"; import Editor, { EditorRefActions } from "./Editor/Editor"; import "../less/memo-editor.less"; -const getCursorPostion = (input: HTMLTextAreaElement) => { - const { offsetLeft: inputX, offsetTop: inputY, selectionEnd: selectionPoint } = input; - const div = document.createElement("div"); - - const copyStyle = window.getComputedStyle(input); - for (const item of copyStyle) { - div.style.setProperty(item, copyStyle.getPropertyValue(item)); - } - div.style.position = "fixed"; - div.style.visibility = "hidden"; - div.style.whiteSpace = "pre-wrap"; - - const swap = "."; - const inputValue = input.tagName === "INPUT" ? input.value.replace(/ /g, swap) : input.value; - const textContent = inputValue.substring(0, selectionPoint || 0); - div.textContent = textContent; - if (input.tagName === "TEXTAREA") { - div.style.height = "auto"; - } - - const span = document.createElement("span"); - span.textContent = inputValue.substring(selectionPoint || 0) || "."; - div.appendChild(span); - document.body.appendChild(div); - const { offsetLeft: spanX, offsetTop: spanY } = span; - document.body.removeChild(div); - return { - x: inputX + spanX, - y: inputY + spanY, - }; -}; - interface Props {} const MemoEditor: React.FC = () => { const editorState = useAppSelector((state) => state.editor); const tags = useAppSelector((state) => state.memo.tags); - const [isTagSeletorShown, toggleTagSeletor] = useToggle(false); const [isUploadingResource, setIsUploadingResource] = useToggle(false); const editorRef = useRef(null); const prevGlobalStateRef = useRef(editorState); @@ -187,61 +154,6 @@ const MemoEditor: React.FC = () => { const handleContentChange = useCallback((content: string) => { setEditorContentCache(content); - - if (editorRef.current) { - const selectionStart = editorRef.current.element.selectionStart; - const prevString = content.slice(0, selectionStart); - const nextString = content.slice(selectionStart); - - if (prevString.endsWith("#") && (nextString.startsWith(" ") || nextString === "")) { - toggleTagSeletor(true); - updateTagSelectorPopupPosition(); - } else { - toggleTagSeletor(false); - } - - editorRef.current?.focus(); - } - }, []); - - const handleTagTextBtnClick = useCallback(() => { - if (!editorRef.current) { - return; - } - - const currentValue = editorRef.current.getContent(); - const selectionStart = editorRef.current.element.selectionStart; - const prevString = currentValue.slice(0, selectionStart); - const nextString = currentValue.slice(selectionStart); - - let nextValue = prevString + "#" + nextString; - let cursorIndex = prevString.length + 1; - - if (prevString.endsWith("#") && nextString.startsWith(" ")) { - nextValue = prevString.slice(0, prevString.length - 1) + nextString.slice(1); - cursorIndex = prevString.length - 1; - } - - editorRef.current.element.value = nextValue; - editorRef.current.element.setSelectionRange(cursorIndex, cursorIndex); - editorRef.current.focus(); - handleContentChange(editorRef.current.element.value); - }, []); - - const updateTagSelectorPopupPosition = useCallback(() => { - if (!editorRef.current || !tagSeletorRef.current) { - return; - } - - const seletorPopupWidth = 128; - const editorWidth = editorRef.current.element.clientWidth; - const { x, y } = getCursorPostion(editorRef.current.element); - const left = x + seletorPopupWidth + 16 > editorWidth ? editorWidth + 20 - seletorPopupWidth : x + 2; - const top = y + 32 + 6; - - tagSeletorRef.current.scroll(0, 0); - tagSeletorRef.current.style.left = `${left}px`; - tagSeletorRef.current.style.top = `${top}px`; }, []); const handleUploadFileBtnClick = useCallback(() => { @@ -265,8 +177,8 @@ const MemoEditor: React.FC = () => { const handleTagSeletorClick = useCallback((event: React.MouseEvent) => { if (tagSeletorRef.current !== event.target && tagSeletorRef.current?.contains(event.target as Node)) { - editorRef.current?.insertText((event.target as HTMLElement).textContent + " " ?? ""); - toggleTagSeletor(false); + editorRef.current?.insertText(`#${(event.target as HTMLElement).textContent} ` ?? ""); + editorRef.current?.focus(); } }, []); @@ -294,8 +206,13 @@ const MemoEditor: React.FC = () => { {...editorConfig} tools={ <> -
- +
+ +
+ {tags.map((t) => { + return {t}; + })} +
@@ -304,15 +221,6 @@ const MemoEditor: React.FC = () => { } /> -
0 ? "" : "!hidden"}`} - onClick={handleTagSeletorClick} - > - {tags.map((t) => { - return {t}; - })} -
); }; diff --git a/web/src/less/editor.less b/web/src/less/editor.less index 05537dc4..79e170d1 100644 --- a/web/src/less/editor.less +++ b/web/src/less/editor.less @@ -38,6 +38,24 @@ > .tip-text { @apply hidden ml-1 text-xs leading-5 text-gray-700 border border-gray-300 rounded-xl px-2; } + + &.tag-action { + @apply relative; + + &:hover { + > .tag-list { + @apply flex; + } + } + + > .tag-list { + @apply hidden flex-col justify-start items-start absolute top-6 left-0 p-1 z-10 rounded w-32 max-h-52 overflow-auto bg-black; + + > span { + @apply w-full text-white cursor-pointer rounded text-sm leading-6 px-2 hover:bg-gray-700; + } + } + } } } diff --git a/web/src/less/memo-content.less b/web/src/less/memo-content.less index b6fcd9af..171e67c7 100644 --- a/web/src/less/memo-content.less +++ b/web/src/less/memo-content.less @@ -21,11 +21,11 @@ .counter-block, .todo-block { - @apply inline-block text-center w-7 font-mono select-none; + @apply float-left inline-block box-border text-center w-7 font-mono select-none; } .todo-block { - @apply w-4 h-4 leading-4 border rounded float-left box-border text-lg cursor-pointer shadow-inner hover:opacity-80; + @apply w-4 h-4 leading-4 border rounded box-border text-lg cursor-pointer shadow-inner hover:opacity-80; margin-top: 6px; margin-left: 6px; margin-right: 6px; diff --git a/web/src/less/memo-editor.less b/web/src/less/memo-editor.less index 6d6c7e2c..614b83ec 100644 --- a/web/src/less/memo-editor.less +++ b/web/src/less/memo-editor.less @@ -12,35 +12,6 @@ } > .memo-editor { - .flex(column, flex-start, flex-start); - position: relative; - width: 100%; - height: auto; - background-color: white; - } - - > .tag-list { - .flex(column, flex-start, flex-start); - position: absolute; - z-index: 10; - background-color: rgba(30, 30, 30, 0.9); - padding: 2px; - border-radius: 4px; - width: 128px; - max-height: 200px; - overflow: auto; - - > span { - width: 100%; - padding: 2px 6px; - color: white; - cursor: pointer; - border-radius: 4px; - font-size: 13px; - - &:hover { - background-color: #505050; - } - } + @apply flex flex-col justify-start items-start relative w-full h-auto bg-white; } }