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
This commit is contained in:
Aakansha Doshi 2021-02-14 18:18:34 +05:30 committed by GitHub
parent 5b343a9d46
commit 830fb64a25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 73 additions and 44 deletions

View File

@ -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) => {

View File

@ -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>
);
};

View File

@ -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;

View File

@ -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");

View File

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

View File

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

View File

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

View File

@ -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;

View File

@ -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%);

View File

@ -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

View File

@ -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")

View File

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

View File

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