docs: add next js with app router example (#7552)
* move the existing example to with-script-in-browser * Add example with next js app router * disable ssr for excalidraw client comp * typo * update output dir * don't include nextjs example in tsconfig * remove meta.json * lint * remove example.ts * port * move the examples outside packages and use the deps as workspaces in examples * update gitignore * fix example * update path of build dir * fix * fix scripts * try local path * fix * update commands * fix * fix * fix script * skip ts * disable ts * add vercel.json * install * update tsconfig * fix lint * remove console.log * lets see if this works * revert * remove ts nocheck * add types and some utils in nextjs example * fix types * updatw example and remove nextjs dynamic syntax so we don't import excal twice * move both examples to workspaces and create generic example to be used by browser and next js both * copy the static assets to nextjs * fix ts config * render custom menu items * fix custom footer * fix types in browser example * use regular imports for importing excal and import it using dynamic next js in app router instead * Add example for pages router * fix css discrepancies * fix css * configure output dir * fix * fix css * rename to with-nextjs * move components to examples/excalidraw/components
92
examples/excalidraw/components/App.scss
Normal file
|
@ -0,0 +1,92 @@
|
|||
.App {
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
|
||||
.comment-avatar {
|
||||
background: #faa2c1;
|
||||
border-radius: 66px 67px 67px 0px;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
padding: 4px;
|
||||
margin: 4px;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
.app-title {
|
||||
margin-block-start: 0.83em;
|
||||
margin-block-end: 0.83em;
|
||||
}
|
||||
}
|
||||
|
||||
.button-wrapper {
|
||||
input[type="checkbox"] {
|
||||
margin: 5px;
|
||||
}
|
||||
button {
|
||||
z-index: 1;
|
||||
height: 40px;
|
||||
max-width: 200px;
|
||||
margin: 10px;
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.excalidraw .App-menu_top .buttonList {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.excalidraw-wrapper {
|
||||
height: 800px;
|
||||
margin: 50px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:root[dir="ltr"]
|
||||
.excalidraw
|
||||
.layer-ui__wrapper
|
||||
.zen-mode-transition.App-menu_bottom--transition-left {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.excalidraw .panelColumn {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.export-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 50px;
|
||||
|
||||
&__checkbox {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.excalidraw {
|
||||
--color-primary: #faa2c1;
|
||||
--color-primary-darker: #f783ac;
|
||||
--color-primary-darkest: #e64980;
|
||||
--color-primary-light: #fcc2d7;
|
||||
|
||||
button.custom-element {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.custom-footer,
|
||||
.custom-element {
|
||||
padding: 0.1rem;
|
||||
margin: 0 8px;
|
||||
}
|
||||
.layer-ui__wrapper__footer.App-menu_bottom {
|
||||
align-items: stretch;
|
||||
}
|
||||
// till its merged in OSS
|
||||
.App-toolbar-container .mobile-misc-tools-container {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
961
examples/excalidraw/components/App.tsx
Normal file
|
@ -0,0 +1,961 @@
|
|||
import React, {
|
||||
useEffect,
|
||||
useState,
|
||||
useRef,
|
||||
useCallback,
|
||||
Children,
|
||||
cloneElement,
|
||||
} from "react";
|
||||
import ExampleSidebar from "./sidebar/ExampleSidebar";
|
||||
|
||||
import type * as TExcalidraw from "@excalidraw/excalidraw";
|
||||
|
||||
import { nanoid } from "nanoid";
|
||||
|
||||
import {
|
||||
resolvablePromise,
|
||||
ResolvablePromise,
|
||||
distance2d,
|
||||
fileOpen,
|
||||
withBatchedUpdates,
|
||||
withBatchedUpdatesThrottled,
|
||||
} from "../utils";
|
||||
|
||||
import CustomFooter from "./CustomFooter";
|
||||
import MobileFooter from "./MobileFooter";
|
||||
import initialData from "../initialData";
|
||||
|
||||
import type {
|
||||
AppState,
|
||||
BinaryFileData,
|
||||
ExcalidrawImperativeAPI,
|
||||
ExcalidrawInitialDataState,
|
||||
Gesture,
|
||||
LibraryItems,
|
||||
PointerDownState as ExcalidrawPointerDownState,
|
||||
} from "@excalidraw/excalidraw/dist/excalidraw/types";
|
||||
import type {
|
||||
NonDeletedExcalidrawElement,
|
||||
Theme,
|
||||
} from "@excalidraw/excalidraw/dist/excalidraw/element/types";
|
||||
import type { ImportedLibraryData } from "@excalidraw/excalidraw/dist/excalidraw/data/types";
|
||||
|
||||
import "./App.scss";
|
||||
|
||||
type Comment = {
|
||||
x: number;
|
||||
y: number;
|
||||
value: string;
|
||||
id?: string;
|
||||
};
|
||||
|
||||
type PointerDownState = {
|
||||
x: number;
|
||||
y: number;
|
||||
hitElement: Comment;
|
||||
onMove: any;
|
||||
onUp: any;
|
||||
hitElementOffsets: {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
};
|
||||
|
||||
const COMMENT_ICON_DIMENSION = 32;
|
||||
const COMMENT_INPUT_HEIGHT = 50;
|
||||
const COMMENT_INPUT_WIDTH = 150;
|
||||
|
||||
export interface AppProps {
|
||||
appTitle: string;
|
||||
useCustom: (api: ExcalidrawImperativeAPI | null, customArgs?: any[]) => void;
|
||||
customArgs?: any[];
|
||||
children: React.ReactNode;
|
||||
excalidrawLib: typeof TExcalidraw;
|
||||
}
|
||||
|
||||
export default function App({
|
||||
appTitle,
|
||||
useCustom,
|
||||
customArgs,
|
||||
children,
|
||||
excalidrawLib,
|
||||
}: AppProps) {
|
||||
const {
|
||||
exportToCanvas,
|
||||
exportToSvg,
|
||||
exportToBlob,
|
||||
exportToClipboard,
|
||||
useHandleLibrary,
|
||||
MIME_TYPES,
|
||||
sceneCoordsToViewportCoords,
|
||||
viewportCoordsToSceneCoords,
|
||||
restoreElements,
|
||||
Sidebar,
|
||||
Footer,
|
||||
WelcomeScreen,
|
||||
MainMenu,
|
||||
LiveCollaborationTrigger,
|
||||
convertToExcalidrawElements,
|
||||
TTDDialog,
|
||||
TTDDialogTrigger,
|
||||
ROUNDNESS,
|
||||
loadSceneOrLibraryFromBlob,
|
||||
} = excalidrawLib;
|
||||
const appRef = useRef<any>(null);
|
||||
const [viewModeEnabled, setViewModeEnabled] = useState(false);
|
||||
const [zenModeEnabled, setZenModeEnabled] = useState(false);
|
||||
const [gridModeEnabled, setGridModeEnabled] = useState(false);
|
||||
const [blobUrl, setBlobUrl] = useState<string>("");
|
||||
const [canvasUrl, setCanvasUrl] = useState<string>("");
|
||||
const [exportWithDarkMode, setExportWithDarkMode] = useState(false);
|
||||
const [exportEmbedScene, setExportEmbedScene] = useState(false);
|
||||
const [theme, setTheme] = useState<Theme>("light");
|
||||
const [disableImageTool, setDisableImageTool] = useState(false);
|
||||
const [isCollaborating, setIsCollaborating] = useState(false);
|
||||
const [commentIcons, setCommentIcons] = useState<{ [id: string]: Comment }>(
|
||||
{},
|
||||
);
|
||||
const [comment, setComment] = useState<Comment | null>(null);
|
||||
|
||||
const initialStatePromiseRef = useRef<{
|
||||
promise: ResolvablePromise<ExcalidrawInitialDataState | null>;
|
||||
}>({ promise: null! });
|
||||
if (!initialStatePromiseRef.current.promise) {
|
||||
initialStatePromiseRef.current.promise =
|
||||
resolvablePromise<ExcalidrawInitialDataState | null>();
|
||||
}
|
||||
|
||||
const [excalidrawAPI, setExcalidrawAPI] =
|
||||
useState<ExcalidrawImperativeAPI | null>(null);
|
||||
|
||||
useCustom(excalidrawAPI, customArgs);
|
||||
|
||||
useHandleLibrary({ excalidrawAPI });
|
||||
|
||||
useEffect(() => {
|
||||
if (!excalidrawAPI) {
|
||||
return;
|
||||
}
|
||||
const fetchData = async () => {
|
||||
const res = await fetch("/images/rocket.jpeg");
|
||||
const imageData = await res.blob();
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(imageData);
|
||||
|
||||
reader.onload = function () {
|
||||
const imagesArray: BinaryFileData[] = [
|
||||
{
|
||||
id: "rocket" as BinaryFileData["id"],
|
||||
dataURL: reader.result as BinaryFileData["dataURL"],
|
||||
mimeType: MIME_TYPES.jpg,
|
||||
created: 1644915140367,
|
||||
lastRetrieved: 1644915140367,
|
||||
},
|
||||
];
|
||||
|
||||
//@ts-ignore
|
||||
initialStatePromiseRef.current.promise.resolve({
|
||||
...initialData,
|
||||
elements: convertToExcalidrawElements(initialData.elements),
|
||||
});
|
||||
excalidrawAPI.addFiles(imagesArray);
|
||||
};
|
||||
};
|
||||
fetchData();
|
||||
}, [excalidrawAPI, convertToExcalidrawElements, MIME_TYPES]);
|
||||
|
||||
const renderExcalidraw = (children: React.ReactNode) => {
|
||||
const Excalidraw: any = Children.toArray(children).find(
|
||||
(child) =>
|
||||
React.isValidElement(child) &&
|
||||
typeof child.type !== "string" &&
|
||||
//@ts-ignore
|
||||
child.type.displayName === "Excalidraw",
|
||||
);
|
||||
if (!Excalidraw) {
|
||||
return;
|
||||
}
|
||||
const newElement = cloneElement(
|
||||
Excalidraw,
|
||||
{
|
||||
excalidrawAPI: (api: ExcalidrawImperativeAPI) => setExcalidrawAPI(api),
|
||||
initialData: initialStatePromiseRef.current.promise,
|
||||
onChange: (
|
||||
elements: NonDeletedExcalidrawElement[],
|
||||
state: AppState,
|
||||
) => {
|
||||
console.info("Elements :", elements, "State : ", state);
|
||||
},
|
||||
onPointerUpdate: (payload: {
|
||||
pointer: { x: number; y: number };
|
||||
button: "down" | "up";
|
||||
pointersMap: Gesture["pointers"];
|
||||
}) => setPointerData(payload),
|
||||
viewModeEnabled,
|
||||
zenModeEnabled,
|
||||
gridModeEnabled,
|
||||
theme,
|
||||
name: "Custom name of drawing",
|
||||
UIOptions: {
|
||||
canvasActions: {
|
||||
loadScene: false,
|
||||
},
|
||||
tools: { image: !disableImageTool },
|
||||
},
|
||||
renderTopRightUI,
|
||||
onLinkOpen,
|
||||
onPointerDown,
|
||||
onScrollChange: rerenderCommentIcons,
|
||||
validateEmbeddable: true,
|
||||
},
|
||||
<>
|
||||
{excalidrawAPI && (
|
||||
<Footer>
|
||||
<CustomFooter
|
||||
excalidrawAPI={excalidrawAPI}
|
||||
excalidrawLib={excalidrawLib}
|
||||
/>
|
||||
</Footer>
|
||||
)}
|
||||
<WelcomeScreen />
|
||||
<Sidebar name="custom">
|
||||
<Sidebar.Tabs>
|
||||
<Sidebar.Header />
|
||||
<Sidebar.Tab tab="one">Tab one!</Sidebar.Tab>
|
||||
<Sidebar.Tab tab="two">Tab two!</Sidebar.Tab>
|
||||
<Sidebar.TabTriggers>
|
||||
<Sidebar.TabTrigger tab="one">One</Sidebar.TabTrigger>
|
||||
<Sidebar.TabTrigger tab="two">Two</Sidebar.TabTrigger>
|
||||
</Sidebar.TabTriggers>
|
||||
</Sidebar.Tabs>
|
||||
</Sidebar>
|
||||
<Sidebar.Trigger
|
||||
name="custom"
|
||||
tab="one"
|
||||
style={{
|
||||
position: "absolute",
|
||||
left: "50%",
|
||||
transform: "translateX(-50%)",
|
||||
bottom: "20px",
|
||||
zIndex: 9999999999999999,
|
||||
}}
|
||||
>
|
||||
Toggle Custom Sidebar
|
||||
</Sidebar.Trigger>
|
||||
{renderMenu()}
|
||||
{excalidrawAPI && (
|
||||
<TTDDialogTrigger icon={<span>😀</span>}>
|
||||
Text to diagram
|
||||
</TTDDialogTrigger>
|
||||
)}
|
||||
<TTDDialog
|
||||
onTextSubmit={async (_) => {
|
||||
console.info("submit");
|
||||
// sleep for 2s
|
||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||
throw new Error("error, go away now");
|
||||
// return "dummy";
|
||||
}}
|
||||
/>
|
||||
</>,
|
||||
);
|
||||
return newElement;
|
||||
};
|
||||
const renderTopRightUI = (isMobile: boolean) => {
|
||||
return (
|
||||
<>
|
||||
{!isMobile && (
|
||||
<LiveCollaborationTrigger
|
||||
isCollaborating={isCollaborating}
|
||||
onSelect={() => {
|
||||
window.alert("Collab dialog clicked");
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<button
|
||||
onClick={() => alert("This is an empty top right UI")}
|
||||
style={{ height: "2.5rem" }}
|
||||
>
|
||||
Click me
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const loadSceneOrLibrary = async () => {
|
||||
const file = await fileOpen({ description: "Excalidraw or library file" });
|
||||
const contents = await loadSceneOrLibraryFromBlob(file, null, null);
|
||||
if (contents.type === MIME_TYPES.excalidraw) {
|
||||
excalidrawAPI?.updateScene(contents.data as any);
|
||||
} else if (contents.type === MIME_TYPES.excalidrawlib) {
|
||||
excalidrawAPI?.updateLibrary({
|
||||
libraryItems: (contents.data as ImportedLibraryData).libraryItems!,
|
||||
openLibraryMenu: true,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const updateScene = () => {
|
||||
const sceneData = {
|
||||
elements: restoreElements(
|
||||
convertToExcalidrawElements([
|
||||
{
|
||||
type: "rectangle",
|
||||
id: "rect-1",
|
||||
fillStyle: "hachure",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
angle: 0,
|
||||
x: 100.50390625,
|
||||
y: 93.67578125,
|
||||
strokeColor: "#c92a2a",
|
||||
width: 186.47265625,
|
||||
height: 141.9765625,
|
||||
seed: 1968410350,
|
||||
roundness: {
|
||||
type: ROUNDNESS.ADAPTIVE_RADIUS,
|
||||
value: 32,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "arrow",
|
||||
x: 300,
|
||||
y: 150,
|
||||
start: { id: "rect-1" },
|
||||
end: { type: "ellipse" },
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
x: 300,
|
||||
y: 100,
|
||||
text: "HELLO WORLD!",
|
||||
},
|
||||
]),
|
||||
null,
|
||||
),
|
||||
appState: {
|
||||
viewBackgroundColor: "#edf2ff",
|
||||
},
|
||||
};
|
||||
excalidrawAPI?.updateScene(sceneData);
|
||||
};
|
||||
|
||||
const onLinkOpen = useCallback(
|
||||
(
|
||||
element: NonDeletedExcalidrawElement,
|
||||
event: CustomEvent<{
|
||||
nativeEvent: MouseEvent | React.PointerEvent<HTMLCanvasElement>;
|
||||
}>,
|
||||
) => {
|
||||
const link = element.link!;
|
||||
const { nativeEvent } = event.detail;
|
||||
const isNewTab = nativeEvent.ctrlKey || nativeEvent.metaKey;
|
||||
const isNewWindow = nativeEvent.shiftKey;
|
||||
const isInternalLink =
|
||||
link.startsWith("/") || link.includes(window.location.origin);
|
||||
if (isInternalLink && !isNewTab && !isNewWindow) {
|
||||
// signal that we're handling the redirect ourselves
|
||||
event.preventDefault();
|
||||
// do a custom redirect, such as passing to react-router
|
||||
// ...
|
||||
}
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const onCopy = async (type: "png" | "svg" | "json") => {
|
||||
if (!excalidrawAPI) {
|
||||
return false;
|
||||
}
|
||||
await exportToClipboard({
|
||||
elements: excalidrawAPI.getSceneElements(),
|
||||
appState: excalidrawAPI.getAppState(),
|
||||
files: excalidrawAPI.getFiles(),
|
||||
type,
|
||||
});
|
||||
window.alert(`Copied to clipboard as ${type} successfully`);
|
||||
};
|
||||
|
||||
const [pointerData, setPointerData] = useState<{
|
||||
pointer: { x: number; y: number };
|
||||
button: "down" | "up";
|
||||
pointersMap: Gesture["pointers"];
|
||||
} | null>(null);
|
||||
|
||||
const onPointerDown = (
|
||||
activeTool: AppState["activeTool"],
|
||||
pointerDownState: ExcalidrawPointerDownState,
|
||||
) => {
|
||||
if (activeTool.type === "custom" && activeTool.customType === "comment") {
|
||||
const { x, y } = pointerDownState.origin;
|
||||
setComment({ x, y, value: "" });
|
||||
}
|
||||
};
|
||||
|
||||
const rerenderCommentIcons = () => {
|
||||
if (!excalidrawAPI) {
|
||||
return false;
|
||||
}
|
||||
const commentIconsElements = appRef.current.querySelectorAll(
|
||||
".comment-icon",
|
||||
) as HTMLElement[];
|
||||
commentIconsElements.forEach((ele) => {
|
||||
const id = ele.id;
|
||||
const appstate = excalidrawAPI.getAppState();
|
||||
const { x, y } = sceneCoordsToViewportCoords(
|
||||
{ sceneX: commentIcons[id].x, sceneY: commentIcons[id].y },
|
||||
appstate,
|
||||
);
|
||||
ele.style.left = `${
|
||||
x - COMMENT_ICON_DIMENSION / 2 - appstate!.offsetLeft
|
||||
}px`;
|
||||
ele.style.top = `${
|
||||
y - COMMENT_ICON_DIMENSION / 2 - appstate!.offsetTop
|
||||
}px`;
|
||||
});
|
||||
};
|
||||
|
||||
const onPointerMoveFromPointerDownHandler = (
|
||||
pointerDownState: PointerDownState,
|
||||
) => {
|
||||
return withBatchedUpdatesThrottled((event) => {
|
||||
if (!excalidrawAPI) {
|
||||
return false;
|
||||
}
|
||||
const { x, y } = viewportCoordsToSceneCoords(
|
||||
{
|
||||
clientX: event.clientX - pointerDownState.hitElementOffsets.x,
|
||||
clientY: event.clientY - pointerDownState.hitElementOffsets.y,
|
||||
},
|
||||
excalidrawAPI.getAppState(),
|
||||
);
|
||||
setCommentIcons({
|
||||
...commentIcons,
|
||||
[pointerDownState.hitElement.id!]: {
|
||||
...commentIcons[pointerDownState.hitElement.id!],
|
||||
x,
|
||||
y,
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
const onPointerUpFromPointerDownHandler = (
|
||||
pointerDownState: PointerDownState,
|
||||
) => {
|
||||
return withBatchedUpdates((event) => {
|
||||
window.removeEventListener("pointermove", pointerDownState.onMove);
|
||||
window.removeEventListener("pointerup", pointerDownState.onUp);
|
||||
excalidrawAPI?.setActiveTool({ type: "selection" });
|
||||
const distance = distance2d(
|
||||
pointerDownState.x,
|
||||
pointerDownState.y,
|
||||
event.clientX,
|
||||
event.clientY,
|
||||
);
|
||||
if (distance === 0) {
|
||||
if (!comment) {
|
||||
setComment({
|
||||
x: pointerDownState.hitElement.x + 60,
|
||||
y: pointerDownState.hitElement.y,
|
||||
value: pointerDownState.hitElement.value,
|
||||
id: pointerDownState.hitElement.id,
|
||||
});
|
||||
} else {
|
||||
setComment(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const renderCommentIcons = () => {
|
||||
return Object.values(commentIcons).map((commentIcon) => {
|
||||
if (!excalidrawAPI) {
|
||||
return false;
|
||||
}
|
||||
const appState = excalidrawAPI.getAppState();
|
||||
const { x, y } = sceneCoordsToViewportCoords(
|
||||
{ sceneX: commentIcon.x, sceneY: commentIcon.y },
|
||||
excalidrawAPI.getAppState(),
|
||||
);
|
||||
return (
|
||||
<div
|
||||
id={commentIcon.id}
|
||||
key={commentIcon.id}
|
||||
style={{
|
||||
top: `${y - COMMENT_ICON_DIMENSION / 2 - appState!.offsetTop}px`,
|
||||
left: `${x - COMMENT_ICON_DIMENSION / 2 - appState!.offsetLeft}px`,
|
||||
position: "absolute",
|
||||
zIndex: 1,
|
||||
width: `${COMMENT_ICON_DIMENSION}px`,
|
||||
height: `${COMMENT_ICON_DIMENSION}px`,
|
||||
cursor: "pointer",
|
||||
touchAction: "none",
|
||||
}}
|
||||
className="comment-icon"
|
||||
onPointerDown={(event) => {
|
||||
event.preventDefault();
|
||||
if (comment) {
|
||||
commentIcon.value = comment.value;
|
||||
saveComment();
|
||||
}
|
||||
const pointerDownState: any = {
|
||||
x: event.clientX,
|
||||
y: event.clientY,
|
||||
hitElement: commentIcon,
|
||||
hitElementOffsets: { x: event.clientX - x, y: event.clientY - y },
|
||||
};
|
||||
const onPointerMove =
|
||||
onPointerMoveFromPointerDownHandler(pointerDownState);
|
||||
const onPointerUp =
|
||||
onPointerUpFromPointerDownHandler(pointerDownState);
|
||||
window.addEventListener("pointermove", onPointerMove);
|
||||
window.addEventListener("pointerup", onPointerUp);
|
||||
|
||||
pointerDownState.onMove = onPointerMove;
|
||||
pointerDownState.onUp = onPointerUp;
|
||||
|
||||
excalidrawAPI?.setActiveTool({
|
||||
type: "custom",
|
||||
customType: "comment",
|
||||
});
|
||||
}}
|
||||
>
|
||||
<div className="comment-avatar">
|
||||
<img src="images/doremon.png" alt="doremon" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const saveComment = () => {
|
||||
if (!comment) {
|
||||
return;
|
||||
}
|
||||
if (!comment.id && !comment.value) {
|
||||
setComment(null);
|
||||
return;
|
||||
}
|
||||
const id = comment.id || nanoid();
|
||||
setCommentIcons({
|
||||
...commentIcons,
|
||||
[id]: {
|
||||
x: comment.id ? comment.x - 60 : comment.x,
|
||||
y: comment.y,
|
||||
id,
|
||||
value: comment.value,
|
||||
},
|
||||
});
|
||||
setComment(null);
|
||||
};
|
||||
|
||||
const renderComment = () => {
|
||||
if (!comment) {
|
||||
return null;
|
||||
}
|
||||
const appState = excalidrawAPI?.getAppState()!;
|
||||
const { x, y } = sceneCoordsToViewportCoords(
|
||||
{ sceneX: comment.x, sceneY: comment.y },
|
||||
appState,
|
||||
);
|
||||
let top = y - COMMENT_ICON_DIMENSION / 2 - appState.offsetTop;
|
||||
let left = x - COMMENT_ICON_DIMENSION / 2 - appState.offsetLeft;
|
||||
|
||||
if (
|
||||
top + COMMENT_INPUT_HEIGHT <
|
||||
appState.offsetTop + COMMENT_INPUT_HEIGHT
|
||||
) {
|
||||
top = COMMENT_ICON_DIMENSION / 2;
|
||||
}
|
||||
if (top + COMMENT_INPUT_HEIGHT > appState.height) {
|
||||
top = appState.height - COMMENT_INPUT_HEIGHT - COMMENT_ICON_DIMENSION / 2;
|
||||
}
|
||||
if (
|
||||
left + COMMENT_INPUT_WIDTH <
|
||||
appState.offsetLeft + COMMENT_INPUT_WIDTH
|
||||
) {
|
||||
left = COMMENT_ICON_DIMENSION / 2;
|
||||
}
|
||||
if (left + COMMENT_INPUT_WIDTH > appState.width) {
|
||||
left = appState.width - COMMENT_INPUT_WIDTH - COMMENT_ICON_DIMENSION / 2;
|
||||
}
|
||||
|
||||
return (
|
||||
<textarea
|
||||
className="comment"
|
||||
style={{
|
||||
top: `${top}px`,
|
||||
left: `${left}px`,
|
||||
position: "absolute",
|
||||
zIndex: 1,
|
||||
height: `${COMMENT_INPUT_HEIGHT}px`,
|
||||
width: `${COMMENT_INPUT_WIDTH}px`,
|
||||
}}
|
||||
ref={(ref) => {
|
||||
setTimeout(() => ref?.focus());
|
||||
}}
|
||||
placeholder={comment.value ? "Reply" : "Comment"}
|
||||
value={comment.value}
|
||||
onChange={(event) => {
|
||||
setComment({ ...comment, value: event.target.value });
|
||||
}}
|
||||
onBlur={saveComment}
|
||||
onKeyDown={(event) => {
|
||||
if (!event.shiftKey && event.key === "Enter") {
|
||||
event.preventDefault();
|
||||
saveComment();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const renderMenu = () => {
|
||||
return (
|
||||
<MainMenu>
|
||||
<MainMenu.DefaultItems.SaveAsImage />
|
||||
<MainMenu.DefaultItems.Export />
|
||||
<MainMenu.Separator />
|
||||
<MainMenu.DefaultItems.LiveCollaborationTrigger
|
||||
isCollaborating={isCollaborating}
|
||||
onSelect={() => window.alert("You clicked on collab button")}
|
||||
/>
|
||||
<MainMenu.Group title="Excalidraw links">
|
||||
<MainMenu.DefaultItems.Socials />
|
||||
</MainMenu.Group>
|
||||
<MainMenu.Separator />
|
||||
<MainMenu.ItemCustom>
|
||||
<button
|
||||
style={{ height: "2rem" }}
|
||||
onClick={() => window.alert("custom menu item")}
|
||||
>
|
||||
custom item
|
||||
</button>
|
||||
</MainMenu.ItemCustom>
|
||||
<MainMenu.DefaultItems.Help />
|
||||
|
||||
{excalidrawAPI && (
|
||||
<MobileFooter
|
||||
excalidrawLib={excalidrawLib}
|
||||
excalidrawAPI={excalidrawAPI}
|
||||
/>
|
||||
)}
|
||||
</MainMenu>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="App" ref={appRef}>
|
||||
<h1>{appTitle}</h1>
|
||||
{/* TODO fix type */}
|
||||
<ExampleSidebar>
|
||||
<div className="button-wrapper">
|
||||
<button onClick={loadSceneOrLibrary}>Load Scene or Library</button>
|
||||
<button className="update-scene" onClick={updateScene}>
|
||||
Update Scene
|
||||
</button>
|
||||
<button
|
||||
className="reset-scene"
|
||||
onClick={() => {
|
||||
excalidrawAPI?.resetScene();
|
||||
}}
|
||||
>
|
||||
Reset Scene
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
const libraryItems: LibraryItems = [
|
||||
{
|
||||
status: "published",
|
||||
id: "1",
|
||||
created: 1,
|
||||
elements: initialData.libraryItems[1] as any,
|
||||
},
|
||||
{
|
||||
status: "unpublished",
|
||||
id: "2",
|
||||
created: 2,
|
||||
elements: initialData.libraryItems[1] as any,
|
||||
},
|
||||
];
|
||||
excalidrawAPI?.updateLibrary({
|
||||
libraryItems,
|
||||
});
|
||||
}}
|
||||
>
|
||||
Update Library
|
||||
</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>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={theme === "dark"}
|
||||
onChange={() => {
|
||||
setTheme(theme === "light" ? "dark" : "light");
|
||||
}}
|
||||
/>
|
||||
Switch to Dark Theme
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={disableImageTool === true}
|
||||
onChange={() => {
|
||||
setDisableImageTool(!disableImageTool);
|
||||
}}
|
||||
/>
|
||||
Disable Image Tool
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={isCollaborating}
|
||||
onChange={() => {
|
||||
if (!isCollaborating) {
|
||||
const collaborators = new Map();
|
||||
collaborators.set("id1", {
|
||||
username: "Doremon",
|
||||
avatarUrl: "images/doremon.png",
|
||||
});
|
||||
collaborators.set("id2", {
|
||||
username: "Excalibot",
|
||||
avatarUrl: "images/excalibot.png",
|
||||
});
|
||||
collaborators.set("id3", {
|
||||
username: "Pika",
|
||||
avatarUrl: "images/pika.jpeg",
|
||||
});
|
||||
collaborators.set("id4", {
|
||||
username: "fallback",
|
||||
avatarUrl: "https://example.com",
|
||||
});
|
||||
excalidrawAPI?.updateScene({ collaborators });
|
||||
} else {
|
||||
excalidrawAPI?.updateScene({
|
||||
collaborators: new Map(),
|
||||
});
|
||||
}
|
||||
setIsCollaborating(!isCollaborating);
|
||||
}}
|
||||
/>
|
||||
Show collaborators
|
||||
</label>
|
||||
<div>
|
||||
<button onClick={onCopy.bind(null, "png")}>
|
||||
Copy to Clipboard as PNG
|
||||
</button>
|
||||
<button onClick={onCopy.bind(null, "svg")}>
|
||||
Copy to Clipboard as SVG
|
||||
</button>
|
||||
<button onClick={onCopy.bind(null, "json")}>
|
||||
Copy to Clipboard as JSON
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
gap: "1em",
|
||||
justifyContent: "center",
|
||||
marginTop: "1em",
|
||||
}}
|
||||
>
|
||||
<div>x: {pointerData?.pointer.x ?? 0}</div>
|
||||
<div>y: {pointerData?.pointer.y ?? 0}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="excalidraw-wrapper">
|
||||
{renderExcalidraw(children)}
|
||||
{Object.keys(commentIcons || []).length > 0 && renderCommentIcons()}
|
||||
{comment && renderComment()}
|
||||
</div>
|
||||
|
||||
<div className="export-wrapper button-wrapper">
|
||||
<label className="export-wrapper__checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={exportWithDarkMode}
|
||||
onChange={() => setExportWithDarkMode(!exportWithDarkMode)}
|
||||
/>
|
||||
Export with dark mode
|
||||
</label>
|
||||
<label className="export-wrapper__checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={exportEmbedScene}
|
||||
onChange={() => setExportEmbedScene(!exportEmbedScene)}
|
||||
/>
|
||||
Export with embed scene
|
||||
</label>
|
||||
<button
|
||||
onClick={async () => {
|
||||
if (!excalidrawAPI) {
|
||||
return;
|
||||
}
|
||||
const svg = await exportToSvg({
|
||||
elements: excalidrawAPI?.getSceneElements(),
|
||||
appState: {
|
||||
...initialData.appState,
|
||||
exportWithDarkMode,
|
||||
exportEmbedScene,
|
||||
width: 300,
|
||||
height: 100,
|
||||
},
|
||||
files: excalidrawAPI?.getFiles(),
|
||||
});
|
||||
appRef.current.querySelector(".export-svg").innerHTML =
|
||||
svg.outerHTML;
|
||||
}}
|
||||
>
|
||||
Export to SVG
|
||||
</button>
|
||||
<div className="export export-svg"></div>
|
||||
|
||||
<button
|
||||
onClick={async () => {
|
||||
if (!excalidrawAPI) {
|
||||
return;
|
||||
}
|
||||
const blob = await exportToBlob({
|
||||
elements: excalidrawAPI?.getSceneElements(),
|
||||
mimeType: "image/png",
|
||||
appState: {
|
||||
...initialData.appState,
|
||||
exportEmbedScene,
|
||||
exportWithDarkMode,
|
||||
},
|
||||
files: excalidrawAPI?.getFiles(),
|
||||
});
|
||||
setBlobUrl(window.URL.createObjectURL(blob));
|
||||
}}
|
||||
>
|
||||
Export to Blob
|
||||
</button>
|
||||
<div className="export export-blob">
|
||||
<img src={blobUrl} alt="" />
|
||||
</div>
|
||||
<button
|
||||
onClick={async () => {
|
||||
if (!excalidrawAPI) {
|
||||
return;
|
||||
}
|
||||
const canvas = await exportToCanvas({
|
||||
elements: excalidrawAPI.getSceneElements(),
|
||||
appState: {
|
||||
...initialData.appState,
|
||||
exportWithDarkMode,
|
||||
},
|
||||
files: excalidrawAPI.getFiles(),
|
||||
});
|
||||
const ctx = canvas.getContext("2d")!;
|
||||
ctx.font = "30px Virgil";
|
||||
ctx.strokeText("My custom text", 50, 60);
|
||||
setCanvasUrl(canvas.toDataURL());
|
||||
}}
|
||||
>
|
||||
Export to Canvas
|
||||
</button>
|
||||
<button
|
||||
onClick={async () => {
|
||||
if (!excalidrawAPI) {
|
||||
return;
|
||||
}
|
||||
const canvas = await exportToCanvas({
|
||||
elements: excalidrawAPI.getSceneElements(),
|
||||
appState: {
|
||||
...initialData.appState,
|
||||
exportWithDarkMode,
|
||||
},
|
||||
files: excalidrawAPI.getFiles(),
|
||||
});
|
||||
const ctx = canvas.getContext("2d")!;
|
||||
ctx.font = "30px Virgil";
|
||||
ctx.strokeText("My custom text", 50, 60);
|
||||
setCanvasUrl(canvas.toDataURL());
|
||||
}}
|
||||
>
|
||||
Export to Canvas
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
if (!excalidrawAPI) {
|
||||
return;
|
||||
}
|
||||
|
||||
const elements = excalidrawAPI.getSceneElements();
|
||||
excalidrawAPI.scrollToContent(elements[0], {
|
||||
fitToViewport: true,
|
||||
});
|
||||
}}
|
||||
>
|
||||
Fit to viewport, first element
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
if (!excalidrawAPI) {
|
||||
return;
|
||||
}
|
||||
|
||||
const elements = excalidrawAPI.getSceneElements();
|
||||
excalidrawAPI.scrollToContent(elements[0], {
|
||||
fitToContent: true,
|
||||
});
|
||||
|
||||
excalidrawAPI.scrollToContent(elements[0], {
|
||||
fitToContent: true,
|
||||
});
|
||||
}}
|
||||
>
|
||||
Fit to content, first element
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
if (!excalidrawAPI) {
|
||||
return;
|
||||
}
|
||||
|
||||
const elements = excalidrawAPI.getSceneElements();
|
||||
excalidrawAPI.scrollToContent(elements[0], {
|
||||
fitToContent: true,
|
||||
});
|
||||
|
||||
excalidrawAPI.scrollToContent(elements[0]);
|
||||
}}
|
||||
>
|
||||
Scroll to first element, no fitToContent, no fitToViewport
|
||||
</button>
|
||||
<div className="export export-canvas">
|
||||
<img src={canvasUrl} alt="" />
|
||||
</div>
|
||||
</div>
|
||||
</ExampleSidebar>
|
||||
</div>
|
||||
);
|
||||
}
|
72
examples/excalidraw/components/CustomFooter.tsx
Normal file
|
@ -0,0 +1,72 @@
|
|||
import type * as TExcalidraw from "@excalidraw/excalidraw";
|
||||
import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/dist/excalidraw/types";
|
||||
|
||||
const COMMENT_SVG = (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className="feather feather-message-circle"
|
||||
>
|
||||
<path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path>
|
||||
</svg>
|
||||
);
|
||||
|
||||
const CustomFooter = ({
|
||||
excalidrawAPI,
|
||||
excalidrawLib,
|
||||
}: {
|
||||
excalidrawAPI: ExcalidrawImperativeAPI;
|
||||
excalidrawLib: typeof TExcalidraw;
|
||||
}) => {
|
||||
const { Button, MIME_TYPES } = excalidrawLib;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
onSelect={() => alert("General Kenobi!")}
|
||||
style={{ marginLeft: "1rem", width: "auto" }}
|
||||
title="Hello there!"
|
||||
>
|
||||
Hit me
|
||||
</Button>
|
||||
<Button
|
||||
className="custom-element"
|
||||
onSelect={() => {
|
||||
excalidrawAPI?.setActiveTool({
|
||||
type: "custom",
|
||||
customType: "comment",
|
||||
});
|
||||
const url = `data:${MIME_TYPES.svg},${encodeURIComponent(
|
||||
`<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="feather feather-message-circle"
|
||||
>
|
||||
<path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path>
|
||||
</svg>`,
|
||||
)}`;
|
||||
excalidrawAPI?.setCursor(`url(${url}), auto`);
|
||||
}}
|
||||
title="Comments!"
|
||||
>
|
||||
{COMMENT_SVG}
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default CustomFooter;
|
27
examples/excalidraw/components/MobileFooter.tsx
Normal file
|
@ -0,0 +1,27 @@
|
|||
import { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/dist/excalidraw/types";
|
||||
import CustomFooter from "./CustomFooter";
|
||||
import type * as TExcalidraw from "@excalidraw/excalidraw";
|
||||
|
||||
const MobileFooter = ({
|
||||
excalidrawAPI,
|
||||
excalidrawLib,
|
||||
}: {
|
||||
excalidrawAPI: ExcalidrawImperativeAPI;
|
||||
excalidrawLib: typeof TExcalidraw;
|
||||
}) => {
|
||||
const { useDevice, Footer } = excalidrawLib;
|
||||
|
||||
const device = useDevice();
|
||||
if (device.editor.isMobile) {
|
||||
return (
|
||||
<Footer>
|
||||
<CustomFooter
|
||||
excalidrawAPI={excalidrawAPI}
|
||||
excalidrawLib={excalidrawLib}
|
||||
/>
|
||||
</Footer>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
export default MobileFooter;
|
66
examples/excalidraw/components/sidebar/ExampleSidebar.scss
Normal file
|
@ -0,0 +1,66 @@
|
|||
.sidebar {
|
||||
height: 100%;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: #111;
|
||||
overflow-x: hidden;
|
||||
transition: 0.5s;
|
||||
padding-top: 60px;
|
||||
|
||||
&.open {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
&-links {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 20px;
|
||||
|
||||
button {
|
||||
padding: 10px;
|
||||
margin: 10px;
|
||||
background: #faa2c1;
|
||||
color: #fff;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar a {
|
||||
padding: 8px 8px 8px 32px;
|
||||
text-decoration: none;
|
||||
font-size: 25px;
|
||||
color: #818181;
|
||||
display: block;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
.sidebar a:hover {
|
||||
color: #f1f1f1;
|
||||
}
|
||||
|
||||
.sidebar .closebtn {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
font-size: 36px;
|
||||
margin-left: 50px;
|
||||
}
|
||||
|
||||
.openbtn {
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
background-color: #111;
|
||||
color: white;
|
||||
padding: 10px 15px;
|
||||
border: none;
|
||||
display: flex;
|
||||
margin-left: 50px;
|
||||
}
|
||||
.sidebar-open {
|
||||
margin-left: 300px;
|
||||
}
|
31
examples/excalidraw/components/sidebar/ExampleSidebar.tsx
Normal file
|
@ -0,0 +1,31 @@
|
|||
import { useState } from "react";
|
||||
import "./ExampleSidebar.scss";
|
||||
|
||||
export default function Sidebar({ children }: { children: React.ReactNode }) {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div id="mySidebar" className={`sidebar ${open ? "open" : ""}`}>
|
||||
<button className="closebtn" onClick={() => setOpen(false)}>
|
||||
x
|
||||
</button>
|
||||
<div className="sidebar-links">
|
||||
<button>Empty Home</button>
|
||||
<button>Empty About</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className={`${open ? "sidebar-open" : ""}`}>
|
||||
<button
|
||||
className="openbtn"
|
||||
onClick={() => {
|
||||
setOpen(!open);
|
||||
}}
|
||||
>
|
||||
Open Sidebar
|
||||
</button>
|
||||
{children}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
994
examples/excalidraw/initialData.tsx
Normal file
|
@ -0,0 +1,994 @@
|
|||
import type { ExcalidrawElementSkeleton } from "@excalidraw/excalidraw/data/transform";
|
||||
import type { FileId } from "@excalidraw/excalidraw/element/types";
|
||||
|
||||
const elements: ExcalidrawElementSkeleton[] = [
|
||||
{
|
||||
type: "rectangle",
|
||||
x: 10,
|
||||
y: 10,
|
||||
strokeWidth: 2,
|
||||
id: "1",
|
||||
},
|
||||
{
|
||||
type: "diamond",
|
||||
x: 120,
|
||||
y: 20,
|
||||
backgroundColor: "#fff3bf",
|
||||
strokeWidth: 2,
|
||||
label: {
|
||||
text: "HELLO EXCALIDRAW",
|
||||
strokeColor: "#099268",
|
||||
fontSize: 30,
|
||||
},
|
||||
id: "2",
|
||||
},
|
||||
{
|
||||
type: "arrow",
|
||||
x: 100,
|
||||
y: 200,
|
||||
label: { text: "HELLO WORLD!!" },
|
||||
start: { type: "rectangle" },
|
||||
end: { type: "ellipse" },
|
||||
},
|
||||
{
|
||||
type: "image",
|
||||
x: 606.1042326312408,
|
||||
y: 153.57729779411773,
|
||||
width: 230,
|
||||
height: 230,
|
||||
fileId: "rocket" as FileId,
|
||||
},
|
||||
{
|
||||
type: "frame",
|
||||
children: ["1", "2"],
|
||||
name: "My frame",
|
||||
},
|
||||
];
|
||||
export default {
|
||||
elements,
|
||||
appState: { viewBackgroundColor: "#AFEEEE", currentItemFontFamily: 1 },
|
||||
scrollToContent: true,
|
||||
libraryItems: [
|
||||
[
|
||||
{
|
||||
type: "line",
|
||||
|
||||
x: 209.72304760646858,
|
||||
y: 338.83587294718825,
|
||||
strokeColor: "#881fa3",
|
||||
backgroundColor: "#be4bdb",
|
||||
width: 116.42036295658873,
|
||||
height: 103.65107323746608,
|
||||
strokeSharpness: "sharp",
|
||||
points: [
|
||||
[-92.28090097254909, 7.105427357601002e-15],
|
||||
[-154.72281841151394, 19.199290805487394],
|
||||
[-155.45758928571422, 79.43840749607878],
|
||||
[-99.89923520113778, 103.6510732374661],
|
||||
[-40.317783799181804, 79.1587107641305],
|
||||
[-39.037226329125524, 21.285677238400705],
|
||||
[-92.28090097254909, 7.105427357601002e-15],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
type: "line",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
x: -249.48446738689245,
|
||||
y: 374.851387389359,
|
||||
strokeColor: "#0a11d3",
|
||||
backgroundColor: "#228be6",
|
||||
width: 88.21658171083376,
|
||||
height: 113.8575037534261,
|
||||
groupIds: ["N2YAi9nU-wlRb0rDaDZoe"],
|
||||
points: [
|
||||
[-0.22814350714115691, -43.414939319563715],
|
||||
[0.06274947619197979, 42.63794490105306],
|
||||
[-0.21453039840335475, 52.43469208825097],
|
||||
[4.315205554872581, 56.66774540453215],
|
||||
[20.089784992984285, 60.25027917349701],
|
||||
[46.7532926683984, 61.365826671969444],
|
||||
[72.22851104292477, 59.584691681394986],
|
||||
[85.76368213524371, 55.325139565662596],
|
||||
[87.67263486434864, 51.7342924478499],
|
||||
[87.94074036468018, 43.84700272879395],
|
||||
[87.73030872197806, -36.195582644606276],
|
||||
[87.2559282533682, -43.758132174307036],
|
||||
[81.5915337527493, -47.984890854524416],
|
||||
[69.66352776578219, -50.4328058257654],
|
||||
[42.481213744224995, -52.49167708145666],
|
||||
[20.68789182864576, -51.26396751574663],
|
||||
[3.5475921483286084, -47.099726468136254],
|
||||
[-0.2758413461535838, -43.46664538034193],
|
||||
[-0.22814350714115691, -43.414939319563715],
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "line",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -249.02524930453623,
|
||||
y: 398.8804363713438,
|
||||
strokeColor: "#0a11d3",
|
||||
backgroundColor: "transparent",
|
||||
width: 88.30808627974527,
|
||||
height: 9.797916664247975,
|
||||
seed: 683951089,
|
||||
groupIds: ["N2YAi9nU-wlRb0rDaDZoe"],
|
||||
strokeSharpness: "round",
|
||||
|
||||
points: [
|
||||
[0, -2.1538602707609424],
|
||||
[2.326538897826852, 1.751753055375216],
|
||||
[12.359939318521995, 5.028526743934819],
|
||||
[25.710950037209347, 7.012921076245119],
|
||||
[46.6269757640547, 7.193749997581346],
|
||||
[71.03526003420632, 5.930375670950649],
|
||||
[85.2899738827162, 1.3342483900732343],
|
||||
[88.30808627974527, -2.6041666666666288],
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "line",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -250.11899081659772,
|
||||
y: 365.80628180927204,
|
||||
strokeColor: "#0a11d3",
|
||||
backgroundColor: "transparent",
|
||||
width: 88.30808627974527,
|
||||
height: 9.797916664247975,
|
||||
seed: 1817746897,
|
||||
groupIds: ["N2YAi9nU-wlRb0rDaDZoe"],
|
||||
strokeSharpness: "round",
|
||||
|
||||
points: [
|
||||
[0, -2.1538602707609424],
|
||||
[2.326538897826852, 1.751753055375216],
|
||||
[12.359939318521995, 5.028526743934819],
|
||||
[25.710950037209347, 7.012921076245119],
|
||||
[46.6269757640547, 7.193749997581346],
|
||||
[71.03526003420632, 5.930375670950649],
|
||||
[85.2899738827162, 1.3342483900732343],
|
||||
[88.30808627974527, -2.6041666666666288],
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "ellipse",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -251.23981350275943,
|
||||
y: 323.4117518426986,
|
||||
strokeColor: "#0a11d3",
|
||||
backgroundColor: "#fff",
|
||||
width: 87.65074610854188,
|
||||
height: 17.72670397681366,
|
||||
seed: 1409727409,
|
||||
groupIds: ["N2YAi9nU-wlRb0rDaDZoe"],
|
||||
strokeSharpness: "sharp",
|
||||
boundElementIds: ["bxuMGTzXLn7H-uBCptINx"],
|
||||
},
|
||||
{
|
||||
type: "ellipse",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -179.73008120217884,
|
||||
y: 347.98755471983213,
|
||||
strokeColor: "#0a11d3",
|
||||
backgroundColor: "#fff",
|
||||
width: 12.846057046979809,
|
||||
height: 13.941904362416096,
|
||||
seed: 1073094033,
|
||||
groupIds: ["N2YAi9nU-wlRb0rDaDZoe"],
|
||||
strokeSharpness: "sharp",
|
||||
},
|
||||
{
|
||||
type: "ellipse",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -179.73008120217884,
|
||||
y: 378.5900085788926,
|
||||
strokeColor: "#0a11d3",
|
||||
backgroundColor: "#fff",
|
||||
width: 12.846057046979809,
|
||||
height: 13.941904362416096,
|
||||
seed: 526271345,
|
||||
groupIds: ["N2YAi9nU-wlRb0rDaDZoe"],
|
||||
strokeSharpness: "sharp",
|
||||
},
|
||||
{
|
||||
type: "ellipse",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -179.73008120217884,
|
||||
y: 411.8508097533892,
|
||||
strokeColor: "#0a11d3",
|
||||
backgroundColor: "#fff",
|
||||
width: 12.846057046979809,
|
||||
height: 13.941904362416096,
|
||||
seed: 243707217,
|
||||
groupIds: ["N2YAi9nU-wlRb0rDaDZoe"],
|
||||
strokeSharpness: "sharp",
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
type: "diamond",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -109.55894395256101,
|
||||
y: 381.22641397493356,
|
||||
strokeColor: "#c92a2a",
|
||||
backgroundColor: "#fd8888",
|
||||
width: 112.64736525303451,
|
||||
height: 36.77344700318558,
|
||||
seed: 511870335,
|
||||
groupIds: ["M6ByXuSmtHCr3RtPPKJQh"],
|
||||
strokeSharpness: "sharp",
|
||||
},
|
||||
{
|
||||
type: "diamond",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -109.55894395256101,
|
||||
y: 372.354634046675,
|
||||
strokeColor: "#c92a2a",
|
||||
backgroundColor: "#fd8888",
|
||||
width: 112.64736525303451,
|
||||
height: 36.77344700318558,
|
||||
seed: 1283079231,
|
||||
groupIds: ["M6ByXuSmtHCr3RtPPKJQh"],
|
||||
strokeSharpness: "sharp",
|
||||
},
|
||||
{
|
||||
type: "diamond",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -109.55894395256101,
|
||||
y: 359.72407445196296,
|
||||
strokeColor: "#c92a2a",
|
||||
backgroundColor: "#fd8888",
|
||||
width: 112.64736525303451,
|
||||
height: 36.77344700318558,
|
||||
seed: 996251633,
|
||||
groupIds: ["M6ByXuSmtHCr3RtPPKJQh"],
|
||||
strokeSharpness: "sharp",
|
||||
},
|
||||
{
|
||||
type: "diamond",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -109.55894395256101,
|
||||
y: 347.1924021546656,
|
||||
strokeColor: "#c92a2a",
|
||||
backgroundColor: "#fd8888",
|
||||
width: 112.64736525303451,
|
||||
height: 36.77344700318558,
|
||||
seed: 1764842481,
|
||||
groupIds: ["M6ByXuSmtHCr3RtPPKJQh"],
|
||||
strokeSharpness: "sharp",
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
type: "line",
|
||||
fillStyle: "hachure",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 1.5707963267948957,
|
||||
x: -471.6208001976387,
|
||||
y: 520.7681448415112,
|
||||
strokeColor: "#087f5b",
|
||||
backgroundColor: "#40c057",
|
||||
width: 52.317507746132115,
|
||||
height: 154.56722543646003,
|
||||
seed: 1424381745,
|
||||
groupIds: ["HSrtfEf-CssQTf160Fb6R"],
|
||||
strokeSharpness: "round",
|
||||
|
||||
points: [
|
||||
[-0.24755378372925183, -40.169554027464216],
|
||||
[-0.07503751055611152, 76.6515171914404],
|
||||
[-0.23948042713317108, 89.95108885873196],
|
||||
[2.446913573036335, 95.69766931810295],
|
||||
[11.802146636255692, 100.56113713047068],
|
||||
[27.615140546177496, 102.07554835500338],
|
||||
[42.72341054254274, 99.65756899883291],
|
||||
[50.75054563137204, 93.87501510096598],
|
||||
[51.88266441510958, 89.00026150397161],
|
||||
[52.04166639997853, 78.29287333983132],
|
||||
[51.916868330459295, -30.36891819848148],
|
||||
[51.635533423123285, -40.63545540065934],
|
||||
[48.27622163143906, -46.37349057843314],
|
||||
[41.202227904674494, -49.69665692879073],
|
||||
[25.081551986374073, -52.49167708145666],
|
||||
[12.15685839679867, -50.825000270901],
|
||||
[1.9916746648394732, -45.171835889467935],
|
||||
[-0.2758413461535838, -40.23974757720194],
|
||||
[-0.24755378372925183, -40.169554027464216],
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "line",
|
||||
version: 2405,
|
||||
versionNonce: 2120341087,
|
||||
isDeleted: false,
|
||||
id: "TYsYe2VvJ60T_yKa3kyOw",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 1.5707963267948957,
|
||||
x: -496.3957643857249,
|
||||
y: 541.7241190920508,
|
||||
strokeColor: "#087f5b",
|
||||
backgroundColor: "transparent",
|
||||
width: 50.7174766392476,
|
||||
height: 12.698053371678215,
|
||||
seed: 726657713,
|
||||
groupIds: ["HSrtfEf-CssQTf160Fb6R"],
|
||||
strokeSharpness: "round",
|
||||
|
||||
points: [
|
||||
[0, -2.0205717204386002],
|
||||
[1.3361877396713384, 3.0410845646550486],
|
||||
[7.098613049589299, 7.287767671898479],
|
||||
[14.766422451441104, 9.859533283467512],
|
||||
[26.779003528407447, 10.093886705011586],
|
||||
[40.79727342221974, 8.456559589697127],
|
||||
[48.98410145879092, 2.500000505196364],
|
||||
[50.7174766392476, -2.6041666666666288],
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "line",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 1.5707963267948957,
|
||||
x: -450.969983237283,
|
||||
y: 542.1789894334747,
|
||||
strokeColor: "#087f5b",
|
||||
backgroundColor: "transparent",
|
||||
width: 50.57247907260371,
|
||||
height: 10.178760037658167,
|
||||
seed: 1977326481,
|
||||
groupIds: ["HSrtfEf-CssQTf160Fb6R"],
|
||||
strokeSharpness: "round",
|
||||
|
||||
points: [
|
||||
[0, -2.136356936862347],
|
||||
[1.332367676378171, 1.9210669226078037],
|
||||
[7.078318632616268, 5.325208253515953],
|
||||
[14.724206326638113, 7.386735659885842],
|
||||
[26.70244431044034, 7.574593370991538],
|
||||
[40.68063699304561, 6.262111896696538],
|
||||
[48.84405948536458, 1.4873339211608216],
|
||||
[50.57247907260371, -2.6041666666666288],
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "ellipse",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 1.5707963267948957,
|
||||
x: -404.36521010516793,
|
||||
y: 534.1894365757241,
|
||||
strokeColor: "#087f5b",
|
||||
backgroundColor: "#fff",
|
||||
width: 51.27812853552538,
|
||||
height: 22.797152568995934,
|
||||
seed: 1774660383,
|
||||
groupIds: ["HSrtfEf-CssQTf160Fb6R"],
|
||||
strokeSharpness: "sharp",
|
||||
boundElementIds: ["bxuMGTzXLn7H-uBCptINx"],
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
type: "rectangle",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 2,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -393.3000561423187,
|
||||
y: 338.9742643666818,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "#fff",
|
||||
width: 70.67858069123133,
|
||||
height: 107.25081879410921,
|
||||
seed: 371096063,
|
||||
groupIds: ["9ppmKFUbA4iKjt8FaDFox"],
|
||||
strokeSharpness: "sharp",
|
||||
boundElementIds: [
|
||||
"CFu0B4Mw_1wC1Hbgx8Fs0",
|
||||
"XIl_NhaFtRO00pX5Pq6VU",
|
||||
"EndiSTFlx1AT7vcBVjgve",
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "rectangle",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 2,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -400.8474891780329,
|
||||
y: 331.95417508096745,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "#fff",
|
||||
width: 70.67858069123133,
|
||||
height: 107.25081879410921,
|
||||
seed: 685932433,
|
||||
groupIds: ["0RJwA-yKP5dqk5oMiSeot", "9ppmKFUbA4iKjt8FaDFox"],
|
||||
strokeSharpness: "sharp",
|
||||
boundElementIds: [
|
||||
"CFu0B4Mw_1wC1Hbgx8Fs0",
|
||||
"XIl_NhaFtRO00pX5Pq6VU",
|
||||
"EndiSTFlx1AT7vcBVjgve",
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "rectangle",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 2,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -410.24257846374826,
|
||||
y: 323.7002688309677,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "#fff",
|
||||
width: 70.67858069123133,
|
||||
height: 107.25081879410921,
|
||||
seed: 58634943,
|
||||
groupIds: ["9ppmKFUbA4iKjt8FaDFox"],
|
||||
strokeSharpness: "sharp",
|
||||
boundElementIds: [
|
||||
"CFu0B4Mw_1wC1Hbgx8Fs0",
|
||||
"XIl_NhaFtRO00pX5Pq6VU",
|
||||
"EndiSTFlx1AT7vcBVjgve",
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "draw",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -398.2561518768373,
|
||||
y: 371.84603609547054,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "#fff",
|
||||
width: 46.57983585730082,
|
||||
height: 3.249953844290203,
|
||||
seed: 1673003743,
|
||||
groupIds: ["9ppmKFUbA4iKjt8FaDFox"],
|
||||
strokeSharpness: "round",
|
||||
|
||||
points: [
|
||||
[0, 0.6014697828497827],
|
||||
[40.42449133807562, 0.7588628355182573],
|
||||
[46.57983585730082, -2.491091008771946],
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "draw",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -396.400899638823,
|
||||
y: 340.9822185794818,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "#fff",
|
||||
width: 45.567415680676426,
|
||||
height: 2.8032978840147194,
|
||||
seed: 1821527807,
|
||||
groupIds: ["9ppmKFUbA4iKjt8FaDFox"],
|
||||
strokeSharpness: "round",
|
||||
|
||||
points: [
|
||||
[0, 0],
|
||||
[16.832548902953302, -2.8032978840147194],
|
||||
[45.567415680676426, -0.3275477042019195],
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "draw",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -396.4774991551924,
|
||||
y: 408.37659284983897,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "#fff",
|
||||
width: 48.33668263438425,
|
||||
height: 4.280657518731036,
|
||||
seed: 1485707039,
|
||||
groupIds: ["9ppmKFUbA4iKjt8FaDFox"],
|
||||
strokeSharpness: "round",
|
||||
|
||||
points: [
|
||||
[0, 0],
|
||||
[26.41225578429045, -0.2552319773002338],
|
||||
[37.62000339651456, 2.3153712935189787],
|
||||
[48.33668263438425, -1.9652862252120569],
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "draw",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -399.6615463367227,
|
||||
y: 419.61974125811776,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "#fff",
|
||||
width: 54.40694982784246,
|
||||
height: 2.9096445412231735,
|
||||
seed: 1042012991,
|
||||
groupIds: ["9ppmKFUbA4iKjt8FaDFox"],
|
||||
strokeSharpness: "round",
|
||||
|
||||
points: [
|
||||
[0, 0],
|
||||
[10.166093050596771, -1.166642430373031],
|
||||
[16.130660965377448, -0.8422655250909383],
|
||||
[46.26079588567538, 0.6125567455206506],
|
||||
[54.40694982784246, -2.297087795702523],
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "draw",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -399.3767034411569,
|
||||
y: 356.042820132743,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "#fff",
|
||||
width: 46.92865289294453,
|
||||
height: 2.4757501798128,
|
||||
seed: 295443295,
|
||||
groupIds: ["9ppmKFUbA4iKjt8FaDFox"],
|
||||
strokeSharpness: "round",
|
||||
|
||||
points: [
|
||||
[0, 0],
|
||||
[18.193786115221407, -0.5912874140789839],
|
||||
[46.92865289294453, 1.884462765733816],
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "draw",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -399.26921524500654,
|
||||
y: 390.5261491685826,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "#fff",
|
||||
width: 46.92865289294453,
|
||||
height: 2.4757501798128,
|
||||
seed: 1734301567,
|
||||
groupIds: ["9ppmKFUbA4iKjt8FaDFox"],
|
||||
strokeSharpness: "round",
|
||||
|
||||
points: [
|
||||
[0, 0],
|
||||
[8.093938105125233, 1.4279702913643746],
|
||||
[18.193786115221407, -0.5912874140789839],
|
||||
[46.92865289294453, 1.884462765733816],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
type: "rectangle",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -593.9896997899341,
|
||||
y: 343.9798351106279,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "transparent",
|
||||
width: 127.88383573213892,
|
||||
height: 76.53703389977764,
|
||||
seed: 106569279,
|
||||
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
||||
strokeSharpness: "sharp",
|
||||
},
|
||||
{
|
||||
type: "line",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -595.0652975408293,
|
||||
y: 354.6963695028721,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "transparent",
|
||||
width: 128.84193229844433,
|
||||
height: 0,
|
||||
seed: 73916127,
|
||||
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
||||
strokeSharpness: "round",
|
||||
|
||||
points: [
|
||||
[0, 0],
|
||||
[128.84193229844433, 0],
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "ellipse",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 0,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -589.5016643209792,
|
||||
y: 348.2514049106367,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "#fa5252",
|
||||
width: 5.001953125,
|
||||
height: 5.001953125,
|
||||
seed: 387857791,
|
||||
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
||||
strokeSharpness: "sharp",
|
||||
},
|
||||
{
|
||||
type: "ellipse",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 0,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -579.2389690084792,
|
||||
y: 348.2514049106367,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "#fab005",
|
||||
width: 5.001953125,
|
||||
height: 5.001953125,
|
||||
seed: 1486370207,
|
||||
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
||||
strokeSharpness: "sharp",
|
||||
},
|
||||
{
|
||||
type: "ellipse",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 0,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -568.525552542133,
|
||||
y: 348.7021260644829,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "#40c057",
|
||||
width: 5.001953125,
|
||||
height: 5.001953125,
|
||||
seed: 610150847,
|
||||
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
||||
strokeSharpness: "sharp",
|
||||
},
|
||||
{
|
||||
type: "ellipse",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 90,
|
||||
angle: 0,
|
||||
x: -552.4984915525058,
|
||||
y: 364.75449494249875,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "#04aaf7",
|
||||
width: 42.72020253937572,
|
||||
height: 42.72020253937572,
|
||||
seed: 144280593,
|
||||
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
||||
strokeSharpness: "sharp",
|
||||
},
|
||||
{
|
||||
type: "draw",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
x: -530.327851842306,
|
||||
y: 378.9357912947449,
|
||||
strokeColor: "#087f5b",
|
||||
backgroundColor: "#40c057",
|
||||
width: 28.226201983883442,
|
||||
height: 24.44112284281997,
|
||||
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
||||
strokeSharpness: "round",
|
||||
points: [
|
||||
[4.907524351775825, 2.043055712211473],
|
||||
[3.0769604829149455, 1.6284171290602836],
|
||||
[-2.66472604008681, -4.228569719133945],
|
||||
[-6.450168189798415, -2.304577297733668],
|
||||
[-7.704241049212052, 4.416384506147983],
|
||||
[-6.361372181234263, 8.783101300254884],
|
||||
[-12.516984713388897, 10.9291595737194],
|
||||
[-12.295677738198286, 15.686226498407976],
|
||||
[-7.473371426945252, 15.393030178104425],
|
||||
[-3.787654025313423, 11.5207568827343],
|
||||
[1.2873793872375165, 19.910682356036197],
|
||||
[4.492232250183542, 20.212553123686025],
|
||||
[1.1302787567009416, 6.843494873631317],
|
||||
[6.294108177816019, 6.390688722156585],
|
||||
[8.070028349098962, 7.910451897221202],
|
||||
[14.143675334886687, 7.910451897221202],
|
||||
[15.709217270494545, 2.6780252579576427],
|
||||
[9.128749989671498, 3.1533849725326517],
|
||||
[10.393751588600717, -3.7167773257046695],
|
||||
[7.380151667177483, -3.30213874255348],
|
||||
[4.669824267311791, 1.1200945145694894],
|
||||
[4.907524351775825, 2.043055712211473],
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "line",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 90,
|
||||
angle: 0,
|
||||
x: -551.4394290784783,
|
||||
y: 385.71736850567976,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "#99bcff",
|
||||
width: 42.095115772272244,
|
||||
height: 0,
|
||||
seed: 1443027377,
|
||||
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
||||
strokeSharpness: "round",
|
||||
|
||||
points: [
|
||||
[0, 0],
|
||||
[42.095115772272244, 0],
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "line",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 0,
|
||||
opacity: 90,
|
||||
angle: 0,
|
||||
x: -546.3441000487039,
|
||||
y: 372.6245229061568,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "#99bcff",
|
||||
width: 29.31860660384862,
|
||||
height: 5.711199931375845,
|
||||
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
||||
strokeSharpness: "round",
|
||||
points: [
|
||||
[0, -2.341683327443203],
|
||||
[0.7724193963150375, -0.06510358900749044],
|
||||
[4.103544916365185, 1.84492589414448],
|
||||
[8.536129150893453, 3.0016281808630056],
|
||||
[15.480325949120388, 3.1070332647092163],
|
||||
[23.583965316012858, 2.3706131055211244],
|
||||
[28.316582284417855, -0.3084668090492442],
|
||||
[29.31860660384862, -2.6041666666666288],
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "ellipse",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 90,
|
||||
angle: 0,
|
||||
x: -538.2701841247845,
|
||||
y: 363.37196531290607,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "transparent",
|
||||
width: 15.528434353116108,
|
||||
height: 44.82230388130942,
|
||||
seed: 683572113,
|
||||
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
||||
strokeSharpness: "sharp",
|
||||
},
|
||||
{
|
||||
type: "line",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
opacity: 90,
|
||||
x: -544.828148539078,
|
||||
y: 402.0199316371545,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "#99bcff",
|
||||
width: 29.31860660384862,
|
||||
height: 5.896061363392446,
|
||||
seed: 318798801,
|
||||
groupIds: ["TC0RSM64Cxmu17MlE12-o"],
|
||||
strokeSharpness: "round",
|
||||
|
||||
points: [
|
||||
[0, 0],
|
||||
[4.103544916365185, -4.322122351104391],
|
||||
[8.536129150893453, -5.516265043290966],
|
||||
[15.480325949120388, -5.625081903117008],
|
||||
[23.583965316012858, -4.8648251269605955],
|
||||
[28.316582284417855, -2.0990281379671547],
|
||||
[29.31860660384862, 0.2709794602754383],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
type: "rectangle",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -715.1043446306466,
|
||||
y: 330.4231266309418,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "#ced4da",
|
||||
width: 70.81644178885557,
|
||||
height: 108.30428902193904,
|
||||
seed: 1914896753,
|
||||
groupIds: ["GMZ-NW9lG7c1AtfBInZ0n"],
|
||||
strokeSharpness: "sharp",
|
||||
},
|
||||
{
|
||||
type: "rectangle",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -706.996640540555,
|
||||
y: 338.68030798133873,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "#fff",
|
||||
width: 55.801163535143246,
|
||||
height: 82.83278895375764,
|
||||
seed: 1306468145,
|
||||
groupIds: ["GMZ-NW9lG7c1AtfBInZ0n"],
|
||||
strokeSharpness: "sharp",
|
||||
},
|
||||
{
|
||||
type: "ellipse",
|
||||
fillStyle: "solid",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -684.8099707762028,
|
||||
y: 425.0579911039235,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "#fff",
|
||||
width: 11.427824006438863,
|
||||
height: 11.427824006438863,
|
||||
seed: 93422161,
|
||||
groupIds: ["GMZ-NW9lG7c1AtfBInZ0n"],
|
||||
strokeSharpness: "sharp",
|
||||
},
|
||||
{
|
||||
type: "rectangle",
|
||||
fillStyle: "cross-hatch",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
angle: 0,
|
||||
x: -698.7169501405845,
|
||||
y: 349.2244646574789,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "#fab005",
|
||||
width: 39.2417827352022,
|
||||
height: 19.889460471185775,
|
||||
seed: 11646495,
|
||||
groupIds: ["GMZ-NW9lG7c1AtfBInZ0n"],
|
||||
strokeSharpness: "sharp",
|
||||
},
|
||||
{
|
||||
type: "rectangle",
|
||||
fillStyle: "cross-hatch",
|
||||
strokeWidth: 1,
|
||||
strokeStyle: "solid",
|
||||
x: -698.7169501405845,
|
||||
y: 384.7822247024333,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "#fab005",
|
||||
width: 39.2417827352022,
|
||||
height: 19.889460471185775,
|
||||
seed: 291717649,
|
||||
groupIds: ["GMZ-NW9lG7c1AtfBInZ0n"],
|
||||
strokeSharpness: "sharp",
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
13
examples/excalidraw/package.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"name": "examples",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"@excalidraw/excalidraw": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5"
|
||||
}
|
||||
}
|
3
examples/excalidraw/tsconfig.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"extends": "../../tsconfig"
|
||||
}
|
146
examples/excalidraw/utils.ts
Normal file
|
@ -0,0 +1,146 @@
|
|||
import { unstable_batchedUpdates } from "react-dom";
|
||||
import { fileOpen as _fileOpen } from "browser-fs-access";
|
||||
import type { MIME_TYPES } from "@excalidraw/excalidraw";
|
||||
import { AbortError } from "../../packages/excalidraw/errors";
|
||||
|
||||
type FILE_EXTENSION = Exclude<keyof typeof MIME_TYPES, "binary">;
|
||||
|
||||
const INPUT_CHANGE_INTERVAL_MS = 500;
|
||||
|
||||
export type ResolvablePromise<T> = Promise<T> & {
|
||||
resolve: [T] extends [undefined] ? (value?: T) => void : (value: T) => void;
|
||||
reject: (error: Error) => void;
|
||||
};
|
||||
export const resolvablePromise = <T>() => {
|
||||
let resolve!: any;
|
||||
let reject!: any;
|
||||
const promise = new Promise((_resolve, _reject) => {
|
||||
resolve = _resolve;
|
||||
reject = _reject;
|
||||
});
|
||||
(promise as any).resolve = resolve;
|
||||
(promise as any).reject = reject;
|
||||
return promise as ResolvablePromise<T>;
|
||||
};
|
||||
|
||||
export const distance2d = (x1: number, y1: number, x2: number, y2: number) => {
|
||||
const xd = x2 - x1;
|
||||
const yd = y2 - y1;
|
||||
return Math.hypot(xd, yd);
|
||||
};
|
||||
|
||||
export const fileOpen = <M extends boolean | undefined = false>(opts: {
|
||||
extensions?: FILE_EXTENSION[];
|
||||
description: string;
|
||||
multiple?: M;
|
||||
}): Promise<M extends false | undefined ? File : File[]> => {
|
||||
// an unsafe TS hack, alas not much we can do AFAIK
|
||||
type RetType = M extends false | undefined ? File : File[];
|
||||
|
||||
const mimeTypes = opts.extensions?.reduce((mimeTypes, type) => {
|
||||
mimeTypes.push(MIME_TYPES[type]);
|
||||
|
||||
return mimeTypes;
|
||||
}, [] as string[]);
|
||||
|
||||
const extensions = opts.extensions?.reduce((acc, ext) => {
|
||||
if (ext === "jpg") {
|
||||
return acc.concat(".jpg", ".jpeg");
|
||||
}
|
||||
return acc.concat(`.${ext}`);
|
||||
}, [] as string[]);
|
||||
|
||||
return _fileOpen({
|
||||
description: opts.description,
|
||||
extensions,
|
||||
mimeTypes,
|
||||
multiple: opts.multiple ?? false,
|
||||
legacySetup: (resolve, reject, input) => {
|
||||
const scheduleRejection = debounce(reject, INPUT_CHANGE_INTERVAL_MS);
|
||||
const focusHandler = () => {
|
||||
checkForFile();
|
||||
document.addEventListener("keyup", scheduleRejection);
|
||||
document.addEventListener("pointerup", scheduleRejection);
|
||||
scheduleRejection();
|
||||
};
|
||||
const checkForFile = () => {
|
||||
// this hack might not work when expecting multiple files
|
||||
if (input.files?.length) {
|
||||
const ret = opts.multiple ? [...input.files] : input.files[0];
|
||||
resolve(ret as RetType);
|
||||
}
|
||||
};
|
||||
requestAnimationFrame(() => {
|
||||
window.addEventListener("focus", focusHandler);
|
||||
});
|
||||
const interval = window.setInterval(() => {
|
||||
checkForFile();
|
||||
}, INPUT_CHANGE_INTERVAL_MS);
|
||||
return (rejectPromise) => {
|
||||
clearInterval(interval);
|
||||
scheduleRejection.cancel();
|
||||
window.removeEventListener("focus", focusHandler);
|
||||
document.removeEventListener("keyup", scheduleRejection);
|
||||
document.removeEventListener("pointerup", scheduleRejection);
|
||||
if (rejectPromise) {
|
||||
// so that something is shown in console if we need to debug this
|
||||
console.warn("Opening the file was canceled (legacy-fs).");
|
||||
rejectPromise(new AbortError());
|
||||
}
|
||||
};
|
||||
},
|
||||
}) as Promise<RetType>;
|
||||
};
|
||||
|
||||
export const debounce = <T extends any[]>(
|
||||
fn: (...args: T) => void,
|
||||
timeout: number,
|
||||
) => {
|
||||
let handle = 0;
|
||||
let lastArgs: T | null = null;
|
||||
const ret = (...args: T) => {
|
||||
lastArgs = args;
|
||||
clearTimeout(handle);
|
||||
handle = window.setTimeout(() => {
|
||||
lastArgs = null;
|
||||
fn(...args);
|
||||
}, timeout);
|
||||
};
|
||||
ret.flush = () => {
|
||||
clearTimeout(handle);
|
||||
if (lastArgs) {
|
||||
const _lastArgs = lastArgs;
|
||||
lastArgs = null;
|
||||
fn(..._lastArgs);
|
||||
}
|
||||
};
|
||||
ret.cancel = () => {
|
||||
lastArgs = null;
|
||||
clearTimeout(handle);
|
||||
};
|
||||
return ret;
|
||||
};
|
||||
|
||||
export const withBatchedUpdates = <
|
||||
TFunction extends ((event: any) => void) | (() => void),
|
||||
>(
|
||||
func: Parameters<TFunction>["length"] extends 0 | 1 ? TFunction : never,
|
||||
) =>
|
||||
((event) => {
|
||||
unstable_batchedUpdates(func as TFunction, event);
|
||||
}) as TFunction;
|
||||
|
||||
/**
|
||||
* barches React state updates and throttles the calls to a single call per
|
||||
* animation frame
|
||||
*/
|
||||
export const withBatchedUpdatesThrottled = <
|
||||
TFunction extends ((event: any) => void) | (() => void),
|
||||
>(
|
||||
func: Parameters<TFunction>["length"] extends 0 | 1 ? TFunction : never,
|
||||
) => {
|
||||
// @ts-ignore
|
||||
return throttleRAF<Parameters<TFunction>>(((event) => {
|
||||
unstable_batchedUpdates(func, event);
|
||||
}) as TFunction);
|
||||
};
|
36
examples/excalidraw/with-nextjs/.gitignore
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
.yarn/install-state.gz
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
36
examples/excalidraw/with-nextjs/README.md
Normal file
|
@ -0,0 +1,36 @@
|
|||
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
|
||||
|
||||
## Getting Started
|
||||
|
||||
First, run the development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
# or
|
||||
yarn dev
|
||||
# or
|
||||
pnpm dev
|
||||
# or
|
||||
bun dev
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3005) with your browser to see the result.
|
||||
|
||||
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
||||
|
||||
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
|
||||
|
||||
## Learn More
|
||||
|
||||
To learn more about Next.js, take a look at the following resources:
|
||||
|
||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||
|
||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
|
||||
|
||||
## Deploy on Vercel
|
||||
|
||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||
|
||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
|
12
examples/excalidraw/with-nextjs/next.config.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
distDir: "build",
|
||||
typescript: {
|
||||
// The ts config doesn't work with `jsx: preserve" and if updated to `react-jsx` it gets ovewritten by next js throwing ts errors hence I am ignoring build errors until this is fixed.
|
||||
ignoreBuildErrors: true,
|
||||
},
|
||||
// This is needed as in pages router the code for importing types throws error as its outside next js app
|
||||
transpilePackages: ["../"],
|
||||
};
|
||||
|
||||
module.exports = nextConfig;
|
25
examples/excalidraw/with-nextjs/package.json
Normal file
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"name": "with-nextjs",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build:workspace": "yarn workspace @excalidraw/excalidraw run build:esm",
|
||||
"dev": "yarn build:workspace && next dev -p 3005",
|
||||
"build": "yarn build:workspace && next build",
|
||||
"start": "next start -p 3006",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@excalidraw/excalidraw": "*",
|
||||
"next": "14.1",
|
||||
"react": "^18",
|
||||
"react-dom": "^18"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^18",
|
||||
"@types/react-dom": "^18",
|
||||
"path2d-polyfill": "2.0.1",
|
||||
"typescript": "^5"
|
||||
}
|
||||
}
|
BIN
examples/excalidraw/with-nextjs/public/images/doremon.png
Normal file
After Width: | Height: | Size: 197 KiB |
BIN
examples/excalidraw/with-nextjs/public/images/excalibot.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
examples/excalidraw/with-nextjs/public/images/pika.jpeg
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
examples/excalidraw/with-nextjs/public/images/rocket.jpeg
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
examples/excalidraw/with-nextjs/src/app/favicon.ico
Normal file
After Width: | Height: | Size: 25 KiB |
11
examples/excalidraw/with-nextjs/src/app/layout.tsx
Normal file
|
@ -0,0 +1,11 @@
|
|||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
23
examples/excalidraw/with-nextjs/src/app/page.tsx
Normal file
|
@ -0,0 +1,23 @@
|
|||
import dynamic from "next/dynamic";
|
||||
import "../common.scss";
|
||||
|
||||
// Since client components get prerenderd on server as well hence importing the excalidraw stuff dynamically
|
||||
// with ssr false
|
||||
const ExcalidrawWithClientOnly = dynamic(
|
||||
async () => (await import("../excalidrawWrapper")).default,
|
||||
{
|
||||
ssr: false,
|
||||
},
|
||||
);
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<>
|
||||
<a href="/excalidraw-in-pages">Switch to Pages router</a>
|
||||
<h1 className="page-title">App Router</h1>
|
||||
|
||||
{/* @ts-expect-error - https://github.com/vercel/next.js/issues/42292 */}
|
||||
<ExcalidrawWithClientOnly />
|
||||
</>
|
||||
);
|
||||
}
|
15
examples/excalidraw/with-nextjs/src/common.scss
Normal file
|
@ -0,0 +1,15 @@
|
|||
* {
|
||||
box-sizing: border-box;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #1c7ed6;
|
||||
font-size: 20px;
|
||||
text-decoration: none;
|
||||
font-weight: 550;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
text-align: center;
|
||||
}
|
22
examples/excalidraw/with-nextjs/src/excalidrawWrapper.tsx
Normal file
|
@ -0,0 +1,22 @@
|
|||
"use client";
|
||||
import * as excalidrawLib from "@excalidraw/excalidraw";
|
||||
import { Excalidraw } from "@excalidraw/excalidraw";
|
||||
import App from "../../components/App";
|
||||
|
||||
import "@excalidraw/excalidraw/index.css";
|
||||
|
||||
const ExcalidrawWrapper: React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
<App
|
||||
appTitle={"Excalidraw with Nextjs Example"}
|
||||
useCustom={(api: any, args?: any[]) => {}}
|
||||
excalidrawLib={excalidrawLib}
|
||||
>
|
||||
<Excalidraw />
|
||||
</App>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExcalidrawWrapper;
|
|
@ -0,0 +1,22 @@
|
|||
import dynamic from "next/dynamic";
|
||||
import "../common.scss";
|
||||
|
||||
// Since client components get prerenderd on server as well hence importing the excalidraw stuff dynamically
|
||||
// with ssr false
|
||||
const Excalidraw = dynamic(
|
||||
async () => (await import("../excalidrawWrapper")).default,
|
||||
{
|
||||
ssr: false,
|
||||
},
|
||||
);
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<>
|
||||
<a href="/">Switch to App router</a>
|
||||
<h1 className="page-title">Pages Router</h1>
|
||||
{/* @ts-expect-error - https://github.com/vercel/next.js/issues/42292 */}
|
||||
<Excalidraw />
|
||||
</>
|
||||
);
|
||||
}
|
28
examples/excalidraw/with-nextjs/tsconfig.json
Normal file
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"incremental": true,
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
},
|
||||
"forceConsistentCasingInFileNames": true
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "build/types/**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
3
examples/excalidraw/with-nextjs/vercel.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"outputDirectory": "build"
|
||||
}
|
252
examples/excalidraw/with-nextjs/yarn.lock
Normal file
|
@ -0,0 +1,252 @@
|
|||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@excalidraw/excalidraw@workspace:^":
|
||||
version "0.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@excalidraw/excalidraw/-/excalidraw-0.17.2.tgz#9a636a1e6bb3c88c5883347d3a7e75e9cce8ab96"
|
||||
integrity sha512-7pqUWD8+mPjDhF4XxG3gw4rvE2JGaLW3Vss5UZfTbITPxAtFaGEc1K081bncitnaYhUwN9ENJE0i87QB3poDwQ==
|
||||
|
||||
"@next/env@14.0.4":
|
||||
version "14.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-14.0.4.tgz#d5cda0c4a862d70ae760e58c0cd96a8899a2e49a"
|
||||
integrity sha512-irQnbMLbUNQpP1wcE5NstJtbuA/69kRfzBrpAD7Gsn8zm/CY6YQYc3HQBz8QPxwISG26tIm5afvvVbu508oBeQ==
|
||||
|
||||
"@next/swc-darwin-arm64@14.0.4":
|
||||
version "14.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.0.4.tgz#27b1854c2cd04eb1d5e75081a1a792ad91526618"
|
||||
integrity sha512-mF05E/5uPthWzyYDyptcwHptucf/jj09i2SXBPwNzbgBNc+XnwzrL0U6BmPjQeOL+FiB+iG1gwBeq7mlDjSRPg==
|
||||
|
||||
"@next/swc-darwin-x64@14.0.4":
|
||||
version "14.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.0.4.tgz#9940c449e757d0ee50bb9e792d2600cc08a3eb3b"
|
||||
integrity sha512-IZQ3C7Bx0k2rYtrZZxKKiusMTM9WWcK5ajyhOZkYYTCc8xytmwSzR1skU7qLgVT/EY9xtXDG0WhY6fyujnI3rw==
|
||||
|
||||
"@next/swc-linux-arm64-gnu@14.0.4":
|
||||
version "14.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.0.4.tgz#0eafd27c8587f68ace7b4fa80695711a8434de21"
|
||||
integrity sha512-VwwZKrBQo/MGb1VOrxJ6LrKvbpo7UbROuyMRvQKTFKhNaXjUmKTu7wxVkIuCARAfiI8JpaWAnKR+D6tzpCcM4w==
|
||||
|
||||
"@next/swc-linux-arm64-musl@14.0.4":
|
||||
version "14.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.0.4.tgz#2b0072adb213f36dada5394ea67d6e82069ae7dd"
|
||||
integrity sha512-8QftwPEW37XxXoAwsn+nXlodKWHfpMaSvt81W43Wh8dv0gkheD+30ezWMcFGHLI71KiWmHK5PSQbTQGUiidvLQ==
|
||||
|
||||
"@next/swc-linux-x64-gnu@14.0.4":
|
||||
version "14.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.0.4.tgz#68c67d20ebc8e3f6ced6ff23a4ba2a679dbcec32"
|
||||
integrity sha512-/s/Pme3VKfZAfISlYVq2hzFS8AcAIOTnoKupc/j4WlvF6GQ0VouS2Q2KEgPuO1eMBwakWPB1aYFIA4VNVh667A==
|
||||
|
||||
"@next/swc-linux-x64-musl@14.0.4":
|
||||
version "14.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.0.4.tgz#67cd81b42fb2caf313f7992fcf6d978af55a1247"
|
||||
integrity sha512-m8z/6Fyal4L9Bnlxde5g2Mfa1Z7dasMQyhEhskDATpqr+Y0mjOBZcXQ7G5U+vgL22cI4T7MfvgtrM2jdopqWaw==
|
||||
|
||||
"@next/swc-win32-arm64-msvc@14.0.4":
|
||||
version "14.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.0.4.tgz#be06585906b195d755ceda28f33c633e1443f1a3"
|
||||
integrity sha512-7Wv4PRiWIAWbm5XrGz3D8HUkCVDMMz9igffZG4NB1p4u1KoItwx9qjATHz88kwCEal/HXmbShucaslXCQXUM5w==
|
||||
|
||||
"@next/swc-win32-ia32-msvc@14.0.4":
|
||||
version "14.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.0.4.tgz#e76cabefa9f2d891599c3d85928475bd8d3f6600"
|
||||
integrity sha512-zLeNEAPULsl0phfGb4kdzF/cAVIfaC7hY+kt0/d+y9mzcZHsMS3hAS829WbJ31DkSlVKQeHEjZHIdhN+Pg7Gyg==
|
||||
|
||||
"@next/swc-win32-x64-msvc@14.0.4":
|
||||
version "14.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.0.4.tgz#e74892f1a9ccf41d3bf5979ad6d3d77c07b9cba1"
|
||||
integrity sha512-yEh2+R8qDlDCjxVpzOTEpBLQTEFAcP2A8fUFLaWNap9GitYKkKv1//y2S6XY6zsR4rCOPRpU7plYDR+az2n30A==
|
||||
|
||||
"@swc/helpers@0.5.2":
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.2.tgz#85ea0c76450b61ad7d10a37050289eded783c27d"
|
||||
integrity sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==
|
||||
dependencies:
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@types/node@^20":
|
||||
version "20.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.0.tgz#8e0b99e70c0c1ade1a86c4a282f7b7ef87c9552f"
|
||||
integrity sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==
|
||||
dependencies:
|
||||
undici-types "~5.26.4"
|
||||
|
||||
"@types/prop-types@*":
|
||||
version "15.7.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.11.tgz#2596fb352ee96a1379c657734d4b913a613ad563"
|
||||
integrity sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==
|
||||
|
||||
"@types/react-dom@^18":
|
||||
version "18.2.18"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.18.tgz#16946e6cd43971256d874bc3d0a72074bb8571dd"
|
||||
integrity sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react@*", "@types/react@^18":
|
||||
version "18.2.47"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.47.tgz#85074b27ab563df01fbc3f68dc64bf7050b0af40"
|
||||
integrity sha512-xquNkkOirwyCgoClNk85BjP+aqnIS+ckAJ8i37gAbDs14jfW/J23f2GItAf33oiUPQnqNMALiFeoM9Y5mbjpVQ==
|
||||
dependencies:
|
||||
"@types/prop-types" "*"
|
||||
"@types/scheduler" "*"
|
||||
csstype "^3.0.2"
|
||||
|
||||
"@types/scheduler@*":
|
||||
version "0.16.8"
|
||||
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.8.tgz#ce5ace04cfeabe7ef87c0091e50752e36707deff"
|
||||
integrity sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==
|
||||
|
||||
busboy@1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893"
|
||||
integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==
|
||||
dependencies:
|
||||
streamsearch "^1.1.0"
|
||||
|
||||
caniuse-lite@^1.0.30001406:
|
||||
version "1.0.30001576"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001576.tgz#893be772cf8ee6056d6c1e2d07df365b9ec0a5c4"
|
||||
integrity sha512-ff5BdakGe2P3SQsMsiqmt1Lc8221NR1VzHj5jXN5vBny9A6fpze94HiVV/n7XRosOlsShJcvMv5mdnpjOGCEgg==
|
||||
|
||||
client-only@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1"
|
||||
integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==
|
||||
|
||||
csstype@^3.0.2:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
|
||||
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
|
||||
|
||||
glob-to-regexp@^0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
|
||||
integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
|
||||
|
||||
graceful-fs@^4.1.2, graceful-fs@^4.2.11:
|
||||
version "4.2.11"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
|
||||
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
|
||||
|
||||
"js-tokens@^3.0.0 || ^4.0.0":
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||
|
||||
loose-envify@^1.1.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
||||
dependencies:
|
||||
js-tokens "^3.0.0 || ^4.0.0"
|
||||
|
||||
nanoid@^3.3.6:
|
||||
version "3.3.7"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
|
||||
integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
|
||||
|
||||
next@14.0.4:
|
||||
version "14.0.4"
|
||||
resolved "https://registry.yarnpkg.com/next/-/next-14.0.4.tgz#bf00b6f835b20d10a5057838fa2dfced1d0d84dc"
|
||||
integrity sha512-qbwypnM7327SadwFtxXnQdGiKpkuhaRLE2uq62/nRul9cj9KhQ5LhHmlziTNqUidZotw/Q1I9OjirBROdUJNgA==
|
||||
dependencies:
|
||||
"@next/env" "14.0.4"
|
||||
"@swc/helpers" "0.5.2"
|
||||
busboy "1.6.0"
|
||||
caniuse-lite "^1.0.30001406"
|
||||
graceful-fs "^4.2.11"
|
||||
postcss "8.4.31"
|
||||
styled-jsx "5.1.1"
|
||||
watchpack "2.4.0"
|
||||
optionalDependencies:
|
||||
"@next/swc-darwin-arm64" "14.0.4"
|
||||
"@next/swc-darwin-x64" "14.0.4"
|
||||
"@next/swc-linux-arm64-gnu" "14.0.4"
|
||||
"@next/swc-linux-arm64-musl" "14.0.4"
|
||||
"@next/swc-linux-x64-gnu" "14.0.4"
|
||||
"@next/swc-linux-x64-musl" "14.0.4"
|
||||
"@next/swc-win32-arm64-msvc" "14.0.4"
|
||||
"@next/swc-win32-ia32-msvc" "14.0.4"
|
||||
"@next/swc-win32-x64-msvc" "14.0.4"
|
||||
|
||||
path2d-polyfill@2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/path2d-polyfill/-/path2d-polyfill-2.0.1.tgz#24c554a738f42700d6961992bf5f1049672f2391"
|
||||
integrity sha512-ad/3bsalbbWhmBo0D6FZ4RNMwsLsPpL6gnvhuSaU5Vm7b06Kr5ubSltQQ0T7YKsiJQO+g22zJ4dJKNTXIyOXtA==
|
||||
|
||||
picocolors@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
|
||||
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
|
||||
|
||||
postcss@8.4.31:
|
||||
version "8.4.31"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d"
|
||||
integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==
|
||||
dependencies:
|
||||
nanoid "^3.3.6"
|
||||
picocolors "^1.0.0"
|
||||
source-map-js "^1.0.2"
|
||||
|
||||
react-dom@^18:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
|
||||
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
scheduler "^0.23.0"
|
||||
|
||||
react@^18:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
|
||||
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
|
||||
scheduler@^0.23.0:
|
||||
version "0.23.0"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
|
||||
integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
|
||||
source-map-js@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
|
||||
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
|
||||
|
||||
streamsearch@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764"
|
||||
integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
|
||||
|
||||
styled-jsx@5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f"
|
||||
integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==
|
||||
dependencies:
|
||||
client-only "0.0.1"
|
||||
|
||||
tslib@^2.4.0:
|
||||
version "2.6.2"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
|
||||
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
|
||||
|
||||
typescript@^5:
|
||||
version "5.3.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37"
|
||||
integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==
|
||||
|
||||
undici-types@~5.26.4:
|
||||
version "5.26.5"
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
|
||||
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
|
||||
|
||||
watchpack@2.4.0:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d"
|
||||
integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==
|
||||
dependencies:
|
||||
glob-to-regexp "^0.4.1"
|
||||
graceful-fs "^4.1.2"
|
32
examples/excalidraw/with-script-in-browser/index.html
Normal file
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
||||
/>
|
||||
<meta name="theme-color" content="#000000" />
|
||||
|
||||
<title>React App</title>
|
||||
<script>
|
||||
window.name = "codesandbox";
|
||||
</script>
|
||||
<link rel="stylesheet" href="/dist/browser/dev/index.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<noscript> You need to enable JavaScript to run this app. </noscript>
|
||||
<div id="root"></div>
|
||||
|
||||
<!-- This is so that we use the bundled excalidraw.development.js file instead
|
||||
of the actual source code -->
|
||||
<script type="module">
|
||||
import * as ExcalidrawLib from "@excalidraw/excalidraw";
|
||||
|
||||
console.log(ExcalidrawLib);
|
||||
window.ExcalidrawLib = ExcalidrawLib;
|
||||
</script>
|
||||
<script type="module" src="index.tsx"></script>
|
||||
</body>
|
||||
</html>
|
28
examples/excalidraw/with-script-in-browser/index.tsx
Normal file
|
@ -0,0 +1,28 @@
|
|||
import App from "../components/App";
|
||||
import React, { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
|
||||
import type * as TExcalidraw from "@excalidraw/excalidraw";
|
||||
|
||||
import "@excalidraw/excalidraw/index.css";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
ExcalidrawLib: typeof TExcalidraw;
|
||||
}
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById("root")!;
|
||||
const root = createRoot(rootElement);
|
||||
const { Excalidraw } = window.ExcalidrawLib;
|
||||
root.render(
|
||||
<StrictMode>
|
||||
<App
|
||||
appTitle={"Excalidraw Example"}
|
||||
useCustom={(api: any, args?: any[]) => {}}
|
||||
excalidrawLib={window.ExcalidrawLib}
|
||||
>
|
||||
<Excalidraw />
|
||||
</App>
|
||||
</StrictMode>,
|
||||
);
|
19
examples/excalidraw/with-script-in-browser/package.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "with-script-in-browser",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"@excalidraw/excalidraw": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "5.0.6",
|
||||
"typescript": "^5"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "yarn workspace @excalidraw/excalidraw run build:esm && vite",
|
||||
"build": "yarn workspace @excalidraw/excalidraw run build:esm && vite build",
|
||||
"build:preview": "yarn build && vite preview --port 5002"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 197 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 39 KiB |
4
examples/excalidraw/with-script-in-browser/vercel.json
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"outputDirectory": "dist",
|
||||
"installCommand": "yarn install"
|
||||
}
|
11
examples/excalidraw/with-script-in-browser/vite.config.mts
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { defineConfig } from "vite";
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
server: {
|
||||
port: 3001,
|
||||
// open the browser
|
||||
open: true,
|
||||
},
|
||||
publicDir: "public",
|
||||
});
|
313
examples/excalidraw/yarn.lock
Normal file
|
@ -0,0 +1,313 @@
|
|||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@esbuild/aix-ppc64@0.19.11":
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.19.11.tgz#2acd20be6d4f0458bc8c784103495ff24f13b1d3"
|
||||
integrity sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==
|
||||
|
||||
"@esbuild/android-arm64@0.19.11":
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.19.11.tgz#b45d000017385c9051a4f03e17078abb935be220"
|
||||
integrity sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==
|
||||
|
||||
"@esbuild/android-arm@0.19.11":
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.19.11.tgz#f46f55414e1c3614ac682b29977792131238164c"
|
||||
integrity sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==
|
||||
|
||||
"@esbuild/android-x64@0.19.11":
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.19.11.tgz#bfc01e91740b82011ef503c48f548950824922b2"
|
||||
integrity sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==
|
||||
|
||||
"@esbuild/darwin-arm64@0.19.11":
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.19.11.tgz#533fb7f5a08c37121d82c66198263dcc1bed29bf"
|
||||
integrity sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==
|
||||
|
||||
"@esbuild/darwin-x64@0.19.11":
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.19.11.tgz#62f3819eff7e4ddc656b7c6815a31cf9a1e7d98e"
|
||||
integrity sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==
|
||||
|
||||
"@esbuild/freebsd-arm64@0.19.11":
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.11.tgz#d478b4195aa3ca44160272dab85ef8baf4175b4a"
|
||||
integrity sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==
|
||||
|
||||
"@esbuild/freebsd-x64@0.19.11":
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.19.11.tgz#7bdcc1917409178257ca6a1a27fe06e797ec18a2"
|
||||
integrity sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==
|
||||
|
||||
"@esbuild/linux-arm64@0.19.11":
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.19.11.tgz#58ad4ff11685fcc735d7ff4ca759ab18fcfe4545"
|
||||
integrity sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==
|
||||
|
||||
"@esbuild/linux-arm@0.19.11":
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.19.11.tgz#ce82246d873b5534d34de1e5c1b33026f35e60e3"
|
||||
integrity sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==
|
||||
|
||||
"@esbuild/linux-ia32@0.19.11":
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.19.11.tgz#cbae1f313209affc74b80f4390c4c35c6ab83fa4"
|
||||
integrity sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==
|
||||
|
||||
"@esbuild/linux-loong64@0.19.11":
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.19.11.tgz#5f32aead1c3ec8f4cccdb7ed08b166224d4e9121"
|
||||
integrity sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==
|
||||
|
||||
"@esbuild/linux-mips64el@0.19.11":
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.19.11.tgz#38eecf1cbb8c36a616261de858b3c10d03419af9"
|
||||
integrity sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==
|
||||
|
||||
"@esbuild/linux-ppc64@0.19.11":
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.19.11.tgz#9c5725a94e6ec15b93195e5a6afb821628afd912"
|
||||
integrity sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==
|
||||
|
||||
"@esbuild/linux-riscv64@0.19.11":
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.19.11.tgz#2dc4486d474a2a62bbe5870522a9a600e2acb916"
|
||||
integrity sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==
|
||||
|
||||
"@esbuild/linux-s390x@0.19.11":
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.19.11.tgz#4ad8567df48f7dd4c71ec5b1753b6f37561a65a8"
|
||||
integrity sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==
|
||||
|
||||
"@esbuild/linux-x64@0.19.11":
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.19.11.tgz#b7390c4d5184f203ebe7ddaedf073df82a658766"
|
||||
integrity sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==
|
||||
|
||||
"@esbuild/netbsd-x64@0.19.11":
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.19.11.tgz#d633c09492a1721377f3bccedb2d821b911e813d"
|
||||
integrity sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==
|
||||
|
||||
"@esbuild/openbsd-x64@0.19.11":
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.19.11.tgz#17388c76e2f01125bf831a68c03a7ffccb65d1a2"
|
||||
integrity sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==
|
||||
|
||||
"@esbuild/sunos-x64@0.19.11":
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.19.11.tgz#e320636f00bb9f4fdf3a80e548cb743370d41767"
|
||||
integrity sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==
|
||||
|
||||
"@esbuild/win32-arm64@0.19.11":
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.19.11.tgz#c778b45a496e90b6fc373e2a2bb072f1441fe0ee"
|
||||
integrity sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==
|
||||
|
||||
"@esbuild/win32-ia32@0.19.11":
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.19.11.tgz#481a65fee2e5cce74ec44823e6b09ecedcc5194c"
|
||||
integrity sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==
|
||||
|
||||
"@esbuild/win32-x64@0.19.11":
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.11.tgz#a5d300008960bb39677c46bf16f53ec70d8dee04"
|
||||
integrity sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==
|
||||
|
||||
"@rollup/rollup-android-arm-eabi@4.9.5":
|
||||
version "4.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.5.tgz#b752b6c88a14ccfcbdf3f48c577ccc3a7f0e66b9"
|
||||
integrity sha512-idWaG8xeSRCfRq9KpRysDHJ/rEHBEXcHuJ82XY0yYFIWnLMjZv9vF/7DOq8djQ2n3Lk6+3qfSH8AqlmHlmi1MA==
|
||||
|
||||
"@rollup/rollup-android-arm64@4.9.5":
|
||||
version "4.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.5.tgz#33757c3a448b9ef77b6f6292d8b0ec45c87e9c1a"
|
||||
integrity sha512-f14d7uhAMtsCGjAYwZGv6TwuS3IFaM4ZnGMUn3aCBgkcHAYErhV1Ad97WzBvS2o0aaDv4mVz+syiN0ElMyfBPg==
|
||||
|
||||
"@rollup/rollup-darwin-arm64@4.9.5":
|
||||
version "4.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.5.tgz#5234ba62665a3f443143bc8bcea9df2cc58f55fb"
|
||||
integrity sha512-ndoXeLx455FffL68OIUrVr89Xu1WLzAG4n65R8roDlCoYiQcGGg6MALvs2Ap9zs7AHg8mpHtMpwC8jBBjZrT/w==
|
||||
|
||||
"@rollup/rollup-darwin-x64@4.9.5":
|
||||
version "4.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.5.tgz#981256c054d3247b83313724938d606798a919d1"
|
||||
integrity sha512-UmElV1OY2m/1KEEqTlIjieKfVwRg0Zwg4PLgNf0s3glAHXBN99KLpw5A5lrSYCa1Kp63czTpVll2MAqbZYIHoA==
|
||||
|
||||
"@rollup/rollup-linux-arm-gnueabihf@4.9.5":
|
||||
version "4.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.5.tgz#120678a5a2b3a283a548dbb4d337f9187a793560"
|
||||
integrity sha512-Q0LcU61v92tQB6ae+udZvOyZ0wfpGojtAKrrpAaIqmJ7+psq4cMIhT/9lfV6UQIpeItnq/2QDROhNLo00lOD1g==
|
||||
|
||||
"@rollup/rollup-linux-arm64-gnu@4.9.5":
|
||||
version "4.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.5.tgz#c99d857e2372ece544b6f60b85058ad259f64114"
|
||||
integrity sha512-dkRscpM+RrR2Ee3eOQmRWFjmV/payHEOrjyq1VZegRUa5OrZJ2MAxBNs05bZuY0YCtpqETDy1Ix4i/hRqX98cA==
|
||||
|
||||
"@rollup/rollup-linux-arm64-musl@4.9.5":
|
||||
version "4.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.5.tgz#3064060f568a5718c2a06858cd6e6d24f2ff8632"
|
||||
integrity sha512-QaKFVOzzST2xzY4MAmiDmURagWLFh+zZtttuEnuNn19AiZ0T3fhPyjPPGwLNdiDT82ZE91hnfJsUiDwF9DClIQ==
|
||||
|
||||
"@rollup/rollup-linux-riscv64-gnu@4.9.5":
|
||||
version "4.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.5.tgz#987d30b5d2b992fff07d055015991a57ff55fbad"
|
||||
integrity sha512-HeGqmRJuyVg6/X6MpE2ur7GbymBPS8Np0S/vQFHDmocfORT+Zt76qu+69NUoxXzGqVP1pzaY6QIi0FJWLC3OPA==
|
||||
|
||||
"@rollup/rollup-linux-x64-gnu@4.9.5":
|
||||
version "4.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.5.tgz#85946ee4d068bd12197aeeec2c6f679c94978a49"
|
||||
integrity sha512-Dq1bqBdLaZ1Gb/l2e5/+o3B18+8TI9ANlA1SkejZqDgdU/jK/ThYaMPMJpVMMXy2uRHvGKbkz9vheVGdq3cJfA==
|
||||
|
||||
"@rollup/rollup-linux-x64-musl@4.9.5":
|
||||
version "4.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.5.tgz#fe0b20f9749a60eb1df43d20effa96c756ddcbd4"
|
||||
integrity sha512-ezyFUOwldYpj7AbkwyW9AJ203peub81CaAIVvckdkyH8EvhEIoKzaMFJj0G4qYJ5sw3BpqhFrsCc30t54HV8vg==
|
||||
|
||||
"@rollup/rollup-win32-arm64-msvc@4.9.5":
|
||||
version "4.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.5.tgz#422661ef0e16699a234465d15b2c1089ef963b2a"
|
||||
integrity sha512-aHSsMnUw+0UETB0Hlv7B/ZHOGY5bQdwMKJSzGfDfvyhnpmVxLMGnQPGNE9wgqkLUs3+gbG1Qx02S2LLfJ5GaRQ==
|
||||
|
||||
"@rollup/rollup-win32-ia32-msvc@4.9.5":
|
||||
version "4.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.5.tgz#7b73a145891c202fbcc08759248983667a035d85"
|
||||
integrity sha512-AiqiLkb9KSf7Lj/o1U3SEP9Zn+5NuVKgFdRIZkvd4N0+bYrTOovVd0+LmYCPQGbocT4kvFyK+LXCDiXPBF3fyA==
|
||||
|
||||
"@rollup/rollup-win32-x64-msvc@4.9.5":
|
||||
version "4.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.5.tgz#10491ccf4f63c814d4149e0316541476ea603602"
|
||||
integrity sha512-1q+mykKE3Vot1kaFJIDoUFv5TuW+QQVaf2FmTT9krg86pQrGStOSJJ0Zil7CFagyxDuouTepzt5Y5TVzyajOdQ==
|
||||
|
||||
"@types/estree@1.0.5":
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4"
|
||||
integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==
|
||||
|
||||
esbuild@^0.19.3:
|
||||
version "0.19.11"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.19.11.tgz#4a02dca031e768b5556606e1b468fe72e3325d96"
|
||||
integrity sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==
|
||||
optionalDependencies:
|
||||
"@esbuild/aix-ppc64" "0.19.11"
|
||||
"@esbuild/android-arm" "0.19.11"
|
||||
"@esbuild/android-arm64" "0.19.11"
|
||||
"@esbuild/android-x64" "0.19.11"
|
||||
"@esbuild/darwin-arm64" "0.19.11"
|
||||
"@esbuild/darwin-x64" "0.19.11"
|
||||
"@esbuild/freebsd-arm64" "0.19.11"
|
||||
"@esbuild/freebsd-x64" "0.19.11"
|
||||
"@esbuild/linux-arm" "0.19.11"
|
||||
"@esbuild/linux-arm64" "0.19.11"
|
||||
"@esbuild/linux-ia32" "0.19.11"
|
||||
"@esbuild/linux-loong64" "0.19.11"
|
||||
"@esbuild/linux-mips64el" "0.19.11"
|
||||
"@esbuild/linux-ppc64" "0.19.11"
|
||||
"@esbuild/linux-riscv64" "0.19.11"
|
||||
"@esbuild/linux-s390x" "0.19.11"
|
||||
"@esbuild/linux-x64" "0.19.11"
|
||||
"@esbuild/netbsd-x64" "0.19.11"
|
||||
"@esbuild/openbsd-x64" "0.19.11"
|
||||
"@esbuild/sunos-x64" "0.19.11"
|
||||
"@esbuild/win32-arm64" "0.19.11"
|
||||
"@esbuild/win32-ia32" "0.19.11"
|
||||
"@esbuild/win32-x64" "0.19.11"
|
||||
|
||||
fsevents@~2.3.2, fsevents@~2.3.3:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
|
||||
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
|
||||
|
||||
"js-tokens@^3.0.0 || ^4.0.0":
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||
|
||||
loose-envify@^1.1.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
||||
dependencies:
|
||||
js-tokens "^3.0.0 || ^4.0.0"
|
||||
|
||||
nanoid@^3.3.7:
|
||||
version "3.3.7"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
|
||||
integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
|
||||
|
||||
picocolors@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
|
||||
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
|
||||
|
||||
postcss@^8.4.32:
|
||||
version "8.4.33"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.33.tgz#1378e859c9f69bf6f638b990a0212f43e2aaa742"
|
||||
integrity sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==
|
||||
dependencies:
|
||||
nanoid "^3.3.7"
|
||||
picocolors "^1.0.0"
|
||||
source-map-js "^1.0.2"
|
||||
|
||||
react-dom@18.2.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
|
||||
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
scheduler "^0.23.0"
|
||||
|
||||
react@18.2.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
|
||||
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
|
||||
rollup@^4.2.0:
|
||||
version "4.9.5"
|
||||
resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.9.5.tgz#62999462c90f4c8b5d7c38fc7161e63b29101b05"
|
||||
integrity sha512-E4vQW0H/mbNMw2yLSqJyjtkHY9dslf/p0zuT1xehNRqUTBOFMqEjguDvqhXr7N7r/4ttb2jr4T41d3dncmIgbQ==
|
||||
dependencies:
|
||||
"@types/estree" "1.0.5"
|
||||
optionalDependencies:
|
||||
"@rollup/rollup-android-arm-eabi" "4.9.5"
|
||||
"@rollup/rollup-android-arm64" "4.9.5"
|
||||
"@rollup/rollup-darwin-arm64" "4.9.5"
|
||||
"@rollup/rollup-darwin-x64" "4.9.5"
|
||||
"@rollup/rollup-linux-arm-gnueabihf" "4.9.5"
|
||||
"@rollup/rollup-linux-arm64-gnu" "4.9.5"
|
||||
"@rollup/rollup-linux-arm64-musl" "4.9.5"
|
||||
"@rollup/rollup-linux-riscv64-gnu" "4.9.5"
|
||||
"@rollup/rollup-linux-x64-gnu" "4.9.5"
|
||||
"@rollup/rollup-linux-x64-musl" "4.9.5"
|
||||
"@rollup/rollup-win32-arm64-msvc" "4.9.5"
|
||||
"@rollup/rollup-win32-ia32-msvc" "4.9.5"
|
||||
"@rollup/rollup-win32-x64-msvc" "4.9.5"
|
||||
fsevents "~2.3.2"
|
||||
|
||||
scheduler@^0.23.0:
|
||||
version "0.23.0"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
|
||||
integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
|
||||
source-map-js@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
|
||||
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
|
||||
|
||||
vite@5.0.6:
|
||||
version "5.0.6"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-5.0.6.tgz#f9e13503a4c5ccd67312c67803dec921f3bdea7c"
|
||||
integrity sha512-MD3joyAEBtV7QZPl2JVVUai6zHms3YOmLR+BpMzLlX2Yzjfcc4gTgNi09d/Rua3F4EtC8zdwPU8eQYyib4vVMQ==
|
||||
dependencies:
|
||||
esbuild "^0.19.3"
|
||||
postcss "^8.4.32"
|
||||
rollup "^4.2.0"
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.3"
|