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

refactor: restructure SelectablePagePageList to use EditablePagePath component for improved readability and maintainability

Shun Miyazawa 8 месяцев назад
Родитель
Сommit
d973d25848

+ 76 - 58
apps/app/src/features/openai/client/components/AiAssistant/AiAssistantManagementModal/SelectablePagePageList.tsx

@@ -6,7 +6,6 @@ import { useRect } from '@growi/ui/dist/utils';
 import { useTranslation } from 'react-i18next';
 import AutosizeInput from 'react-input-autosize';
 
-
 import { getAdjustedMaxWidthForAutosizeInput } from '~/client/components/Common/SubmittableInput';
 
 import { type SelectablePage } from '../../../../interfaces/selectable-page';
@@ -50,26 +49,14 @@ const MethodButton = memo((props: MethodButtonProps) => {
 });
 
 
-type SelectablePagePageListProps = {
-  pages: SelectablePage[],
-  method: 'add' | 'remove' | 'delete'
-  methodButtonPosition?: 'left' | 'right',
-  disablePagePaths?: string[],
-  isEditable?: boolean,
-  onClickMethodButton: (page: SelectablePage) => void,
+type EditablePagePathProps = {
+  isEditable?: boolean;
+  page: SelectablePage;
+  methodButtonPosition?: 'left' | 'right';
 }
 
-export const SelectablePagePageList = (props: SelectablePagePageListProps): JSX.Element => {
-  const {
-    pages,
-    method,
-    methodButtonPosition = 'left',
-    disablePagePaths = [],
-    isEditable,
-    onClickMethodButton,
-  } = props;
-
-  const { t } = useTranslation();
+const EditablePagePath = memo((props: EditablePagePathProps): JSX.Element => {
+  const { page, isEditable, methodButtonPosition = 'left' } = props;
 
   const [editingPagePath, setEditingPagePath] = useState<string | null>(null);
   const [inputValue, setInputValue] = useState('');
@@ -78,14 +65,15 @@ export const SelectablePagePageList = (props: SelectablePagePageListProps): JSX.
   const editingContainerRef = useRef<HTMLDivElement>(null);
   const [editingContainerRect] = useRect(editingContainerRef);
 
-  const maxInputWidth = useMemo(() => {
+  const isEditing = isEditable && editingPagePath === page.path;
+
+  const maxWidth = useMemo(() => {
     if (editingContainerRect == null) {
       return undefined;
     }
     return getAdjustedMaxWidthForAutosizeInput(editingContainerRect.width, 'sm', true);
   }, [editingContainerRect]);
 
-
   const handlePagePathClick = useCallback((page: SelectablePage) => {
     if (!isEditable) {
       return;
@@ -104,6 +92,68 @@ export const SelectablePagePageList = (props: SelectablePagePageListProps): JSX.
     }
   }, [handleInputBlur]);
 
+  // Autofocus
+  useEffect(() => {
+    if (editingPagePath != null && inputRef.current != null) {
+      inputRef.current.focus();
+    }
+  }, [editingPagePath]);
+
+  return (
+    <div
+      ref={editingContainerRef}
+      className={`flex-grow-1 ${methodButtonPosition === 'left' ? 'me-2' : 'mx-2'}`}
+      style={{ minWidth: 0 }}
+    >
+      {isEditing
+        ? (
+          <AutosizeInput
+            id="page-path-input"
+            inputClassName="page-path-input"
+            type="text"
+            ref={inputRef}
+            value={inputValue}
+            onBlur={handleInputBlur}
+            onChange={e => setInputValue(e.target.value)}
+            onKeyDown={handleInputKeyDown}
+            inputStyle={{ maxWidth }}
+          />
+        )
+        : (
+          <span
+            className={`page-path ${isEditable ? 'page-path-editable' : ''}`}
+            onClick={() => handlePagePathClick(page)}
+            title={page.path}
+          >
+            {page.path}
+          </span>
+        )}
+    </div>
+  );
+});
+
+
+type SelectablePagePageListProps = {
+  pages: SelectablePage[],
+  method: 'add' | 'remove' | 'delete'
+  methodButtonPosition?: 'left' | 'right',
+  disablePagePaths?: string[],
+  isEditable?: boolean,
+  onClickMethodButton: (page: SelectablePage) => void,
+}
+
+export const SelectablePagePageList = (props: SelectablePagePageListProps): JSX.Element => {
+  const {
+    pages,
+    method,
+    methodButtonPosition = 'left',
+    disablePagePaths = [],
+    isEditable,
+    onClickMethodButton,
+  } = props;
+
+  const { t } = useTranslation();
+
   const methodButtonIconName = useMemo(() => {
     switch (method) {
       case 'add':
@@ -130,13 +180,6 @@ export const SelectablePagePageList = (props: SelectablePagePageListProps): JSX.
     }
   }, [method]);
 
-  // Autofocus
-  useEffect(() => {
-    if (editingPagePath != null && inputRef.current != null) {
-      inputRef.current.focus();
-    }
-  }, [editingPagePath]);
-
   if (pages.length === 0) {
     return (
       <div className={moduleClass}>
@@ -150,7 +193,6 @@ export const SelectablePagePageList = (props: SelectablePagePageListProps): JSX.
   return (
     <div className={`list-group ${moduleClass}`}>
       {pages.map((page) => {
-        const isEditing = isEditable && editingPagePath === page.path;
         return (
           <div
             key={page.path}
@@ -169,35 +211,11 @@ export const SelectablePagePageList = (props: SelectablePagePageListProps): JSX.
               )
             }
 
-            <div
-              ref={editingContainerRef}
-              className={`flex-grow-1 ${methodButtonPosition === 'left' ? 'me-2' : 'mx-2'}`}
-              style={{ minWidth: 0 }}
-            >
-              {isEditing
-                ? (
-                  <AutosizeInput
-                    id="page-path-input"
-                    inputClassName="page-path-input"
-                    type="text"
-                    ref={inputRef}
-                    value={inputValue}
-                    onBlur={handleInputBlur}
-                    onChange={e => setInputValue(e.target.value)}
-                    onKeyDown={handleInputKeyDown}
-                    inputStyle={{ maxWidth: maxInputWidth }}
-                  />
-                )
-                : (
-                  <span
-                    className={`page-path ${isEditable ? 'page-path-editable' : ''}`}
-                    onClick={() => handlePagePathClick(page)}
-                    title={page.path}
-                  >
-                    {page.path}
-                  </span>
-                )}
-            </div>
+            <EditablePagePath
+              page={page}
+              isEditable={isEditable}
+              methodButtonPosition={methodButtonPosition}
+            />
 
             <span className={`badge bg-body-secondary rounded-pill ${methodButtonPosition === 'left' ? 'me-2' : ''}`}>
               <span className="text-body-tertiary">