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

+ 1 - 1
apps/app/src/components/Common/PagePathHierarchicalLink/PagePathHierarchicalLink.tsx

@@ -3,7 +3,7 @@ import React, { memo, useCallback } from 'react';
 import Link from 'next/link';
 import urljoin from 'url-join';
 
-import type LinkedPagePath from '../../../models/linked-page-path';
+import type LinkedPagePath from '~/models/linked-page-path';
 
 import styles from './PagePathHierarchicalLink.module.scss';
 

+ 0 - 22
apps/app/src/components/Common/PagePathNav/PagePathNav.module.scss

@@ -1,27 +1,5 @@
-@use '@growi/core-styles/scss/bootstrap/init' as bs;
 @use '@growi/ui/scss/atoms/btn-muted';
 
-.grw-mx-02em {
-  margin-right: 0.2em;
-  margin-left: 0.2em;
-}
-
-.grw-page-path-nav-sticky :global {
-  min-height: 75px;
-
-  .sticky-inner-wrapper {
-    z-index: bs.$zindex-sticky;
-  }
-
-  // TODO:Responsive font size
-  // set smaller font-size when sticky
-  .sticky-inner-wrapper.active {
-    h1 {
-      font-size: 1.75rem !important;
-    }
-  }
-}
-
 .grw-page-path-nav :global {
   .btn-copy {
     @include btn-muted.colorize(bs.$orange);

+ 12 - 129
apps/app/src/components/Common/PagePathNav/PagePathNav.tsx

@@ -1,76 +1,37 @@
-import React, {
-  useEffect,
-  useRef,
-  useState,
-} from 'react';
-
 import { DevidedPagePath } from '@growi/core/dist/models';
 import { pagePathUtils } from '@growi/core/dist/utils';
-import dynamic from 'next/dynamic';
-import Sticky from 'react-stickynode';
 
-import { useIsNotFound } from '~/stores/page';
-import {
-  usePageControlsX, useCurrentProductNavWidth, useSidebarMode,
-} from '~/stores/ui';
+import LinkedPagePath from '~/models/linked-page-path';
 
-import LinkedPagePath from '../../../models/linked-page-path';
 import { PagePathHierarchicalLink } from '../PagePathHierarchicalLink';
-import { CollapsedParentsDropdown } from '../PagePathHierarchicalLink/CollapsedParentsDropdown';
+
+import type { PagePathNavLayoutProps } from './PagePathNavLayout';
+import { PagePathNavLayout } from './PagePathNavLayout';
 
 import styles from './PagePathNav.module.scss';
 
 
 const { isTrashPage } = pagePathUtils;
 
-type Props = {
-  pagePath: string,
-  pageId?: string | null,
-  isWipPage?: boolean,
-  isSingleLineMode?: boolean,
-  isCollapseParents?: boolean,
-  formerLinkClassName?: string,
-  latterLinkClassName?: string,
-  maxWidth?: number,
-}
-
-const CopyDropdown = dynamic(() => import('../CopyDropdown').then(mod => mod.CopyDropdown), { ssr: false });
 
 const Separator = ({ className }: {className?: string}): JSX.Element => {
   return <span className={`separator ${className ?? ''} ${styles['grw-mx-02em']}`}>/</span>;
 };
 
-export const PagePathNav = (props: Props): JSX.Element => {
-  const {
-    pageId, pagePath, isWipPage, isSingleLineMode, isCollapseParents,
-    formerLinkClassName, latterLinkClassName, maxWidth,
-  } = props;
+export const PagePathNav = (props: PagePathNavLayoutProps): JSX.Element => {
+  const { pagePath } = props;
   const dPagePath = new DevidedPagePath(pagePath, false, true);
 
-  const { data: isNotFound } = useIsNotFound();
-
   const isInTrash = isTrashPage(pagePath);
 
   let formerLink;
   let latterLink;
 
   // one line
-  if (dPagePath.isRoot || dPagePath.isFormerRoot || (!isCollapseParents && isSingleLineMode)) {
+  if (dPagePath.isRoot || dPagePath.isFormerRoot) {
     const linkedPagePath = new LinkedPagePath(pagePath);
     latterLink = <PagePathHierarchicalLink linkedPagePath={linkedPagePath} isInTrash={isInTrash} />;
   }
-  // collapse parents
-  else if (isCollapseParents) {
-    const linkedPagePathFormer = new LinkedPagePath(dPagePath.former);
-    const linkedPagePathLatter = new LinkedPagePath(dPagePath.latter);
-    latterLink = (
-      <>
-        <CollapsedParentsDropdown linkedPagePath={linkedPagePathFormer} />
-        <Separator />
-        <PagePathHierarchicalLink linkedPagePath={linkedPagePathLatter} basePath={dPagePath.former} isInTrash={isInTrash} />
-      </>
-    );
-  }
   // two line
   else {
     const linkedPagePathFormer = new LinkedPagePath(dPagePath.former);
@@ -86,89 +47,11 @@ export const PagePathNav = (props: Props): JSX.Element => {
     );
   }
 
-  const copyDropdownId = `copydropdown-${pageId}`;
-
   return (
-    <div style={{ maxWidth }}>
-      <span className={`${formerLinkClassName ?? ''} ${styles['grw-former-link']}`}>{formerLink}</span>
-      <div className="d-flex align-items-center">
-        <h1 className={`m-0 ${latterLinkClassName}`}>
-          {latterLink}
-        </h1>
-        { pageId != null && !isNotFound && (
-          <div className="d-flex align-items-center ms-2">
-            { isWipPage && (
-              <span className="badge text-bg-secondary ms-1 me-1">WIP</span>
-            )}
-            <CopyDropdown pageId={pageId} pagePath={pagePath} dropdownToggleId={copyDropdownId} dropdownToggleClassName="p-2">
-              <span className="material-symbols-outlined">content_paste</span>
-            </CopyDropdown>
-          </div>
-        ) }
-      </div>
-    </div>
+    <PagePathNavLayout
+      {...props}
+      formerLink={formerLink}
+      latterLink={latterLink}
+    />
   );
 };
-
-PagePathNav.displayName = 'PagePathNav';
-
-
-type PagePathNavStickyProps = Omit<Props, 'isCollapseParents'>;
-
-export const PagePathNavSticky = (props: PagePathNavStickyProps): JSX.Element => {
-
-  const { data: pageControlsX } = usePageControlsX();
-  const { data: sidebarWidth } = useCurrentProductNavWidth();
-  const { data: sidebarMode } = useSidebarMode();
-  const pagePathNavRef = useRef<HTMLDivElement>(null);
-
-  const [navMaxWidth, setNavMaxWidth] = useState<number | undefined>();
-
-  useEffect(() => {
-    if (pageControlsX == null || pagePathNavRef.current == null || sidebarWidth == null) {
-      return;
-    }
-    setNavMaxWidth(pageControlsX - pagePathNavRef.current.getBoundingClientRect().x - 10);
-  }, [pageControlsX, pagePathNavRef, sidebarWidth]);
-
-  useEffect(() => {
-    // wait for the end of the animation of the opening and closing of the sidebar
-    const timeout = setTimeout(() => {
-      if (pageControlsX == null || pagePathNavRef.current == null || sidebarMode == null) {
-        return;
-      }
-      setNavMaxWidth(pageControlsX - pagePathNavRef.current.getBoundingClientRect().x - 10);
-    }, 200);
-    return () => {
-      clearTimeout(timeout);
-    };
-  }, [pageControlsX, pagePathNavRef, sidebarMode]);
-
-  return (
-    // Controlling pointer-events
-    //  1. disable pointer-events with 'pe-none'
-    <div ref={pagePathNavRef}>
-      <Sticky className={`${styles['grw-page-path-nav-sticky']} mb-4`} innerClass="mt-1 pe-none" innerActiveClass="active">
-        {({ status }) => {
-          const isCollapseParents = status === Sticky.STATUS_FIXED;
-          return (
-          // Controlling pointer-events
-          //  2. enable pointer-events with 'pe-auto' only against the children
-          //      which width is minimized by 'd-inline-block'
-          //
-            <div className="d-inline-block pe-auto">
-              <PagePathNav
-                {...props}
-                isCollapseParents={isCollapseParents}
-                latterLinkClassName={isCollapseParents ? 'fs-3  text-truncate' : 'fs-2'}
-                maxWidth={isCollapseParents ? navMaxWidth : undefined}
-              />
-            </div>
-          );
-        }}
-      </Sticky>
-    </div>
-  );
-};
-
-PagePathNavSticky.displayName = 'PagePathNavSticky';

+ 58 - 0
apps/app/src/components/Common/PagePathNav/PagePathNavLayout.tsx

@@ -0,0 +1,58 @@
+import type { ReactNode } from 'react';
+
+import dynamic from 'next/dynamic';
+
+import { useIsNotFound } from '~/stores/page';
+
+import styles from './PagePathNav.module.scss';
+
+
+export type PagePathNavLayoutProps = {
+  pagePath: string,
+  pageId?: string | null,
+  isWipPage?: boolean,
+  maxWidth?: number,
+  formerLinkClassName?: string,
+  latterLinkClassName?: string,
+}
+
+type Props = PagePathNavLayoutProps & {
+  formerLink?: ReactNode,
+  latterLink?: ReactNode,
+}
+
+const CopyDropdown = dynamic(() => import('../CopyDropdown').then(mod => mod.CopyDropdown), { ssr: false });
+
+export const PagePathNavLayout = (props: Props): JSX.Element => {
+  const {
+    pageId, pagePath, isWipPage,
+    formerLink, formerLinkClassName,
+    latterLink, latterLinkClassName,
+    maxWidth,
+  } = props;
+
+  const { data: isNotFound } = useIsNotFound();
+
+  const copyDropdownId = `copydropdown-${pageId}`;
+
+  return (
+    <div style={{ maxWidth }}>
+      <span className={`${formerLinkClassName ?? ''} ${styles['grw-former-link']}`}>{formerLink}</span>
+      <div className="d-flex align-items-center">
+        <h1 className={`m-0 ${latterLinkClassName}`}>
+          {latterLink}
+        </h1>
+        { pageId != null && !isNotFound && (
+          <div className="d-flex align-items-center ms-2">
+            { isWipPage && (
+              <span className="badge text-bg-secondary ms-1 me-1">WIP</span>
+            )}
+            <CopyDropdown pageId={pageId} pagePath={pagePath} dropdownToggleId={copyDropdownId} dropdownToggleClassName="p-2">
+              <span className="material-symbols-outlined">content_paste</span>
+            </CopyDropdown>
+          </div>
+        ) }
+      </div>
+    </div>
+  );
+};

+ 4 - 0
apps/app/src/components/Common/PagePathNav/Separator.module.scss

@@ -0,0 +1,4 @@
+.grw-mx-02em {
+  margin-right: 0.2em;
+  margin-left: 0.2em;
+}

+ 5 - 0
apps/app/src/components/Common/PagePathNav/Separator.tsx

@@ -0,0 +1,5 @@
+import styles from './Separator.module.scss';
+
+export const Separator = ({ className }: {className?: string}): JSX.Element => (
+  <span className={`separator ${className ?? ''} ${styles['grw-mx-02em']}`}>/</span>
+);

+ 2 - 0
apps/app/src/components/Common/PagePathNav/index.ts

@@ -1 +1,3 @@
 export * from './PagePathNav';
+export * from './PagePathNavLayout';
+export * from './Separator';

+ 0 - 0
apps/app/src/components/Common/PagePathHierarchicalLink/CollapsedParentsDropdown.module.scss → apps/app/src/components/Common/PagePathNavSticky/CollapsedParentsDropdown.module.scss


+ 0 - 0
apps/app/src/components/Common/PagePathHierarchicalLink/CollapsedParentsDropdown.tsx → apps/app/src/components/Common/PagePathNavSticky/CollapsedParentsDropdown.tsx


+ 17 - 0
apps/app/src/components/Common/PagePathNavSticky/PagePathNavSticky.module.scss

@@ -0,0 +1,17 @@
+@use '@growi/core-styles/scss/bootstrap/init' as bs;
+
+.grw-page-path-nav-sticky :global {
+  min-height: 75px;
+
+  .sticky-inner-wrapper {
+    z-index: bs.$zindex-sticky;
+  }
+
+  // TODO:Responsive font size
+  // set smaller font-size when sticky
+  .sticky-inner-wrapper.active {
+    h1 {
+      font-size: 1.75rem !important;
+    }
+  }
+}

+ 105 - 0
apps/app/src/components/Common/PagePathNavSticky/PagePathNavSticky.tsx

@@ -0,0 +1,105 @@
+import {
+  useEffect,
+  useMemo,
+  useRef,
+  useState,
+} from 'react';
+
+import { DevidedPagePath } from '@growi/core/dist/models';
+import { pagePathUtils } from '@growi/core/dist/utils';
+import Sticky from 'react-stickynode';
+
+import LinkedPagePath from '~/models/linked-page-path';
+import {
+  usePageControlsX, useCurrentProductNavWidth, useSidebarMode,
+} from '~/stores/ui';
+
+import { PagePathHierarchicalLink } from '../PagePathHierarchicalLink';
+import type { PagePathNavLayoutProps } from '../PagePathNav';
+import { PagePathNavLayout, Separator } from '../PagePathNav';
+
+import { CollapsedParentsDropdown } from './CollapsedParentsDropdown';
+
+import styles from './PagePathNavSticky.module.scss';
+
+const moduleClass = styles['grw-page-path-nav-sticky'];
+
+const { isTrashPage } = pagePathUtils;
+
+
+export const PagePathNavSticky = (props: PagePathNavLayoutProps): JSX.Element => {
+  const { pagePath } = props;
+
+  const { data: pageControlsX } = usePageControlsX();
+  const { data: sidebarWidth } = useCurrentProductNavWidth();
+  const { data: sidebarMode } = useSidebarMode();
+  const pagePathNavRef = useRef<HTMLDivElement>(null);
+
+  const [navMaxWidth, setNavMaxWidth] = useState<number | undefined>();
+
+  useEffect(() => {
+    if (pageControlsX == null || pagePathNavRef.current == null || sidebarWidth == null) {
+      return;
+    }
+    setNavMaxWidth(pageControlsX - pagePathNavRef.current.getBoundingClientRect().x - 10);
+  }, [pageControlsX, pagePathNavRef, sidebarWidth]);
+
+  useEffect(() => {
+    // wait for the end of the animation of the opening and closing of the sidebar
+    const timeout = setTimeout(() => {
+      if (pageControlsX == null || pagePathNavRef.current == null || sidebarMode == null) {
+        return;
+      }
+      setNavMaxWidth(pageControlsX - pagePathNavRef.current.getBoundingClientRect().x - 10);
+    }, 200);
+    return () => {
+      clearTimeout(timeout);
+    };
+  }, [pageControlsX, pagePathNavRef, sidebarMode]);
+
+  // one line with collapsed parents
+  const latterLink = useMemo(() => {
+    const dPagePath = new DevidedPagePath(pagePath, false, true);
+
+    const isInTrash = isTrashPage(pagePath);
+
+    const linkedPagePathFormer = new LinkedPagePath(dPagePath.former);
+    const linkedPagePathLatter = new LinkedPagePath(dPagePath.latter);
+
+    return (
+      <>
+        <CollapsedParentsDropdown linkedPagePath={linkedPagePathFormer} />
+        <Separator />
+        <PagePathHierarchicalLink linkedPagePath={linkedPagePathLatter} basePath={dPagePath.former} isInTrash={isInTrash} />
+      </>
+    );
+  }, [pagePath]);
+
+  return (
+    // Controlling pointer-events
+    //  1. disable pointer-events with 'pe-none'
+    <div ref={pagePathNavRef}>
+      <Sticky className={`${moduleClass} mb-4`} innerClass="mt-1 pe-none" innerActiveClass="active">
+        {({ status }) => {
+          const isCollapseParents = status === Sticky.STATUS_FIXED;
+          return (
+          // Controlling pointer-events
+          //  2. enable pointer-events with 'pe-auto' only against the children
+          //      which width is minimized by 'd-inline-block'
+          //
+            <div className="d-inline-block pe-auto">
+              <PagePathNavLayout
+                {...props}
+                latterLink={latterLink}
+                latterLinkClassName={isCollapseParents ? 'fs-3  text-truncate' : 'fs-2'}
+                maxWidth={isCollapseParents ? navMaxWidth : undefined}
+              />
+            </div>
+          );
+        }}
+      </Sticky>
+    </div>
+  );
+};
+
+PagePathNavSticky.displayName = 'PagePathNavSticky';