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

devide component into emojiHintItem and emojiHInt

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

+ 14 - 5
packages/editor/src/components/CodeMirrorEditor/CodeMirrorEditor.tsx

@@ -5,9 +5,12 @@ import {
 import { indentUnit } from '@codemirror/language';
 import type { ReactCodeMirrorProps } from '@uiw/react-codemirror';
 
+import { useEmojiHintModal } from '~/stores/modal';
+
 import { GlobalCodeMirrorEditorKey } from '../../consts';
 import { useCodeMirrorEditorIsolated } from '../../stores';
 
+
 import { Toolbar } from './Toolbar';
 
 import style from './CodeMirrorEditor.module.scss';
@@ -32,6 +35,8 @@ export const CodeMirrorEditor = (props: Props): JSX.Element => {
     indentSize,
   } = props;
 
+  const { open: openEmojiHintModal } = useEmojiHintModal();
+
   const containerRef = useRef(null);
 
   const cmProps = useMemo<ReactCodeMirrorProps>(() => {
@@ -52,20 +57,24 @@ export const CodeMirrorEditor = (props: Props): JSX.Element => {
 
   }, [codeMirrorEditor, indentSize]);
 
-  const onInputColonHandler = useCallback((event) => {
-    if (event.keyCode === ':') {
-      // 処理を書く
+  const onInputColonHandler = useCallback((event: any) => {
+    if (event.key === ':') {
+      console.log('ころん!');
+      openEmojiHintModal();
     }
   }, []);
 
   useEffect(() => {
-    // addevent, cleanup
+    document.addEventListener('keydown', onInputColonHandler, false);
+    return () => {
+      document.removeEventListener('keydown', onInputColonHandler, false);
+    };
   }, [onInputColonHandler]);
 
   return (
     <div className="flex-expand-vert">
       <CodeMirrorEditorContainer ref={containerRef} />
-      <Toolbar />
+      <Toolbar codeMirrorEditor={codeMirrorEditor} />
     </div>
   );
 };

+ 34 - 37
packages/editor/src/components/CodeMirrorEditor/Toolbar/EmojiHint.tsx → packages/editor/src/components/CodeMirrorEditor/EmojiHint/EmojiHint.tsx

@@ -1,9 +1,16 @@
-import React, { useState, CSSProperties } from 'react';
+import React, { FC } from 'react';
+
 
 import { Emoji } from 'emoji-mart';
 import emojiData from 'emoji-mart/data/all.json';
+
+import { useEmojiHintModal } from '~/stores/modal';
 import 'emoji-mart/css/emoji-mart.css';
 
+import { EmojiHintItem } from './EmojiHintItem';
+
+import type { UseCodeMirrorEditor } from 'src';
+
 export const useEmojiAutoCompletion = (inputChar: string): string[] => {
   const rawEmojiDataArray = emojiData.categories;
 
@@ -41,49 +48,39 @@ export const useEmojiAutoCompletion = (inputChar: string): string[] => {
   return suggestedEmojiArray;
 };
 
-const EmojiHintItem = (props) => {
-  const { emojiName } = props;
-
-  const [itemColor, setItemColor] = useState('');
-
-  const onClickEmojiHintItemHandler = () => {};
-
-  const hoverOnHandler = () => {
-    setItemColor('#0d6efd');
-  };
-
-  const hoverOutHandler = () => {
-    setItemColor('');
-  };
-
-  return (
-    <div>
-      <div
-        className="d-flex align-items-center pt-2 pb-2 ps-2"
-        onMouseEnter={() => hoverOnHandler()}
-        onMouseLeave={() => hoverOutHandler()}
-        style={{ backgroundColor: itemColor }}
-      >
-        <Emoji emoji={emojiName} size={16} />
-        <p className="mb-0 ps-1">:{emojiName}</p>
-      </div>
-    </div>
-  );
-};
-
 const EmojiHintModalStyle = {
   maxHeight: '40vh',
   overflowY: 'auto',
   width: '70vh',
 };
 
-export const EmojiHint = () => {
+type EmojiHintProps = {
+  codeMirrorEditor: UseCodeMirrorEditor | undefined,
+}
+
+export const EmojiHint: FC<EmojiHintProps> = (props) => {
+  const { codeMirrorEditor } = props;
+
+  const { data: emojiHintModalData } = useEmojiHintModal();
+
+  const { isOpened } = emojiHintModalData;
+
   const suggestedEmojiArray = useEmojiAutoCompletion('f');
+
   return (
-    <div style={EmojiHintModalStyle} className="modal-content">
-      {suggestedEmojiArray.map(emojiName => (
-        <EmojiHintItem emojiName={emojiName} />
-      ))}
-    </div>
+    <>
+      {
+        isOpened
+          ? (
+            <div style={EmojiHintModalStyle} className="modal-content">
+              {suggestedEmojiArray.map(emojiName => (
+                <EmojiHintItem codeMirrorEditor={codeMirrorEditor} emojiName={emojiName} />
+              ))}
+            </div>
+          ) : (
+            ''
+          )
+      }
+    </>
   );
 };

+ 69 - 0
packages/editor/src/components/CodeMirrorEditor/EmojiHint/EmojiHintItem.tsx

@@ -0,0 +1,69 @@
+
+import React, { FC, useState, CSSProperties } from 'react';
+
+
+import { Emoji } from 'emoji-mart';
+import emojiData from 'emoji-mart/data/all.json';
+
+import { useEmojiHintModal } from '~/stores/modal';
+import 'emoji-mart/css/emoji-mart.css';
+
+import type { UseCodeMirrorEditor } from 'src';
+
+type EmojiHintItemProps = {
+  emojiName: string,
+  codeMirrorEditor: UseCodeMirrorEditor | undefined,
+}
+
+export const EmojiHintItem: FC<EmojiHintItemProps> = (props) => {
+  const { emojiName, codeMirrorEditor } = props;
+  const [itemColor, setItemColor] = useState('');
+
+  const view = codeMirrorEditor?.view;
+
+  if (view == null) {
+    return;
+  }
+
+  const cursorIndex = view.state.selection.main.head;
+
+  const { close: closeEmojiHintModal } = useEmojiHintModal();
+
+  const onClickEmojiHintItemHandler = () => {
+    if (cursorIndex == null) {
+      return;
+    }
+
+    view?.dispatch({
+      changes: {
+        from: cursorIndex,
+        insert: `${emojiName}:`,
+      },
+    });
+
+    closeEmojiHintModal();
+  };
+
+  const hoverOnHandler = () => {
+    setItemColor('#0d6efd');
+  };
+
+  const hoverOutHandler = () => {
+    setItemColor('');
+  };
+
+  return (
+    <div>
+      <div
+        className="d-flex align-items-center pt-2 pb-2 ps-2"
+        onMouseEnter={() => hoverOnHandler()}
+        onMouseLeave={() => hoverOutHandler()}
+        style={{ backgroundColor: itemColor }}
+        onClick={() => onClickEmojiHintItemHandler()}
+      >
+        <Emoji emoji={emojiName} size={16} />
+        <p className="mb-0 ps-1">:{emojiName}</p>
+      </div>
+    </div>
+  );
+};

+ 11 - 4
packages/editor/src/components/CodeMirrorEditor/Toolbar/Toolbar.tsx

@@ -1,17 +1,24 @@
 import { memo } from 'react';
 
+import { EmojiHint } from '../EmojiHint/EmojiHint';
+
 import { AttachmentsDropup } from './AttachmentsDropup';
 import { DiagramButton } from './DiagramButton';
 import { EmojiButton } from './EmojiButton';
-import { EmojiHint } from './EmojiHint';
 import { TableButton } from './TableButton';
 import { TemplateButton } from './TemplateButton';
 import { TextFormatTools } from './TextFormatTools';
 
+import type { UseCodeMirrorEditor } from 'src';
+
 import styles from './Toolbar.module.scss';
 
-export const Toolbar = memo((): JSX.Element => {
-  EmojiHint();
+type Props = {
+  codeMirrorEditor: UseCodeMirrorEditor | undefined
+}
+
+export const Toolbar = memo((props: Props): JSX.Element => {
+  const { codeMirrorEditor } = props;
 
   return (
     <div className={`d-flex gap-2 p-2 codemirror-editor-toolbar ${styles['codemirror-editor-toolbar']}`}>
@@ -21,7 +28,7 @@ export const Toolbar = memo((): JSX.Element => {
       <TableButton />
       <DiagramButton />
       <TemplateButton />
-      <EmojiHint />
+      <EmojiHint codeMirrorEditor={codeMirrorEditor} />
     </div>
   );
 });

+ 3 - 0
packages/editor/vite.config.ts

@@ -50,6 +50,9 @@ export default defineConfig({
         preserveModules: true,
         preserveModulesRoot: 'src',
       },
+      external: [
+        '~/stores/modal',
+      ],
     },
   },
 });