WNomunomu 2 лет назад
Родитель
Сommit
7dceee57f9

+ 1 - 9
packages/editor/src/components/CodeMirrorEditor/CodeMirrorEditor.tsx

@@ -5,7 +5,7 @@ import {
 import { indentUnit } from '@codemirror/language';
 import type { ReactCodeMirrorProps } from '@uiw/react-codemirror';
 
-import { useEmojiPickerModal } from '~/stores/modal';
+// import { useEmojiPickerModal } from '~/stores/modal';
 
 import { GlobalCodeMirrorEditorKey } from '../../consts';
 import { useCodeMirrorEditorIsolated } from '../../stores';
@@ -34,8 +34,6 @@ export const CodeMirrorEditor = (props: Props): JSX.Element => {
     indentSize,
   } = props;
 
-  const { open } = useEmojiPickerModal();
-
   const containerRef = useRef(null);
 
   const cmProps = useMemo<ReactCodeMirrorProps>(() => {
@@ -56,12 +54,6 @@ export const CodeMirrorEditor = (props: Props): JSX.Element => {
 
   }, [codeMirrorEditor, indentSize]);
 
-  const onInputColonHandler = useCallback((event) => {
-    if (event.key === 'DOM_VK_COLON') {
-      // emoji pickerを起動する処理
-    }
-  }, []);
-
   return (
     <div className="flex-expand-vert">
       <CodeMirrorEditorContainer ref={containerRef} />

+ 50 - 15
packages/editor/src/components/CodeMirrorEditor/Toolbar/EmojiButton.tsx

@@ -1,10 +1,9 @@
-import React, { FC, useState } from 'react';
+import React, { FC, useState, CSSProperties } from 'react';
 
 import { Picker } from 'emoji-mart';
 import i18n from 'i18next';
 import { Modal } from 'reactstrap';
 
-
 import { useNextThemes } from '~/stores/use-next-themes';
 
 import type { UseCodeMirrorEditor } from 'src';
@@ -69,6 +68,13 @@ export const EmojiButton: FC<Props> = (props) => {
   const [isOpen, setIsOpen] = useState(false);
 
   const { codeMirrorEditor } = props;
+  const view = codeMirrorEditor?.view;
+
+  if (view == null) {
+    return;
+  }
+
+  const cursorIndex = view?.state.selection.main.head;
 
   const { resolvedTheme } = useNextThemes();
   const translation = getEmojiTranslation();
@@ -76,19 +82,45 @@ export const EmojiButton: FC<Props> = (props) => {
   const toggle = () => setIsOpen(!isOpen);
 
   const selectEmoji = (emoji: { colons: string }): void => {
-    const view = codeMirrorEditor?.view;
-    const currentPos = view?.state.selection.main.head;
 
-    if (currentPos == null) {
+    if (cursorIndex == null) {
       return;
     }
 
     view?.dispatch({
       changes: {
-        from: currentPos,
+        from: cursorIndex,
         insert: emoji.colons,
       },
     });
+
+    toggle();
+  };
+
+  const setStyle = (): CSSProperties => {
+    const offset = 20;
+    const emojiPickerHeight = 420;
+    // const cursorPos = this.editor.cursorCoords(true);
+    const cursorRect = view.coordsAtPos(cursorIndex);
+    const editorRect = view.dom.getBoundingClientRect();
+
+    if (cursorRect == null) {
+      return {};
+    }
+
+    // Emoji Picker bottom position exceed editor's bottom position
+    if (cursorRect.bottom + emojiPickerHeight > editorRect.bottom) {
+      return {
+        top: editorRect.bottom - emojiPickerHeight,
+        left: cursorRect.left + offset,
+        position: 'fixed',
+      };
+    }
+    return {
+      top: cursorRect.top + offset,
+      left: cursorRect.left + offset,
+      position: 'fixed',
+    };
   };
 
   return (
@@ -96,15 +128,18 @@ export const EmojiButton: FC<Props> = (props) => {
       <button type="button" className="btn btn-toolbar-button" onClick={toggle}>
         <span className="material-icons-outlined fs-6">emoji_emotions</span>
       </button>
-      <Modal isOpen={isOpen} toggle={toggle} backdropClassName="emoji-picker-modal" fade={false}>
-        <Picker
-          onSelect={(emoji: any) => selectEmoji(emoji)}
-          i18n={translation}
-          title={translation.title}
-          emojiTooltip
-          theme={resolvedTheme}
-        />
-      </Modal>
+      <div className="mb-2 d-none d-md-block">
+        <Modal isOpen={isOpen} toggle={toggle} backdropClassName="emoji-picker-modal" fade={false}>
+          <Picker
+            onSelect={(emoji: any) => selectEmoji(emoji)}
+            i18n={translation}
+            title={translation.title}
+            emojiTooltip
+            style={setStyle()}
+            theme={resolvedTheme}
+          />
+        </Modal>
+      </div>
     </>
   );
 };