Yuki Takei 1 год назад
Родитель
Сommit
8ed31942cf

+ 21 - 0
apps/app/src/components/Sidebar/PageTreeItem/CountBadgeForPageTreeItem.tsx

@@ -0,0 +1,21 @@
+import CountBadge from '~/components/Common/CountBadge';
+import type { TreeItemToolProps } from '~/components/TreeItem';
+import { usePageTreeDescCountMap } from '~/stores/ui';
+
+export const CountBadgeForPageTreeItem = (props: TreeItemToolProps): JSX.Element => {
+  const { getDescCount } = usePageTreeDescCountMap();
+
+  const { page } = props.itemNode;
+
+  const descendantCount = getDescCount(page._id) || page.descendantCount || 0;
+
+  return (
+    <>
+      {descendantCount > 0 && (
+        <div className="d-hover-none">
+          <CountBadge count={descendantCount} />
+        </div>
+      )}
+    </>
+  );
+};

+ 9 - 0
apps/app/src/components/Sidebar/PageTreeItem/Ellipsis.module.scss

@@ -0,0 +1,9 @@
+.rename-input-container {
+  &:global {
+    // right: 0;
+    // left: 0;
+    // display: inline-flex;
+
+    // width: calc(100% - 80px);
+  }
+}

+ 56 - 42
apps/app/src/components/Sidebar/PageTreeItem/Ellipsis.tsx

@@ -1,6 +1,6 @@
 import type { FC } from 'react';
 import React, {
-  useCallback, useState,
+  useCallback, useRef, useState,
 } from 'react';
 
 import nodePath from 'path';
@@ -8,6 +8,7 @@ import nodePath from 'path';
 
 import type { IPageInfoAll, IPageToDeleteWithMeta } from '@growi/core';
 import { pathUtils } from '@growi/core/dist/utils';
+import { useRect } from '@growi/ui/dist/utils';
 import { useTranslation } from 'next-i18next';
 import { DropdownToggle } from 'reactstrap';
 
@@ -15,16 +16,22 @@ import { bookmark, unbookmark, resumeRenameOperation } from '~/client/services/p
 import { apiv3Put } from '~/client/util/apiv3-client';
 import { ValidationTarget } from '~/client/util/input-validator';
 import { toastError, toastSuccess } from '~/client/util/toastr';
+import { AutosizeSubmittableInput } from '~/components/Common/SubmittableInput';
 import { NotAvailableForGuest } from '~/components/NotAvailableForGuest';
 import { useSWRMUTxCurrentUserBookmarks } from '~/stores/bookmark';
 import { useSWRMUTxPageInfo } from '~/stores/page';
 
-import ClosableTextInput from '../../Common/ClosableTextInput';
 import { PageItemControl } from '../../Common/Dropdown/PageItemControl';
 import {
-  type TreeItemToolProps, NotDraggableForClosableTextInput, SimpleItemTool,
+  type TreeItemToolProps, NotDraggableForClosableTextInput,
 } from '../../TreeItem';
 
+
+import styles from './Ellipsis.module.scss';
+
+const renameInputContainerClass = styles['rename-input-container'] ?? '';
+
+
 export const Ellipsis: FC<TreeItemToolProps> = (props) => {
   const [isRenameInputShown, setRenameInputShown] = useState(false);
   const { t } = useTranslation();
@@ -34,6 +41,9 @@ export const Ellipsis: FC<TreeItemToolProps> = (props) => {
     onClickDeleteMenuItem, isEnableActions, isReadOnlyUser,
   } = props;
 
+  const parentRef = useRef<HTMLDivElement>(null);
+  const parentRect = useRect(parentRef);
+
   const { page } = itemNode;
 
   const { trigger: mutateCurrentUserBookmarks } = useSWRMUTxCurrentUserBookmarks();
@@ -132,48 +142,52 @@ export const Ellipsis: FC<TreeItemToolProps> = (props) => {
     }
   };
 
-  const hasChildren = page.descendantCount ? page.descendantCount > 0 : false;
+  const maxWidth = parentRect[0]?.width;
+  console.log({ parentRef });
+  console.log('maxWidth:', maxWidth);
 
   return (
     <>
-      {isRenameInputShown ? (
-        <div className={`position-absolute ${hasChildren ? 'ms-5' : 'ms-4'}`}>
-          <NotDraggableForClosableTextInput>
-            <ClosableTextInput
-              value={nodePath.basename(page.path ?? '')}
-              placeholder={t('Input page name')}
-              onPressEnter={rename}
-              onBlur={rename}
-              onPressEscape={cancel}
-              validationTarget={ValidationTarget.PAGE}
-            />
-          </NotDraggableForClosableTextInput>
-        </div>
-      ) : (
-        <SimpleItemTool itemNode={itemNode} isEnableActions={false} isReadOnlyUser={false} />
-      )}
-      <NotAvailableForGuest>
-        <div className="grw-pagetree-control d-flex">
-          <PageItemControl
-            pageId={page._id}
-            isEnableActions={isEnableActions}
-            isReadOnlyUser={isReadOnlyUser}
-            onClickBookmarkMenuItem={bookmarkMenuItemClickHandler}
-            onClickDuplicateMenuItem={duplicateMenuItemClickHandler}
-            onClickRenameMenuItem={renameMenuItemClickHandler}
-            onClickDeleteMenuItem={deleteMenuItemClickHandler}
-            onClickPathRecoveryMenuItem={pathRecoveryMenuItemClickHandler}
-            isInstantRename
-            // Todo: It is wanted to find a better way to pass operationProcessData to PageItemControl
-            operationProcessData={page.processData}
-          >
-            {/* pass the color property to reactstrap dropdownToggle props. https://6-4-0--reactstrap.netlify.app/components/dropdowns/  */}
-            <DropdownToggle color="transparent" className="border-0 rounded btn-page-item-control p-0 grw-visible-on-hover mr-1">
-              <span id="option-button-in-page-tree" className="material-symbols-outlined p-1">more_vert</span>
-            </DropdownToggle>
-          </PageItemControl>
-        </div>
-      </NotAvailableForGuest>
+      {/* {isRenameInputShown || page._id === '6630d957b26dc26e85ee21a8' ? ( */}
+      {/* <NotDraggableForClosableTextInput> */}
+      <div ref={parentRef} className={`position-absolute ${renameInputContainerClass} ${isRenameInputShown || page._id === '6630d957b26dc26e85ee21a8' ? '' : 'd-none'}`}>
+        <AutosizeSubmittableInput
+          value={nodePath.basename(page.path ?? '')}
+          inputClassName="form-control"
+          inputStyle={{ maxWidth }}
+          placeholder={t('Input page name')}
+          onSubmit={rename}
+          onCancel={cancel}
+          // validationTarget={ValidationTarget.PAGE}
+          autoFocus
+        />
+      </div>
+      {/* </NotDraggableForClosableTextInput> */}
+
+      { !isRenameInputShown && (
+        <NotAvailableForGuest>
+          <div className="grw-pagetree-control d-flex">
+            <PageItemControl
+              pageId={page._id}
+              isEnableActions={isEnableActions}
+              isReadOnlyUser={isReadOnlyUser}
+              onClickBookmarkMenuItem={bookmarkMenuItemClickHandler}
+              onClickDuplicateMenuItem={duplicateMenuItemClickHandler}
+              onClickRenameMenuItem={renameMenuItemClickHandler}
+              onClickDeleteMenuItem={deleteMenuItemClickHandler}
+              onClickPathRecoveryMenuItem={pathRecoveryMenuItemClickHandler}
+              isInstantRename
+              // Todo: It is wanted to find a better way to pass operationProcessData to PageItemControl
+              operationProcessData={page.processData}
+            >
+              {/* pass the color property to reactstrap dropdownToggle props. https://6-4-0--reactstrap.netlify.app/components/dropdowns/  */}
+              <DropdownToggle color="transparent" className="border-0 rounded btn-page-item-control d-none d-hover-block p-0 mr-1">
+                <span id="option-button-in-page-tree" className="material-symbols-outlined p-1">more_vert</span>
+              </DropdownToggle>
+            </PageItemControl>
+          </div>
+        </NotAvailableForGuest>
+      ) }
     </>
   );
 };

+ 2 - 1
apps/app/src/components/Sidebar/PageTreeItem/PageTreeItem.tsx

@@ -22,6 +22,7 @@ import {
   SimpleItem, useNewPageInput, type TreeItemProps,
 } from '../../TreeItem';
 
+import { CountBadgeForPageTreeItem } from './CountBadgeForPageTreeItem';
 import { Ellipsis } from './Ellipsis';
 
 import styles from './PageTreeItem.module.scss';
@@ -186,7 +187,7 @@ export const PageTreeItem: FC<TreeItemProps> = (props) => {
       itemRef={itemRef}
       itemClass={PageTreeItem}
       mainClassName={mainClassName}
-      customEndComponents={[Ellipsis, NewPageCreateButton]}
+      customEndComponents={[CountBadgeForPageTreeItem, Ellipsis, NewPageCreateButton]}
       customNextComponents={[NewPageInput]}
     />
   );

+ 2 - 21
apps/app/src/components/TreeItem/SimpleItem.tsx

@@ -15,8 +15,6 @@ import { useSWRxPageChildren } from '~/stores/page-listing';
 import { usePageTreeDescCountMap } from '~/stores/ui';
 import { shouldRecoverPagePaths } from '~/utils/page-operation';
 
-import CountBadge from '../Common/CountBadge';
-
 import { ItemNode } from './ItemNode';
 import { useNewPageInput } from './NewPageInput';
 import type { TreeItemProps, TreeItemToolProps } from './interfaces';
@@ -79,23 +77,6 @@ const SimpleItemContent = ({ page }: { page: IPageForItem }) => {
   );
 };
 
-export const SimpleItemTool: FC<TreeItemToolProps> = (props) => {
-  const { getDescCount } = usePageTreeDescCountMap();
-
-  const { page } = props.itemNode;
-
-  const descendantCount = getDescCount(page._id) || page.descendantCount || 0;
-
-  return (
-    <>
-      {descendantCount > 0 && (
-        <div className="d-hover-none">
-          <CountBadge count={descendantCount} />
-        </div>
-      )}
-    </>
-  );
-};
 
 type SimpleItemProps = TreeItemProps & {
   itemRef?: RefObject<any> | RefCallback<any>,
@@ -173,7 +154,7 @@ export const SimpleItem: FC<SimpleItemProps> = (props) => {
 
   const ItemClassFixed = itemClass ?? SimpleItem;
 
-  const EndComponents = props.customEndComponents ?? [SimpleItemTool];
+  const EndComponents = props.customEndComponents;
 
   const baseProps: Omit<TreeItemProps, 'itemNode'> = {
     isEnableActions,
@@ -227,7 +208,7 @@ export const SimpleItem: FC<SimpleItemProps> = (props) => {
 
         <SimpleItemContent page={page} />
 
-        {EndComponents.map((EndComponent, index) => (
+        {EndComponents?.map((EndComponent, index) => (
           // eslint-disable-next-line react/no-array-index-key
           <EndComponent key={index} {...toolProps} />
         ))}