Bladeren bron

Separate Component

satof3 6 maanden geleden
bovenliggende
commit
42fc8eeba1

+ 56 - 0
apps/app/src/client/components/PageEditor/EditorGuideModal.tsx

@@ -0,0 +1,56 @@
+import type { JSX } from 'react';
+
+type Props = {
+  isOpen: boolean;
+  onClose: () => void;
+};
+
+export const EditorGuideModal = (props: Props): JSX.Element => {
+  const { isOpen, onClose } = props;
+
+  if (!isOpen) {
+    return <></>;
+  }
+
+  return (
+    <>
+      {/* Editor Guide Modal Overlay */}
+      <div
+        className="position-absolute top-0 start-0 w-100 h-100 bg-dark opacity-50"
+        style={{
+          zIndex: 1040,
+        }}
+        onClick={onClose}
+      />
+
+      {/* Editor Guide Modal */}
+      <div
+        className="position-fixed top-0 bottom-0 start-50 end-0 d-flex align-items-center justify-content-center"
+        style={{
+          zIndex: 1050,
+          pointerEvents: 'none',
+        }}
+      >
+        <div className="px-3" style={{ pointerEvents: 'auto' }}>
+          <div className="card shadow-lg">
+            <div className="card-header d-flex justify-content-between align-items-center">
+              <h5 className="mb-0">Editor Guide</h5>
+              <button
+                type="button"
+                className="btn-close"
+                onClick={onClose}
+                aria-label="Close"
+              />
+            </div>
+            <div className="card-body overflow-auto">
+              <p>This is a test modal.</p>
+              <p>It appears in the center of the preview area on the right side.</p>
+              <p>The background is darkened to emphasize the modal.</p>
+              <p className="mb-0">Click the close button or the background to close.</p>
+            </div>
+          </div>
+        </div>
+      </div>
+    </>
+  );
+};

+ 5 - 0
apps/app/src/client/components/PageEditor/PageEditor.tsx

@@ -12,6 +12,7 @@ import { pathUtils } from '@growi/core/dist/utils';
 import { GlobalCodeMirrorEditorKey } from '@growi/editor';
 import { CodeMirrorEditorMain } from '@growi/editor/dist/client/components/CodeMirrorEditorMain';
 import { useCodeMirrorEditorIsolated } from '@growi/editor/dist/client/stores/codemirror-editor';
+import { useEditorGuideModal } from '@growi/editor/dist/client/stores/use-editor-guide-modal';
 import { useResolvedThemeForEditor } from '@growi/editor/dist/client/stores/use-resolved-theme';
 import { useRect } from '@growi/ui/dist/utils';
 import detectIndent from 'detect-indent';
@@ -330,6 +331,8 @@ export const PageEditorSubstance = (props: Props): JSX.Element => {
     }
   }, [editorMode, mutateReservedNextCaretLine]);
 
+  const { data: editorGuideModalStatus, close: closeEditorGuideModal } = useEditorGuideModal();
+
 
   // TODO: Check the reproduction conditions that made this code necessary and confirm reproduction
   // // when transitioning to a different page, if the initialValue is the same,
@@ -394,6 +397,8 @@ export const PageEditorSubstance = (props: Props): JSX.Element => {
           pagePath={currentPagePath}
           expandContentWidth={shouldExpandContent}
           style={pastEndStyle}
+          isEditorGuideModalOpen={editorGuideModalStatus?.isOpened ?? false}
+          onCloseEditorGuideModal={closeEditorGuideModal}
         />
       </div>
     </div>

+ 24 - 79
apps/app/src/client/components/PageEditor/Preview.tsx

@@ -1,15 +1,15 @@
 import type { CSSProperties, JSX } from 'react';
-import { useState } from 'react';
 
 import { useSlidesByFrontmatter } from '@growi/presentation/dist/services';
 
-
 import RevisionRenderer from '~/components/PageView/RevisionRenderer';
 import type { RendererOptions } from '~/interfaces/renderer-options';
 import { useIsEnabledMarp } from '~/stores-universal/context';
 
 import { SlideRenderer } from '../Page/SlideRenderer';
 
+import { EditorGuideModal } from './EditorGuideModal';
+
 import styles from './Preview.module.scss';
 
 const moduleClass = styles['page-editor-preview-body'] ?? '';
@@ -22,6 +22,8 @@ type Props = {
   expandContentWidth?: boolean,
   style?: CSSProperties,
   onScroll?: (scrollTop: number) => void,
+  isEditorGuideModalOpen?: boolean,
+  onCloseEditorGuideModal?: () => void,
 }
 
 const Preview = (props: Props): JSX.Element => {
@@ -30,6 +32,8 @@ const Preview = (props: Props): JSX.Element => {
     rendererOptions,
     markdown, pagePath, style,
     expandContentWidth,
+    isEditorGuideModalOpen,
+    onCloseEditorGuideModal,
   } = props;
 
   const { data: isEnabledMarp } = useIsEnabledMarp();
@@ -37,84 +41,25 @@ const Preview = (props: Props): JSX.Element => {
 
   const fluidLayoutClass = expandContentWidth ? 'fluid-layout' : '';
 
-  const [isModalOpen, setIsModalOpen] = useState(false);
-
-  const toggleModal = () => setIsModalOpen(!isModalOpen);
-
   return (
-    <>
-      {/* wip Trigger */}
-      <button
-        type="button"
-        className="btn btn-light btn-sm position-fixed top-0 end-0 m-3 shadow-sm"
-        style={{
-          top: '70px',
-          zIndex: 10,
-        }}
-        onClick={toggleModal}
-      >
-        <span className="material-symbols-outlined align-middle" style={{ fontSize: '18px' }}>
-          help
-        </span>
-        <span className="ms-1">Guide</span>
-      </button>
-
-      {/* Editor Guide Modal */}
-      {isModalOpen && (
-        <div
-          className="position-fixed top-0 bottom-0 start-50 end-0 d-flex align-items-center justify-content-center"
-          style={{
-            zIndex: 1050,
-            pointerEvents: 'none',
-          }}
-        >
-          <div className="px-3" style={{ pointerEvents: 'auto' }}>
-            <div className="card shadow-lg">
-              <div className="card-header d-flex justify-content-between align-items-center">
-                <h5 className="mb-0">Editor Guide</h5>
-                <button
-                  type="button"
-                  className="btn-close"
-                  onClick={toggleModal}
-                  aria-label="Close"
-                />
-              </div>
-              <div className="card-body overflow-auto">
-                <p>This is a test modal.</p>
-                <p>It appears in the center of the preview area on the right side.</p>
-                <p>The background is darkened to emphasize the modal.</p>
-                <p className="mb-0">Click the close button or the background to close.</p>
-              </div>
-            </div>
-          </div>
-        </div>
-      )}
-
-      <div
-        data-testid="page-editor-preview-body"
-        className={`${moduleClass} ${fluidLayoutClass} ${pagePath === '/Sidebar' ? 'preview-sidebar' : ''} position-relative`}
-        style={style}
-      >
-        {/* Editor Guide Modal Overlay */}
-        {isModalOpen && (
-          <div
-            className="position-absolute top-0 start-0 w-100 h-100 bg-dark opacity-50"
-            style={{
-              zIndex: 1040,
-            }}
-            onClick={toggleModal}
-          />
-        )}
-
-        { markdown != null
-          && (
-            isSlide != null
-              ? <SlideRenderer marp={isSlide.marp} markdown={markdown} />
-              : <RevisionRenderer rendererOptions={rendererOptions} markdown={markdown}></RevisionRenderer>
-          )
-        }
-      </div>
-    </>
+    <div
+      data-testid="page-editor-preview-body"
+      className={`${moduleClass} ${fluidLayoutClass} ${pagePath === '/Sidebar' ? 'preview-sidebar' : ''} position-relative`}
+      style={style}
+    >
+      <EditorGuideModal
+        isOpen={isEditorGuideModalOpen ?? false}
+        onClose={onCloseEditorGuideModal ?? (() => {})}
+      />
+
+      { markdown != null
+        && (
+          isSlide != null
+            ? <SlideRenderer marp={isSlide.marp} markdown={markdown} />
+            : <RevisionRenderer rendererOptions={rendererOptions} markdown={markdown}></RevisionRenderer>
+        )
+      }
+    </div>
   );
 
 };

+ 6 - 9
packages/editor/src/client/components-internal/CodeMirrorEditor/Toolbar/EditorGuideButton.tsx

@@ -1,17 +1,14 @@
 import { type JSX, useCallback } from 'react';
 
-import { useDrawioModalForEditor } from '../../../stores/use-drawio';
+import { useEditorGuideModal } from '../../../stores/use-editor-guide-modal';
 
-type Props = {
-  editorKey: string;
-};
+export const EditorGuideButton = (): JSX.Element => {
+  const { open: openEditorGuideModal } = useEditorGuideModal();
 
-export const EditorGuideButton = (props: Props): JSX.Element => {
-  const { editorKey } = props;
-  const { open: openDrawioModal } = useDrawioModalForEditor();
   const onClickEditorGuideButton = useCallback(() => {
-    openDrawioModal(editorKey);
-  }, [editorKey, openDrawioModal]);
+    openEditorGuideModal();
+  }, [openEditorGuideModal]);
+
   return (
     <button
       type="button"

+ 33 - 0
packages/editor/src/client/stores/use-editor-guide-modal.ts

@@ -0,0 +1,33 @@
+import { useSWRStatic } from '@growi/core/dist/swr';
+import type { SWRResponse } from 'swr';
+
+export type EditorGuideModalStatus = {
+  isOpened: boolean;
+};
+
+type EditorGuideModalUtils = {
+  open(): void;
+  close(): void;
+};
+
+export const useEditorGuideModal = (): SWRResponse<
+  EditorGuideModalStatus,
+  Error
+> &
+  EditorGuideModalUtils => {
+  const initialStatus: EditorGuideModalStatus = { isOpened: false };
+  const swrResponse = useSWRStatic<EditorGuideModalStatus, Error>(
+    'editorGuideModal',
+    undefined,
+    { fallbackData: initialStatus },
+  );
+
+  return Object.assign(swrResponse, {
+    open: () => {
+      swrResponse.mutate({ isOpened: true });
+    },
+    close: () => {
+      swrResponse.mutate({ isOpened: false });
+    },
+  });
+};