Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
antoine-excalidraw
Advanced tools
Excalidraw exported as a component to directly embed in your projects
You can use npm
npm install react react-dom @excalidraw/excalidraw
or via yarn
yarn add react react-dom @excalidraw/excalidraw
After installation you will see a folder excalidraw-assets
in dist
directory which contains the assets needed for this app.
Move the folder excalidraw-assets
to the path where your assets are served.
By default it will try to load the files from {rootUrl}/excalidraw-assets/
With Webpack, if you want to load the files from different path you can use
__webpack_public_path__
.
With create-react-app, the assets can be served from public/static/js/excalidraw-assets
since CRA tries to load the assets from {rootUrl}/static/js
path by default.
You can update the value of PUBLIC_URL
if you want to serve it from a different URL.
import React, { useEffect, useState, useRef } from "react";
import Excalidraw from "@excalidraw/excalidraw";
import InitialData from "./initialData";
import "./styles.scss";
export default function App() {
const excalidrawRef = useRef(null);
const excalidrawWrapperRef = useRef(null);
const [dimensions, setDimensions] = useState({
width: undefined,
height: undefined,
});
const [viewModeEnabled, setViewModeEnabled] = useState(false);
const [zenModeEnabled, setZenModeEnabled] = useState(false);
const [gridModeEnabled, setGridModeEnabled] = useState(false);
useEffect(() => {
setDimensions({
width: excalidrawWrapperRef.current.getBoundingClientRect().width,
height: excalidrawWrapperRef.current.getBoundingClientRect().height,
});
const onResize = () => {
setDimensions({
width: excalidrawWrapperRef.current.getBoundingClientRect().width,
height: excalidrawWrapperRef.current.getBoundingClientRect().height,
});
};
window.addEventListener("resize", onResize);
return () => window.removeEventListener("resize", onResize);
}, [excalidrawWrapperRef]);
const updateScene = () => {
const sceneData = {
elements: [
{
type: "rectangle",
version: 141,
versionNonce: 361174001,
isDeleted: false,
id: "oDVXy8D6rom3H1-LLH2-f",
fillStyle: "hachure",
strokeWidth: 1,
strokeStyle: "solid",
roughness: 1,
opacity: 100,
angle: 0,
x: 100.50390625,
y: 93.67578125,
strokeColor: "#c92a2a",
backgroundColor: "transparent",
width: 186.47265625,
height: 141.9765625,
seed: 1968410350,
groupIds: [],
},
],
appState: {
viewBackgroundColor: "#edf2ff",
},
};
excalidrawRef.current.updateScene(sceneData);
};
return (
<div className="App">
<h1> Excalidraw Example</h1>
<div className="button-wrapper">
<button className="update-scene" onClick={updateScene}>
Update Scene
</button>
<button
className="reset-scene"
onClick={() => {
excalidrawRef.current.resetScene();
}}
>
Reset Scene
</button>
<label>
<input
type="checkbox"
checked={viewModeEnabled}
onChange={() => setViewModeEnabled(!viewModeEnabled)}
/>
View mode
</label>
<label>
<input
type="checkbox"
checked={zenModeEnabled}
onChange={() => setZenModeEnabled(!zenModeEnabled)}
/>
Zen mode
</label>
<label>
<input
type="checkbox"
checked={gridModeEnabled}
onChange={() => setGridModeEnabled(!gridModeEnabled)}
/>
Grid mode
</label>
</div>
<div className="excalidraw-wrapper" ref={excalidrawWrapperRef}>
<Excalidraw
ref={excalidrawRef}
width={dimensions.width}
height={dimensions.height}
initialData={InitialData}
onChange={(elements, state) =>
console.log("Elements :", elements, "State : ", state)
}
onPointerUpdate={(payload) => console.log(payload)}
onCollabButtonClick={() =>
window.alert("You clicked on collab button")
}
viewModeEnabled={viewModeEnabled}
zenModeEnabled={zenModeEnabled}
gridModeEnabled={gridModeEnabled}
/>
</div>
</div>
);
}
You will need to make sure react
, react-dom
is available as shown below.
<!DOCTYPE html>
<html>
<head>
<title>Excalidraw in browser</title>
<meta charset="UTF-8" />
<script src="https://unpkg.com/react@16.14.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.13.1/umd/react-dom.development.js"></script>
<script
type="text/javascript"
src="https://unpkg.com/@excalidraw/excalidraw@0.2.2/dist/excalidraw.min.js"
></script>
</head>
<body>
<div class="container">
<h4>Excalidraw Embed Example</h4>
<div id="app"></div>
</div>
<script type="text/javascript" src="src/index.js"></script>
</body>
</html>
import "./styles.css";
const excalidrawWrapper = document.getElementById("app");
const props = {
onChange: (data, appState) => {
console.log(data, appState);
},
};
/*eslint-disable */
ReactDOM.render(
React.createElement(Excalidraw.default, props),
excalidrawWrapper,
);
Since Excalidraw doesn't support server side rendering yet so you will have to make sure the component is rendered once host is mounted.
import { useState, useEffect } from "react";
export default function IndexPage() {
const [Comp, setComp] = useState(null);
useEffect(() => {
import("@excalidraw/excalidraw").then((comp) => setComp(comp.default));
});
return <>{Comp && <Comp />}</>;
}
Name | Type | Default | Description |
---|---|---|---|
width | Number | window.innerWidth | The width of Excalidraw component |
height | Number | window.innerHeight | The height of Excalidraw component |
offsetLeft | Number | 0 | left position relative to which Excalidraw should be rendered |
offsetTop | Number | 0 | top position relative to which Excalidraw should render |
onChange | Function | This callback is triggered whenever the component updates due to any change. This callback will receive the excalidraw elements and the current app state. | |
initialData | {elements?: ExcalidrawElement[], appState?: AppState } | null | The initial data with which app loads. |
excalidrawRef | createRef or callbackRef or { current: { readyPromise: resolvablePromise } } | Ref to be passed to Excalidraw | |
onCollabButtonClick | Function | Callback to be triggered when the collab button is clicked | |
isCollaborating | boolean | This implies if the app is in collaboration mode | |
onPointerUpdate | Function | Callback triggered when mouse pointer is updated. | |
onExportToBackend | Function | Callback triggered when link button is clicked on export dialog | |
langCode | string | en | Language code string |
renderFooter | Function | Function that renders custom UI footer | |
viewModeEnabled | boolean | This implies if the app is in view mode. | |
zenModeEnabled | boolean | This implies if the zen mode is enabled | |
gridModeEnabled | boolean | This implies if the grid mode is enabled |
width
This props defines the width
of the Excalidraw component. Defaults to window.innerWidth
if not passed.
height
This props defines the height
of the Excalidraw component. Defaults to window.innerHeight
if not passed.
offsetLeft
This prop defines left
position relative to which Excalidraw should be rendered. Defaults to 0
if not passed.
offsetTop
This prop defines top
position relative to which Excalidraw should be rendered. Defaults to 0
if not passed.
onChange
Every time component updates, this callback if passed will get triggered and has the below signature.
(excalidrawElements, appState) => void;
1.excalidrawElements
: Array of excalidrawElements in the scene.
2.appState
: AppState of the scene
Here you can try saving the data to your backend or local storage for example.
initialData
This helps to load Excalidraw with initialData
. It must be an object or a promise which resolves to an object containing the below optional fields.
name | type |
---|---|
elements | ExcalidrawElement[] |
appState | AppState |
{
"elements": [
{
"type": "rectangle",
"version": 141,
"versionNonce": 361174001,
"isDeleted": false,
"id": "oDVXy8D6rom3H1-LLH2-f",
"fillStyle": "hachure",
"strokeWidth": 1,
"strokeStyle": "solid",
"roughness": 1,
"opacity": 100,
"angle": 0,
"x": 100.50390625,
"y": 93.67578125,
"strokeColor": "#000000",
"backgroundColor": "transparent",
"width": 186.47265625,
"height": 141.9765625,
"seed": 1968410350,
"groupIds": []
}
],
"appState": { "zenModeEnabled": true, "viewBackgroundColor": "#AFEEEE" }
}
You might want to use this when you want to load excalidraw with some initial elements and app state.
excalidrawRef
You can pass a ref
when you want to access some excalidraw APIs. We expose the below APIs:
API | signature | Usage |
---|---|---|
ready | boolean | This is set to true once Excalidraw is rendered |
readyPromise | resolvablePromise | This promise will be resolved with the api once excalidraw has rendered. This will be helpful when you want do some action on the host app once this promise resolves. For this to work you will have to pass ref as shown here |
updateScene | (sceneData)) => void | updates the scene with the sceneData |
resetScene | ({ resetLoadingState: boolean }) => void | Resets the scene. If resetLoadingState is passed as true then it will also force set the loading state to false. |
getSceneElementsIncludingDeleted | () => ExcalidrawElement[] | Returns all the elements including the deleted in the scene |
getSceneElements | () => ExcalidrawElement[] | Returns all the elements excluding the deleted in the scene |
getAppState | () => AppState | Returns current appState |
history | { clear: () => void } | This is the history API. history.clear() will clear the history |
setScrollToCenter | (ExcalidrawElement[]) => void | sets the elements to center |
readyPromise
const excalidrawRef = { current: { readyPromise: resolvablePromise}}
onCollabButtonClick
This callback is triggered when clicked on the collab button in excalidraw. If not supplied, the collab dialog button is not rendered.
isCollaborating
This prop indicates if the app is in collaboration mode.
onPointerUpdate
This callback is triggered when mouse pointer is updated.
({ x, y }, button, pointersMap}) => void;
1.{x, y}
: Pointer coordinates
2.button
: The position of the button. This will be one of ["down", "up"]
3.pointersMap
: pointers map
of the scene
onExportToBackend
This callback is triggered when the shareable-link button is clicked in the export dialog. The link button will only be shown if this callback is passed.
(exportedElements, appState, canvas) => void
exportedElements
: An array of non deleted elements which needs to be exported.appState
: AppState of the scene.canvas
: The HTMLCanvasElement
of the scene.langCode
Determines the language of the UI. It should be one of the available language codes. Defaults to en
(English). We also export default language and supported languages which you can import as shown below.
import { defaultLang, languages } from "@excalidraw/excalidraw";
name | type |
---|---|
defaultLang | string |
languages | Language[] |
renderFooter
A function that renders (returns JSX) custom UI footer. For example, you can use this to render a language picker that was previously being rendered by Excalidraw itself (for now, you'll need to implement your own language picker).
viewModeEnabled
This prop indicates whether the app is in view mode
. When supplied, the value takes precedence over intialData.appState.viewModeEnabled
, the view mode
will be fully controlled by the host app, and users won't be able to toggle it from within the app.
zenModeEnabled
This prop indicates whether the app is in zen mode
. When supplied, the value takes precedence over intialData.appState.zenModeEnabled
, the zen mode
will be fully controlled by the host app, and users won't be able to toggle it from within the app.
gridModeEnabled
This prop indicates whether the shows the grid. When supplied, the value takes precedence over intialData.appState.gridModeEnabled
, the grid will be fully controlled by the host app, and users won't be able to toggle it from within the app.
getSceneVersion
How to use
import { getSceneVersion } from "@excalidraw/excalidraw"; getSceneVersion(elements: ExcalidrawElement[])
This function returns the current scene version.
getSyncableElements
Signature
getSyncableElements(elements: ExcalidrawElement[]):ExcalidrawElement[]
How to use
import { getSyncableElements } from "@excalidraw/excalidraw";
This function returns all the deleted elements of the scene.
getElementMap
Signature
getElementsMap(elements: ExcalidrawElement[]): {[id: string]: ExcalidrawElement}
How to use
import { getElementsMap } from "@excalidraw/excalidraw";
This function returns an object where each element is mapped to its id.
The below api's will be available in next version
restoreAppState
Signature
restoreAppState(appState: ImportedDataState["appState"], localAppState: Partial<AppState> | null): AppState
How to use
import { restoreAppState } from "@excalidraw/excalidraw";
This function will make sure all the keys have appropriate values in appState and if any key is missing, it will be set to default value. If you pass localAppState
, localAppState
value will be preferred over the appState
passed in params.
restoreElements
Signature
restoreElements(elements: ImportedDataState["elements"]): ExcalidrawElement[]
How to use
import { restoreElements } from "@excalidraw/excalidraw";
This function will make sure all properties of element is correctly set and if any attribute is missing, it will be set to default value.
restore
Signature
restoreElements(data: ImportedDataState): DataState
How to use
import { restore } from "@excalidraw/excalidraw";
This function makes sure elements and state is set to appropriate values and set to default value if not present. It is combination of restoreElements and restoreAppState
FAQs
Excalidraw as a React component
The npm package antoine-excalidraw receives a total of 1 weekly downloads. As such, antoine-excalidraw popularity was classified as not popular.
We found that antoine-excalidraw demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.