소스 검색

fix: Support Excalidraw inside scrollable container (#3018)

* refactor: remove position fixed from excalidraw container, modal and stats

* remove unused css

* remove position fixed from toast and scroll to content

* Make excal interactable by fixing offsets and set popover as fixed since position needs to be calculate from viewport  top

* Assign 200px less than height of Excalidraw to the selected shapes actions o UI doesn't overflow

* update changelog, readme and package.json
Aakansha Doshi 4 년 전
부모
커밋
830fb64a25

+ 6 - 0
src/components/App.tsx

@@ -51,6 +51,7 @@ import {
   LINE_CONFIRM_THRESHOLD,
   MIME_TYPES,
   POINTER_BUTTON,
+  SCROLL_TIMEOUT,
   TAP_TWICE_TIMEOUT,
   TEXT_TO_CENTER_SNAP_THRESHOLD,
   TOUCH_CTX_MENU_TIMEOUT,
@@ -825,6 +826,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
 
     document.addEventListener(EVENT.PASTE, this.pasteFromClipboard);
     document.addEventListener(EVENT.CUT, this.onCut);
+    document.addEventListener(EVENT.SCROLL, this.onScroll);
 
     window.addEventListener(EVENT.RESIZE, this.onResize, false);
     window.addEventListener(EVENT.UNLOAD, this.onUnload, false);
@@ -998,6 +1000,10 @@ class App extends React.Component<ExcalidrawProps, AppState> {
     }
   }
 
+  private onScroll = debounce(() => {
+    this.setState({ ...this.getCanvasOffsets() });
+  }, SCROLL_TIMEOUT);
+
   // Copy/paste
 
   private onCut = withBatchedUpdates((event: ClipboardEvent) => {

+ 21 - 13
src/components/LayerUI.tsx

@@ -442,7 +442,15 @@ const LayerUI = ({
         "transition-left": zenModeEnabled,
       })}
     >
-      <Island className={CLASSES.SHAPE_ACTIONS_MENU} padding={2}>
+      <Island
+        className={CLASSES.SHAPE_ACTIONS_MENU}
+        padding={2}
+        style={{
+          // we want to make sure this doesn't overflow so substracting 200
+          // which is approximately height of zoom footer and top left menu items with some buffer
+          maxHeight: `${appState.height - 200}px`,
+        }}
+      >
         <SelectedShapeActions
           appState={appState}
           elements={elements}
@@ -603,18 +611,6 @@ const LayerUI = ({
       >
         {t("buttons.exitZenMode")}
       </button>
-      {appState.scrolledOutside && (
-        <button
-          className="scroll-back-to-content"
-          onClick={() => {
-            setAppState({
-              ...calculateScrollCenter(elements, appState, canvas),
-            });
-          }}
-        >
-          {t("buttons.scrollBackToContent")}
-        </button>
-      )}
     </footer>
   );
 
@@ -677,6 +673,18 @@ const LayerUI = ({
       {renderBottomAppMenu()}
       {renderGitHubCorner()}
       {renderFooter()}
+      {appState.scrolledOutside && (
+        <button
+          className="scroll-back-to-content"
+          onClick={() => {
+            setAppState({
+              ...calculateScrollCenter(elements, appState, canvas),
+            });
+          }}
+        >
+          {t("buttons.scrollBackToContent")}
+        </button>
+      )}
     </div>
   );
 };

+ 8 - 3
src/components/Modal.scss

@@ -1,8 +1,13 @@
 @import "../css/variables.module";
 
 .excalidraw {
+  &.excalidraw-modal-container {
+    position: absolute;
+    z-index: 10;
+  }
+
   .Modal {
-    position: fixed;
+    position: absolute;
     top: 0;
     left: 0;
     right: 0;
@@ -15,7 +20,7 @@
   }
 
   .Modal__background {
-    position: fixed;
+    position: absolute;
     top: 0;
     left: 0;
     right: 0;
@@ -82,7 +87,7 @@
     }
 
     .Modal__content {
-      position: fixed;
+      position: absolute;
       top: 0;
       left: 0;
       right: 0;

+ 1 - 1
src/components/Modal.tsx

@@ -54,7 +54,7 @@ const useBodyRoot = () => {
       ?.classList.contains("Appearance_dark");
     const div = document.createElement("div");
 
-    div.classList.add("excalidraw");
+    div.classList.add("excalidraw", "excalidraw-modal-container");
 
     if (isDarkTheme) {
       div.classList.add("Appearance_dark");

+ 1 - 9
src/components/Popover.scss

@@ -1,14 +1,6 @@
 .excalidraw {
   .popover {
-    position: absolute;
-    z-index: 10;
-  }
-
-  .popover .cover {
     position: fixed;
-    top: 0;
-    left: 0;
-    right: 0;
-    bottom: 0;
+    z-index: 10;
   }
 }

+ 1 - 1
src/components/Stats.scss

@@ -1,7 +1,7 @@
 @import "../css/variables.module";
 
 .Stats {
-  position: fixed;
+  position: absolute;
   top: 64px;
   right: 12px;
   font-size: 12px;

+ 1 - 1
src/components/Toast.scss

@@ -11,7 +11,7 @@
     left: 50%;
     margin-left: -150px;
     padding: 4px 0;
-    position: fixed;
+    position: absolute;
     text-align: center;
     width: 300px;
     z-index: 999999;

+ 2 - 0
src/constants.ts

@@ -47,6 +47,7 @@ export enum EVENT {
   TOUCH_END = "touchend",
   HASHCHANGE = "hashchange",
   VISIBILITY_CHANGE = "visibilitychange",
+  SCROLL = "scroll",
 }
 
 export const ENV = {
@@ -92,6 +93,7 @@ export const TOUCH_CTX_MENU_TIMEOUT = 500;
 export const TITLE_TIMEOUT = 10000;
 export const TOAST_TIMEOUT = 5000;
 export const VERSION_TIMEOUT = 30000;
+export const SCROLL_TIMEOUT = 500;
 
 export const ZOOM_STEP = 0.1;
 

+ 1 - 3
src/css/styles.scss

@@ -10,7 +10,6 @@
 .excalidraw {
   color: var(--text-color-primary);
   display: flex;
-  position: fixed;
   top: 0;
   bottom: 0;
   left: 0;
@@ -362,7 +361,6 @@
 
   .App-menu__left {
     overflow-y: auto;
-    max-height: calc(100vh - 236px);
   }
 
   .dropdown-select {
@@ -434,7 +432,7 @@
 
   .scroll-back-to-content {
     color: var(--popup-text-color);
-    position: fixed;
+    position: absolute;
     left: 50%;
     bottom: 30px;
     transform: translateX(-50%);

+ 14 - 0
src/packages/excalidraw/CHANGELOG.md

@@ -12,6 +12,20 @@ The change should be grouped under one of the below section and must contain PR
 Please add the latest change on the top under the correct section.
 -->
 
+## 0.3.1
+
+## Excalidraw API
+
+### Fixes
+
+- Support Excalidraw inside scrollable container [#3018](https://github.com/excalidraw/excalidraw/pull/3018)
+
+## Excalidraw Library
+
+### Fixes
+
+- Allow to toggle between modes when view only mode to make UI consistent [#3009](https://github.com/excalidraw/excalidraw/pull/3009)
+
 ## 0.3.0
 
 ## Excalidraw API

+ 15 - 11
src/packages/excalidraw/README.md

@@ -37,18 +37,18 @@ You can update the value of `PUBLIC_URL` if you want to serve it from a differen
 1. If you are using a Web bundler (for instance, Webpack), you can import it as an ES6 module as shown below
 
 ```js
-import React, { useEffect, useState, createRef } from "react";
+import React, { useEffect, useState, useRef } from "react";
 import Excalidraw from "@excalidraw/excalidraw";
 import InitialData from "./initialData";
 
-import "./styles.css";
+import "./styles.scss";
 
 export default function App() {
-  const excalidrawRef = createRef();
-
+  const excalidrawRef = useRef(null);
+  const excalidrawWrapperRef = useRef(null);
   const [dimensions, setDimensions] = useState({
-    width: window.innerWidth,
-    height: window.innerHeight,
+    width: undefined,
+    height: undefined,
   });
 
   const [viewModeEnabled, setViewModeEnabled] = useState(false);
@@ -56,17 +56,21 @@ export default function App() {
   const [gridModeEnabled, setGridModeEnabled] = useState(false);
 
   useEffect(() => {
+    setDimensions({
+      width: excalidrawWrapperRef.current.getBoundingClientRect().width,
+      height: excalidrawWrapperRef.current.getBoundingClientRect().height,
+    });
     const onResize = () => {
       setDimensions({
-        width: window.innerWidth,
-        height: window.innerHeight,
+        width: excalidrawWrapperRef.current.getBoundingClientRect().width,
+        height: excalidrawWrapperRef.current.getBoundingClientRect().height,
       });
     };
 
     window.addEventListener("resize", onResize);
 
     return () => window.removeEventListener("resize", onResize);
-  }, []);
+  }, [excalidrawWrapperRef]);
 
   const updateScene = () => {
     const sceneData = {
@@ -102,6 +106,7 @@ export default function App() {
 
   return (
     <div className="App">
+      <h1> Excalidraw Example</h1>
       <div className="button-wrapper">
         <button className="update-scene" onClick={updateScene}>
           Update Scene
@@ -139,7 +144,7 @@ export default function App() {
           Grid mode
         </label>
       </div>
-      <div className="excalidraw-wrapper">
+      <div className="excalidraw-wrapper" ref={excalidrawWrapperRef}>
         <Excalidraw
           ref={excalidrawRef}
           width={dimensions.width}
@@ -148,7 +153,6 @@ export default function App() {
           onChange={(elements, state) =>
             console.log("Elements :", elements, "State : ", state)
           }
-          user={{ name: "Excalidraw User" }}
           onPointerUpdate={(payload) => console.log(payload)}
           onCollabButtonClick={() =>
             window.alert("You clicked on collab button")

+ 1 - 1
src/packages/excalidraw/package-lock.json

@@ -1,6 +1,6 @@
 {
   "name": "@excalidraw/excalidraw",
-  "version": "0.3.0",
+  "version": "0.3.1",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {

+ 1 - 1
src/packages/excalidraw/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@excalidraw/excalidraw",
-  "version": "0.3.0",
+  "version": "0.3.1",
   "main": "dist/excalidraw.min.js",
   "files": [
     "dist/*"