Browse Source

refactor: update EditorGuideModal to use containerRef instead of rect for positioning

Yuki Takei 5 months ago
parent
commit
5161368f59

+ 27 - 12
apps/app/src/client/components/PageEditor/EditorGuideModal/EditorGuideModal.tsx

@@ -1,12 +1,12 @@
 import {
-  useState, useEffect, type JSX, type CSSProperties,
+  useState, useEffect, type JSX, type CSSProperties, type RefObject,
 } from 'react';
 
 import { useEditorGuideModalStatus, useEditorGuideModalActions } from '@growi/editor/dist/states/modal/editor-guide';
 import { createPortal } from 'react-dom';
 
 type SubstanceProps = {
-  rect: DOMRectReadOnly,
+  containerRef: RefObject<HTMLDivElement | null>,
   close: () => void,
 };
 
@@ -15,8 +15,23 @@ type SubstanceProps = {
  * Renders backdrop and modal content over the specified area
  * Uses position:fixed to prevent scrolling with the container
  */
-const EditorGuideModalSubstance = ({ rect, close }: SubstanceProps): JSX.Element => {
+const EditorGuideModalSubstance = ({ containerRef, close }: SubstanceProps): JSX.Element => {
   const [isShown, setIsShown] = useState(false);
+  const [rect, setRect] = useState<DOMRect | null>(null);
+
+  // Get rect on mount and on resize
+  useEffect(() => {
+    const updateRect = () => {
+      if (containerRef.current != null) {
+        setRect(containerRef.current.getBoundingClientRect());
+      }
+    };
+
+    updateRect();
+    window.addEventListener('resize', updateRect);
+
+    return () => window.removeEventListener('resize', updateRect);
+  }, [containerRef]);
 
   // Trigger fade-in after mount
   useEffect(() => {
@@ -30,10 +45,10 @@ const EditorGuideModalSubstance = ({ rect, close }: SubstanceProps): JSX.Element
   // Fixed positioning style based on container's viewport position
   const fixedStyle: CSSProperties = {
     position: 'fixed',
-    top: rect.top,
-    left: rect.left,
-    width: rect.width,
-    height: rect.height,
+    top: rect?.top,
+    left: rect?.left,
+    width: rect?.width,
+    height: rect?.height,
   };
 
   return createPortal(
@@ -77,22 +92,22 @@ const EditorGuideModalSubstance = ({ rect, close }: SubstanceProps): JSX.Element
 };
 
 type Props = {
-  rect: DOMRectReadOnly,
+  containerRef: RefObject<HTMLDivElement | null>,
 };
 
 /**
  * EditorGuideModal (Container)
  *
- * This modal overlays only the preview area (specified by rect),
+ * This modal overlays only the preview area (specified by containerRef),
  * not the entire screen. Uses createPortal to render into document.body.
  */
-export const EditorGuideModal = ({ rect }: Props): JSX.Element => {
+export const EditorGuideModal = ({ containerRef }: Props): JSX.Element => {
   const { isOpened } = useEditorGuideModalStatus();
   const { close } = useEditorGuideModalActions();
 
-  if (!isOpened) {
+  if (!isOpened || containerRef == null) {
     return <></>;
   }
 
-  return <EditorGuideModalSubstance rect={rect} close={close} />;
+  return <EditorGuideModalSubstance containerRef={containerRef} close={close} />;
 };

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

@@ -1,14 +1,14 @@
-import type { JSX } from 'react';
+import type { JSX, RefObject } from 'react';
 
 import { useEditorGuideModalStatus } from '@growi/editor/dist/states/modal/editor-guide';
 
 import { useLazyLoader } from '~/components/utils/use-lazy-loader';
 
 type Props = {
-  rect: DOMRectReadOnly | undefined,
+  containerRef: RefObject<HTMLDivElement | null>,
 };
 
-export const EditorGuideModalLazyLoaded = ({ rect }: Props): JSX.Element => {
+export const EditorGuideModalLazyLoaded = ({ containerRef }: Props): JSX.Element => {
   const { isOpened } = useEditorGuideModalStatus();
 
   const EditorGuideModal = useLazyLoader(
@@ -17,7 +17,7 @@ export const EditorGuideModalLazyLoaded = ({ rect }: Props): JSX.Element => {
     isOpened,
   );
 
-  return (EditorGuideModal != null && rect != null)
-    ? <EditorGuideModal rect={rect} />
+  return (EditorGuideModal != null)
+    ? <EditorGuideModal containerRef={containerRef} />
     : <></>;
 };

+ 1 - 1
apps/app/src/client/components/PageEditor/PageEditor.tsx

@@ -404,7 +404,7 @@ export const PageEditorSubstance = (props: Props): JSX.Element => {
           />
         </div>
       </div>
-      <EditorGuideModalLazyLoaded rect={previewRect} />
+      <EditorGuideModalLazyLoaded containerRef={previewRef} />
     </>
   );
 };