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

implement an operation when escape key is pressed

kosei-n 2 лет назад
Родитель
Сommit
4bfb8b80ea

+ 11 - 2
apps/app/src/components/Common/ClosableTextInput.tsx

@@ -1,16 +1,19 @@
+import type { FC } from 'react';
 import React, {
-  FC, memo, useEffect, useRef, useState,
+  memo, useEffect, useRef, useState,
 } from 'react';
 
 import { useTranslation } from 'next-i18next';
 
-import { AlertInfo, AlertType, inputValidator } from '~/client/util/input-validator';
+import type { AlertInfo } from '~/client/util/input-validator';
+import { AlertType, inputValidator } from '~/client/util/input-validator';
 
 type ClosableTextInputProps = {
   value?: string
   placeholder?: string
   validationTarget?: string,
   onPressEnter?(inputText: string | null): void
+  onPressEscape?: () => void
   onClickOutside?(): void
   handleInputChange?: (string) => void
 }
@@ -66,6 +69,12 @@ const ClosableTextInput: FC<ClosableTextInputProps> = memo((props: ClosableTextI
         }
         onPressEnter();
         break;
+      case 'Escape':
+        if (isComposing) {
+          return;
+        }
+        props.onPressEscape?.();
+        break;
       default:
         break;
     }

+ 48 - 53
apps/app/src/components/PageHeader/PagePathHeader.tsx

@@ -12,14 +12,9 @@ import { EditorMode, useEditorMode } from '~/stores/ui';
 import { PagePathNav } from '../Common/PagePathNav';
 import { PageSelectModal } from '../PageSelectModal/PageSelectModal';
 
-import { TextInputForPageTitleAndPath } from './TextInputForPageTitleAndPath';
+import { TextInputForPageTitleAndPath, type editingPagePathHandler } from './TextInputForPageTitleAndPath';
 import { usePagePathRenameHandler } from './page-header-utils';
 
-type editingPagePathHandler = {
-  editingPagePath: string
-  setEditingPagePath: Dispatch<SetStateAction<string>>
-}
-
 export type Props = {
   currentPagePath: string
   currentPage: IPagePopulatedToShowRevision
@@ -27,7 +22,7 @@ export type Props = {
 }
 
 export const PagePathHeader: FC<Props> = (props) => {
-  const { currentPagePath, currentPage } = props;
+  const { currentPagePath, currentPage, editingPagePathHandler } = props;
 
   const [isRenameInputShown, setRenameInputShown] = useState(false);
   const [isButtonsShown, setButtonShown] = useState(false);
@@ -35,7 +30,7 @@ export const PagePathHeader: FC<Props> = (props) => {
   const { data: editorMode } = useEditorMode();
   const { data: PageSelectModalData, open: openPageSelectModal } = usePageSelectModal();
 
-  const { editingPagePath, setEditingPagePath } = props.editingPagePathHandler;
+  const { editingPagePath, setEditingPagePath } = editingPagePathHandler;
 
   const onRenameFinish = () => {
     setRenameInputShown(false);
@@ -81,59 +76,59 @@ export const PagePathHeader: FC<Props> = (props) => {
 
   const buttonStyle = isButtonsShown ? '' : 'd-none';
 
-  const clickOutSideHandler = (e) => {
-    const container = document.getElementById('page-path-header');
+  // const clickOutSideHandler = (e) => {
+  //   const container = document.getElementById('page-path-header');
 
-    if (container && !container.contains(e.target)) {
-      setRenameInputShown(false);
-    }
-  };
+  //   if (container && !container.contains(e.target)) {
+  //     pagePathRenameHandler(editingPagePath);
+  //     console.log('click outside');
+  //   }
+  // };
 
-  useEffect(() => {
-    document.addEventListener('click', clickOutSideHandler);
+  // useEffect(() => {
+  //   document.addEventListener('click', clickOutSideHandler);
 
-    return () => {
-      document.removeEventListener('click', clickOutSideHandler);
-    };
-  }, []);
+  //   return () => {
+  //     document.removeEventListener('click', clickOutSideHandler);
+  //   };
+  // }, []);
 
   return (
-    <>
-      <div
-        id="page-path-header"
-        onMouseLeave={() => setButtonShown(false)}
-      >
-        <div className="row">
-          <div
-            className="col-4"
-            onMouseEnter={() => setButtonShown(true)}
-          >
-            <TextInputForPageTitleAndPath
-              currentPage={currentPage}
-              stateHandler={stateHandler}
-              inputValue={editingPagePath}
-              CustomComponent={PagePath}
-              handleInputChange={handleInputChange}
-            />
+    <div
+      id="page-path-header"
+      onMouseLeave={() => setButtonShown(false)}
+    >
+      <div className="row">
+        <div
+          className="col-4"
+          onMouseEnter={() => setButtonShown(true)}
+        >
+          <TextInputForPageTitleAndPath
+            currentPage={currentPage}
+            stateHandler={stateHandler}
+            editingPagePathHandler={editingPagePathHandler}
+            inputValue={editingPagePath}
+            CustomComponent={PagePath}
+            handleInputChange={handleInputChange}
+          />
+        </div>
+        <div className={`${buttonStyle} col-4 row`}>
+          <div className="col-4">
+            <button type="button" onClick={handleEditButtonClick}>
+              {isRenameInputShown ? <span className="material-symbols-outlined">check_circle</span> : <span className="material-symbols-outlined">edit</span>}
+            </button>
           </div>
-          <div className={`${buttonStyle} col-4 row`}>
-            <div className="col-4">
-              <button type="button" onClick={handleEditButtonClick}>
-                {isRenameInputShown ? <span className="material-symbols-outlined">check_circle</span> : <span className="material-symbols-outlined">edit</span>}
-              </button>
-            </div>
-            <div className="col-4">
-              <button type="button" onClick={openPageSelectModal}>
-                <span className="material-symbols-outlined">account_tree</span>
-              </button>
-            </div>
+          <div className="col-4">
+            <button type="button" onClick={openPageSelectModal}>
+              <span className="material-symbols-outlined">account_tree</span>
+            </button>
           </div>
-          {isOpened
-            && (
-              <PageSelectModal />
-            )}
         </div>
+        {isOpened
+          && (
+            <PageSelectModal />
+          )}
       </div>
-    </>
+    </div>
   );
 };

+ 48 - 4
apps/app/src/components/PageHeader/PageTitleHeader.tsx

@@ -1,5 +1,7 @@
 import type { FC } from 'react';
-import { useState, useMemo, useEffect } from 'react';
+import {
+  useState, useMemo, useEffect, useRef,
+} from 'react';
 
 import nodePath from 'path';
 
@@ -12,12 +14,14 @@ import { usePagePathRenameHandler } from './page-header-utils';
 
 
 export const PageTitleHeader: FC<Props> = (props) => {
-  const { currentPagePath, currentPage } = props;
+  const { currentPagePath, currentPage, editingPagePathHandler } = props;
   const pageTitle = nodePath.basename(currentPagePath ?? '') || '/';
 
   const [isRenameInputShown, setRenameInputShown] = useState(false);
 
-  const { editingPagePath, setEditingPagePath } = props.editingPagePathHandler;
+  const ref = useRef<HTMLDivElement>(null);
+
+  const { editingPagePath, setEditingPagePath } = editingPagePathHandler;
 
   const editingPageTitle = nodePath.basename(editingPagePath);
 
@@ -52,15 +56,55 @@ export const PageTitleHeader: FC<Props> = (props) => {
     pagePathRenameHandler(editingPagePath);
   };
 
+  // useEffect(() => {
+  //   const element = ref.current;
+
+  //   if (element == null) {
+  //     return;
+  //   }
+
+  //   const handleClickOutside = (e) => {
+  //     if (!element.contains(e.target)) {
+  //       pagePathRenameHandler(editingPagePath);
+  //     }
+  //   };
+
+  //   document.addEventListener('click', handleClickOutside);
+
+  //   return () => {
+  //     document.removeEventListener('click', handleClickOutside);
+  //   };
+
+  // }, []);
+
+  // const clickOutSideHandler = (e) => {
+  //   const container = document.getElementById('page-title-header');
+
+  //   if (container && !container.contains(e.target)) {
+  //     pagePathRenameHandler(editingPagePath);
+  //     console.log('click outside');
+  //   }
+  // };
+
+  // useEffect(() => {
+  //   document.addEventListener('click', clickOutSideHandler);
+
+  //   return () => {
+  //     document.removeEventListener('click', clickOutSideHandler);
+  //   };
+  // }, []);
+
   return (
     <div
       className="row"
-      onBlur={onBlurHandler}
+      // onBlur={onBlurHandler}
+      ref={ref}
     >
       <div className="col-4">
         <TextInputForPageTitleAndPath
           currentPage={currentPage}
           stateHandler={stateHandler}
+          editingPagePathHandler={editingPagePathHandler}
           inputValue={editingPageTitle}
           CustomComponent={PageTitle}
           handleInputChange={handleInputChange}

+ 14 - 1
apps/app/src/components/PageHeader/TextInputForPageTitleAndPath.tsx

@@ -15,6 +15,11 @@ import ClosableTextInput from '../Common/ClosableTextInput';
 import { usePagePathRenameHandler } from './page-header-utils';
 
 
+export type editingPagePathHandler = {
+  editingPagePath: string
+  setEditingPagePath: Dispatch<SetStateAction<string>>
+}
+
 type StateHandler = {
   isRenameInputShown: boolean
   setRenameInputShown: Dispatch<SetStateAction<boolean>>
@@ -23,6 +28,7 @@ type StateHandler = {
 type Props = {
   currentPage: IPagePopulatedToShowRevision
   stateHandler: StateHandler
+  editingPagePathHandler: editingPagePathHandler
   inputValue: string
   CustomComponent: JSX.Element
   handleInputChange?: (string) => void
@@ -30,12 +36,13 @@ type Props = {
 
 export const TextInputForPageTitleAndPath: FC<Props> = (props) => {
   const {
-    currentPage, stateHandler, inputValue, CustomComponent, handleInputChange,
+    currentPage, stateHandler, inputValue, CustomComponent, handleInputChange, editingPagePathHandler,
   } = props;
 
   const { t } = useTranslation();
 
   const { isRenameInputShown, setRenameInputShown } = stateHandler;
+  const { setEditingPagePath } = editingPagePathHandler;
 
   const onRenameFinish = () => {
     setRenameInputShown(false);
@@ -56,6 +63,11 @@ export const TextInputForPageTitleAndPath: FC<Props> = (props) => {
 
   }, [currentPage.path, pagePathRenameHandler]);
 
+  const onPressEscape = useCallback(() => {
+    setEditingPagePath(currentPage.path);
+    setRenameInputShown(false);
+  }, [currentPage.path, setEditingPagePath, setRenameInputShown]);
+
   return (
     <>
       {isRenameInputShown ? (
@@ -64,6 +76,7 @@ export const TextInputForPageTitleAndPath: FC<Props> = (props) => {
             value={inputValue}
             placeholder={t('Input page name')}
             onPressEnter={onPressEnter}
+            onPressEscape={onPressEscape}
             validationTarget={ValidationTarget.PAGE}
             handleInputChange={handleInputChange}
           />