Просмотр исходного кода

https://youtrack.weseek.co.jp/issue/GW-7750
- Get cursor coordinate
- Create custom position for emoji-picker
- Calculate position of cursor and emoji-picker
- Add scroll to bottom of editor if cursor location is invisible
- Apply custom position of emoji picker

Mudana-grune 4 лет назад
Родитель
Сommit
b9f8bb0e7d

+ 9 - 3
packages/app/src/components/PageEditor/EmojiPicker.tsx

@@ -1,8 +1,11 @@
-import React, { FC } from 'react';
+import React, { FC, useState } from 'react';
+
 import { Picker } from 'emoji-mart';
 import i18n from 'i18next';
 import { Modal } from 'reactstrap';
+
 import { isDarkMode } from '~/client/util/color-scheme';
+
 import EmojiPickerHelper from './EmojiPickerHelper';
 
 type Props = {
@@ -19,6 +22,7 @@ const EmojiPicker: FC<Props> = (props: Props) => {
     onClose, emojiSearchText, emojiPickerHelper, isOpen,
   } = props;
 
+  const [style, setStyle] = useState({});
   // Set search emoji input and trigger search
   const searchEmoji = () => {
     if (emojiSearchText !== null) {
@@ -28,6 +32,8 @@ const EmojiPicker: FC<Props> = (props: Props) => {
       const event = new Event('input', { bubbles: true });
       input.dispatchEvent(event);
       input.focus();
+      const emojiPickerHeight = window.document.querySelector('[id^="emoji-mart-search"]')?.clientHeight;
+      setStyle(emojiPickerHelper.getCursorCoords(emojiPickerHeight));
     }
   };
 
@@ -84,7 +90,7 @@ const EmojiPicker: FC<Props> = (props: Props) => {
   const translation = getEmojiTranslation();
   const theme = isDarkMode() ? 'dark' : 'light';
 
-  return (
+  return Object.keys(style).length !== 0 ? (
     <Modal isOpen={isOpen} toggle={onClose} onOpened={searchEmoji}>
       <Picker
         onSelect={selectEmoji}
@@ -95,7 +101,7 @@ const EmojiPicker: FC<Props> = (props: Props) => {
         theme={theme}
       />
     </Modal>
-  );
+  ) : <></>;
 };
 
 export default EmojiPicker;

+ 21 - 0
packages/app/src/components/PageEditor/EmojiPickerHelper.ts

@@ -1,3 +1,5 @@
+import { CSSProperties } from 'react';
+
 export default class EmojiPickerHelper {
 
 editor;
@@ -9,6 +11,25 @@ constructor(editor) {
   this.pattern = /:[^:\s]+/;
 }
 
+getCursorCoords = (emojiPickerHeight):CSSProperties => {
+  const offset = 30;
+  const cursorPos = this.editor.cursorCoords(true);
+  const editorPos = this.editor.getWrapperElement().getBoundingClientRect();
+  this.editor.focus();
+  // Emoji Picker bottom position exceed editor's bottom position
+  if (cursorPos.bottom + emojiPickerHeight > editorPos.bottom) {
+    return {
+      top: editorPos.bottom - emojiPickerHeight,
+      left: cursorPos.left,
+      position: 'absolute',
+    };
+  }
+  return {
+    top: cursorPos.top + offset,
+    left: cursorPos.left,
+    position: 'absolute',
+  };
+}
 
 getSearchCursor() {
   const currentPos = this.editor.getCursor();