refactor: auto ordered imports (#9163)
All checks were successful
Tests / test (push) Successful in 4m38s

This commit is contained in:
Marcel Mraz 2025-03-12 15:23:31 +01:00 committed by GitHub
parent 82b9a6b464
commit 21ffaf4d76
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
421 changed files with 3532 additions and 2763 deletions

View file

@ -1,6 +1,21 @@
{
"extends": ["@excalidraw/eslint-config", "react-app"],
"rules": {
"import/order": [
"warn",
{
"groups": ["builtin", "external", "internal", "parent", "sibling", "index", "object", "type"],
"pathGroups": [
{
"pattern": "@excalidraw/**",
"group": "external",
"position": "after"
}
],
"newlines-between": "always-and-inside-groups",
"warnOnUnassignedImports": true
}
],
"import/no-anonymous-default-export": "off",
"no-restricted-globals": "off",
"@typescript-eslint/consistent-type-imports": [

View file

@ -1,5 +1,6 @@
import React from "react";
import clsx from "clsx";
import React from "react";
import styles from "./styles.module.css";
const FeatureList = [

View file

@ -1,5 +1,6 @@
import React from "react";
import clsx from "clsx";
import React from "react";
import styles from "./styles.module.css";
type FeatureItem = {

View file

@ -1,10 +1,11 @@
import React from "react";
import clsx from "clsx";
import Layout from "@theme/Layout";
import Link from "@docusaurus/Link";
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
import styles from "./index.module.css";
import HomepageFeatures from "@site/src/components/Homepage";
import Layout from "@theme/Layout";
import clsx from "clsx";
import React from "react";
import styles from "./index.module.css";
function HomepageHeader() {
const { siteConfig } = useDocusaurusContext();

View file

@ -1,6 +1,6 @@
// Import the original mapper
import MDXComponents from "@theme-original/MDXComponents";
import Highlight from "@site/src/components/Highlight";
import MDXComponents from "@theme-original/MDXComponents";
export default {
// Re-use the default mapping

View file

@ -1,5 +1,6 @@
import dynamic from "next/dynamic";
import Script from "next/script";
import "../common.scss";
// Since client components get prerenderd on server as well hence importing the excalidraw stuff dynamically

View file

@ -1,10 +1,11 @@
"use client";
import * as excalidrawLib from "@excalidraw/excalidraw";
import { Excalidraw } from "@excalidraw/excalidraw";
import App from "../../with-script-in-browser/components/ExampleApp";
import "@excalidraw/excalidraw/index.css";
import App from "../../with-script-in-browser/components/ExampleApp";
const ExcalidrawWrapper: React.FC = () => {
return (
<>

View file

@ -1,4 +1,5 @@
import dynamic from "next/dynamic";
import "../common.scss";
// Since client components get prerenderd on server as well hence importing the excalidraw stuff dynamically

View file

@ -1,4 +1,5 @@
import React from "react";
import type * as TExcalidraw from "@excalidraw/excalidraw";
import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/types";

View file

@ -1,3 +1,4 @@
import { nanoid } from "nanoid";
import React, {
useEffect,
useState,
@ -6,13 +7,24 @@ import React, {
Children,
cloneElement,
} from "react";
import ExampleSidebar from "./sidebar/ExampleSidebar";
import type * as TExcalidraw from "@excalidraw/excalidraw";
import type { ImportedLibraryData } from "@excalidraw/excalidraw/data/types";
import type {
NonDeletedExcalidrawElement,
Theme,
} from "@excalidraw/excalidraw/element/types";
import type {
AppState,
BinaryFileData,
ExcalidrawImperativeAPI,
ExcalidrawInitialDataState,
Gesture,
LibraryItems,
PointerDownState as ExcalidrawPointerDownState,
} from "@excalidraw/excalidraw/types";
import { nanoid } from "nanoid";
import type { ResolvablePromise } from "../utils";
import initialData from "../initialData";
import {
resolvablePromise,
distance2d,
@ -23,25 +35,12 @@ import {
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/types";
import type {
NonDeletedExcalidrawElement,
Theme,
} from "@excalidraw/excalidraw/element/types";
import type { ImportedLibraryData } from "@excalidraw/excalidraw/data/types";
import ExampleSidebar from "./sidebar/ExampleSidebar";
import "./ExampleApp.scss";
import type { ResolvablePromise } from "../utils";
type Comment = {
x: number;
y: number;

View file

@ -1,7 +1,9 @@
import React from "react";
import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/types";
import CustomFooter from "./CustomFooter";
import type * as TExcalidraw from "@excalidraw/excalidraw";
import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/types";
import CustomFooter from "./CustomFooter";
const MobileFooter = ({
excalidrawAPI,

View file

@ -1,4 +1,5 @@
import React, { useState } from "react";
import "./ExampleSidebar.scss";
export default function Sidebar({ children }: { children: React.ReactNode }) {

View file

@ -1,10 +1,11 @@
import App from "./components/ExampleApp";
import React, { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "@excalidraw/excalidraw/index.css";
import type * as TExcalidraw from "@excalidraw/excalidraw";
import "@excalidraw/excalidraw/index.css";
import App from "./components/ExampleApp";
declare global {
interface Window {

View file

@ -1,6 +1,6 @@
import { unstable_batchedUpdates } from "react-dom";
import { fileOpen as _fileOpen } from "browser-fs-access";
import { MIME_TYPES } from "@excalidraw/excalidraw";
import { fileOpen as _fileOpen } from "browser-fs-access";
import { unstable_batchedUpdates } from "react-dom";
type FILE_EXTENSION = Exclude<keyof typeof MIME_TYPES, "binary">;

View file

@ -1,24 +1,3 @@
import polyfill from "@excalidraw/excalidraw/polyfill";
import { useCallback, useEffect, useRef, useState } from "react";
import { trackEvent } from "@excalidraw/excalidraw/analytics";
import { getDefaultAppState } from "@excalidraw/excalidraw/appState";
import { ErrorDialog } from "@excalidraw/excalidraw/components/ErrorDialog";
import { TopErrorBoundary } from "./components/TopErrorBoundary";
import {
APP_NAME,
EVENT,
THEME,
TITLE_TIMEOUT,
VERSION_TIMEOUT,
} from "@excalidraw/excalidraw/constants";
import { loadFromBlob } from "@excalidraw/excalidraw/data/blob";
import type {
FileId,
NonDeletedExcalidrawElement,
OrderedExcalidrawElement,
} from "@excalidraw/excalidraw/element/types";
import { useCallbackRefState } from "@excalidraw/excalidraw/hooks/useCallbackRefState";
import { t } from "@excalidraw/excalidraw/i18n";
import {
Excalidraw,
LiveCollaborationTrigger,
@ -26,14 +5,29 @@ import {
CaptureUpdateAction,
reconcileElements,
} from "@excalidraw/excalidraw";
import type {
AppState,
ExcalidrawImperativeAPI,
BinaryFiles,
ExcalidrawInitialDataState,
UIAppState,
} from "@excalidraw/excalidraw/types";
import type { ResolvablePromise } from "@excalidraw/excalidraw/utils";
import { trackEvent } from "@excalidraw/excalidraw/analytics";
import { getDefaultAppState } from "@excalidraw/excalidraw/appState";
import {
CommandPalette,
DEFAULT_CATEGORIES,
} from "@excalidraw/excalidraw/components/CommandPalette/CommandPalette";
import { ErrorDialog } from "@excalidraw/excalidraw/components/ErrorDialog";
import { OverwriteConfirmDialog } from "@excalidraw/excalidraw/components/OverwriteConfirm/OverwriteConfirm";
import { openConfirmModal } from "@excalidraw/excalidraw/components/OverwriteConfirm/OverwriteConfirmState";
import { ShareableLinkDialog } from "@excalidraw/excalidraw/components/ShareableLinkDialog";
import Trans from "@excalidraw/excalidraw/components/Trans";
import {
APP_NAME,
EVENT,
THEME,
TITLE_TIMEOUT,
VERSION_TIMEOUT,
} from "@excalidraw/excalidraw/constants";
import polyfill from "@excalidraw/excalidraw/polyfill";
import { useCallback, useEffect, useRef, useState } from "react";
import { loadFromBlob } from "@excalidraw/excalidraw/data/blob";
import { useCallbackRefState } from "@excalidraw/excalidraw/hooks/useCallbackRefState";
import { t } from "@excalidraw/excalidraw/i18n";
import {
debounce,
getVersion,
@ -43,74 +37,6 @@ import {
resolvablePromise,
isRunningInIframe,
} from "@excalidraw/excalidraw/utils";
import {
FIREBASE_STORAGE_PREFIXES,
isExcalidrawPlusSignedUser,
STORAGE_KEYS,
SYNC_BROWSER_TABS_TIMEOUT,
} from "./app_constants";
import type { CollabAPI } from "./collab/Collab";
import Collab, {
collabAPIAtom,
isCollaboratingAtom,
isOfflineAtom,
} from "./collab/Collab";
import {
exportToBackend,
getCollaborationLinkData,
isCollaborationLink,
loadScene,
} from "./data";
import {
importFromLocalStorage,
importUsernameFromLocalStorage,
} from "./data/localStorage";
import CustomStats from "./CustomStats";
import type { RestoredDataState } from "@excalidraw/excalidraw/data/restore";
import { restore, restoreAppState } from "@excalidraw/excalidraw/data/restore";
import {
ExportToExcalidrawPlus,
exportToExcalidrawPlus,
} from "./components/ExportToExcalidrawPlus";
import { updateStaleImageStatuses } from "./data/FileManager";
import { newElementWith } from "@excalidraw/excalidraw/element/mutateElement";
import { isInitializedImageElement } from "@excalidraw/excalidraw/element/typeChecks";
import { loadFilesFromFirebase } from "./data/firebase";
import {
LibraryIndexedDBAdapter,
LibraryLocalStorageMigrationAdapter,
LocalData,
} from "./data/LocalData";
import { isBrowserStorageStateNewer } from "./data/tabSync";
import clsx from "clsx";
import {
parseLibraryTokensFromUrl,
useHandleLibrary,
} from "@excalidraw/excalidraw/data/library";
import { AppMainMenu } from "./components/AppMainMenu";
import { AppWelcomeScreen } from "./components/AppWelcomeScreen";
import { AppFooter } from "./components/AppFooter";
import {
Provider,
useAtom,
useAtomValue,
useAtomWithInitialValue,
appJotaiStore,
} from "./app-jotai";
import "./index.scss";
import type { ResolutionType } from "@excalidraw/excalidraw/utility-types";
import { ShareableLinkDialog } from "@excalidraw/excalidraw/components/ShareableLinkDialog";
import { openConfirmModal } from "@excalidraw/excalidraw/components/OverwriteConfirm/OverwriteConfirmState";
import { OverwriteConfirmDialog } from "@excalidraw/excalidraw/components/OverwriteConfirm/OverwriteConfirm";
import Trans from "@excalidraw/excalidraw/components/Trans";
import { ShareDialog, shareDialogStateAtom } from "./share/ShareDialog";
import CollabError, { collabErrorIndicatorAtom } from "./collab/CollabError";
import type { RemoteExcalidrawElement } from "@excalidraw/excalidraw/data/reconcile";
import {
CommandPalette,
DEFAULT_CATEGORIES,
} from "@excalidraw/excalidraw/components/CommandPalette/CommandPalette";
import {
GithubIcon,
XBrandIcon,
@ -121,6 +47,83 @@ import {
share,
youtubeIcon,
} from "@excalidraw/excalidraw/components/icons";
import { isElementLink } from "@excalidraw/excalidraw/element/elementLink";
import { restore, restoreAppState } from "@excalidraw/excalidraw/data/restore";
import { newElementWith } from "@excalidraw/excalidraw/element/mutateElement";
import { isInitializedImageElement } from "@excalidraw/excalidraw/element/typeChecks";
import clsx from "clsx";
import {
parseLibraryTokensFromUrl,
useHandleLibrary,
} from "@excalidraw/excalidraw/data/library";
import type { RemoteExcalidrawElement } from "@excalidraw/excalidraw/data/reconcile";
import type { RestoredDataState } from "@excalidraw/excalidraw/data/restore";
import type {
FileId,
NonDeletedExcalidrawElement,
OrderedExcalidrawElement,
} from "@excalidraw/excalidraw/element/types";
import type {
AppState,
ExcalidrawImperativeAPI,
BinaryFiles,
ExcalidrawInitialDataState,
UIAppState,
} from "@excalidraw/excalidraw/types";
import type { ResolutionType } from "@excalidraw/excalidraw/utility-types";
import type { ResolvablePromise } from "@excalidraw/excalidraw/utils";
import CustomStats from "./CustomStats";
import {
Provider,
useAtom,
useAtomValue,
useAtomWithInitialValue,
appJotaiStore,
} from "./app-jotai";
import {
FIREBASE_STORAGE_PREFIXES,
isExcalidrawPlusSignedUser,
STORAGE_KEYS,
SYNC_BROWSER_TABS_TIMEOUT,
} from "./app_constants";
import Collab, {
collabAPIAtom,
isCollaboratingAtom,
isOfflineAtom,
} from "./collab/Collab";
import { AppFooter } from "./components/AppFooter";
import { AppMainMenu } from "./components/AppMainMenu";
import { AppWelcomeScreen } from "./components/AppWelcomeScreen";
import {
ExportToExcalidrawPlus,
exportToExcalidrawPlus,
} from "./components/ExportToExcalidrawPlus";
import { TopErrorBoundary } from "./components/TopErrorBoundary";
import {
exportToBackend,
getCollaborationLinkData,
isCollaborationLink,
loadScene,
} from "./data";
import { updateStaleImageStatuses } from "./data/FileManager";
import {
importFromLocalStorage,
importUsernameFromLocalStorage,
} from "./data/localStorage";
import { loadFilesFromFirebase } from "./data/firebase";
import {
LibraryIndexedDBAdapter,
LibraryLocalStorageMigrationAdapter,
LocalData,
} from "./data/LocalData";
import { isBrowserStorageStateNewer } from "./data/tabSync";
import { ShareDialog, shareDialogStateAtom } from "./share/ShareDialog";
import CollabError, { collabErrorIndicatorAtom } from "./collab/CollabError";
import { useHandleAppTheme } from "./useHandleAppTheme";
import { getPreferredLanguage } from "./app-language/language-detector";
import { useAppLangCode } from "./app-language/language-state";
@ -131,7 +134,10 @@ import DebugCanvas, {
} from "./components/DebugCanvas";
import { AIComponents } from "./components/AI";
import { ExcalidrawPlusIframeExport } from "./ExcalidrawPlusIframeExport";
import { isElementLink } from "@excalidraw/excalidraw/element/elementLink";
import "./index.scss";
import type { CollabAPI } from "./collab/Collab";
polyfill();

View file

@ -1,15 +1,17 @@
import { useEffect, useState } from "react";
import { Stats } from "@excalidraw/excalidraw";
import { copyTextToSystemClipboard } from "@excalidraw/excalidraw/clipboard";
import { DEFAULT_VERSION } from "@excalidraw/excalidraw/constants";
import { t } from "@excalidraw/excalidraw/i18n";
import { debounce, getVersion, nFormatter } from "@excalidraw/excalidraw/utils";
import { useEffect, useState } from "react";
import type { NonDeletedExcalidrawElement } from "@excalidraw/excalidraw/element/types";
import type { UIAppState } from "@excalidraw/excalidraw/types";
import {
getElementsStorageSize,
getTotalStorageSize,
} from "./data/localStorage";
import { DEFAULT_VERSION } from "@excalidraw/excalidraw/constants";
import { t } from "@excalidraw/excalidraw/i18n";
import { copyTextToSystemClipboard } from "@excalidraw/excalidraw/clipboard";
import type { NonDeletedExcalidrawElement } from "@excalidraw/excalidraw/element/types";
import type { UIAppState } from "@excalidraw/excalidraw/types";
import { Stats } from "@excalidraw/excalidraw";
type StorageSizes = { scene: number; total: number };

View file

@ -1,13 +1,15 @@
import { base64urlToString } from "@excalidraw/excalidraw/data/encode";
import { ExcalidrawError } from "@excalidraw/excalidraw/errors";
import { useLayoutEffect, useRef } from "react";
import { STORAGE_KEYS } from "./app_constants";
import { LocalData } from "./data/LocalData";
import type {
FileId,
OrderedExcalidrawElement,
} from "@excalidraw/excalidraw/element/types";
import type { AppState, BinaryFileData } from "@excalidraw/excalidraw/types";
import { ExcalidrawError } from "@excalidraw/excalidraw/errors";
import { base64urlToString } from "@excalidraw/excalidraw/data/encode";
import { STORAGE_KEYS } from "./app_constants";
import { LocalData } from "./data/LocalData";
const EVENT_REQUEST_SCENE = "REQUEST_SCENE";

View file

@ -1,6 +1,8 @@
import React from "react";
import { useI18n, languages } from "@excalidraw/excalidraw/i18n";
import React from "react";
import { useSetAtom } from "../app-jotai";
import { appLangCodeAtom } from "./language-state";
export const LanguageList = ({ style }: { style?: React.CSSProperties }) => {

View file

@ -1,5 +1,5 @@
import LanguageDetector from "i18next-browser-languagedetector";
import { defaultLang, languages } from "@excalidraw/excalidraw";
import LanguageDetector from "i18next-browser-languagedetector";
export const languageDetector = new LanguageDetector();

View file

@ -1,5 +1,7 @@
import { useEffect } from "react";
import { atom, useAtom } from "../app-jotai";
import { getPreferredLanguage, languageDetector } from "./language-detector";
export const appLangCodeAtom = atom(getPreferredLanguage());

View file

@ -1,21 +1,3 @@
import throttle from "lodash.throttle";
import { PureComponent } from "react";
import type {
BinaryFileData,
ExcalidrawImperativeAPI,
SocketId,
Collaborator,
Gesture,
} from "@excalidraw/excalidraw/types";
import { ErrorDialog } from "@excalidraw/excalidraw/components/ErrorDialog";
import { APP_NAME, ENV, EVENT } from "@excalidraw/excalidraw/constants";
import type { ImportedDataState } from "@excalidraw/excalidraw/data/types";
import type {
ExcalidrawElement,
FileId,
InitializedExcalidrawImageElement,
OrderedExcalidrawElement,
} from "@excalidraw/excalidraw/element/types";
import {
CaptureUpdateAction,
getSceneVersion,
@ -23,12 +5,53 @@ import {
zoomToFitBounds,
reconcileElements,
} from "@excalidraw/excalidraw";
import { ErrorDialog } from "@excalidraw/excalidraw/components/ErrorDialog";
import { APP_NAME, ENV, EVENT } from "@excalidraw/excalidraw/constants";
import {
IDLE_THRESHOLD,
ACTIVE_THRESHOLD,
UserIdleState,
} from "@excalidraw/excalidraw/constants";
import { decryptData } from "@excalidraw/excalidraw/data/encryption";
import { getVisibleSceneBounds } from "@excalidraw/excalidraw/element/bounds";
import { newElementWith } from "@excalidraw/excalidraw/element/mutateElement";
import {
isImageElement,
isInitializedImageElement,
} from "@excalidraw/excalidraw/element/typeChecks";
import { AbortError } from "@excalidraw/excalidraw/errors";
import { t } from "@excalidraw/excalidraw/i18n";
import { withBatchedUpdates } from "@excalidraw/excalidraw/reactUtils";
import {
assertNever,
preventUnload,
resolvablePromise,
throttleRAF,
} from "@excalidraw/excalidraw/utils";
import throttle from "lodash.throttle";
import { PureComponent } from "react";
import type {
ReconciledExcalidrawElement,
RemoteExcalidrawElement,
} from "@excalidraw/excalidraw/data/reconcile";
import type { ImportedDataState } from "@excalidraw/excalidraw/data/types";
import type {
ExcalidrawElement,
FileId,
InitializedExcalidrawImageElement,
OrderedExcalidrawElement,
} from "@excalidraw/excalidraw/element/types";
import type {
BinaryFileData,
ExcalidrawImperativeAPI,
SocketId,
Collaborator,
Gesture,
} from "@excalidraw/excalidraw/types";
import type { Mutable, ValueOf } from "@excalidraw/excalidraw/utility-types";
import { appJotaiStore, atom } from "../app-jotai";
import {
CURSOR_SYNC_TIMEOUT,
FILE_UPLOAD_MAX_BYTES,
@ -39,15 +62,17 @@ import {
SYNC_FULL_SCENE_INTERVAL_MS,
WS_EVENTS,
} from "../app_constants";
import type {
SocketUpdateDataSource,
SyncableExcalidrawElement,
} from "../data";
import {
generateCollaborationLinkData,
getCollaborationLink,
getSyncableElements,
} from "../data";
import {
encodeFilesForUpload,
FileManager,
updateStaleImageStatuses,
} from "../data/FileManager";
import { LocalData } from "../data/LocalData";
import {
isSavedToFirebase,
loadFilesFromFirebase,
@ -59,36 +84,15 @@ import {
importUsernameFromLocalStorage,
saveUsernameToLocalStorage,
} from "../data/localStorage";
import Portal from "./Portal";
import { t } from "@excalidraw/excalidraw/i18n";
import {
IDLE_THRESHOLD,
ACTIVE_THRESHOLD,
UserIdleState,
} from "@excalidraw/excalidraw/constants";
import {
encodeFilesForUpload,
FileManager,
updateStaleImageStatuses,
} from "../data/FileManager";
import { AbortError } from "@excalidraw/excalidraw/errors";
import {
isImageElement,
isInitializedImageElement,
} from "@excalidraw/excalidraw/element/typeChecks";
import { newElementWith } from "@excalidraw/excalidraw/element/mutateElement";
import { decryptData } from "@excalidraw/excalidraw/data/encryption";
import { resetBrowserStateVersions } from "../data/tabSync";
import { LocalData } from "../data/LocalData";
import { appJotaiStore, atom } from "../app-jotai";
import type { Mutable, ValueOf } from "@excalidraw/excalidraw/utility-types";
import { getVisibleSceneBounds } from "@excalidraw/excalidraw/element/bounds";
import { withBatchedUpdates } from "@excalidraw/excalidraw/reactUtils";
import { collabErrorIndicatorAtom } from "./CollabError";
import Portal from "./Portal";
import type {
ReconciledExcalidrawElement,
RemoteExcalidrawElement,
} from "@excalidraw/excalidraw/data/reconcile";
SocketUpdateDataSource,
SyncableExcalidrawElement,
} from "../data";
export const collabAPIAtom = atom<CollabAPI | null>(null);
export const isCollaboratingAtom = atom(false);

View file

@ -2,6 +2,7 @@ import { Tooltip } from "@excalidraw/excalidraw/components/Tooltip";
import { warning } from "@excalidraw/excalidraw/components/icons";
import clsx from "clsx";
import { useEffect, useRef, useState } from "react";
import { atom } from "../app-jotai";
import "./CollabError.scss";

View file

@ -1,25 +1,26 @@
import { CaptureUpdateAction } from "@excalidraw/excalidraw";
import { trackEvent } from "@excalidraw/excalidraw/analytics";
import { encryptData } from "@excalidraw/excalidraw/data/encryption";
import { newElementWith } from "@excalidraw/excalidraw/element/mutateElement";
import throttle from "lodash.throttle";
import type { UserIdleState } from "@excalidraw/excalidraw/constants";
import type { OrderedExcalidrawElement } from "@excalidraw/excalidraw/element/types";
import type {
OnUserFollowedPayload,
SocketId,
} from "@excalidraw/excalidraw/types";
import { WS_EVENTS, FILE_UPLOAD_TIMEOUT, WS_SUBTYPES } from "../app_constants";
import { isSyncableElement } from "../data";
import type {
SocketUpdateData,
SocketUpdateDataSource,
SyncableExcalidrawElement,
} from "../data";
import { isSyncableElement } from "../data";
import type { TCollabClass } from "./Collab";
import type { OrderedExcalidrawElement } from "@excalidraw/excalidraw/element/types";
import { WS_EVENTS, FILE_UPLOAD_TIMEOUT, WS_SUBTYPES } from "../app_constants";
import type {
OnUserFollowedPayload,
SocketId,
} from "@excalidraw/excalidraw/types";
import type { UserIdleState } from "@excalidraw/excalidraw/constants";
import { trackEvent } from "@excalidraw/excalidraw/analytics";
import throttle from "lodash.throttle";
import { newElementWith } from "@excalidraw/excalidraw/element/mutateElement";
import { encryptData } from "@excalidraw/excalidraw/data/encryption";
import type { Socket } from "socket.io-client";
import { CaptureUpdateAction } from "@excalidraw/excalidraw";
class Portal {
collab: TCollabClass;

View file

@ -1,4 +1,3 @@
import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/types";
import {
DiagramToCodePlugin,
exportToBlob,
@ -9,6 +8,8 @@ import {
import { getDataURL } from "@excalidraw/excalidraw/data/blob";
import { safelyParseJSON } from "@excalidraw/excalidraw/utils";
import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/types";
export const AIComponents = ({
excalidrawAPI,
}: {

View file

@ -1,9 +1,11 @@
import React from "react";
import { Footer } from "@excalidraw/excalidraw/index";
import React from "react";
import { isExcalidrawPlusSignedUser } from "../app_constants";
import { DebugFooter, isVisualDebuggerEnabled } from "./DebugCanvas";
import { EncryptedIcon } from "./EncryptedIcon";
import { ExcalidrawPlusAppLink } from "./ExcalidrawPlusAppLink";
import { isExcalidrawPlusSignedUser } from "../app_constants";
import { DebugFooter, isVisualDebuggerEnabled } from "./DebugCanvas";
export const AppFooter = React.memo(
({ onChange }: { onChange: () => void }) => {

View file

@ -1,13 +1,16 @@
import React from "react";
import {
loginIcon,
ExcalLogo,
eyeIcon,
} from "@excalidraw/excalidraw/components/icons";
import type { Theme } from "@excalidraw/excalidraw/element/types";
import { MainMenu } from "@excalidraw/excalidraw/index";
import { isExcalidrawPlusSignedUser } from "../app_constants";
import React from "react";
import type { Theme } from "@excalidraw/excalidraw/element/types";
import { LanguageList } from "../app-language/LanguageList";
import { isExcalidrawPlusSignedUser } from "../app_constants";
import { saveDebugState } from "./DebugCanvas";
export const AppMainMenu: React.FC<{

View file

@ -1,9 +1,10 @@
import React from "react";
import { loginIcon } from "@excalidraw/excalidraw/components/icons";
import { POINTER_EVENTS } from "@excalidraw/excalidraw/constants";
import { useI18n } from "@excalidraw/excalidraw/i18n";
import { WelcomeScreen } from "@excalidraw/excalidraw/index";
import React from "react";
import { isExcalidrawPlusSignedUser } from "../app_constants";
import { POINTER_EVENTS } from "@excalidraw/excalidraw/constants";
export const AppWelcomeScreen: React.FC<{
onCollabDialogOpen: () => any;

View file

@ -1,24 +1,27 @@
import { useCallback, useImperativeHandle, useRef } from "react";
import { type AppState } from "@excalidraw/excalidraw/types";
import { throttleRAF } from "@excalidraw/excalidraw/utils";
import {
bootstrapCanvas,
getNormalizedCanvasDimensions,
} from "@excalidraw/excalidraw/renderer/helpers";
import type { DebugElement } from "@excalidraw/excalidraw/visualdebug";
import {
ArrowheadArrowIcon,
CloseIcon,
TrashIcon,
} from "@excalidraw/excalidraw/components/icons";
import { STORAGE_KEYS } from "../app_constants";
import type { Curve } from "../../packages/math";
import {
bootstrapCanvas,
getNormalizedCanvasDimensions,
} from "@excalidraw/excalidraw/renderer/helpers";
import { type AppState } from "@excalidraw/excalidraw/types";
import { throttleRAF } from "@excalidraw/excalidraw/utils";
import { useCallback, useImperativeHandle, useRef } from "react";
import type { DebugElement } from "@excalidraw/excalidraw/visualdebug";
import {
isLineSegment,
type GlobalPoint,
type LineSegment,
} from "../../packages/math";
import { isCurve } from "../../packages/math/curve";
import { STORAGE_KEYS } from "../app_constants";
import type { Curve } from "../../packages/math";
const renderLine = (
context: CanvasRenderingContext2D,

View file

@ -1,5 +1,5 @@
import { shield } from "@excalidraw/excalidraw/components/icons";
import { Tooltip } from "@excalidraw/excalidraw/components/Tooltip";
import { shield } from "@excalidraw/excalidraw/components/icons";
import { useI18n } from "@excalidraw/excalidraw/i18n";
export const EncryptedIcon = () => {

View file

@ -1,8 +1,20 @@
import React from "react";
import { trackEvent } from "@excalidraw/excalidraw/analytics";
import { Card } from "@excalidraw/excalidraw/components/Card";
import { ExcalidrawLogo } from "@excalidraw/excalidraw/components/ExcalidrawLogo";
import { ToolButton } from "@excalidraw/excalidraw/components/ToolButton";
import { MIME_TYPES } from "@excalidraw/excalidraw/constants";
import {
encryptData,
generateEncryptionKey,
} from "@excalidraw/excalidraw/data/encryption";
import { serializeAsJSON } from "@excalidraw/excalidraw/data/json";
import { loadFirebaseStorage, saveFilesToFirebase } from "../data/firebase";
import { isInitializedImageElement } from "@excalidraw/excalidraw/element/typeChecks";
import { useI18n } from "@excalidraw/excalidraw/i18n";
import { getFrame } from "@excalidraw/excalidraw/utils";
import { uploadBytes, ref } from "firebase/storage";
import { nanoid } from "nanoid";
import React from "react";
import type {
FileId,
NonDeletedExcalidrawElement,
@ -12,20 +24,10 @@ import type {
BinaryFileData,
BinaryFiles,
} from "@excalidraw/excalidraw/types";
import { nanoid } from "nanoid";
import { useI18n } from "@excalidraw/excalidraw/i18n";
import {
encryptData,
generateEncryptionKey,
} from "@excalidraw/excalidraw/data/encryption";
import { isInitializedImageElement } from "@excalidraw/excalidraw/element/typeChecks";
import { FILE_UPLOAD_MAX_BYTES } from "../app_constants";
import { encodeFilesForUpload } from "../data/FileManager";
import { uploadBytes, ref } from "firebase/storage";
import { MIME_TYPES } from "@excalidraw/excalidraw/constants";
import { trackEvent } from "@excalidraw/excalidraw/analytics";
import { getFrame } from "@excalidraw/excalidraw/utils";
import { ExcalidrawLogo } from "@excalidraw/excalidraw/components/ExcalidrawLogo";
import { loadFirebaseStorage, saveFilesToFirebase } from "../data/firebase";
export const exportToExcalidrawPlus = async (
elements: readonly NonDeletedExcalidrawElement[],

View file

@ -1,6 +1,7 @@
import { THEME } from "@excalidraw/excalidraw/constants";
import oc from "open-color";
import React from "react";
import { THEME } from "@excalidraw/excalidraw/constants";
import type { Theme } from "@excalidraw/excalidraw/element/types";
// https://github.com/tholman/github-corners

View file

@ -1,7 +1,7 @@
import React from "react";
import * as Sentry from "@sentry/browser";
import { t } from "@excalidraw/excalidraw/i18n";
import Trans from "@excalidraw/excalidraw/components/Trans";
import { t } from "@excalidraw/excalidraw/i18n";
import * as Sentry from "@sentry/browser";
import React from "react";
interface TopErrorBoundaryState {
hasError: boolean;

View file

@ -2,13 +2,14 @@ import { CaptureUpdateAction } from "@excalidraw/excalidraw";
import { compressData } from "@excalidraw/excalidraw/data/encode";
import { newElementWith } from "@excalidraw/excalidraw/element/mutateElement";
import { isInitializedImageElement } from "@excalidraw/excalidraw/element/typeChecks";
import { t } from "@excalidraw/excalidraw/i18n";
import type {
ExcalidrawElement,
ExcalidrawImageElement,
FileId,
InitializedExcalidrawImageElement,
} from "@excalidraw/excalidraw/element/types";
import { t } from "@excalidraw/excalidraw/i18n";
import type {
BinaryFileData,
BinaryFileMetadata,

View file

@ -10,6 +10,13 @@
* (localStorage, indexedDB).
*/
import { clearAppStateForLocalStorage } from "@excalidraw/excalidraw/appState";
import {
CANVAS_SEARCH_TAB,
DEFAULT_SIDEBAR,
} from "@excalidraw/excalidraw/constants";
import { clearElementsForLocalStorage } from "@excalidraw/excalidraw/element";
import { debounce } from "@excalidraw/excalidraw/utils";
import {
createStore,
entries,
@ -19,14 +26,9 @@ import {
setMany,
get,
} from "idb-keyval";
import { clearAppStateForLocalStorage } from "@excalidraw/excalidraw/appState";
import {
CANVAS_SEARCH_TAB,
DEFAULT_SIDEBAR,
} from "@excalidraw/excalidraw/constants";
import type { LibraryPersistedData } from "@excalidraw/excalidraw/data/library";
import type { ImportedDataState } from "@excalidraw/excalidraw/data/types";
import { clearElementsForLocalStorage } from "@excalidraw/excalidraw/element";
import type {
ExcalidrawElement,
FileId,
@ -37,8 +39,9 @@ import type {
BinaryFiles,
} from "@excalidraw/excalidraw/types";
import type { MaybePromise } from "@excalidraw/excalidraw/utility-types";
import { debounce } from "@excalidraw/excalidraw/utils";
import { SAVE_TO_LOCAL_STORAGE_TIMEOUT, STORAGE_KEYS } from "../app_constants";
import { FileManager } from "./FileManager";
import { Locker } from "./Locker";
import { updateBrowserStateVersion } from "./tabSync";

View file

@ -1,27 +1,12 @@
import { reconcileElements } from "@excalidraw/excalidraw";
import type {
ExcalidrawElement,
FileId,
OrderedExcalidrawElement,
} from "@excalidraw/excalidraw/element/types";
import { getSceneVersion } from "@excalidraw/excalidraw/element";
import type Portal from "../collab/Portal";
import { restoreElements } from "@excalidraw/excalidraw/data/restore";
import type {
AppState,
BinaryFileData,
BinaryFileMetadata,
DataURL,
} from "@excalidraw/excalidraw/types";
import { FILE_CACHE_MAX_AGE_SEC } from "../app_constants";
import { MIME_TYPES } from "@excalidraw/excalidraw/constants";
import { decompressData } from "@excalidraw/excalidraw/data/encode";
import {
encryptData,
decryptData,
} from "@excalidraw/excalidraw/data/encryption";
import { MIME_TYPES } from "@excalidraw/excalidraw/constants";
import type { SyncableExcalidrawElement } from ".";
import { getSyncableElements } from ".";
import { restoreElements } from "@excalidraw/excalidraw/data/restore";
import { getSceneVersion } from "@excalidraw/excalidraw/element";
import { initializeApp } from "firebase/app";
import {
getFirestore,
@ -31,8 +16,27 @@ import {
Bytes,
} from "firebase/firestore";
import { getStorage, ref, uploadBytes } from "firebase/storage";
import type { Socket } from "socket.io-client";
import type { RemoteExcalidrawElement } from "@excalidraw/excalidraw/data/reconcile";
import type {
ExcalidrawElement,
FileId,
OrderedExcalidrawElement,
} from "@excalidraw/excalidraw/element/types";
import type {
AppState,
BinaryFileData,
BinaryFileMetadata,
DataURL,
} from "@excalidraw/excalidraw/types";
import { FILE_CACHE_MAX_AGE_SEC } from "../app_constants";
import { getSyncableElements } from ".";
import type { SyncableExcalidrawElement } from ".";
import type Portal from "../collab/Portal";
import type { Socket } from "socket.io-client";
// private
// -----------------------------------------------------------------------------

View file

@ -9,34 +9,38 @@ import {
} from "@excalidraw/excalidraw/data/encryption";
import { serializeAsJSON } from "@excalidraw/excalidraw/data/json";
import { restore } from "@excalidraw/excalidraw/data/restore";
import type { ImportedDataState } from "@excalidraw/excalidraw/data/types";
import type { SceneBounds } from "@excalidraw/excalidraw/element/bounds";
import { isInvisiblySmallElement } from "@excalidraw/excalidraw/element/sizeHelpers";
import { isInitializedImageElement } from "@excalidraw/excalidraw/element/typeChecks";
import { t } from "@excalidraw/excalidraw/i18n";
import { bytesToHexString } from "@excalidraw/excalidraw/utils";
import type { UserIdleState } from "@excalidraw/excalidraw/constants";
import type { ImportedDataState } from "@excalidraw/excalidraw/data/types";
import type { SceneBounds } from "@excalidraw/excalidraw/element/bounds";
import type {
ExcalidrawElement,
FileId,
OrderedExcalidrawElement,
} from "@excalidraw/excalidraw/element/types";
import { t } from "@excalidraw/excalidraw/i18n";
import type {
AppState,
BinaryFileData,
BinaryFiles,
SocketId,
} from "@excalidraw/excalidraw/types";
import type { UserIdleState } from "@excalidraw/excalidraw/constants";
import type { MakeBrand } from "@excalidraw/excalidraw/utility-types";
import { bytesToHexString } from "@excalidraw/excalidraw/utils";
import type { WS_SUBTYPES } from "../app_constants";
import {
DELETED_ELEMENT_TIMEOUT,
FILE_UPLOAD_MAX_BYTES,
ROOM_ID_BYTES,
} from "../app_constants";
import { encodeFilesForUpload } from "./FileManager";
import { saveFilesToFirebase } from "./firebase";
import type { WS_SUBTYPES } from "../app_constants";
export type SyncableExcalidrawElement = OrderedExcalidrawElement &
MakeBrand<"SyncableExcalidrawElement">;

View file

@ -1,10 +1,12 @@
import type { ExcalidrawElement } from "@excalidraw/excalidraw/element/types";
import type { AppState } from "@excalidraw/excalidraw/types";
import {
clearAppStateForLocalStorage,
getDefaultAppState,
} from "@excalidraw/excalidraw/appState";
import { clearElementsForLocalStorage } from "@excalidraw/excalidraw/element";
import type { ExcalidrawElement } from "@excalidraw/excalidraw/element/types";
import type { AppState } from "@excalidraw/excalidraw/types";
import { STORAGE_KEYS } from "../app_constants";
export const saveUsernameToLocalStorage = (username: string) => {

View file

@ -1,9 +1,11 @@
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import ExcalidrawApp from "./App";
import { registerSW } from "virtual:pwa-register";
import "../excalidraw-app/sentry";
import ExcalidrawApp from "./App";
window.__EXCALIDRAW_SHA__ = import.meta.env.VITE_APP_GIT_SHA;
const rootElement = document.getElementById("root")!;
const root = createRoot(rootElement);

View file

@ -1,10 +1,8 @@
import { useEffect, useRef, useState } from "react";
import { copyTextToSystemClipboard } from "@excalidraw/excalidraw/clipboard";
import { trackEvent } from "@excalidraw/excalidraw/analytics";
import { getFrame } from "@excalidraw/excalidraw/utils";
import { useI18n } from "@excalidraw/excalidraw/i18n";
import { KEYS } from "@excalidraw/excalidraw/keys";
import { copyTextToSystemClipboard } from "@excalidraw/excalidraw/clipboard";
import { Dialog } from "@excalidraw/excalidraw/components/Dialog";
import { FilledButton } from "@excalidraw/excalidraw/components/FilledButton";
import { TextField } from "@excalidraw/excalidraw/components/TextField";
import {
copyIcon,
LinkIcon,
@ -14,16 +12,20 @@ import {
shareIOS,
shareWindows,
} from "@excalidraw/excalidraw/components/icons";
import { TextField } from "@excalidraw/excalidraw/components/TextField";
import { FilledButton } from "@excalidraw/excalidraw/components/FilledButton";
import type { CollabAPI } from "../collab/Collab";
import { activeRoomLinkAtom } from "../collab/Collab";
import { useUIAppState } from "@excalidraw/excalidraw/context/ui-appState";
import { useCopyStatus } from "@excalidraw/excalidraw/hooks/useCopiedIndicator";
import { useI18n } from "@excalidraw/excalidraw/i18n";
import { KEYS } from "@excalidraw/excalidraw/keys";
import { getFrame } from "@excalidraw/excalidraw/utils";
import { useEffect, useRef, useState } from "react";
import { atom, useAtom, useAtomValue } from "../app-jotai";
import { activeRoomLinkAtom } from "../collab/Collab";
import "./ShareDialog.scss";
import type { CollabAPI } from "../collab/Collab";
type OnExportToBackend = () => void;
type ShareDialogType = "share" | "collaborationOnly";

View file

@ -1,11 +1,11 @@
import ExcalidrawApp from "../App";
import { UI } from "@excalidraw/excalidraw/tests/helpers/ui";
import {
mockBoundingClientRect,
render,
restoreOriginalGetBoundingClientRect,
} from "@excalidraw/excalidraw/tests/test-utils";
import { UI } from "@excalidraw/excalidraw/tests/helpers/ui";
import ExcalidrawApp from "../App";
describe("Test MobileMenu", () => {
const { h } = window;

View file

@ -1,13 +1,14 @@
import { vi } from "vitest";
import { act, render, waitFor } from "@excalidraw/excalidraw/tests/test-utils";
import ExcalidrawApp from "../App";
import { API } from "@excalidraw/excalidraw/tests/helpers/api";
import { syncInvalidIndices } from "@excalidraw/excalidraw/fractionalIndex";
import { CaptureUpdateAction, newElementWith } from "@excalidraw/excalidraw";
import {
createRedoAction,
createUndoAction,
} from "@excalidraw/excalidraw/actions/actionHistory";
import { CaptureUpdateAction, newElementWith } from "@excalidraw/excalidraw";
import { syncInvalidIndices } from "@excalidraw/excalidraw/fractionalIndex";
import { API } from "@excalidraw/excalidraw/tests/helpers/api";
import { act, render, waitFor } from "@excalidraw/excalidraw/tests/test-utils";
import { vi } from "vitest";
import ExcalidrawApp from "../App";
const { h } = window;

View file

@ -1,8 +1,10 @@
import { useEffect, useLayoutEffect, useState } from "react";
import { THEME } from "@excalidraw/excalidraw";
import { EVENT } from "@excalidraw/excalidraw/constants";
import type { Theme } from "@excalidraw/excalidraw/element/types";
import { CODES, KEYS } from "@excalidraw/excalidraw/keys";
import { useEffect, useLayoutEffect, useState } from "react";
import type { Theme } from "@excalidraw/excalidraw/element/types";
import { STORAGE_KEYS } from "./app_constants";
const getDarkThemeMediaQuery = (): MediaQueryList | undefined =>

View file

@ -26,6 +26,7 @@
"dotenv": "16.0.1",
"eslint-config-prettier": "8.5.0",
"eslint-config-react-app": "7.0.1",
"eslint-plugin-import": "2.31.0",
"eslint-plugin-prettier": "3.3.1",
"http-server": "14.1.1",
"husky": "7.0.4",

View file

@ -1,10 +1,11 @@
import { register } from "./register";
import { deepCopyElement } from "../element/newElement";
import { randomId } from "../random";
import { t } from "../i18n";
import { LIBRARY_DISABLED_TYPES } from "../constants";
import { deepCopyElement } from "../element/newElement";
import { t } from "../i18n";
import { randomId } from "../random";
import { CaptureUpdateAction } from "../store";
import { register } from "./register";
export const actionAddToLibrary = register({
name: "addToLibrary",
trackEvent: { category: "element" },

View file

@ -1,5 +1,5 @@
import type { Alignment } from "../align";
import { alignElements } from "../align";
import { ToolButton } from "../components/ToolButton";
import {
AlignBottomIcon,
AlignLeftIcon,
@ -8,19 +8,21 @@ import {
CenterHorizontallyIcon,
CenterVerticallyIcon,
} from "../components/icons";
import { ToolButton } from "../components/ToolButton";
import { getNonDeletedElements } from "../element";
import { isFrameLikeElement } from "../element/typeChecks";
import type { ExcalidrawElement } from "../element/types";
import { updateFrameMembershipOfSelectedElements } from "../frame";
import { t } from "../i18n";
import { KEYS } from "../keys";
import { isSomeElementSelected } from "../scene";
import { CaptureUpdateAction } from "../store";
import type { AppClassProperties, AppState, UIAppState } from "../types";
import { arrayToMap, getShortcutKey } from "../utils";
import { register } from "./register";
import type { Alignment } from "../align";
import type { ExcalidrawElement } from "../element/types";
import type { AppClassProperties, AppState, UIAppState } from "../types";
export const alignActionsPredicate = (
appState: UIAppState,
app: AppClassProperties,

View file

@ -5,6 +5,11 @@ import {
VERTICAL_ALIGN,
} from "../constants";
import { isTextElement, newElement } from "../element";
import {
getOriginalContainerHeightFromCache,
resetOriginalContainerCache,
updateOriginalContainerCache,
} from "../element/containerCache";
import { mutateElement } from "../element/mutateElement";
import {
computeBoundTextPosition,
@ -12,16 +17,18 @@ import {
getBoundTextElement,
redrawTextBoundingBox,
} from "../element/textElement";
import {
getOriginalContainerHeightFromCache,
resetOriginalContainerCache,
updateOriginalContainerCache,
} from "../element/containerCache";
import { measureText } from "../element/textMeasurements";
import {
hasBoundTextElement,
isTextBindableContainer,
isUsingAdaptiveRadius,
} from "../element/typeChecks";
import { syncMovedIndices } from "../fractionalIndex";
import { CaptureUpdateAction } from "../store";
import { arrayToMap, getFontString } from "../utils";
import { register } from "./register";
import type {
ExcalidrawElement,
ExcalidrawLinearElement,
@ -30,11 +37,6 @@ import type {
} from "../element/types";
import type { AppState } from "../types";
import type { Mutable } from "../utility-types";
import { arrayToMap, getFontString } from "../utils";
import { register } from "./register";
import { syncMovedIndices } from "../fractionalIndex";
import { CaptureUpdateAction } from "../store";
import { measureText } from "../element/textMeasurements";
export const actionUnbindText = register({
name: "unbindText",

View file

@ -1,4 +1,14 @@
import { clamp, roundToStep } from "@excalidraw/math";
import {
getDefaultAppState,
isEraserActive,
isHandToolActive,
} from "../appState";
import { DEFAULT_CANVAS_BACKGROUND_PICKS } from "../colors";
import { ColorPicker } from "../components/ColorPicker/ColorPicker";
import { ToolButton } from "../components/ToolButton";
import { Tooltip } from "../components/Tooltip";
import {
handIcon,
MoonIcon,
@ -9,7 +19,6 @@ import {
ZoomOutIcon,
ZoomResetIcon,
} from "../components/icons";
import { ToolButton } from "../components/ToolButton";
import {
CURSOR_TYPE,
MAX_ZOOM,
@ -17,28 +26,22 @@ import {
THEME,
ZOOM_STEP,
} from "../constants";
import { setCursor } from "../cursor";
import { getCommonBounds, getNonDeletedElements } from "../element";
import type { ExcalidrawElement } from "../element/types";
import { newElementWith } from "../element/mutateElement";
import { t } from "../i18n";
import { CODES, KEYS } from "../keys";
import { getNormalizedZoom } from "../scene";
import { centerScrollOn } from "../scene/scroll";
import { getStateForZoom } from "../scene/zoom";
import type { AppState, Offsets } from "../types";
import { getShortcutKey, updateActiveTool } from "../utils";
import { register } from "./register";
import { Tooltip } from "../components/Tooltip";
import { newElementWith } from "../element/mutateElement";
import {
getDefaultAppState,
isEraserActive,
isHandToolActive,
} from "../appState";
import { DEFAULT_CANVAS_BACKGROUND_PICKS } from "../colors";
import type { SceneBounds } from "../element/bounds";
import { setCursor } from "../cursor";
import { CaptureUpdateAction } from "../store";
import { clamp, roundToStep } from "@excalidraw/math";
import { getShortcutKey, updateActiveTool } from "../utils";
import { register } from "./register";
import type { SceneBounds } from "../element/bounds";
import type { ExcalidrawElement } from "../element/types";
import type { AppState, Offsets } from "../types";
export const actionChangeViewBackgroundColor = register({
name: "changeViewBackgroundColor",

View file

@ -1,5 +1,3 @@
import { CODES, KEYS } from "../keys";
import { register } from "./register";
import {
copyTextToSystemClipboard,
copyToClipboard,
@ -8,14 +6,17 @@ import {
probablySupportsClipboardWriteText,
readSystemClipboard,
} from "../clipboard";
import { actionDeleteSelected } from "./actionDeleteSelected";
import { DuplicateIcon, cutIcon, pngIcon, svgIcon } from "../components/icons";
import { isFirefox } from "../constants";
import { exportCanvas, prepareElementsForExport } from "../data/index";
import { getTextFromElements, isTextElement } from "../element";
import { t } from "../i18n";
import { isFirefox } from "../constants";
import { DuplicateIcon, cutIcon, pngIcon, svgIcon } from "../components/icons";
import { CODES, KEYS } from "../keys";
import { CaptureUpdateAction } from "../store";
import { actionDeleteSelected } from "./actionDeleteSelected";
import { register } from "./register";
export const actionCopy = register({
name: "copy",
label: "labels.copy",

View file

@ -1,9 +1,11 @@
import { register } from "./register";
import { cropIcon } from "../components/icons";
import { CaptureUpdateAction } from "../store";
import { ToolButton } from "../components/ToolButton";
import { t } from "../i18n";
import { cropIcon } from "../components/icons";
import { isImageElement } from "../element/typeChecks";
import { t } from "../i18n";
import { CaptureUpdateAction } from "../store";
import { register } from "./register";
import type { ExcalidrawImageElement } from "../element/types";
export const actionToggleCropEditor = register({

View file

@ -1,7 +1,9 @@
import React from "react";
import { Excalidraw, mutateElement } from "../index";
import { act, assertElements, render } from "../tests/test-utils";
import { API } from "../tests/helpers/api";
import { act, assertElements, render } from "../tests/test-utils";
import { actionDeleteSelected } from "./actionDeleteSelected";
const { h } = window;

View file

@ -1,25 +1,27 @@
import { getSelectedElements, isSomeElementSelected } from "../scene";
import { KEYS } from "../keys";
import { ToolButton } from "../components/ToolButton";
import { t } from "../i18n";
import { register } from "./register";
import { TrashIcon } from "../components/icons";
import { getNonDeletedElements } from "../element";
import type { ExcalidrawElement } from "../element/types";
import type { AppClassProperties, AppState } from "../types";
import { mutateElement, newElementWith } from "../element/mutateElement";
import { getElementsInGroup, selectGroupsForSelectedElements } from "../groups";
import { LinearElementEditor } from "../element/linearElementEditor";
import { fixBindingsAfterDeletion } from "../element/binding";
import { LinearElementEditor } from "../element/linearElementEditor";
import { mutateElement, newElementWith } from "../element/mutateElement";
import { getContainerElement } from "../element/textElement";
import {
isBoundToContainer,
isElbowArrow,
isFrameLikeElement,
} from "../element/typeChecks";
import { updateActiveTool } from "../utils";
import { TrashIcon } from "../components/icons";
import { CaptureUpdateAction } from "../store";
import { getContainerElement } from "../element/textElement";
import { getFrameChildren } from "../frame";
import { getElementsInGroup, selectGroupsForSelectedElements } from "../groups";
import { t } from "../i18n";
import { KEYS } from "../keys";
import { getSelectedElements, isSomeElementSelected } from "../scene";
import { CaptureUpdateAction } from "../store";
import { updateActiveTool } from "../utils";
import { register } from "./register";
import type { ExcalidrawElement } from "../element/types";
import type { AppClassProperties, AppState } from "../types";
const deleteSelectedElements = (
elements: readonly ExcalidrawElement[],

View file

@ -1,22 +1,24 @@
import { ToolButton } from "../components/ToolButton";
import {
DistributeHorizontallyIcon,
DistributeVerticallyIcon,
} from "../components/icons";
import { ToolButton } from "../components/ToolButton";
import type { Distribution } from "../distribute";
import { distributeElements } from "../distribute";
import { getNonDeletedElements } from "../element";
import { isFrameLikeElement } from "../element/typeChecks";
import type { ExcalidrawElement } from "../element/types";
import { updateFrameMembershipOfSelectedElements } from "../frame";
import { t } from "../i18n";
import { CODES, KEYS } from "../keys";
import { isSomeElementSelected } from "../scene";
import { CaptureUpdateAction } from "../store";
import type { AppClassProperties, AppState } from "../types";
import { arrayToMap, getShortcutKey } from "../utils";
import { register } from "./register";
import type { Distribution } from "../distribute";
import type { ExcalidrawElement } from "../element/types";
import type { AppClassProperties, AppState } from "../types";
const enableActionGroup = (appState: AppState, app: AppClassProperties) => {
const selectedElements = app.scene.getSelectedElements(appState);
return (

View file

@ -1,14 +1,16 @@
import React from "react";
import { ORIG_ID } from "../constants";
import { Excalidraw } from "../index";
import { API } from "../tests/helpers/api";
import {
act,
assertElements,
getCloneByOrigId,
render,
} from "../tests/test-utils";
import { API } from "../tests/helpers/api";
import { actionDuplicateSelection } from "./actionDuplicateSelection";
import React from "react";
import { ORIG_ID } from "../constants";
const { h } = window;

View file

@ -1,27 +1,8 @@
import { KEYS } from "../keys";
import { register } from "./register";
import type { ExcalidrawElement } from "../element/types";
import { duplicateElement, getNonDeletedElements } from "../element";
import { isSomeElementSelected } from "../scene";
import { ToolButton } from "../components/ToolButton";
import { t } from "../i18n";
import {
arrayToMap,
castArray,
findLastIndex,
getShortcutKey,
invariant,
} from "../utils";
import { LinearElementEditor } from "../element/linearElementEditor";
import {
selectGroupsForSelectedElements,
getSelectedGroupForElement,
getElementsInGroup,
} from "../groups";
import type { AppState } from "../types";
import { fixBindingsAfterDuplication } from "../element/binding";
import type { ActionResult } from "./types";
import { DuplicateIcon } from "../components/icons";
import { DEFAULT_GRID_SIZE } from "../constants";
import { duplicateElement, getNonDeletedElements } from "../element";
import { fixBindingsAfterDuplication } from "../element/binding";
import {
bindTextToShapeAfterDuplication,
getBoundTextElement,
@ -33,16 +14,37 @@ import {
isFrameLikeElement,
} from "../element/typeChecks";
import { normalizeElementOrder } from "../element/sortElements";
import { DuplicateIcon } from "../components/icons";
import { LinearElementEditor } from "../element/linearElementEditor";
import {
bindElementsToFramesAfterDuplication,
getFrameChildren,
} from "../frame";
import {
selectGroupsForSelectedElements,
getSelectedGroupForElement,
getElementsInGroup,
} from "../groups";
import { t } from "../i18n";
import { KEYS } from "../keys";
import { isSomeElementSelected } from "../scene";
import {
excludeElementsInFramesFromSelection,
getSelectedElements,
} from "../scene/selection";
import { CaptureUpdateAction } from "../store";
import {
arrayToMap,
castArray,
findLastIndex,
getShortcutKey,
invariant,
} from "../utils";
import { register } from "./register";
import type { ActionResult } from "./types";
import type { ExcalidrawElement } from "../element/types";
import type { AppState } from "../types";
export const actionDuplicateSelection = register({
name: "duplicateSelection",

View file

@ -8,6 +8,7 @@ import {
import { t } from "../i18n";
import { getSelectedElements } from "../scene";
import { CaptureUpdateAction } from "../store";
import { register } from "./register";
export const actionCopyElementLink = register({

View file

@ -1,9 +1,10 @@
import React from "react";
import { Excalidraw } from "../index";
import { queryByTestId, fireEvent } from "@testing-library/react";
import { render } from "../tests/test-utils";
import { Pointer, UI } from "../tests/helpers/ui";
import React from "react";
import { Excalidraw } from "../index";
import { API } from "../tests/helpers/api";
import { Pointer, UI } from "../tests/helpers/ui";
import { render } from "../tests/test-utils";
const { h } = window;
const mouse = new Pointer("mouse");

View file

@ -1,13 +1,15 @@
import { LockedIcon, UnlockedIcon } from "../components/icons";
import { newElementWith } from "../element/mutateElement";
import { isFrameLikeElement } from "../element/typeChecks";
import type { ExcalidrawElement } from "../element/types";
import { KEYS } from "../keys";
import { getSelectedElements } from "../scene";
import { CaptureUpdateAction } from "../store";
import { arrayToMap } from "../utils";
import { register } from "./register";
import type { ExcalidrawElement } from "../element/types";
const shouldLock = (elements: readonly ExcalidrawElement[]) =>
elements.every((el) => !el.locked);

View file

@ -1,25 +1,27 @@
import { ExportIcon, questionCircle, saveAs } from "../components/icons";
import { useDevice } from "../components/App";
import { CheckboxItem } from "../components/CheckboxItem";
import { DarkModeToggle } from "../components/DarkModeToggle";
import { ProjectName } from "../components/ProjectName";
import { ToolButton } from "../components/ToolButton";
import { Tooltip } from "../components/Tooltip";
import { DarkModeToggle } from "../components/DarkModeToggle";
import { loadFromJSON, saveAsJSON } from "../data";
import { resaveAsImageWithScene } from "../data/resave";
import { t } from "../i18n";
import { useDevice } from "../components/App";
import { KEYS } from "../keys";
import { register } from "./register";
import { CheckboxItem } from "../components/CheckboxItem";
import { getExportSize } from "../scene/export";
import { ExportIcon, questionCircle, saveAs } from "../components/icons";
import { DEFAULT_EXPORT_PADDING, EXPORT_SCALES, THEME } from "../constants";
import { getSelectedElements, isSomeElementSelected } from "../scene";
import { getNonDeletedElements } from "../element";
import { loadFromJSON, saveAsJSON } from "../data";
import { isImageFileHandle } from "../data/blob";
import { nativeFileSystemSupported } from "../data/filesystem";
import type { Theme } from "../element/types";
import { resaveAsImageWithScene } from "../data/resave";
import { getNonDeletedElements } from "../element";
import { t } from "../i18n";
import { KEYS } from "../keys";
import { getSelectedElements, isSomeElementSelected } from "../scene";
import { getExportSize } from "../scene/export";
import { CaptureUpdateAction } from "../store";
import "../components/ToolIcon.scss";
import { CaptureUpdateAction } from "../store";
import { register } from "./register";
import type { Theme } from "../element/types";
export const actionChangeProjectName = register({
name: "changeProjectName",

View file

@ -1,22 +1,25 @@
import { KEYS } from "../keys";
import { isInvisiblySmallElement } from "../element";
import { arrayToMap, updateActiveTool } from "../utils";
import { pointFrom } from "@excalidraw/math";
import { ToolButton } from "../components/ToolButton";
import { done } from "../components/icons";
import { t } from "../i18n";
import { register } from "./register";
import { mutateElement } from "../element/mutateElement";
import { LinearElementEditor } from "../element/linearElementEditor";
import { resetCursor } from "../cursor";
import { isInvisiblySmallElement } from "../element";
import {
maybeBindLinearElement,
bindOrUnbindLinearElement,
} from "../element/binding";
import { LinearElementEditor } from "../element/linearElementEditor";
import { mutateElement } from "../element/mutateElement";
import { isBindingElement, isLinearElement } from "../element/typeChecks";
import type { AppState } from "../types";
import { resetCursor } from "../cursor";
import { CaptureUpdateAction } from "../store";
import { pointFrom } from "@excalidraw/math";
import { t } from "../i18n";
import { KEYS } from "../keys";
import { isPathALoop } from "../shapes";
import { CaptureUpdateAction } from "../store";
import { arrayToMap, updateActiveTool } from "../utils";
import { register } from "./register";
import type { AppState } from "../types";
export const actionFinalize = register({
name: "finalize",

View file

@ -1,8 +1,10 @@
import React from "react";
import { Excalidraw } from "../index";
import { render } from "../tests/test-utils";
import { API } from "../tests/helpers/api";
import { pointFrom } from "@excalidraw/math";
import React from "react";
import { Excalidraw } from "../index";
import { API } from "../tests/helpers/api";
import { render } from "../tests/test-utils";
import { actionFlipHorizontal, actionFlipVertical } from "./actionFlip";
const { h } = window;

View file

@ -1,6 +1,26 @@
import { register } from "./register";
import { getSelectedElements } from "../scene";
import { flipHorizontal, flipVertical } from "../components/icons";
import { getNonDeletedElements } from "../element";
import {
bindOrUnbindLinearElements,
isBindingEnabled,
} from "../element/binding";
import { getCommonBoundingBox } from "../element/bounds";
import { mutateElement, newElementWith } from "../element/mutateElement";
import { deepCopyElement } from "../element/newElement";
import { resizeMultipleElements } from "../element/resizeElements";
import {
isArrowElement,
isElbowArrow,
isLinearElement,
} from "../element/typeChecks";
import { updateFrameMembershipOfSelectedElements } from "../frame";
import { CODES, KEYS } from "../keys";
import { getSelectedElements } from "../scene";
import { CaptureUpdateAction } from "../store";
import { arrayToMap } from "../utils";
import { register } from "./register";
import type {
ExcalidrawArrowElement,
ExcalidrawElbowArrowElement,
@ -8,25 +28,7 @@ import type {
NonDeleted,
NonDeletedSceneElementsMap,
} from "../element/types";
import { resizeMultipleElements } from "../element/resizeElements";
import type { AppClassProperties, AppState } from "../types";
import { arrayToMap } from "../utils";
import { CODES, KEYS } from "../keys";
import {
bindOrUnbindLinearElements,
isBindingEnabled,
} from "../element/binding";
import { updateFrameMembershipOfSelectedElements } from "../frame";
import { flipHorizontal, flipVertical } from "../components/icons";
import { CaptureUpdateAction } from "../store";
import {
isArrowElement,
isElbowArrow,
isLinearElement,
} from "../element/typeChecks";
import { mutateElement, newElementWith } from "../element/mutateElement";
import { deepCopyElement } from "../element/newElement";
import { getCommonBoundingBox } from "../element/bounds";
export const actionFlipHorizontal = register({
name: "flipHorizontal",

View file

@ -1,19 +1,21 @@
import { frameToolIcon } from "../components/icons";
import { setCursorForShape } from "../cursor";
import { getCommonBounds, getNonDeletedElements } from "../element";
import type { ExcalidrawElement } from "../element/types";
import { mutateElement } from "../element/mutateElement";
import { newFrameElement } from "../element/newElement";
import { isFrameLikeElement } from "../element/typeChecks";
import { addElementsToFrame, removeAllElementsFromFrame } from "../frame";
import { getFrameChildren } from "../frame";
import { KEYS } from "../keys";
import type { AppClassProperties, AppState, UIAppState } from "../types";
import { updateActiveTool } from "../utils";
import { setCursorForShape } from "../cursor";
import { register } from "./register";
import { isFrameLikeElement } from "../element/typeChecks";
import { frameToolIcon } from "../components/icons";
import { CaptureUpdateAction } from "../store";
import { getSelectedElements } from "../scene";
import { newFrameElement } from "../element/newElement";
import { getElementsInGroup } from "../groups";
import { mutateElement } from "../element/mutateElement";
import { KEYS } from "../keys";
import { getSelectedElements } from "../scene";
import { CaptureUpdateAction } from "../store";
import { updateActiveTool } from "../utils";
import { register } from "./register";
import type { ExcalidrawElement } from "../element/types";
import type { AppClassProperties, AppState, UIAppState } from "../types";
const isSingleFrameSelected = (
appState: UIAppState,

View file

@ -1,29 +1,9 @@
import { KEYS } from "../keys";
import { t } from "../i18n";
import { arrayToMap, getShortcutKey } from "../utils";
import { register } from "./register";
import { UngroupIcon, GroupIcon } from "../components/icons";
import { newElementWith } from "../element/mutateElement";
import { isSomeElementSelected } from "../scene";
import {
getSelectedGroupIds,
selectGroup,
selectGroupsForSelectedElements,
getElementsInGroup,
addToGroup,
removeFromSelectedGroups,
isElementInGroup,
} from "../groups";
import { getNonDeletedElements } from "../element";
import { randomId } from "../random";
import { ToolButton } from "../components/ToolButton";
import type {
ExcalidrawElement,
ExcalidrawTextElement,
OrderedExcalidrawElement,
} from "../element/types";
import type { AppClassProperties, AppState } from "../types";
import { UngroupIcon, GroupIcon } from "../components/icons";
import { getNonDeletedElements } from "../element";
import { newElementWith } from "../element/mutateElement";
import { isBoundToContainer } from "../element/typeChecks";
import { syncMovedIndices } from "../fractionalIndex";
import {
frameAndChildrenSelectedTogether,
getElementsInResizingFrame,
@ -33,8 +13,30 @@ import {
removeElementsFromFrame,
replaceAllElementsInFrame,
} from "../frame";
import { syncMovedIndices } from "../fractionalIndex";
import {
getSelectedGroupIds,
selectGroup,
selectGroupsForSelectedElements,
getElementsInGroup,
addToGroup,
removeFromSelectedGroups,
isElementInGroup,
} from "../groups";
import { t } from "../i18n";
import { KEYS } from "../keys";
import { randomId } from "../random";
import { isSomeElementSelected } from "../scene";
import { CaptureUpdateAction } from "../store";
import { arrayToMap, getShortcutKey } from "../utils";
import { register } from "./register";
import type {
ExcalidrawElement,
ExcalidrawTextElement,
OrderedExcalidrawElement,
} from "../element/types";
import type { AppClassProperties, AppState } from "../types";
const allElementsInSameGroup = (elements: readonly ExcalidrawElement[]) => {
if (elements.length >= 2) {

View file

@ -1,17 +1,18 @@
import type { Action, ActionResult } from "./types";
import { UndoIcon, RedoIcon } from "../components/icons";
import { ToolButton } from "../components/ToolButton";
import { t } from "../i18n";
import type { History } from "../history";
import { HistoryChangedEvent } from "../history";
import type { AppClassProperties, AppState } from "../types";
import { KEYS, matchKey } from "../keys";
import { arrayToMap } from "../utils";
import { UndoIcon, RedoIcon } from "../components/icons";
import { isWindows } from "../constants";
import type { SceneElementsMap } from "../element/types";
import type { Store } from "../store";
import { CaptureUpdateAction } from "../store";
import { HistoryChangedEvent } from "../history";
import { useEmitter } from "../hooks/useEmitter";
import { t } from "../i18n";
import { KEYS, matchKey } from "../keys";
import { CaptureUpdateAction } from "../store";
import { arrayToMap } from "../utils";
import type { SceneElementsMap } from "../element/types";
import type { History } from "../history";
import type { Store } from "../store";
import type { AppClassProperties, AppState } from "../types";
import type { Action, ActionResult } from "./types";
const executeHistoryAction = (
app: AppClassProperties,

View file

@ -1,12 +1,14 @@
import { DEFAULT_CATEGORIES } from "../components/CommandPalette/CommandPalette";
import { ToolButton } from "../components/ToolButton";
import { lineEditorIcon } from "../components/icons";
import { LinearElementEditor } from "../element/linearElementEditor";
import { isElbowArrow, isLinearElement } from "../element/typeChecks";
import type { ExcalidrawLinearElement } from "../element/types";
import { CaptureUpdateAction } from "../store";
import { register } from "./register";
import { ToolButton } from "../components/ToolButton";
import { t } from "../i18n";
import { lineEditorIcon } from "../components/icons";
import { CaptureUpdateAction } from "../store";
import { register } from "./register";
import type { ExcalidrawLinearElement } from "../element/types";
export const actionToggleLinearEditor = register({
name: "toggleLinearEditor",

View file

@ -1,12 +1,13 @@
import { ToolButton } from "../components/ToolButton";
import { getContextMenuLabel } from "../components/hyperlink/Hyperlink";
import { LinkIcon } from "../components/icons";
import { ToolButton } from "../components/ToolButton";
import { isEmbeddableElement } from "../element/typeChecks";
import { t } from "../i18n";
import { KEYS } from "../keys";
import { getSelectedElements } from "../scene";
import { CaptureUpdateAction } from "../store";
import { getShortcutKey } from "../utils";
import { register } from "./register";
export const actionLink = register({

View file

@ -1,11 +1,12 @@
import { HamburgerMenuIcon, HelpIconThin, palette } from "../components/icons";
import { ToolButton } from "../components/ToolButton";
import { t } from "../i18n";
import { HamburgerMenuIcon, HelpIconThin, palette } from "../components/icons";
import { showSelectedShapeActions, getNonDeletedElements } from "../element";
import { register } from "./register";
import { t } from "../i18n";
import { KEYS } from "../keys";
import { CaptureUpdateAction } from "../store";
import { register } from "./register";
export const actionToggleCanvasMenu = register({
name: "toggleCanvasMenu",
label: "buttons.menu",

View file

@ -1,6 +1,7 @@
import clsx from "clsx";
import { getClientColor } from "../clients";
import { Avatar } from "../components/Avatar";
import type { GoToCollaboratorComponentProps } from "../components/UserList";
import {
eyeIcon,
microphoneIcon,
@ -8,9 +9,11 @@ import {
} from "../components/icons";
import { t } from "../i18n";
import { CaptureUpdateAction } from "../store";
import type { Collaborator } from "../types";
import { register } from "./register";
import clsx from "clsx";
import type { GoToCollaboratorComponentProps } from "../components/UserList";
import type { Collaborator } from "../types";
export const actionGoToCollaborator = register({
name: "goToCollaborator",

View file

@ -1,11 +1,12 @@
import React from "react";
import { Excalidraw } from "../index";
import { queryByTestId } from "@testing-library/react";
import { render } from "../tests/test-utils";
import { UI } from "../tests/helpers/ui";
import { API } from "../tests/helpers/api";
import React from "react";
import { COLOR_PALETTE, DEFAULT_ELEMENT_BACKGROUND_PICKS } from "../colors";
import { FONT_FAMILY, STROKE_WIDTH } from "../constants";
import { Excalidraw } from "../index";
import { API } from "../tests/helpers/api";
import { UI } from "../tests/helpers/ui";
import { render } from "../tests/test-utils";
describe("element locking", () => {
beforeEach(async () => {

View file

@ -1,20 +1,23 @@
import { pointFrom } from "@excalidraw/math";
import { useEffect, useMemo, useRef, useState } from "react";
import type { AppClassProperties, AppState, Primitive } from "../types";
import type { CaptureUpdateActionType } from "../store";
import type { LocalPoint } from "@excalidraw/math";
import { trackEvent } from "../analytics";
import {
DEFAULT_ELEMENT_BACKGROUND_COLOR_PALETTE,
DEFAULT_ELEMENT_BACKGROUND_PICKS,
DEFAULT_ELEMENT_STROKE_COLOR_PALETTE,
DEFAULT_ELEMENT_STROKE_PICKS,
} from "../colors";
import { trackEvent } from "../analytics";
import { ButtonIconSelect } from "../components/ButtonIconSelect";
import { ColorPicker } from "../components/ColorPicker/ColorPicker";
import { IconPicker } from "../components/IconPicker";
import { FontPicker } from "../components/FontPicker/FontPicker";
import { IconPicker } from "../components/IconPicker";
// TODO barnabasmolnar/editor-redesign
// TextAlignTopIcon, TextAlignBottomIcon,TextAlignMiddleIcon,
// ArrowHead icons
import { Range } from "../components/Range";
import {
ArrowheadArrowIcon,
ArrowheadBarIcon,
@ -71,6 +74,14 @@ import {
isTextElement,
redrawTextBoundingBox,
} from "../element";
import {
bindLinearElement,
bindPointToSnapToElementOutline,
calculateFixedPointForElbowArrowBinding,
getHoveredElementForBinding,
updateBoundElements,
} from "../element/binding";
import { LinearElementEditor } from "../element/linearElementEditor";
import { mutateElement, newElementWith } from "../element/mutateElement";
import { getBoundTextElement } from "../element/textElement";
import {
@ -80,17 +91,7 @@ import {
isLinearElement,
isUsingAdaptiveRadius,
} from "../element/typeChecks";
import type {
Arrowhead,
ExcalidrawBindableElement,
ExcalidrawElement,
ExcalidrawLinearElement,
ExcalidrawTextElement,
FontFamilyValues,
TextAlign,
VerticalAlign,
NonDeletedSceneElementsMap,
} from "../element/types";
import { Fonts, getLineHeight } from "../fonts";
import { getLanguage, t } from "../i18n";
import { KEYS } from "../keys";
import { randomInteger } from "../random";
@ -102,26 +103,29 @@ import {
isSomeElementSelected,
} from "../scene";
import { hasStrokeColor } from "../scene/comparisons";
import { CaptureUpdateAction } from "../store";
import {
arrayToMap,
getFontFamilyString,
getShortcutKey,
tupleToCoors,
} from "../utils";
import { register } from "./register";
import { CaptureUpdateAction } from "../store";
import { Fonts, getLineHeight } from "../fonts";
import {
bindLinearElement,
bindPointToSnapToElementOutline,
calculateFixedPointForElbowArrowBinding,
getHoveredElementForBinding,
updateBoundElements,
} from "../element/binding";
import { LinearElementEditor } from "../element/linearElementEditor";
import type { LocalPoint } from "@excalidraw/math";
import { pointFrom } from "@excalidraw/math";
import { Range } from "../components/Range";
import type {
Arrowhead,
ExcalidrawBindableElement,
ExcalidrawElement,
ExcalidrawLinearElement,
ExcalidrawTextElement,
FontFamilyValues,
TextAlign,
VerticalAlign,
NonDeletedSceneElementsMap,
} from "../element/types";
import type { CaptureUpdateActionType } from "../store";
import type { AppClassProperties, AppState, Primitive } from "../types";
const FONT_SIZE_RELATIVE_INCREASE_STEP = 0.1;

View file

@ -1,13 +1,15 @@
import { KEYS } from "../keys";
import { register } from "./register";
import { selectGroupsForSelectedElements } from "../groups";
import { getNonDeletedElements, isTextElement } from "../element";
import type { ExcalidrawElement } from "../element/types";
import { isLinearElement } from "../element/typeChecks";
import { LinearElementEditor } from "../element/linearElementEditor";
import { selectAllIcon } from "../components/icons";
import { getNonDeletedElements, isTextElement } from "../element";
import { LinearElementEditor } from "../element/linearElementEditor";
import { isLinearElement } from "../element/typeChecks";
import { selectGroupsForSelectedElements } from "../groups";
import { KEYS } from "../keys";
import { CaptureUpdateAction } from "../store";
import { register } from "./register";
import type { ExcalidrawElement } from "../element/types";
export const actionSelectAll = register({
name: "selectAll",
label: "labels.selectAll",

View file

@ -1,17 +1,15 @@
import {
isTextElement,
isExcalidrawElement,
redrawTextBoundingBox,
} from "../element";
import { CODES, KEYS } from "../keys";
import { t } from "../i18n";
import { register } from "./register";
import { newElementWith } from "../element/mutateElement";
import { paintIcon } from "../components/icons";
import {
DEFAULT_FONT_SIZE,
DEFAULT_FONT_FAMILY,
DEFAULT_TEXT_ALIGN,
} from "../constants";
import {
isTextElement,
isExcalidrawElement,
redrawTextBoundingBox,
} from "../element";
import { newElementWith } from "../element/mutateElement";
import { getBoundTextElement } from "../element/textElement";
import {
hasBoundTextElement,
@ -20,11 +18,15 @@ import {
isFrameLikeElement,
isArrowElement,
} from "../element/typeChecks";
import { getSelectedElements } from "../scene";
import type { ExcalidrawTextElement } from "../element/types";
import { paintIcon } from "../components/icons";
import { CaptureUpdateAction } from "../store";
import { getLineHeight } from "../fonts";
import { t } from "../i18n";
import { CODES, KEYS } from "../keys";
import { getSelectedElements } from "../scene";
import { CaptureUpdateAction } from "../store";
import { register } from "./register";
import type { ExcalidrawTextElement } from "../element/types";
// `copiedStyles` is exported only for tests.
export let copiedStyles: string = "{}";

View file

@ -3,10 +3,12 @@ import { newElementWith } from "../element/mutateElement";
import { measureText } from "../element/textMeasurements";
import { getSelectedElements } from "../scene";
import { CaptureUpdateAction } from "../store";
import type { AppClassProperties } from "../types";
import { getFontString } from "../utils";
import { register } from "./register";
import type { AppClassProperties } from "../types";
export const actionTextAutoResize = register({
name: "autoResize",
label: "labels.autoResize",

View file

@ -1,9 +1,11 @@
import { CODES, KEYS } from "../keys";
import { register } from "./register";
import type { AppState } from "../types";
import { gridIcon } from "../components/icons";
import { CODES, KEYS } from "../keys";
import { CaptureUpdateAction } from "../store";
import { register } from "./register";
import type { AppState } from "../types";
export const actionToggleGridMode = register({
name: "gridMode",
icon: gridIcon,

View file

@ -1,6 +1,7 @@
import { magnetIcon } from "../components/icons";
import { CODES, KEYS } from "../keys";
import { CaptureUpdateAction } from "../store";
import { register } from "./register";
export const actionToggleObjectsSnapMode = register({

View file

@ -1,9 +1,11 @@
import { KEYS } from "../keys";
import { register } from "./register";
import type { AppState } from "../types";
import { searchIcon } from "../components/icons";
import { CaptureUpdateAction } from "../store";
import { CANVAS_SEARCH_TAB, CLASSES, DEFAULT_SIDEBAR } from "../constants";
import { KEYS } from "../keys";
import { CaptureUpdateAction } from "../store";
import { register } from "./register";
import type { AppState } from "../types";
export const actionToggleSearchMenu = register({
name: "searchMenu",

View file

@ -1,8 +1,9 @@
import { register } from "./register";
import { CODES, KEYS } from "../keys";
import { abacusIcon } from "../components/icons";
import { CODES, KEYS } from "../keys";
import { CaptureUpdateAction } from "../store";
import { register } from "./register";
export const actionToggleStats = register({
name: "stats",
label: "stats.fullTitle",

View file

@ -1,6 +1,7 @@
import { eyeIcon } from "../components/icons";
import { CODES, KEYS } from "../keys";
import { CaptureUpdateAction } from "../store";
import { register } from "./register";
export const actionToggleViewMode = register({

View file

@ -1,6 +1,7 @@
import { coffeeIcon } from "../components/icons";
import { CODES, KEYS } from "../keys";
import { CaptureUpdateAction } from "../store";
import { register } from "./register";
export const actionToggleZenMode = register({

View file

@ -1,13 +1,3 @@
import {
moveOneLeft,
moveOneRight,
moveAllLeft,
moveAllRight,
} from "../zindex";
import { KEYS, CODES } from "../keys";
import { t } from "../i18n";
import { getShortcutKey } from "../utils";
import { register } from "./register";
import {
BringForwardIcon,
BringToFrontIcon,
@ -15,7 +5,18 @@ import {
SendToBackIcon,
} from "../components/icons";
import { isDarwin } from "../constants";
import { t } from "../i18n";
import { KEYS, CODES } from "../keys";
import { CaptureUpdateAction } from "../store";
import { getShortcutKey } from "../utils";
import {
moveOneLeft,
moveOneRight,
moveAllLeft,
moveAllRight,
} from "../zindex";
import { register } from "./register";
export const actionSendBackward = register({
name: "sendBackward",

View file

@ -1,4 +1,13 @@
import React from "react";
import { trackEvent } from "../analytics";
import { isPromiseLike } from "../utils";
import type {
ExcalidrawElement,
OrderedExcalidrawElement,
} from "../element/types";
import type { AppClassProperties, AppState } from "../types";
import type {
Action,
UpdaterFn,
@ -7,13 +16,6 @@ import type {
PanelComponentProps,
ActionSource,
} from "./types";
import type {
ExcalidrawElement,
OrderedExcalidrawElement,
} from "../element/types";
import type { AppClassProperties, AppState } from "../types";
import { trackEvent } from "../analytics";
import { isPromiseLike } from "../utils";
const trackAction = (
action: Action,

View file

@ -1,7 +1,8 @@
import { isDarwin } from "../constants";
import { t } from "../i18n";
import type { SubtypeOf } from "../utility-types";
import { getShortcutKey } from "../utils";
import type { SubtypeOf } from "../utility-types";
import type { ActionName } from "./types";
export type ShortcutName =

View file

@ -1,8 +1,8 @@
import type React from "react";
import type {
ExcalidrawElement,
OrderedExcalidrawElement,
} from "../element/types";
import type { CaptureUpdateActionType } from "../store";
import type {
AppClassProperties,
AppState,
@ -10,7 +10,7 @@ import type {
BinaryFiles,
UIAppState,
} from "../types";
import type { CaptureUpdateActionType } from "../store";
import type React from "react";
export type ActionSource =
| "ui"

View file

@ -1,9 +1,10 @@
import type { ElementsMap, ExcalidrawElement } from "./element/types";
import { mutateElement } from "./element/mutateElement";
import type { BoundingBox } from "./element/bounds";
import { getCommonBoundingBox } from "./element/bounds";
import { getMaximumGroups } from "./groups";
import { updateBoundElements } from "./element/binding";
import { getCommonBoundingBox } from "./element/bounds";
import { mutateElement } from "./element/mutateElement";
import { getMaximumGroups } from "./groups";
import type { BoundingBox } from "./element/bounds";
import type { ElementsMap, ExcalidrawElement } from "./element/types";
import type Scene from "./scene/Scene";
export interface Alignment {

View file

@ -1,10 +1,13 @@
import type { LaserPointerOptions } from "@excalidraw/laser-pointer";
import { LaserPointer } from "@excalidraw/laser-pointer";
import type { AnimationFrameHandler } from "./animation-frame-handler";
import type { AppState } from "./types";
import { getSvgPathFromStroke, sceneCoordsToViewportCoords } from "./utils";
import type App from "./components/App";
import type { LaserPointerOptions } from "@excalidraw/laser-pointer";
import { SVG_NS } from "./constants";
import { getSvgPathFromStroke, sceneCoordsToViewportCoords } from "./utils";
import type { AnimationFrameHandler } from "./animation-frame-handler";
import type App from "./components/App";
import type { AppState } from "./types";
export interface Trail {
start(container: SVGSVGElement): void;

View file

@ -11,6 +11,7 @@ import {
THEME,
DEFAULT_GRID_STEP,
} from "./constants";
import type { AppState, NormalizedZoomValue } from "./types";
const defaultExportScale = EXPORT_SCALES.includes(devicePixelRatio)

View file

@ -1,5 +1,4 @@
import { ENV } from "./constants";
import type { BindableProp, BindingProp } from "./element/binding";
import {
BoundElement,
BindableElement,
@ -7,7 +6,6 @@ import {
updateBoundElements,
} from "./element/binding";
import { LinearElementEditor } from "./element/linearElementEditor";
import type { ElementUpdate } from "./element/mutateElement";
import { mutateElement, newElementWith } from "./element/mutateElement";
import {
getBoundTextElementId,
@ -20,6 +18,19 @@ import {
isImageElement,
isTextElement,
} from "./element/typeChecks";
import { orderByFractionalIndex, syncMovedIndices } from "./fractionalIndex";
import { getNonDeletedGroupIds } from "./groups";
import { getObservedAppState } from "./store";
import {
arrayToMap,
arrayToObject,
assertNever,
isShallowEqual,
toBrandedType,
} from "./utils";
import type { BindableProp, BindingProp } from "./element/binding";
import type { ElementUpdate } from "./element/mutateElement";
import type {
ExcalidrawElement,
ExcalidrawImageElement,
@ -30,9 +41,6 @@ import type {
OrderedExcalidrawElement,
SceneElementsMap,
} from "./element/types";
import { orderByFractionalIndex, syncMovedIndices } from "./fractionalIndex";
import { getNonDeletedGroupIds } from "./groups";
import { getObservedAppState } from "./store";
import type {
AppState,
ObservedAppState,
@ -40,13 +48,6 @@ import type {
ObservedStandaloneAppState,
} from "./types";
import type { SubtypeOf, ValueOf } from "./utility-types";
import {
arrayToMap,
arrayToObject,
assertNever,
isShallowEqual,
toBrandedType,
} from "./utils";
/**
* Represents the difference between two objects of the same type.

View file

@ -1,6 +1,7 @@
import type { Spreadsheet } from "./charts";
import { tryParseCells, tryParseNumber, VALID_SPREADSHEET } from "./charts";
import type { Spreadsheet } from "./charts";
describe("charts", () => {
describe("tryParseNumber", () => {
it.each<[string, number]>([

View file

@ -1,5 +1,7 @@
import type { Radians } from "@excalidraw/math";
import { pointFrom } from "@excalidraw/math";
import type { Radians } from "@excalidraw/math";
import {
COLOR_PALETTE,
DEFAULT_CHART_COLOR_INDEX,
@ -11,9 +13,10 @@ import {
VERTICAL_ALIGN,
} from "./constants";
import { newElement, newLinearElement, newTextElement } from "./element";
import type { NonDeletedExcalidrawElement } from "./element/types";
import { randomId } from "./random";
import type { NonDeletedExcalidrawElement } from "./element/types";
export type ChartElements = readonly NonDeletedExcalidrawElement[];
const BAR_WIDTH = 32;

View file

@ -6,6 +6,7 @@ import {
UserIdleState,
} from "./constants";
import { roundRect } from "./renderer/roundRect";
import type { InteractiveCanvasRenderConfig } from "./scene/types";
import type {
Collaborator,

View file

@ -1,25 +1,26 @@
import type {
ExcalidrawElement,
NonDeletedExcalidrawElement,
} from "./element/types";
import type { BinaryFiles } from "./types";
import type { Spreadsheet } from "./charts";
import { tryParseSpreadsheet, VALID_SPREADSHEET } from "./charts";
import {
ALLOWED_PASTE_MIME_TYPES,
EXPORT_DATA_TYPES,
MIME_TYPES,
} from "./constants";
import { createFile, isSupportedImageFileType } from "./data/blob";
import { mutateElement } from "./element/mutateElement";
import { deepCopyElement } from "./element/newElement";
import {
isFrameLikeElement,
isInitializedImageElement,
} from "./element/typeChecks";
import { deepCopyElement } from "./element/newElement";
import { mutateElement } from "./element/mutateElement";
import { ExcalidrawError } from "./errors";
import { getContainingFrame } from "./frame";
import { arrayToMap, isMemberOf, isPromiseLike } from "./utils";
import { createFile, isSupportedImageFileType } from "./data/blob";
import { ExcalidrawError } from "./errors";
import type { Spreadsheet } from "./charts";
import type {
ExcalidrawElement,
NonDeletedExcalidrawElement,
} from "./element/types";
import type { BinaryFiles } from "./types";
type ElementsClipboard = {
type: typeof EXPORT_DATA_TYPES.excalidrawClipboard;

View file

@ -1,4 +1,5 @@
import oc from "open-color";
import type { Merge } from "./utility-types";
// FIXME can't put to utils.ts rn because of circular dependency

View file

@ -1,13 +1,25 @@
import clsx from "clsx";
import { useState } from "react";
import type { ActionManager } from "../actions/manager";
import type {
ExcalidrawElement,
ExcalidrawElementType,
NonDeletedElementsMap,
NonDeletedSceneElementsMap,
} from "../element/types";
import { actionToggleZenMode } from "../actions";
import { KEYS } from "../keys";
import { CLASSES } from "../constants";
import { alignActionsPredicate } from "../actions/actionAlign";
import { trackEvent } from "../analytics";
import { useTunnels } from "../context/tunnels";
import {
shouldAllowVerticalAlign,
suppportsHorizontalAlign,
} from "../element/textElement";
import {
hasBoundTextElement,
isElbowArrow,
isImageElement,
isLinearElement,
isTextElement,
} from "../element/typeChecks";
import { t } from "../i18n";
import { useDevice } from "./App";
import {
canChangeRoundness,
canHaveArrowheads,
@ -16,29 +28,16 @@ import {
hasStrokeStyle,
hasStrokeWidth,
} from "../scene";
import { SHAPES } from "../shapes";
import type { AppClassProperties, AppProps, UIAppState, Zoom } from "../types";
import { capitalizeString, isTransparent } from "../utils";
import Stack from "./Stack";
import { ToolButton } from "./ToolButton";
import { hasStrokeColor, toolIsArrow } from "../scene/comparisons";
import { trackEvent } from "../analytics";
import {
hasBoundTextElement,
isElbowArrow,
isImageElement,
isLinearElement,
isTextElement,
} from "../element/typeChecks";
import clsx from "clsx";
import { actionToggleZenMode } from "../actions";
import { Tooltip } from "./Tooltip";
import {
shouldAllowVerticalAlign,
suppportsHorizontalAlign,
} from "../element/textElement";
import { SHAPES } from "../shapes";
import { capitalizeString, isTransparent } from "../utils";
import "./Actions.scss";
import { useDevice } from "./App";
import Stack from "./Stack";
import { ToolButton } from "./ToolButton";
import { Tooltip } from "./Tooltip";
import DropdownMenu from "./dropdownMenu/DropdownMenu";
import {
EmbedIcon,
@ -48,10 +47,15 @@ import {
laserPointerToolIcon,
MagicIcon,
} from "./icons";
import { KEYS } from "../keys";
import { useTunnels } from "../context/tunnels";
import { CLASSES } from "../constants";
import { alignActionsPredicate } from "../actions/actionAlign";
import type {
ExcalidrawElement,
ExcalidrawElementType,
NonDeletedElementsMap,
NonDeletedSceneElementsMap,
} from "../element/types";
import type { AppClassProperties, AppProps, UIAppState, Zoom } from "../types";
import type { ActionManager } from "../actions/manager";
export const canChangeStrokeColor = (
appState: UIAppState,

View file

@ -1,6 +1,7 @@
import { actionClearCanvas } from "../actions";
import { t } from "../i18n";
import { atom, useAtom } from "../editor-jotai";
import { t } from "../i18n";
import { useExcalidrawActionManager } from "./App";
import ConfirmDialog from "./ConfirmDialog";

View file

@ -1,10 +1,26 @@
import {
clamp,
pointFrom,
pointDistance,
vector,
pointRotateRads,
vectorScale,
vectorFromPoint,
vectorSubtract,
vectorDot,
vectorNormalize,
} from "@excalidraw/math";
import { isPointInShape } from "@excalidraw/utils/collision";
import { getSelectionBoxShape } from "@excalidraw/utils/geometry/shape";
import clsx from "clsx";
import throttle from "lodash.throttle";
import { nanoid } from "nanoid";
import React, { useContext } from "react";
import { flushSync } from "react-dom";
import type { RoughCanvas } from "roughjs/bin/canvas";
import rough from "roughjs/bin/rough";
import clsx from "clsx";
import { nanoid } from "nanoid";
import type { LocalPoint, Radians } from "@excalidraw/math";
import {
actionAddToLibrary,
actionBringForward,
@ -37,17 +53,29 @@ import {
actionToggleObjectsSnapMode,
actionToggleCropEditor,
} from "../actions";
import { actionWrapTextInContainer } from "../actions/actionBoundText";
import { actionToggleHandTool, zoomToFit } from "../actions/actionCanvas";
import { actionPaste } from "../actions/actionClipboard";
import { actionCopyElementLink } from "../actions/actionElementLink";
import { actionUnlockAllElements } from "../actions/actionElementLock";
import {
actionRemoveAllElementsFromFrame,
actionSelectAllElementsInFrame,
actionWrapSelectionInFrame,
} from "../actions/actionFrame";
import { createRedoAction, createUndoAction } from "../actions/actionHistory";
import { actionTextAutoResize } from "../actions/actionTextAutoResize";
import { actionToggleViewMode } from "../actions/actionToggleViewMode";
import { ActionManager } from "../actions/manager";
import { actions } from "../actions/register";
import type { Action, ActionResult } from "../actions/types";
import { getShortcutFromShortcutName } from "../actions/shortcuts";
import { trackEvent } from "../analytics";
import { AnimationFrameHandler } from "../animation-frame-handler";
import {
getDefaultAppState,
isEraserActive,
isHandToolActive,
} from "../appState";
import type { PastedMixedContent } from "../clipboard";
import { copyTextToSystemClipboard, parseClipboard } from "../clipboard";
import {
APP_NAME,
@ -92,7 +120,6 @@ import {
isSafari,
type EXPORT_IMAGE_TYPES,
} from "../constants";
import type { ExportedElements } from "../data";
import { exportCanvas, loadFromBlob } from "../data";
import Library, { distributeLibraryItemsOnSquareGrid } from "../data/library";
import { restore, restoreElements } from "../data/restore";
@ -167,30 +194,6 @@ import {
isFlowchartNodeElement,
isBindableElement,
} from "../element/typeChecks";
import type {
ExcalidrawBindableElement,
ExcalidrawElement,
ExcalidrawFreeDrawElement,
ExcalidrawGenericElement,
ExcalidrawLinearElement,
ExcalidrawTextElement,
NonDeleted,
InitializedExcalidrawImageElement,
ExcalidrawImageElement,
FileId,
NonDeletedExcalidrawElement,
ExcalidrawTextContainer,
ExcalidrawFrameLikeElement,
ExcalidrawMagicFrameElement,
ExcalidrawIframeLikeElement,
IframeData,
ExcalidrawIframeElement,
ExcalidrawEmbeddableElement,
Ordered,
MagicGenerationData,
ExcalidrawNonSelectionElement,
ExcalidrawArrowElement,
} from "../element/types";
import { getCenter, getDistance } from "../gesture";
import {
editGroupForSelectedElement,
@ -224,10 +227,6 @@ import {
isSomeElementSelected,
} from "../scene";
import Scene from "../scene/Scene";
import type {
RenderInteractiveSceneCallback,
ScrollBars,
} from "../scene/types";
import { getStateForZoom } from "../scene/zoom";
import {
findShapeByKey,
@ -236,36 +235,6 @@ import {
getElementShape,
isPathALoop,
} from "../shapes";
import { getSelectionBoxShape } from "@excalidraw/utils/geometry/shape";
import { isPointInShape } from "@excalidraw/utils/collision";
import type {
AppClassProperties,
AppProps,
AppState,
BinaryFileData,
DataURL,
ExcalidrawImperativeAPI,
BinaryFiles,
Gesture,
GestureEvent,
LibraryItems,
PointerDownState,
SceneData,
Device,
FrameNameBoundsCache,
SidebarName,
SidebarTabName,
KeyboardModifiersObject,
CollaboratorPointer,
ToolType,
OnUserFollowedPayload,
UnsubscribeCallback,
EmbedsValidationStatus,
ElementsPendingErasure,
GenerateDiagramToCode,
NullableGridSize,
Offsets,
} from "../types";
import {
debounce,
distance,
@ -299,11 +268,6 @@ import {
maybeParseEmbedSrc,
getEmbedLink,
} from "../element/embeddable";
import type { ContextMenuItems } from "./ContextMenu";
import { ContextMenu, CONTEXT_MENU_SEPARATOR } from "./ContextMenu";
import LayerUI from "./LayerUI";
import { Toast } from "./Toast";
import { actionToggleViewMode } from "../actions/actionToggleViewMode";
import {
dataURLToFile,
dataURLToString,
@ -326,8 +290,6 @@ import {
normalizeSVG,
updateImageCache as _updateImageCache,
} from "../element/image";
import throttle from "lodash.throttle";
import type { FileSystemHandle } from "../data/filesystem";
import { fileOpen } from "../data/filesystem";
import {
bindTextToShapeAfterDuplication,
@ -343,7 +305,6 @@ import {
} from "../components/hyperlink/Hyperlink";
import { isLocalLink, normalizeLink, toValidURL } from "../data/url";
import { shouldShowBoundingBox } from "../element/transformHandles";
import { actionUnlockAllElements } from "../actions/actionElementLock";
import { Fonts, getLineHeight } from "../fonts";
import {
getFrameChildren,
@ -366,15 +327,7 @@ import {
excludeElementsInFramesFromSelection,
makeNextSelectedElementIds,
} from "../scene/selection";
import { actionPaste } from "../actions/actionClipboard";
import {
actionRemoveAllElementsFromFrame,
actionSelectAllElementsInFrame,
actionWrapSelectionInFrame,
} from "../actions/actionFrame";
import { actionToggleHandTool, zoomToFit } from "../actions/actionCanvas";
import { editorJotaiStore } from "../editor-jotai";
import { activeConfirmDialogAtom } from "./ActiveConfirmDialog";
import { ImageSceneDataError } from "../errors";
import {
getSnapLinesAtPointer,
@ -389,17 +342,9 @@ import {
isGridModeEnabled,
getGridPoint,
} from "../snapping";
import { actionWrapTextInContainer } from "../actions/actionBoundText";
import BraveMeasureTextError from "./BraveMeasureTextError";
import { activeEyeDropperAtom } from "./EyeDropper";
import type { ExcalidrawElementSkeleton } from "../data/transform";
import { convertToExcalidrawElements } from "../data/transform";
import type { ValueOf } from "../utility-types";
import { isSidebarDockedAtom } from "./Sidebar/Sidebar";
import { StaticCanvas, InteractiveCanvas } from "./canvases";
import { Renderer } from "../scene/Renderer";
import { ShapeCache } from "../scene/ShapeCache";
import { SVGLayer } from "./SVGLayer";
import {
setEraserCursor,
setCursor,
@ -409,11 +354,7 @@ import {
import { Emitter } from "../emitter";
import { ElementCanvasButtons } from "../element/ElementCanvasButtons";
import { COLOR_PALETTE } from "../colors";
import { ElementCanvasButton } from "./MagicButton";
import { MagicIcon, copyIcon, fullscreenIcon } from "./icons";
import FollowMode from "./FollowMode/FollowMode";
import { Store, CaptureUpdateAction } from "../store";
import { AnimationFrameHandler } from "../animation-frame-handler";
import { AnimatedTrail } from "../animated-trail";
import { LaserTrails } from "../laser-trails";
import { withBatchedUpdates, withBatchedUpdatesThrottled } from "../reactUtils";
@ -426,37 +367,15 @@ import {
import { textWysiwyg } from "../element/textWysiwyg";
import { isOverScrollBars } from "../scene/scrollbars";
import { syncInvalidIndices, syncMovedIndices } from "../fractionalIndex";
import {
isPointHittingLink,
isPointHittingLinkIcon,
} from "./hyperlink/helpers";
import { getShortcutFromShortcutName } from "../actions/shortcuts";
import { actionTextAutoResize } from "../actions/actionTextAutoResize";
import { getVisibleSceneBounds } from "../element/bounds";
import { isMaybeMermaidDefinition } from "../mermaid";
import NewElementCanvas from "./canvases/NewElementCanvas";
import {
FlowChartCreator,
FlowChartNavigator,
getLinkDirectionFromKey,
} from "../element/flowchart";
import { searchItemInFocusAtom } from "./SearchMenu";
import type { LocalPoint, Radians } from "@excalidraw/math";
import {
clamp,
pointFrom,
pointDistance,
vector,
pointRotateRads,
vectorScale,
vectorFromPoint,
vectorSubtract,
vectorDot,
vectorNormalize,
} from "@excalidraw/math";
import { cropElement } from "../element/cropElement";
import { wrapText } from "../element/textWrapping";
import { actionCopyElementLink } from "../actions/actionElementLink";
import { isElementLink, parseElementLinkFromURL } from "../element/elementLink";
import {
isMeasureTextSupported,
@ -468,6 +387,90 @@ import {
getMinTextElementWidth,
} from "../element/textMeasurements";
import { activeConfirmDialogAtom } from "./ActiveConfirmDialog";
import BraveMeasureTextError from "./BraveMeasureTextError";
import { ContextMenu, CONTEXT_MENU_SEPARATOR } from "./ContextMenu";
import { activeEyeDropperAtom } from "./EyeDropper";
import FollowMode from "./FollowMode/FollowMode";
import LayerUI from "./LayerUI";
import { ElementCanvasButton } from "./MagicButton";
import { SVGLayer } from "./SVGLayer";
import { searchItemInFocusAtom } from "./SearchMenu";
import { isSidebarDockedAtom } from "./Sidebar/Sidebar";
import { StaticCanvas, InteractiveCanvas } from "./canvases";
import NewElementCanvas from "./canvases/NewElementCanvas";
import {
isPointHittingLink,
isPointHittingLinkIcon,
} from "./hyperlink/helpers";
import { MagicIcon, copyIcon, fullscreenIcon } from "./icons";
import { Toast } from "./Toast";
import type { Action, ActionResult } from "../actions/types";
import type { PastedMixedContent } from "../clipboard";
import type { ExportedElements } from "../data";
import type { ContextMenuItems } from "./ContextMenu";
import type { FileSystemHandle } from "../data/filesystem";
import type { ExcalidrawElementSkeleton } from "../data/transform";
import type {
ExcalidrawBindableElement,
ExcalidrawElement,
ExcalidrawFreeDrawElement,
ExcalidrawGenericElement,
ExcalidrawLinearElement,
ExcalidrawTextElement,
NonDeleted,
InitializedExcalidrawImageElement,
ExcalidrawImageElement,
FileId,
NonDeletedExcalidrawElement,
ExcalidrawTextContainer,
ExcalidrawFrameLikeElement,
ExcalidrawMagicFrameElement,
ExcalidrawIframeLikeElement,
IframeData,
ExcalidrawIframeElement,
ExcalidrawEmbeddableElement,
Ordered,
MagicGenerationData,
ExcalidrawNonSelectionElement,
ExcalidrawArrowElement,
} from "../element/types";
import type {
RenderInteractiveSceneCallback,
ScrollBars,
} from "../scene/types";
import type {
AppClassProperties,
AppProps,
AppState,
BinaryFileData,
DataURL,
ExcalidrawImperativeAPI,
BinaryFiles,
Gesture,
GestureEvent,
LibraryItems,
PointerDownState,
SceneData,
Device,
FrameNameBoundsCache,
SidebarName,
SidebarTabName,
KeyboardModifiersObject,
CollaboratorPointer,
ToolType,
OnUserFollowedPayload,
UnsubscribeCallback,
EmbedsValidationStatus,
ElementsPendingErasure,
GenerateDiagramToCode,
NullableGridSize,
Offsets,
} from "../types";
import type { ValueOf } from "../utility-types";
import type { RoughCanvas } from "roughjs/bin/canvas";
const AppContext = React.createContext<AppClassProperties>(null!);
const AppPropsContext = React.createContext<AppProps>(null!);

View file

@ -1,8 +1,9 @@
import "./Avatar.scss";
import React, { useState } from "react";
import { getNameInitial } from "../clients";
import clsx from "clsx";
import React, { useState } from "react";
import { getNameInitial } from "../clients";
import "./Avatar.scss";
type AvatarProps = {
onClick: (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;

View file

@ -1,6 +1,8 @@
import clsx from "clsx";
import React from "react";
import { composeEventHandlers } from "../utils";
import "./Button.scss";
interface ButtonProps

View file

@ -1,9 +1,10 @@
import { forwardRef } from "react";
import type { JSX } from "react";
import clsx from "clsx";
import { forwardRef } from "react";
import "./ButtonIcon.scss";
import type { JSX } from "react";
interface ButtonIconProps {
icon: JSX.Element;
title: string;

View file

@ -1,6 +1,7 @@
import type { JSX } from "react";
import clsx from "clsx";
import type { JSX } from "react";
export const ButtonIconCycle = <T extends any>({
options,
value,

View file

@ -1,7 +1,9 @@
import type { JSX } from "react";
import clsx from "clsx";
import { ButtonIcon } from "./ButtonIcon";
import type { JSX } from "react";
// TODO: It might be "clever" to add option.icon to the existing component <ButtonSelect />
export const ButtonIconSelect = <T extends Object>(
props: {

Some files were not shown because too many files have changed in this diff Show more