Compare commits

..

8 Commits

Author SHA1 Message Date
tk338g 232412d7bc Test fixup 2021-02-19 21:17:58 +03:00
tk338g 6a8680f500 Moved minimap rendering to offscreen canvas 2021-02-19 21:07:09 +03:00
tk338g 3b0aff0ac6 Fix minimap rerendering on scroll 2021-02-19 20:12:48 +03:00
tk338g 93d0a56bdb Check for NaN before applying styles 2021-02-19 20:12:48 +03:00
tk338g 0a3675e1b9 Update test snapshots 2021-02-19 20:12:48 +03:00
tk338g cf35caaf23 Toggle minimap with "M" key 2021-02-19 20:12:48 +03:00
tk338g 4e3bf7e8d2 Use one canvas for minimap and preserve viewport borders 2021-02-19 20:12:47 +03:00
tk338g 4c3544df4a Simple minimap implementation 2021-02-19 20:12:47 +03:00
74 changed files with 59915 additions and 20654 deletions
+6 -6
View File
@@ -1,10 +1,10 @@
* *
!.env
!.eslintrc.json
!.npmrc
!.prettierrc
!package.json
!public/ !public/
!src/ !src/
!.npmrc
!.eslintrc.json
!.prettierrc
!package-lock.json
!package.json
!tsconfig.json !tsconfig.json
!yarn.lock !.env
+6 -3
View File
@@ -1,33 +1,36 @@
version: 2 version: 2
updates: updates:
- package-ecosystem: npm - package-ecosystem: npm
directory: / directory: "/"
schedule: schedule:
interval: weekly interval: weekly
day: sunday day: sunday
time: "01:00" time: "01:00"
open-pull-requests-limit: 99
reviewers: reviewers:
- lipis - lipis
assignees: assignees:
- lipis - lipis
- package-ecosystem: npm - package-ecosystem: npm
directory: /src/packages/excalidraw/ directory: "/src/packages/excalidraw/"
schedule: schedule:
interval: weekly interval: weekly
day: sunday day: sunday
time: "01:00" time: "01:00"
open-pull-requests-limit: 99
reviewers: reviewers:
- ad1992 - ad1992
assignees: assignees:
- ad1992 - ad1992
- package-ecosystem: npm - package-ecosystem: npm
directory: /src/packages/utils/ directory: "/src/packages/utils/"
schedule: schedule:
interval: weekly interval: weekly
day: sunday day: sunday
time: "01:00" time: "01:00"
open-pull-requests-limit: 99
reviewers: reviewers:
- ad1992 - ad1992
assignees: assignees:
+3 -2
View File
@@ -6,8 +6,9 @@ on:
- master - master
jobs: jobs:
build-docker: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v1
- run: docker build -t excalidraw . - run: docker build -t excalidraw .
+12 -8
View File
@@ -7,23 +7,27 @@ on:
pull_request: pull_request:
jobs: jobs:
packages: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v1
- name: Setup Node.js 14.x - name: Setup Node.js 14.x
uses: actions/setup-node@v2 uses: actions/setup-node@v1
with: with:
node-version: 14.x node-version: 14.x
- name: Install dependencies - name: Install dependencies
run: | run: |
yarn --frozen-lockfile npm ci
yarn --cwd src/packages/excalidraw npm ci --prefix src/packages/excalidraw
yarn --cwd src/packages/utils npm ci --prefix src/packages/utils
- name: Build @excalidraw/excalidraw - name: Build @excalidraw/excalidraw
run: | run: |
yarn --cwd src/packages/excalidraw run pack npm run pack --prefix src/packages/excalidraw
- name: Build @excalidraw/utils - name: Build @excalidraw/utils
run: | run: |
yarn --cwd src/packages/utils run pack npm run pack --prefix src/packages/utils
+1
View File
@@ -9,6 +9,7 @@ on:
jobs: jobs:
cancel: cancel:
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 3 timeout-minutes: 3
steps: steps:
- uses: styfle/cancel-workflow-action@0.6.0 - uses: styfle/cancel-workflow-action@0.6.0
+6 -6
View File
@@ -7,16 +7,16 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v1
- name: Setup Node.js 14.x - name: Setup Node.js 14.x
uses: actions/setup-node@v2 uses: actions/setup-node@v1
with: with:
node-version: 14.x node-version: 14.x
- name: Install and lint - name: Install and lint
run: | run: |
yarn --frozen-lockfile npm ci
yarn test:other npm run test:other
yarn test:code npm run test:code
yarn test:typecheck npm run test:typecheck
+4 -4
View File
@@ -3,7 +3,7 @@ name: Build locales coverage
on: on:
push: push:
branches: branches:
- l10n_master - "l10n_master"
jobs: jobs:
locales: locales:
@@ -15,13 +15,13 @@ jobs:
token: ${{ secrets.PUSH_TRANSLATIONS_COVERAGE_PAT }} token: ${{ secrets.PUSH_TRANSLATIONS_COVERAGE_PAT }}
- name: Setup Node.js 14.x - name: Setup Node.js 14.x
uses: actions/setup-node@v2 uses: actions/setup-node@v1
with: with:
node-version: 14.x node-version: 14.x
- name: Create report file - name: Create report file
run: | run: |
yarn locales-coverage npm run locales-coverage
FILE_CHANGED=$(git diff src/locales/percentages.json) FILE_CHANGED=$(git diff src/locales/percentages.json)
if [ ! -z "${FILE_CHANGED}" ]; then if [ ! -z "${FILE_CHANGED}" ]; then
git config --global user.name 'Excalidraw Bot' git config --global user.name 'Excalidraw Bot'
@@ -33,7 +33,7 @@ jobs:
- name: Construct comment body - name: Construct comment body
id: getCommentBody id: getCommentBody
run: | run: |
body=$(yarn locales-coverage:description | grep '^[^>]') body=$(npm run locales-coverage:description | grep '^[^>]')
body="${body//'%'/'%25'}" body="${body//'%'/'%25'}"
body="${body//$'\n'/'%0A'}" body="${body//$'\n'/'%0A'}"
body="${body//$'\r'/'%0D'}" body="${body//$'\r'/'%0D'}"
+3 -2
View File
@@ -1,4 +1,4 @@
name: Semantic PR title name: "Semantic PR title"
on: on:
pull_request_target: pull_request_target:
@@ -8,8 +8,9 @@ on:
- synchronize - synchronize
jobs: jobs:
semantic: main:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: amannn/action-semantic-pull-request@v3.0.0 - uses: amannn/action-semantic-pull-request@v3.0.0
env: env:
+11 -6
View File
@@ -1,4 +1,4 @@
name: New Sentry production release name: New Sentry Production Release
on: on:
push: push:
@@ -6,23 +6,28 @@ on:
- master - master
jobs: jobs:
sentry: release:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v1.0.0
- name: Setup Node.js 14.x - name: Setup Node.js 14.x
uses: actions/setup-node@v2 uses: actions/setup-node@v1
with: with:
node-version: 14.x node-version: 14.x
- name: Install and build - name: Install and build
run: | run: |
yarn --frozen-lockfile npm ci
yarn build:app npm run build:app
env: env:
CI: true CI: true
- name: Install Sentry - name: Install Sentry
run: | run: |
curl -sL https://sentry.io/get-cli/ | bash curl -sL https://sentry.io/get-cli/ | bash
- name: Create new Sentry release - name: Create new Sentry release
run: | run: |
export SENTRY_RELEASE=$(sentry-cli releases propose-version) export SENTRY_RELEASE=$(sentry-cli releases propose-version)
+7 -4
View File
@@ -5,13 +5,16 @@ on: pull_request
jobs: jobs:
test: test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v1
- name: Setup Node.js 14.x - name: Setup Node.js 14.x
uses: actions/setup-node@v2 uses: actions/setup-node@v1
with: with:
node-version: 14.x node-version: 14.x
- name: Install and test - name: Install and test
run: | run: |
yarn --frozen-lockfile npm ci
yarn test:app npm run test:app
+1 -1
View File
@@ -16,7 +16,7 @@ firebase
logs logs
node_modules node_modules
npm-debug.log* npm-debug.log*
package-lock.json
static static
yarn-debug.log* yarn-debug.log*
yarn-error.log* yarn-error.log*
yarn.lock
+4
View File
@@ -0,0 +1,4 @@
{
"proseWrap": "never",
"trailingComma": "all"
}
+3 -3
View File
@@ -2,13 +2,13 @@ FROM node:14-alpine AS build
WORKDIR /opt/node_app WORKDIR /opt/node_app
COPY package.json yarn.lock ./ COPY package.json package-lock.json ./
RUN yarn --ignore-optional RUN npm i --no-optional
ARG NODE_ENV=production ARG NODE_ENV=production
COPY . . COPY . .
RUN yarn build:app:docker RUN npm run build:app:docker
FROM nginx:1.17-alpine FROM nginx:1.17-alpine
+8 -14
View File
@@ -86,12 +86,6 @@ Try out [`@excalidraw/excalidraw`](https://www.npmjs.com/package/@excalidraw/exc
These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. These instructions will get you a copy of the project up and running on your local machine for development and testing purposes.
#### Requirements
- [Node.js](https://nodejs.org/en/)
- [Yarn](https://yarnpkg.com/getting-started/install)
- [Git](https://git-scm.com/downloads)
#### Clone the repo #### Clone the repo
```bash ```bash
@@ -100,14 +94,14 @@ git clone https://github.com/excalidraw/excalidraw.git
#### Commands #### Commands
| Command | Description | | Command | Description |
| ------------------ | --------------------------------- | | --------------------- | --------------------------------- |
| `yarn` | Install the dependencies | | `npm install` | Install the dependencies |
| `yarn start` | Run the project | | `npm start` | Run the project |
| `yarn fix` | Reformat all files with Prettier | | `npm run fix` | Reformat all files with Prettier |
| `yarn test` | Run tests | | `npm test` | Run tests |
| `yarn test:update` | Update test snapshots | | `npm run test:update` | Update test snapshots |
| `yarn test:code` | Test for formatting with Prettier | | `npm run test:code` | Test for formatting with Prettier |
#### Docker Compose #### Docker Compose
+1 -1
View File
@@ -18,7 +18,7 @@ services:
volumes: volumes:
- ./:/opt/node_app/app:delegated - ./:/opt/node_app/app:delegated
- ./package.json:/opt/node_app/package.json - ./package.json:/opt/node_app/package.json
- ./yarn.lock:/opt/node_app/yarn.lock - ./package-lock.json:/opt/node_app/package-lock.json
- notused:/opt/node_app/app/node_modules - notused:/opt/node_app/app/node_modules
volumes: volumes:
+51482
View File
File diff suppressed because it is too large Load Diff
+22 -20
View File
@@ -19,20 +19,21 @@
] ]
}, },
"dependencies": { "dependencies": {
"@sentry/browser": "6.2.0", "@sentry/browser": "6.1.0",
"@sentry/integrations": "6.2.0", "@sentry/integrations": "6.1.0",
"@testing-library/jest-dom": "5.11.9", "@testing-library/jest-dom": "5.11.9",
"@testing-library/react": "11.2.5", "@testing-library/react": "11.2.5",
"@types/jest": "26.0.20", "@types/jest": "26.0.20",
"@types/react": "17.0.2", "@types/react": "17.0.2",
"@types/react-dom": "17.0.1", "@types/react-dom": "17.0.1",
"@types/socket.io-client": "1.4.35", "@types/socket.io-client": "1.4.35",
"browser-fs-access": "0.14.0", "browser-fs-access": "0.13.1",
"clsx": "1.1.1", "clsx": "1.1.1",
"firebase": "8.2.9", "firebase": "8.2.7",
"i18next-browser-languagedetector": "6.0.1", "i18next-browser-languagedetector": "6.0.1",
"lodash.throttle": "4.1.1", "lodash.throttle": "4.1.1",
"nanoid": "3.1.20", "nanoid": "3.1.20",
"node-sass": "4.14.1",
"open-color": "1.8.0", "open-color": "1.8.0",
"pako": "1.0.11", "pako": "1.0.11",
"png-chunk-text": "1.0.0", "png-chunk-text": "1.0.0",
@@ -42,29 +43,28 @@
"pwacompat": "2.0.17", "pwacompat": "2.0.17",
"react": "17.0.1", "react": "17.0.1",
"react-dom": "17.0.1", "react-dom": "17.0.1",
"react-scripts": "4.0.3", "react-scripts": "4.0.2",
"roughjs": "4.3.1", "roughjs": "4.3.1",
"sass": "1.32.8",
"socket.io-client": "2.3.1", "socket.io-client": "2.3.1",
"typescript": "4.1.5" "typescript": "4.1.5"
}, },
"devDependencies": { "devDependencies": {
"@excalidraw/prettier-config": "1.0.2",
"@types/lodash.throttle": "4.1.6", "@types/lodash.throttle": "4.1.6",
"@types/pako": "1.0.1", "@types/pako": "1.0.1",
"@types/resize-observer-browser": "0.1.5", "@types/resize-observer-browser": "0.1.5",
"eslint-config-prettier": "8.1.0", "eslint-config-prettier": "7.2.0",
"eslint-plugin-prettier": "3.3.1", "eslint-plugin-prettier": "3.3.1",
"firebase-tools": "9.5.0", "firebase-tools": "9.3.0",
"husky": "4.3.8", "husky": "4.3.8",
"jest-canvas-mock": "2.3.1", "jest-canvas-mock": "2.3.1",
"lint-staged": "10.5.4", "lint-staged": "10.5.4",
"pepjs": "0.5.3", "pepjs": "0.5.3",
"prettier": "2.2.1", "prettier": "2.2.1",
"rewire": "5.0.0" "rewire": "5.0.0",
"worker-loader": "3.0.8"
}, },
"engines": { "engines": {
"node": ">=14.0.0" "node": ">=12.0.0"
}, },
"homepage": ".", "homepage": ".",
"husky": { "husky": {
@@ -76,32 +76,34 @@
"transformIgnorePatterns": [ "transformIgnorePatterns": [
"node_modules/(?!(roughjs|points-on-curve|path-data-parser|points-on-path|browser-fs-access)/)" "node_modules/(?!(roughjs|points-on-curve|path-data-parser|points-on-path|browser-fs-access)/)"
], ],
"moduleNameMapper": {
"^worker-loader!.+": "<rootDir>/src/__mocks__/worker-mock.js"
},
"resetMocks": false "resetMocks": false
}, },
"name": "excalidraw", "name": "excalidraw",
"prettier": "@excalidraw/prettier-config",
"private": true, "private": true,
"scripts": { "scripts": {
"build-node": "node ./scripts/build-node.js", "build-node": "node ./scripts/build-node.js",
"build:app:docker": "REACT_APP_DISABLE_SENTRY=true react-scripts build", "build:app:docker": "REACT_APP_DISABLE_SENTRY=true react-scripts build",
"build:app": "REACT_APP_GIT_SHA=$VERCEL_GIT_COMMIT_SHA react-scripts build", "build:app": "REACT_APP_GIT_SHA=$VERCEL_GIT_COMMIT_SHA react-scripts build",
"build:version": "node ./scripts/build-version.js", "build:version": "node ./scripts/build-version.js",
"build": "yarn build:app && yarn build:version", "build": "npm run build:app && npm run build:version",
"eject": "react-scripts eject", "eject": "react-scripts eject",
"fix:code": "yarn test:code --fix", "fix:code": "npm run test:code -- --fix",
"fix:other": "yarn prettier --write", "fix:other": "npm run prettier -- --write",
"fix": "yarn fix:other && yarn fix:code", "fix": "npm run fix:other && npm run fix:code",
"locales-coverage": "node scripts/build-locales-coverage.js", "locales-coverage": "node scripts/build-locales-coverage.js",
"locales-coverage:description": "node scripts/locales-coverage-description.js", "locales-coverage:description": "node scripts/locales-coverage-description.js",
"prettier": "prettier \"**/*.{css,scss,json,md,html,yml}\" --ignore-path=.eslintignore", "prettier": "prettier \"**/*.{css,scss,json,md,html,yml}\" --ignore-path=.eslintignore",
"start": "react-scripts start", "start": "react-scripts start",
"test:all": "yarn test:typecheck && yarn test:code && yarn test:other && yarn test:app --watchAll=false", "test:all": "npm run test:typecheck && npm run test:code && npm run test:other && npm run test:app -- --watchAll=false",
"test:app": "react-scripts test --passWithNoTests", "test:app": "react-scripts test --passWithNoTests",
"test:code": "eslint --max-warnings=0 --ignore-path .gitignore --ext .js,.ts,.tsx .", "test:code": "eslint --max-warnings=0 --ignore-path .gitignore --ext .js,.ts,.tsx .",
"test:debug": "react-scripts --inspect-brk test --runInBand --no-cache", "test:debug": "react-scripts --inspect-brk test --runInBand --no-cache",
"test:other": "yarn prettier --list-different", "test:other": "npm run prettier -- --list-different",
"test:typecheck": "tsc", "test:typecheck": "tsc",
"test:update": "yarn test:app --updateSnapshot --watchAll=false", "test:update": "npm run test:app -- --updateSnapshot --watchAll=false",
"test": "yarn test:app" "test": "npm run test:app"
} }
} }
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1,7 +1,7 @@
/* http://www.eaglefonts.com/fg-virgil-ttf-131249.htm */ /* http://www.eaglefonts.com/fg-virgil-ttf-131249.htm */
@font-face { @font-face {
font-family: "Virgil"; font-family: "Virgil";
src: url("Virgil.woff2"); src: url("FG_Virgil.woff2");
font-display: swap; font-display: swap;
} }
+2 -4
View File
@@ -60,7 +60,7 @@
<link <link
rel="preload" rel="preload"
href="Virgil.woff2" href="FG_Virgil.woff2"
as="font" as="font"
type="font/woff2" type="font/woff2"
crossorigin="anonymous" crossorigin="anonymous"
@@ -86,9 +86,7 @@
/> />
<link rel="stylesheet" href="fonts.css" type="text/css" /> <link rel="stylesheet" href="fonts.css" type="text/css" />
<script>
window.EXCALIDRAW_ASSET_PATH = "/";
</script>
<% if (process.env.REACT_APP_GOOGLE_ANALYTICS_ID) { %> <% if (process.env.REACT_APP_GOOGLE_ANALYTICS_ID) { %>
<script <script
async async
+1 -1
View File
@@ -5,7 +5,7 @@
// In order to run: // In order to run:
// npm install canvas # please do not check it in // npm install canvas # please do not check it in
// yarn build-node // npm run build-node
// node build/static/js/build-node.js // node build/static/js/build-node.js
// open test.png // open test.png
+4
View File
@@ -0,0 +1,4 @@
module.exports = class {
postMessage() {}
terminate() {}
};
-29
View File
@@ -5,7 +5,6 @@ import { ProjectName } from "../components/ProjectName";
import { ToolButton } from "../components/ToolButton"; import { ToolButton } from "../components/ToolButton";
import "../components/ToolIcon.scss"; import "../components/ToolIcon.scss";
import { Tooltip } from "../components/Tooltip"; import { Tooltip } from "../components/Tooltip";
import { DarkModeToggle, Appearence } from "../components/DarkModeToggle";
import { loadFromJSON, saveAsJSON } from "../data"; import { loadFromJSON, saveAsJSON } from "../data";
import { t } from "../i18n"; import { t } from "../i18n";
import useIsMobile from "../is-mobile"; import useIsMobile from "../is-mobile";
@@ -205,31 +204,3 @@ export const actionLoadScene = register({
/> />
), ),
}); });
export const actionExportWithDarkMode = register({
name: "exportWithDarkMode",
perform: (_elements, appState, value) => {
return {
appState: { ...appState, exportWithDarkMode: value },
commitToHistory: false,
};
},
PanelComponent: ({ appState, updateData }) => (
<div
style={{
display: "flex",
justifyContent: "flex-end",
marginTop: "-45px",
marginBottom: "10px",
}}
>
<DarkModeToggle
value={appState.exportWithDarkMode ? "dark" : "light"}
onChange={(appearance: Appearence) => {
updateData(appearance === "dark");
}}
title={t("labels.toggleExportColorScheme")}
/>
</div>
),
});
+19
View File
@@ -7,6 +7,7 @@ import { register } from "./register";
import { allowFullScreen, exitFullScreen, isFullScreen } from "../utils"; import { allowFullScreen, exitFullScreen, isFullScreen } from "../utils";
import { CODES, KEYS } from "../keys"; import { CODES, KEYS } from "../keys";
import { HelpIcon } from "../components/HelpIcon"; import { HelpIcon } from "../components/HelpIcon";
import { MiniMap } from "../components/MiniMap";
export const actionToggleCanvasMenu = register({ export const actionToggleCanvasMenu = register({
name: "toggleCanvasMenu", name: "toggleCanvasMenu",
@@ -84,3 +85,21 @@ export const actionShortcuts = register({
), ),
keyTest: (event) => event.key === KEYS.QUESTION_MARK, keyTest: (event) => event.key === KEYS.QUESTION_MARK,
}); });
export const actionMinimap = register({
name: "toggleMinimap",
perform: (_elements, appState) => {
return {
appState: {
...appState,
isMinimapEnabled: !appState.isMinimapEnabled,
},
commitToHistory: false,
};
},
PanelComponent: ({ appState, elements }) =>
appState.isMinimapEnabled ? (
<MiniMap appState={appState} elements={elements} />
) : null,
keyTest: (event) => event.key === KEYS.M,
});
+1
View File
@@ -44,6 +44,7 @@ export {
actionToggleEditMenu, actionToggleEditMenu,
actionFullScreen, actionFullScreen,
actionShortcuts, actionShortcuts,
actionMinimap,
} from "./actionMenu"; } from "./actionMenu";
export { actionGroup, actionUngroup } from "./actionGroup"; export { actionGroup, actionUngroup } from "./actionGroup";
+1 -1
View File
@@ -86,7 +86,7 @@ export type ActionName =
| "distributeHorizontally" | "distributeHorizontally"
| "distributeVertically" | "distributeVertically"
| "viewMode" | "viewMode"
| "exportWithDarkMode"; | "toggleMinimap";
export interface Action { export interface Action {
name: ActionName; name: ActionName;
+4 -4
View File
@@ -40,10 +40,9 @@ export const getDefaultAppState = (): Omit<
errorMessage: null, errorMessage: null,
exportBackground: true, exportBackground: true,
exportEmbedScene: false, exportEmbedScene: false,
exportWithDarkMode: false,
fileHandle: null, fileHandle: null,
gridSize: null, gridSize: null,
height: window.innerHeight, height: globalThis.innerHeight,
isBindingEnabled: true, isBindingEnabled: true,
isLibraryOpen: false, isLibraryOpen: false,
isLoading: false, isLoading: false,
@@ -70,10 +69,11 @@ export const getDefaultAppState = (): Omit<
suggestedBindings: [], suggestedBindings: [],
toastMessage: null, toastMessage: null,
viewBackgroundColor: oc.white, viewBackgroundColor: oc.white,
width: window.innerWidth, width: globalThis.innerWidth,
zenModeEnabled: false, zenModeEnabled: false,
zoom: { value: 1 as NormalizedZoomValue, translation: { x: 0, y: 0 } }, zoom: { value: 1 as NormalizedZoomValue, translation: { x: 0, y: 0 } },
viewModeEnabled: false, viewModeEnabled: false,
isMinimapEnabled: false,
}; };
}; };
@@ -119,7 +119,6 @@ const APP_STATE_STORAGE_CONF = (<
errorMessage: { browser: false, export: false }, errorMessage: { browser: false, export: false },
exportBackground: { browser: true, export: false }, exportBackground: { browser: true, export: false },
exportEmbedScene: { browser: true, export: false }, exportEmbedScene: { browser: true, export: false },
exportWithDarkMode: { browser: true, export: false },
fileHandle: { browser: false, export: false }, fileHandle: { browser: false, export: false },
gridSize: { browser: true, export: true }, gridSize: { browser: true, export: true },
height: { browser: false, export: false }, height: { browser: false, export: false },
@@ -155,6 +154,7 @@ const APP_STATE_STORAGE_CONF = (<
zenModeEnabled: { browser: true, export: false }, zenModeEnabled: { browser: true, export: false },
zoom: { browser: true, export: false }, zoom: { browser: true, export: false },
viewModeEnabled: { browser: false, export: false }, viewModeEnabled: { browser: false, export: false },
isMinimapEnabled: { browser: true, export: false },
}); });
const _clearAppStateForStorage = <ExportType extends "export" | "browser">( const _clearAppStateForStorage = <ExportType extends "export" | "browser">(
+11 -16
View File
@@ -672,24 +672,19 @@ class App extends React.Component<ExcalidrawProps, AppState> {
scene.appState = { scene.appState = {
...scene.appState, ...scene.appState,
...calculateScrollCenter(
scene.elements,
{
...scene.appState,
width: this.state.width,
height: this.state.height,
offsetTop: this.state.offsetTop,
offsetLeft: this.state.offsetLeft,
},
null,
),
isLoading: false, isLoading: false,
}; };
if (initialData?.scrollToCenter) {
scene.appState = {
...scene.appState,
...calculateScrollCenter(
scene.elements,
{
...scene.appState,
width: this.state.width,
height: this.state.height,
offsetTop: this.state.offsetTop,
offsetLeft: this.state.offsetLeft,
},
null,
),
};
}
this.resetHistory(); this.resetHistory();
this.syncActionResult({ this.syncActionResult({
+8 -9
View File
@@ -10,18 +10,13 @@ export type Appearence = "light" | "dark";
export const DarkModeToggle = (props: { export const DarkModeToggle = (props: {
value: Appearence; value: Appearence;
onChange: (value: Appearence) => void; onChange: (value: Appearence) => void;
title?: string;
}) => { }) => {
const title = props.title
? props.title
: props.value === "dark"
? t("buttons.lightMode")
: t("buttons.darkMode");
return ( return (
<label <label
className={`ToolIcon ToolIcon_type_floating ToolIcon_size_M`} className={`ToolIcon ToolIcon_type_floating ToolIcon_size_M`}
title={title} title={
props.value === "dark" ? t("buttons.lightMode") : t("buttons.darkMode")
}
> >
<input <input
className="ToolIcon_type_checkbox ToolIcon_toggle_opaque" className="ToolIcon_type_checkbox ToolIcon_toggle_opaque"
@@ -30,7 +25,11 @@ export const DarkModeToggle = (props: {
props.onChange(event.target.checked ? "dark" : "light") props.onChange(event.target.checked ? "dark" : "light")
} }
checked={props.value === "dark"} checked={props.value === "dark"}
aria-label={title} aria-label={
props.value === "dark"
? t("buttons.lightMode")
: t("buttons.darkMode")
}
/> />
<div className="ToolIcon__icon"> <div className="ToolIcon__icon">
{props.value === "light" ? ICONS.MOON : ICONS.SUN} {props.value === "light" ? ICONS.MOON : ICONS.SUN}
+4 -5
View File
@@ -19,9 +19,6 @@ import { ToolButton } from "./ToolButton";
const scales = [1, 2, 3]; const scales = [1, 2, 3];
const defaultScale = scales.includes(devicePixelRatio) ? devicePixelRatio : 1; const defaultScale = scales.includes(devicePixelRatio) ? devicePixelRatio : 1;
const supportsContextFilters =
"filter" in document.createElement("canvas").getContext("2d")!;
export const ErrorCanvasPreview = () => { export const ErrorCanvasPreview = () => {
return ( return (
<div> <div>
@@ -104,6 +101,10 @@ const ExportModal = ({
shouldAddWatermark, shouldAddWatermark,
}); });
if (canvas instanceof OffscreenCanvas) {
return;
}
// if converting to blob fails, there's some problem that will // if converting to blob fails, there's some problem that will
// likely prevent preview and export (e.g. canvas too big) // likely prevent preview and export (e.g. canvas too big)
canvasToBlob(canvas) canvasToBlob(canvas)
@@ -131,8 +132,6 @@ const ExportModal = ({
return ( return (
<div className="ExportDialog"> <div className="ExportDialog">
<div className="ExportDialog__preview" ref={previewRef} /> <div className="ExportDialog__preview" ref={previewRef} />
{supportsContextFilters &&
actionManager.renderAction("exportWithDarkMode")}
<Stack.Col gap={2} align="center"> <Stack.Col gap={2} align="center">
<div className="ExportDialog__actions"> <div className="ExportDialog__actions">
<Stack.Row gap={2}> <Stack.Row gap={2}>
+1
View File
@@ -602,6 +602,7 @@ const LayerUI = ({
> >
{renderCustomFooter?.(false)} {renderCustomFooter?.(false)}
{actionManager.renderAction("toggleShortcuts")} {actionManager.renderAction("toggleShortcuts")}
{actionManager.renderAction("toggleMinimap")}
</div> </div>
<button <button
className={clsx("disable-zen-mode", { className={clsx("disable-zen-mode", {
+5
View File
@@ -0,0 +1,5 @@
.Island.MiniMap {
position: absolute;
bottom: 50px;
right: calc(var(--space-factor) * 4);
}
+151
View File
@@ -0,0 +1,151 @@
import "./MiniMap.scss";
import React, { useEffect, useRef, useMemo, useState } from "react";
import { getCommonBounds, getNonDeletedElements } from "../element";
import { ExcalidrawElement } from "../element/types";
import { AppState } from "../types";
import { distance, viewportCoordsToSceneCoords } from "../utils";
import { Island } from "./Island";
// eslint-disable-next-line import/no-webpack-loader-syntax
import MinimapWorker from "worker-loader!../renderer/minimapWorker";
const RATIO = 1.2;
const MINIMAP_HEIGHT = 150;
const MINIMAP_WIDTH = MINIMAP_HEIGHT * RATIO;
const MinimapViewport = ({
elements,
appState,
}: {
elements: readonly ExcalidrawElement[];
appState: AppState;
}) => {
const [minX, minY, maxX, maxY] = useMemo(
() => getCommonBounds(getNonDeletedElements(elements)),
[elements],
);
const minimapScale = Math.min(
MINIMAP_WIDTH / distance(minX, maxX),
MINIMAP_HEIGHT / distance(minY, maxY),
);
const leftTop = viewportCoordsToSceneCoords(
{ clientX: 0, clientY: 0 },
appState,
);
const rightBot = viewportCoordsToSceneCoords(
{ clientX: appState.width, clientY: appState.height },
appState,
);
const top = (leftTop.y - minY) * minimapScale;
const left = (leftTop.x - minX) * minimapScale;
const width = (rightBot.x - leftTop.x) * minimapScale;
const height = (rightBot.y - leftTop.y) * minimapScale;
// Set viewport boundaries
const viewportTop = Math.min(Math.max(0, top), MINIMAP_HEIGHT);
const viewportLeft = Math.min(Math.max(0, left), MINIMAP_WIDTH);
const viewportWidth = Math.min(
MINIMAP_WIDTH - viewportLeft,
width,
width + left,
);
const viewportHeight = Math.min(
MINIMAP_HEIGHT - viewportTop,
height,
height + top,
);
if (
Number.isNaN(viewportTop) ||
Number.isNaN(viewportLeft) ||
Number.isNaN(viewportWidth) ||
Number.isNaN(viewportHeight)
) {
return null;
}
return (
<div
style={{
border: "2px solid orange",
boxSizing: "border-box",
position: "absolute",
pointerEvents: "none",
top: viewportTop,
left: viewportLeft,
width: viewportWidth,
height: viewportHeight,
}}
/>
);
};
export function MiniMap({
appState,
elements,
}: {
appState: AppState;
elements: readonly ExcalidrawElement[];
}) {
const [minimapWorker] = useState(() => new MinimapWorker());
const canvasRef = useRef<HTMLCanvasElement>(null);
const elementsRef = useRef(elements);
elementsRef.current = elements;
const appStateRef = useRef(appState);
appStateRef.current = appState;
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) {
return;
}
const offscreenCanvas = canvas.transferControlToOffscreen();
minimapWorker.postMessage({ type: "INIT", canvas: offscreenCanvas }, [
offscreenCanvas,
]);
minimapWorker.postMessage({
type: "DRAW",
elements: elementsRef.current,
appState: appStateRef.current,
width: MINIMAP_WIDTH,
height: MINIMAP_HEIGHT,
});
setInterval(() => {
minimapWorker.postMessage({
type: "DRAW",
elements: elementsRef.current,
appState: appStateRef.current,
width: MINIMAP_WIDTH,
height: MINIMAP_HEIGHT,
});
}, 1000);
return () => {
minimapWorker.terminate();
};
}, [minimapWorker]);
return (
<Island padding={1} className="MiniMap">
<div
style={{
width: MINIMAP_WIDTH,
height: MINIMAP_HEIGHT,
position: "relative",
overflow: "hidden",
backgroundColor: appState.viewBackgroundColor,
}}
>
<canvas ref={canvasRef} />
<MinimapViewport elements={elements} appState={appState} />
</div>
</Island>
);
}
-3
View File
@@ -1,5 +1,4 @@
import { FontFamily } from "./element/types"; import { FontFamily } from "./element/types";
import cssVariables from "./css/variables.module.scss";
export const APP_NAME = "Excalidraw"; export const APP_NAME = "Excalidraw";
@@ -108,5 +107,3 @@ export const MODES = {
ZEN: "zenMode", ZEN: "zenMode",
GRID: "gridMode", GRID: "gridMode",
}; };
export const APPEARANCE_FILTER = cssVariables.appearanceFilter;
+1 -2
View File
@@ -1,5 +1,4 @@
@import "open-color/open-color.scss"; @import "open-color/open-color.scss";
@import "./variables.module.scss";
:root { :root {
--appearance-filter: none; --appearance-filter: none;
@@ -46,7 +45,7 @@
} }
&.Appearance_dark { &.Appearance_dark {
--appearance-filter: #{$appearance-filter}; --appearance-filter: invert(93%) hue-rotate(180deg);
--button-destructive-bg-color: #5a0000; --button-destructive-bg-color: #5a0000;
--button-destructive-color: #{$oc-red-3}; --button-destructive-color: #{$oc-red-3};
--button-gray-1: #363636; --button-gray-1: #363636;
-2
View File
@@ -2,9 +2,7 @@
// keep up to date with is-mobile.tsx // keep up to date with is-mobile.tsx
$is-mobile-query: "(max-width: 600px), (max-height: 500px) and (max-width: 1000px)"; $is-mobile-query: "(max-width: 600px), (max-height: 500px) and (max-width: 1000px)";
$appearance-filter: "invert(93%) hue-rotate(180deg)";
:export { :export {
isMobileQuery: unquote($is-mobile-query); isMobileQuery: unquote($is-mobile-query);
appearanceFilter: unquote($appearance-filter);
} }
+5 -1
View File
@@ -41,7 +41,6 @@ export const exportCanvas = async (
if (type === "svg" || type === "clipboard-svg") { if (type === "svg" || type === "clipboard-svg") {
const tempSvg = exportToSvg(elements, { const tempSvg = exportToSvg(elements, {
exportBackground, exportBackground,
exportWithDarkMode: appState.exportWithDarkMode,
viewBackgroundColor, viewBackgroundColor,
exportPadding, exportPadding,
scale, scale,
@@ -74,6 +73,11 @@ export const exportCanvas = async (
scale, scale,
shouldAddWatermark, shouldAddWatermark,
}); });
if (tempCanvas instanceof OffscreenCanvas) {
return;
}
tempCanvas.style.display = "none"; tempCanvas.style.display = "none";
document.body.appendChild(tempCanvas); document.body.appendChild(tempCanvas);
-1
View File
@@ -15,7 +15,6 @@ export interface ImportedDataState {
source?: string; source?: string;
elements?: DataState["elements"] | null; elements?: DataState["elements"] | null;
appState?: Partial<DataState["appState"]> | null; appState?: Partial<DataState["appState"]> | null;
scrollToCenter?: boolean;
} }
export interface LibraryData { export interface LibraryData {
+1 -5
View File
@@ -256,7 +256,6 @@ class CollabWrapper extends PureComponent<Props, CollabState> {
if (elements) { if (elements) {
scenePromise.resolve({ scenePromise.resolve({
elements, elements,
scrollToCenter: true,
}); });
} }
} catch (error) { } catch (error) {
@@ -308,10 +307,7 @@ class CollabWrapper extends PureComponent<Props, CollabState> {
init: true, init: true,
}); });
// noop if already resolved via init from firebase // noop if already resolved via init from firebase
scenePromise.resolve({ scenePromise.resolve({ elements: reconciledElements });
elements: reconciledElements,
scrollToCenter: true,
});
} }
break; break;
} }
+2 -7
View File
@@ -13,7 +13,7 @@ import { ExcalidrawImperativeAPI } from "../components/App";
import { ErrorDialog } from "../components/ErrorDialog"; import { ErrorDialog } from "../components/ErrorDialog";
import { TopErrorBoundary } from "../components/TopErrorBoundary"; import { TopErrorBoundary } from "../components/TopErrorBoundary";
import { APP_NAME, EVENT, TITLE_TIMEOUT, VERSION_TIMEOUT } from "../constants"; import { APP_NAME, EVENT, TITLE_TIMEOUT, VERSION_TIMEOUT } from "../constants";
import { DataState, ImportedDataState } from "../data/types"; import { ImportedDataState } from "../data/types";
import { import {
ExcalidrawElement, ExcalidrawElement,
NonDeletedExcalidrawElement, NonDeletedExcalidrawElement,
@@ -75,11 +75,7 @@ const initializeScene = async (opts: {
const initialData = importFromLocalStorage(); const initialData = importFromLocalStorage();
let scene: DataState & { scrollToCenter?: boolean } = await loadScene( let scene = await loadScene(null, null, initialData);
null,
null,
initialData,
);
let roomLinkData = getCollaborationLinkData(window.location.href); let roomLinkData = getCollaborationLinkData(window.location.href);
const isExternalScene = !!(id || jsonMatch || roomLinkData); const isExternalScene = !!(id || jsonMatch || roomLinkData);
@@ -98,7 +94,6 @@ const initializeScene = async (opts: {
} else if (jsonMatch) { } else if (jsonMatch) {
scene = await loadScene(jsonMatch[1], jsonMatch[2], initialData); scene = await loadScene(jsonMatch[1], jsonMatch[2], initialData);
} }
scene.scrollToCenter = true;
if (!roomLinkData) { if (!roomLinkData) {
window.history.replaceState({}, APP_NAME, window.location.origin); window.history.replaceState({}, APP_NAME, window.location.origin);
} }
+11 -1
View File
@@ -12,7 +12,6 @@ interface Document {
interface Window { interface Window {
ClipboardItem: any; ClipboardItem: any;
__EXCALIDRAW_SHA__: string | undefined; __EXCALIDRAW_SHA__: string | undefined;
EXCALIDRAW_ASSET_PATH: string | undefined;
gtag: Function; gtag: Function;
} }
@@ -89,3 +88,14 @@ interface Blob {
handle?: import("browser-fs-acces").FileSystemHandle; handle?: import("browser-fs-acces").FileSystemHandle;
name?: string; name?: string;
} }
declare module "worker-loader!*" {
// You need to change `Worker`, if you specified a different value for the `workerType` option
class WebpackWorker extends Worker {
constructor();
}
// Uncomment this if you set the `esModule` option to `false`
// export = WebpackWorker;
export default WebpackWorker;
}
+2 -2
View File
@@ -54,8 +54,8 @@ const elements = [
}, },
]; ];
registerFont("./public/Virgil.woff2", { family: "Virgil" }); registerFont("./public/FG_Virgil.ttf", { family: "Virgil" });
registerFont("./public/Cascadia.woff2", { family: "Cascadia" }); registerFont("./public/Cascadia.ttf", { family: "Cascadia" });
const canvas = exportToCanvas( const canvas = exportToCanvas(
elements as any, elements as any,
+1
View File
@@ -4,6 +4,7 @@ import ExcalidrawApp from "./excalidraw-app";
import "./excalidraw-app/pwa"; import "./excalidraw-app/pwa";
import "./excalidraw-app/sentry"; import "./excalidraw-app/sentry";
window.__EXCALIDRAW_SHA__ = process.env.REACT_APP_GIT_SHA; window.__EXCALIDRAW_SHA__ = process.env.REACT_APP_GIT_SHA;
ReactDOM.render(<ExcalidrawApp />, document.getElementById("root")); ReactDOM.render(<ExcalidrawApp />, document.getElementById("root"));
+5 -2
View File
@@ -1,5 +1,7 @@
export const isDarwin = /Mac|iPod|iPhone|iPad/.test(window.navigator.platform); export const isDarwin = /Mac|iPod|iPhone|iPad/.test(
export const isWindows = /^Win/.test(window.navigator.platform); globalThis.navigator.platform,
);
export const isWindows = /^Win/.test(globalThis.navigator.platform);
export const CODES = { export const CODES = {
EQUAL: "Equal", EQUAL: "Equal",
@@ -43,6 +45,7 @@ export const KEYS = {
D: "d", D: "d",
E: "e", E: "e",
L: "l", L: "l",
M: "m",
O: "o", O: "o",
P: "p", P: "p",
Q: "q", Q: "q",
+1 -2
View File
@@ -92,8 +92,7 @@
"centerHorizontally": "Center horizontally", "centerHorizontally": "Center horizontally",
"distributeHorizontally": "Distribute horizontally", "distributeHorizontally": "Distribute horizontally",
"distributeVertically": "Distribute vertically", "distributeVertically": "Distribute vertically",
"viewMode": "View mode", "viewMode": "View mode"
"toggleExportColorScheme": "Toggle export color scheme"
}, },
"buttons": { "buttons": {
"clearReset": "Reset the canvas", "clearReset": "Reset the canvas",
+2 -18
View File
@@ -12,34 +12,18 @@ The change should be grouped under one of the below section and must contain PR
Please add the latest change on the top under the correct section. Please add the latest change on the top under the correct section.
--> -->
## 0.4.0 ## [Unreleased]
## Excalidraw API ## Excalidraw API
### Features ### Features
- Expose `window.EXCALIDRAW_ASSET_PATH` which host can use to load assets from a different URL. By default it will be loaded from `https://unpkg.com/@excalidraw/excalidraw{currentVersion}/dist/`[#3068](https://github.com/excalidraw/excalidraw/pull/3068). - Export [`restore`](https://github.com/excalidraw/excalidraw/blob/master/src/data/restore.ts#L182), [`restoreAppState`](https://github.com/excalidraw/excalidraw/blob/master/src/data/restore.ts#L144) and [`restoreElements`](https://github.com/excalidraw/excalidraw/blob/master/src/data/restore.ts#L128) to host
Also now the assets will have a hash in filename so cache bursting can easily happen with version bump.
- Add support for `scrollToCenter` in [initialData](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L18) so host can control whether to scroll to center on mount [#3070](https://github.com/excalidraw/excalidraw/pull/3070).
- Export [`restore`](https://github.com/excalidraw/excalidraw/blob/master/src/data/restore.ts#L182), [`restoreAppState`](https://github.com/excalidraw/excalidraw/blob/master/src/data/restore.ts#L144) and [`restoreElements`](https://github.com/excalidraw/excalidraw/blob/master/src/data/restore.ts#L128) to host [#3049](https://github.com/excalidraw/excalidraw/pull/3049)
### Fixes ### Fixes
- Show user state only when [userState](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L35) is passed on remote pointers during collaboration [#3050](https://github.com/excalidraw/excalidraw/pull/3050) - Show user state only when [userState](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L35) is passed on remote pointers during collaboration [#3050](https://github.com/excalidraw/excalidraw/pull/3050)
## Excalidraw Library
### Features
- Adjust line-confirm-threshold based on zoom [#2884](https://github.com/excalidraw/excalidraw/pull/2884)
### Fixes
- Hide scrollbars on mobile [#3044](https://github.com/excalidraw/excalidraw/pull/3044)
## 0.3.1 ## 0.3.1
## Excalidraw API ## Excalidraw API
+10 -7
View File
@@ -20,9 +20,13 @@ After installation you will see a folder `excalidraw-assets` in `dist` directory
Move the folder `excalidraw-assets` to the path where your assets are served. Move the folder `excalidraw-assets` to the path where your assets are served.
By default it will try to load the files from `https://unpkg.com/@excalidraw/excalidraw/{currentVersion}/dist/` By default it will try to load the files from `{rootUrl}/excalidraw-assets/`
If you want to load assets from a different path you can set a variable `window.EXCALIDRAW_ASSET_PATH` to the url from where you want to load the assets. With **Webpack**, if you want to load the files from different path you can use <pre><a href="https://webpack.js.org/guides/public-path/#on-the-fly">`__webpack_public_path__`</a></pre>.
With **create-react-app**, the assets can be served from `public/static/js/excalidraw-assets`since CRA tries to load the assets from `{rootUrl}/static/js` path by default.
You can update the value of `PUBLIC_URL` if you want to serve it from a different URL.
### Demo ### Demo
@@ -282,11 +286,10 @@ Here you can try saving the data to your backend or local storage for example.
This helps to load Excalidraw with `initialData`. It must be an object or a [promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise) which resolves to an object containing the below optional fields. This helps to load Excalidraw with `initialData`. It must be an object or a [promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise) which resolves to an object containing the below optional fields.
| Name | Type | Descrption | | name | type |
| --- | --- | --- | | --- | --- |
| `elements` | [ExcalidrawElement[]](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78) | The elements with which Excalidraw should be mounted. | | elements | [ExcalidrawElement[]](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78) |
| `appState` | [AppState](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L37) | The App state with which Excalidraw should be mounted. | | appState | [AppState](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L37) |
| `scrollToCenter` | boolean | This attribute implies whether to scroll to the nearest element to center once Excalidraw is mounted. By default, it will not scroll the nearest element to the center. Make sure you pass `initialData.appState.scrollX` and `initialData.appState.scrollY` when `scrollToCenter` is false so that scroll positions are retained |
```json ```json
{ {
-1
View File
@@ -1,5 +1,4 @@
import React, { useEffect, forwardRef } from "react"; import React, { useEffect, forwardRef } from "react";
import "./publicPath";
import { InitializeApp } from "../../components/InitializeApp"; import { InitializeApp } from "../../components/InitializeApp";
import App from "../../components/App"; import App from "../../components/App";
File diff suppressed because it is too large Load Diff
+12 -12
View File
@@ -1,6 +1,6 @@
{ {
"name": "@excalidraw/excalidraw", "name": "@excalidraw/excalidraw",
"version": "0.4.0", "version": "0.3.1",
"main": "dist/excalidraw.min.js", "main": "dist/excalidraw.min.js",
"files": [ "files": [
"dist/*" "dist/*"
@@ -41,24 +41,24 @@
"react-dom": "^17.0.1" "react-dom": "^17.0.1"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "7.13.8", "@babel/core": "7.12.16",
"@babel/plugin-transform-arrow-functions": "7.13.0", "@babel/plugin-transform-arrow-functions": "7.12.13",
"@babel/plugin-transform-async-to-generator": "7.13.0", "@babel/plugin-transform-async-to-generator": "7.12.13",
"@babel/plugin-transform-runtime": "7.13.8", "@babel/plugin-transform-runtime": "7.12.15",
"@babel/plugin-transform-typescript": "7.13.0", "@babel/plugin-transform-typescript": "7.12.16",
"@babel/preset-env": "7.13.8", "@babel/preset-env": "7.12.16",
"@babel/preset-react": "7.12.13", "@babel/preset-react": "7.12.13",
"@babel/preset-typescript": "7.13.0", "@babel/preset-typescript": "7.12.16",
"babel-loader": "8.2.2", "babel-loader": "8.2.2",
"babel-plugin-transform-class-properties": "6.24.1", "babel-plugin-transform-class-properties": "6.24.1",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"css-loader": "5.1.0", "css-loader": "5.0.2",
"file-loader": "6.2.0", "file-loader": "6.2.0",
"mini-css-extract-plugin": "1.3.9", "mini-css-extract-plugin": "1.3.6",
"sass-loader": "11.0.1", "sass-loader": "11.0.1",
"terser-webpack-plugin": "5.1.1", "terser-webpack-plugin": "5.1.1",
"ts-loader": "8.0.17", "ts-loader": "8.0.17",
"webpack": "5.24.2", "webpack": "5.21.2",
"webpack-bundle-analyzer": "4.4.0", "webpack-bundle-analyzer": "4.4.0",
"webpack-cli": "4.5.0" "webpack-cli": "4.5.0"
}, },
@@ -68,6 +68,6 @@
"scripts": { "scripts": {
"build:umd": "cross-env NODE_ENV=production webpack --config webpack.prod.config.js", "build:umd": "cross-env NODE_ENV=production webpack --config webpack.prod.config.js",
"build:umd:withAnalyzer": "cross-env NODE_ENV=production ANALYZER=true webpack --config webpack.prod.config.js", "build:umd:withAnalyzer": "cross-env NODE_ENV=production ANALYZER=true webpack --config webpack.prod.config.js",
"pack": "yarn build:umd && yarn pack" "pack": "npm run build:umd && npm pack"
} }
} }
-9
View File
@@ -1,9 +0,0 @@
import { ENV } from "../../constants";
import pkg from "./package.json";
if (process.env.NODE_ENV !== ENV.TEST) {
/* eslint-disable */
/* global __webpack_public_path__:writable */
__webpack_public_path__ =
window.EXCALIDRAW_ASSET_PATH ||
`https://unpkg.com/${pkg.name}@${pkg.version}/dist/`;
}
@@ -13,8 +13,7 @@ module.exports = {
library: "Excalidraw", library: "Excalidraw",
libraryTarget: "umd", libraryTarget: "umd",
filename: "[name].js", filename: "[name].js",
chunkFilename: "excalidraw-assets/[name]-[contenthash].js", chunkFilename: "excalidraw-assets/[name].js",
publicPath: "",
}, },
resolve: { resolve: {
extensions: [".js", ".ts", ".tsx", ".css", ".scss"], extensions: [".js", ".ts", ".tsx", ".css", ".scss"],
File diff suppressed because it is too large Load Diff
+3
View File
@@ -48,6 +48,9 @@ export const exportToBlob = (
}, },
): Promise<Blob | null> => { ): Promise<Blob | null> => {
const canvas = exportToCanvas(opts); const canvas = exportToCanvas(opts);
if (canvas instanceof OffscreenCanvas) {
return Promise.resolve(null);
}
let { mimeType = "image/png", quality } = opts; let { mimeType = "image/png", quality } = opts;
File diff suppressed because it is too large Load Diff
+8 -10
View File
@@ -34,21 +34,19 @@
] ]
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "7.13.8", "@babel/core": "7.12.16",
"@babel/plugin-transform-arrow-functions": "7.13.0", "@babel/plugin-transform-arrow-functions": "7.12.13",
"@babel/plugin-transform-async-to-generator": "7.13.0", "@babel/plugin-transform-async-to-generator": "7.12.13",
"@babel/plugin-transform-runtime": "^7.12.10", "@babel/plugin-transform-runtime": "^7.12.10",
"@babel/plugin-transform-typescript": "7.13.0", "@babel/plugin-transform-typescript": "7.12.16",
"@babel/preset-env": "7.13.8", "@babel/preset-env": "7.12.16",
"@babel/preset-typescript": "7.13.0", "@babel/preset-typescript": "7.12.16",
"babel-loader": "8.2.2", "babel-loader": "8.2.2",
"babel-plugin-transform-class-properties": "6.24.1", "babel-plugin-transform-class-properties": "6.24.1",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"css-loader": "5.1.0",
"file-loader": "6.2.0", "file-loader": "6.2.0",
"sass-loader": "11.0.1",
"ts-loader": "8.0.17", "ts-loader": "8.0.17",
"webpack": "5.24.2", "webpack": "5.21.2",
"webpack-bundle-analyzer": "4.4.0", "webpack-bundle-analyzer": "4.4.0",
"webpack-cli": "4.5.0" "webpack-cli": "4.5.0"
}, },
@@ -57,6 +55,6 @@
"scripts": { "scripts": {
"build:umd": "cross-env NODE_ENV=production webpack --config webpack.prod.config.js", "build:umd": "cross-env NODE_ENV=production webpack --config webpack.prod.config.js",
"build:umd:withAnalyzer": "cross-env NODE_ENV=production ANALYZER=true webpack --config webpack.prod.config.js", "build:umd:withAnalyzer": "cross-env NODE_ENV=production ANALYZER=true webpack --config webpack.prod.config.js",
"pack": "yarn build:umd && npm pack" "pack": "npm run build:umd && npm pack"
} }
} }
+1 -6
View File
@@ -13,18 +13,13 @@ module.exports = {
libraryTarget: "umd", libraryTarget: "umd",
}, },
resolve: { resolve: {
extensions: [".tsx", ".ts", ".js", ".css", ".scss"], extensions: [".tsx", ".ts", ".js"],
}, },
optimization: { optimization: {
runtimeChunk: false, runtimeChunk: false,
}, },
module: { module: {
rules: [ rules: [
{
test: /\.(sa|sc|c)ss$/,
exclude: /node_modules/,
use: ["style-loader", { loader: "css-loader" }, "sass-loader"],
},
{ {
test: /\.(ts|tsx|js)$/, test: /\.(ts|tsx|js)$/,
use: [ use: [
File diff suppressed because it is too large Load Diff
+48
View File
@@ -0,0 +1,48 @@
/* eslint-disable no-restricted-globals */
import { getNonDeletedElements } from "../element";
import { ExcalidrawElement } from "../element/types";
import { exportToCanvas } from "../scene/export";
import { AppState } from "../types";
const ctx: Worker = self as any;
let canvas: OffscreenCanvas;
ctx.addEventListener("message", (ev) => {
if (ev.data.type === "INIT") {
canvas = ev.data.canvas;
}
if (ev.data.type === "DRAW") {
const { elements, appState, width, height } = ev.data;
drawScene(canvas, elements, appState, width, height);
}
});
function drawScene(
canvas: OffscreenCanvas,
elements: readonly ExcalidrawElement[],
appState: AppState,
minimapWidth: number,
minimapHeight: number,
) {
exportToCanvas(
getNonDeletedElements(elements),
appState,
{
exportBackground: true,
viewBackgroundColor: appState.viewBackgroundColor,
shouldAddWatermark: false,
},
(width, height) => {
const scale = Math.min(minimapWidth / width, minimapHeight / height);
canvas.width = width * scale;
canvas.height = height * scale;
return {
canvas,
scale,
};
},
);
}
+16 -10
View File
@@ -115,7 +115,7 @@ const generateElementCanvas = (
const drawElementOnCanvas = ( const drawElementOnCanvas = (
element: NonDeletedExcalidrawElement, element: NonDeletedExcalidrawElement,
rc: RoughCanvas, rc: RoughCanvas,
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
) => { ) => {
context.globalAlpha = element.opacity / 100; context.globalAlpha = element.opacity / 100;
switch (element.type) { switch (element.type) {
@@ -136,13 +136,16 @@ const drawElementOnCanvas = (
default: { default: {
if (isTextElement(element)) { if (isTextElement(element)) {
const rtl = isRTL(element.text); const rtl = isRTL(element.text);
const shouldTemporarilyAttach = rtl && !context.canvas.isConnected; let shouldTemporarilyAttach = false;
if (shouldTemporarilyAttach) { if (!(context instanceof OffscreenCanvasRenderingContext2D)) {
// to correctly render RTL text mixed with LTR, we have to append it shouldTemporarilyAttach = rtl && !context.canvas.isConnected;
// to the DOM if (shouldTemporarilyAttach) {
document.body.appendChild(context.canvas); // to correctly render RTL text mixed with LTR, we have to append it
// to the DOM
document.body.appendChild(context.canvas);
}
context.canvas.setAttribute("dir", rtl ? "rtl" : "ltr");
} }
context.canvas.setAttribute("dir", rtl ? "rtl" : "ltr");
const font = context.font; const font = context.font;
context.font = getFontString(element); context.font = getFontString(element);
const fillStyle = context.fillStyle; const fillStyle = context.fillStyle;
@@ -170,7 +173,10 @@ const drawElementOnCanvas = (
context.fillStyle = fillStyle; context.fillStyle = fillStyle;
context.font = font; context.font = font;
context.textAlign = textAlign; context.textAlign = textAlign;
if (shouldTemporarilyAttach) { if (
shouldTemporarilyAttach &&
!(context instanceof OffscreenCanvasRenderingContext2D)
) {
context.canvas.remove(); context.canvas.remove();
} }
} else { } else {
@@ -451,7 +457,7 @@ const generateElementWithCanvas = (
const drawElementFromCanvas = ( const drawElementFromCanvas = (
elementWithCanvas: ExcalidrawElementWithCanvas, elementWithCanvas: ExcalidrawElementWithCanvas,
rc: RoughCanvas, rc: RoughCanvas,
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
sceneState: SceneState, sceneState: SceneState,
) => { ) => {
const element = elementWithCanvas.element; const element = elementWithCanvas.element;
@@ -482,7 +488,7 @@ const drawElementFromCanvas = (
export const renderElement = ( export const renderElement = (
element: NonDeletedExcalidrawElement, element: NonDeletedExcalidrawElement,
rc: RoughCanvas, rc: RoughCanvas,
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
renderOptimizations: boolean, renderOptimizations: boolean,
sceneState: SceneState, sceneState: SceneState,
) => { ) => {
+12 -17
View File
@@ -49,12 +49,11 @@ import {
} from "../element/transformHandles"; } from "../element/transformHandles";
import { viewportCoordsToSceneCoords, supportsEmoji } from "../utils"; import { viewportCoordsToSceneCoords, supportsEmoji } from "../utils";
import { UserIdleState } from "../excalidraw-app/collab/types"; import { UserIdleState } from "../excalidraw-app/collab/types";
import { APPEARANCE_FILTER } from "../constants";
const hasEmojiSupport = supportsEmoji(); const hasEmojiSupport = supportsEmoji();
const strokeRectWithRotation = ( const strokeRectWithRotation = (
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
x: number, x: number,
y: number, y: number,
width: number, width: number,
@@ -75,7 +74,7 @@ const strokeRectWithRotation = (
}; };
const strokeDiamondWithRotation = ( const strokeDiamondWithRotation = (
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
width: number, width: number,
height: number, height: number,
cx: number, cx: number,
@@ -96,7 +95,7 @@ const strokeDiamondWithRotation = (
}; };
const strokeEllipseWithRotation = ( const strokeEllipseWithRotation = (
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
width: number, width: number,
height: number, height: number,
cx: number, cx: number,
@@ -109,7 +108,7 @@ const strokeEllipseWithRotation = (
}; };
const fillCircle = ( const fillCircle = (
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
cx: number, cx: number,
cy: number, cy: number,
radius: number, radius: number,
@@ -121,7 +120,7 @@ const fillCircle = (
}; };
const strokeGrid = ( const strokeGrid = (
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
gridSize: number, gridSize: number,
offsetX: number, offsetX: number,
offsetY: number, offsetY: number,
@@ -144,7 +143,7 @@ const strokeGrid = (
}; };
const renderLinearPointHandles = ( const renderLinearPointHandles = (
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
appState: AppState, appState: AppState,
sceneState: SceneState, sceneState: SceneState,
element: NonDeleted<ExcalidrawLinearElement>, element: NonDeleted<ExcalidrawLinearElement>,
@@ -183,7 +182,7 @@ export const renderScene = (
selectionElement: NonDeletedExcalidrawElement | null, selectionElement: NonDeletedExcalidrawElement | null,
scale: number, scale: number,
rc: RoughCanvas, rc: RoughCanvas,
canvas: HTMLCanvasElement, canvas: HTMLCanvasElement | OffscreenCanvas,
sceneState: SceneState, sceneState: SceneState,
// extra options, currently passed by export helper // extra options, currently passed by export helper
{ {
@@ -212,10 +211,6 @@ export const renderScene = (
const normalizedCanvasWidth = canvas.width / scale; const normalizedCanvasWidth = canvas.width / scale;
const normalizedCanvasHeight = canvas.height / scale; const normalizedCanvasHeight = canvas.height / scale;
if (sceneState.exportWithDarkMode) {
context.filter = APPEARANCE_FILTER;
}
// Paint background // Paint background
if (typeof sceneState.viewBackgroundColor === "string") { if (typeof sceneState.viewBackgroundColor === "string") {
const hasTransparence = const hasTransparence =
@@ -578,7 +573,7 @@ export const renderScene = (
}; };
const renderTransformHandles = ( const renderTransformHandles = (
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
sceneState: SceneState, sceneState: SceneState,
transformHandles: TransformHandles, transformHandles: TransformHandles,
angle: number, angle: number,
@@ -614,7 +609,7 @@ const renderTransformHandles = (
}; };
const renderSelectionBorder = ( const renderSelectionBorder = (
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
sceneState: SceneState, sceneState: SceneState,
elementProperties: { elementProperties: {
angle: number; angle: number;
@@ -676,7 +671,7 @@ const renderSelectionBorder = (
}; };
const renderBindingHighlight = ( const renderBindingHighlight = (
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
sceneState: SceneState, sceneState: SceneState,
suggestedBinding: SuggestedBinding, suggestedBinding: SuggestedBinding,
) => { ) => {
@@ -698,7 +693,7 @@ const renderBindingHighlight = (
}; };
const renderBindingHighlightForBindableElement = ( const renderBindingHighlightForBindableElement = (
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
element: ExcalidrawBindableElement, element: ExcalidrawBindableElement,
) => { ) => {
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element); const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
@@ -753,7 +748,7 @@ const renderBindingHighlightForBindableElement = (
}; };
const renderBindingHighlightForSuggestedPointBinding = ( const renderBindingHighlightForSuggestedPointBinding = (
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
suggestedBinding: SuggestedPointBinding, suggestedBinding: SuggestedPointBinding,
) => { ) => {
const [element, startOrEnd, bindableElement] = suggestedBinding; const [element, startOrEnd, bindableElement] = suggestedBinding;
+1 -1
View File
@@ -9,7 +9,7 @@
* @param {Number} radius The corner radius * @param {Number} radius The corner radius
*/ */
export const roundRect = ( export const roundRect = (
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
x: number, x: number,
y: number, y: number,
width: number, width: number,
+7 -14
View File
@@ -7,11 +7,7 @@ import { renderScene, renderSceneToSvg } from "../renderer/renderScene";
import { distance, SVG_NS } from "../utils"; import { distance, SVG_NS } from "../utils";
import { AppState } from "../types"; import { AppState } from "../types";
import { t } from "../i18n"; import { t } from "../i18n";
import { import { DEFAULT_FONT_FAMILY, DEFAULT_VERTICAL_ALIGN } from "../constants";
DEFAULT_FONT_FAMILY,
DEFAULT_VERTICAL_ALIGN,
APPEARANCE_FILTER,
} from "../constants";
import { getDefaultAppState } from "../appState"; import { getDefaultAppState } from "../appState";
export const SVG_EXPORT_TAG = `<!-- svg-source:excalidraw -->`; export const SVG_EXPORT_TAG = `<!-- svg-source:excalidraw -->`;
@@ -36,7 +32,10 @@ export const exportToCanvas = (
createCanvas: ( createCanvas: (
width: number, width: number,
height: number, height: number,
) => { canvas: HTMLCanvasElement; scale: number } = (width, height) => { ) => { canvas: HTMLCanvasElement | OffscreenCanvas; scale: number } = (
width,
height,
) => {
const tempCanvas = document.createElement("canvas"); const tempCanvas = document.createElement("canvas");
tempCanvas.width = width * scale; tempCanvas.width = width * scale;
tempCanvas.height = height * scale; tempCanvas.height = height * scale;
@@ -61,11 +60,10 @@ export const exportToCanvas = (
appState, appState,
null, null,
newScale, newScale,
rough.canvas(tempCanvas), rough.canvas((tempCanvas as unknown) as HTMLCanvasElement),
tempCanvas, tempCanvas,
{ {
viewBackgroundColor: exportBackground ? viewBackgroundColor : null, viewBackgroundColor: exportBackground ? viewBackgroundColor : null,
exportWithDarkMode: appState.exportWithDarkMode,
scrollX: -minX + exportPadding, scrollX: -minX + exportPadding,
scrollY: -minY + exportPadding, scrollY: -minY + exportPadding,
zoom: getDefaultAppState().zoom, zoom: getDefaultAppState().zoom,
@@ -92,7 +90,6 @@ export const exportToSvg = (
exportBackground, exportBackground,
exportPadding = 10, exportPadding = 10,
viewBackgroundColor, viewBackgroundColor,
exportWithDarkMode,
scale = 1, scale = 1,
shouldAddWatermark, shouldAddWatermark,
metadata = "", metadata = "",
@@ -101,7 +98,6 @@ export const exportToSvg = (
exportPadding?: number; exportPadding?: number;
scale?: number; scale?: number;
viewBackgroundColor: string; viewBackgroundColor: string;
exportWithDarkMode?: boolean;
shouldAddWatermark: boolean; shouldAddWatermark: boolean;
metadata?: string; metadata?: string;
}, },
@@ -121,9 +117,6 @@ export const exportToSvg = (
svgRoot.setAttribute("viewBox", `0 0 ${width} ${height}`); svgRoot.setAttribute("viewBox", `0 0 ${width} ${height}`);
svgRoot.setAttribute("width", `${width * scale}`); svgRoot.setAttribute("width", `${width * scale}`);
svgRoot.setAttribute("height", `${height * scale}`); svgRoot.setAttribute("height", `${height * scale}`);
if (exportWithDarkMode) {
svgRoot.setAttribute("filter", APPEARANCE_FILTER);
}
svgRoot.innerHTML = ` svgRoot.innerHTML = `
${SVG_EXPORT_TAG} ${SVG_EXPORT_TAG}
@@ -132,7 +125,7 @@ export const exportToSvg = (
<style> <style>
@font-face { @font-face {
font-family: "Virgil"; font-family: "Virgil";
src: url("https://excalidraw.com/Virgil.woff2"); src: url("https://excalidraw.com/FG_Virgil.woff2");
} }
@font-face { @font-face {
font-family: "Cascadia"; font-family: "Cascadia";
-1
View File
@@ -6,7 +6,6 @@ export type SceneState = {
scrollY: number; scrollY: number;
// null indicates transparent bg // null indicates transparent bg
viewBackgroundColor: string | null; viewBackgroundColor: string | null;
exportWithDarkMode?: boolean;
zoom: Zoom; zoom: Zoom;
shouldCacheIgnoreZoom: boolean; shouldCacheIgnoreZoom: boolean;
remotePointerViewportCoords: { [id: string]: { x: number; y: number } }; remotePointerViewportCoords: { [id: string]: { x: number; y: number } };
@@ -29,13 +29,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -490,13 +490,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -957,13 +957,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": false, "isBindingEnabled": false,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -1733,13 +1733,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -1937,13 +1937,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -2395,13 +2395,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -2648,13 +2648,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -2812,13 +2812,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -3289,13 +3289,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -3597,13 +3597,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -3801,13 +3801,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -4045,13 +4045,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -4297,13 +4297,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -4680,13 +4680,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -4975,13 +4975,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -5282,13 +5282,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -5490,13 +5490,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -5654,13 +5654,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -6107,13 +6107,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -6425,13 +6425,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -8459,13 +8459,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -8821,13 +8821,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -9076,13 +9076,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -9329,13 +9329,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -9644,13 +9644,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -9808,13 +9808,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -9972,13 +9972,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -10136,13 +10136,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -10330,13 +10330,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -10524,13 +10524,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -10718,13 +10718,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -10912,13 +10912,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -11076,13 +11076,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -11240,13 +11240,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -11434,13 +11434,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -11598,13 +11598,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -11792,13 +11792,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -12508,13 +12508,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -12761,13 +12761,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "touch", "lastPointerDownWith": "touch",
@@ -12863,13 +12863,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -12963,13 +12963,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -13127,13 +13127,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -13435,13 +13435,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -13743,13 +13743,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -13907,13 +13907,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -14103,13 +14103,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -14352,13 +14352,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -14676,13 +14676,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -15515,13 +15515,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -15823,13 +15823,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -16131,13 +16131,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -16510,13 +16510,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -16677,13 +16677,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -16998,13 +16998,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -17237,13 +17237,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -17492,13 +17492,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -17819,13 +17819,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -17919,13 +17919,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -18083,13 +18083,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -18904,13 +18904,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -19004,13 +19004,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -19758,13 +19758,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -20163,13 +20163,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -20436,13 +20436,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "touch", "lastPointerDownWith": "touch",
@@ -20538,13 +20538,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -21036,13 +21036,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
@@ -21136,13 +21136,13 @@ Object {
"errorMessage": null, "errorMessage": null,
"exportBackground": true, "exportBackground": true,
"exportEmbedScene": false, "exportEmbedScene": false,
"exportWithDarkMode": false,
"fileHandle": null, "fileHandle": null,
"gridSize": null, "gridSize": null,
"height": 768, "height": 768,
"isBindingEnabled": true, "isBindingEnabled": true,
"isLibraryOpen": false, "isLibraryOpen": false,
"isLoading": false, "isLoading": false,
"isMinimapEnabled": false,
"isResizing": false, "isResizing": false,
"isRotating": false, "isRotating": false,
"lastPointerDownWith": "mouse", "lastPointerDownWith": "mouse",
+2 -2
View File
@@ -5,7 +5,7 @@
<style> <style>
@font-face { @font-face {
font-family: "Virgil"; font-family: "Virgil";
src: url("https://excalidraw.com/Virgil.woff2"); src: url("https://excalidraw.com/FG_Virgil.woff2");
} }
@font-face { @font-face {
font-family: "Cascadia"; font-family: "Cascadia";
@@ -13,4 +13,4 @@
} }
</style> </style>
</defs> </defs>
<rect x="0" y="0" width="56" height="77" fill="#ffffff"></rect><g transform="translate(10 10) rotate(0 18 28.5)"><text x="0" y="41" font-family="Virgil, Segoe UI Emoji" font-size="36px" fill="#c92a2a" text-anchor="start" style="white-space: pre;" direction="ltr">😀</text></g></svg> <rect x="0" y="0" width="56" height="77" fill="#ffffff"></rect><g transform="translate(10 10) rotate(0 18 28.5)"><text x="0" y="41" font-family="Virgil, Segoe UI Emoji" font-size="36px" fill="#c92a2a" text-anchor="start" style="white-space: pre;" direction="ltr">😀</text></g></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

+2 -2
View File
@@ -5,7 +5,7 @@
<style> <style>
@font-face { @font-face {
font-family: "Virgil"; font-family: "Virgil";
src: url("https://excalidraw.com/Virgil.woff2"); src: url("https://excalidraw.com/FG_Virgil.woff2");
} }
@font-face { @font-face {
font-family: "Cascadia"; font-family: "Cascadia";
@@ -13,4 +13,4 @@
} }
</style> </style>
</defs> </defs>
<rect x="0" y="0" width="97" height="77" fill="#ffffff"></rect><g transform="translate(10 10) rotate(0 38.5 28.5)"><text x="0" y="41" font-family="Virgil, Segoe UI Emoji" font-size="36px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">test</text></g></svg> <rect x="0" y="0" width="97" height="77" fill="#ffffff"></rect><g transform="translate(10 10) rotate(0 38.5 28.5)"><text x="0" y="41" font-family="Virgil, Segoe UI Emoji" font-size="36px" fill="#000000" text-anchor="start" style="white-space: pre;" direction="ltr">test</text></g></svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

-1
View File
@@ -30,7 +30,6 @@ describe("appState", () => {
height: ELEM_HEIGHT, height: ELEM_HEIGHT,
}), }),
], ],
scrollToCenter: true,
}} }}
/>, />,
); );
+1 -1
View File
@@ -57,7 +57,6 @@ export type AppState = {
elementLocked: boolean; elementLocked: boolean;
exportBackground: boolean; exportBackground: boolean;
exportEmbedScene: boolean; exportEmbedScene: boolean;
exportWithDarkMode: boolean;
shouldAddWatermark: boolean; shouldAddWatermark: boolean;
currentItemStrokeColor: string; currentItemStrokeColor: string;
currentItemBackgroundColor: string; currentItemBackgroundColor: string;
@@ -118,6 +117,7 @@ export type AppState = {
shown: true; shown: true;
data: Spreadsheet; data: Spreadsheet;
}; };
isMinimapEnabled: boolean;
}; };
export type NormalizedZoomValue = number & { _brand: "normalizedZoom" }; export type NormalizedZoomValue = number & { _brand: "normalizedZoom" };
+3
View File
@@ -372,6 +372,9 @@ export const getVersion = () => {
// Adapted from https://github.com/Modernizr/Modernizr/blob/master/feature-detects/emoji.js // Adapted from https://github.com/Modernizr/Modernizr/blob/master/feature-detects/emoji.js
export const supportsEmoji = () => { export const supportsEmoji = () => {
if (typeof document === "undefined") {
return;
}
const canvas = document.createElement("canvas"); const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d"); const ctx = canvas.getContext("2d");
if (!ctx) { if (!ctx) {
-14933
View File
File diff suppressed because it is too large Load Diff