mirror of
https://github.com/excalidraw/excalidraw
synced 2025-07-25 13:58:22 +08:00
Compare commits
64 Commits
kb/redirec
...
cascadia
Author | SHA1 | Date | |
---|---|---|---|
105f7fdaad | |||
053353841a | |||
286642ffcf | |||
7090938ec1 | |||
6233bc52e3 | |||
7f8ee06710 | |||
3e200634e0 | |||
701b02d6df | |||
535b2b682e | |||
1a4a736d94 | |||
bb207ef861 | |||
2fcbf8658f | |||
6a8c6e7f47 | |||
f962503425 | |||
02fdc506ee | |||
2ba6088e97 | |||
4e421e6e9e | |||
d213dbb42d | |||
a5779dd5d8 | |||
628b4c1eec | |||
31333e597b | |||
872b340f1b | |||
83e8167adf | |||
baea88942c | |||
ae35037a3b | |||
4f31ae1e4b | |||
704ee30ae6 | |||
176baef9c2 | |||
3558f07fe0 | |||
fd24c74ab1 | |||
ae6892501d | |||
1e6adaf0b5 | |||
7ccd38a37f | |||
e6ce9e0ea7 | |||
c0e05445b1 | |||
b44531d94a | |||
464c2cc05e | |||
bd13c2ed48 | |||
2e58aaae66 | |||
d4c14d484c | |||
06d1871640 | |||
e7a59335e4 | |||
0dbef18044 | |||
e16c2d592f | |||
1f4cf4610f | |||
1bee959660 | |||
f609a4ac3a | |||
eee9d1bc16 | |||
ecdc2582e9 | |||
245e13a884 | |||
8a322b22ed | |||
3f784d76fc | |||
ba5afe9139 | |||
9e6f351672 | |||
fcd10a6a43 | |||
3bc18f6aed | |||
7c5481b877 | |||
d17464fbaa | |||
baf9da2b83 | |||
4bfcf105a5 | |||
74e82d0d7c | |||
9dd2257932 | |||
9c0f832a41 | |||
6cafb6bb90 |
@ -1,10 +1,10 @@
|
||||
*
|
||||
!.env
|
||||
!.eslintrc.json
|
||||
!.npmrc
|
||||
!.prettierrc
|
||||
!package.json
|
||||
!public/
|
||||
!src/
|
||||
!.npmrc
|
||||
!.eslintrc.json
|
||||
!.prettierrc
|
||||
!package-lock.json
|
||||
!package.json
|
||||
!tsconfig.json
|
||||
!.env
|
||||
!yarn.lock
|
||||
|
9
.github/dependabot.yml
vendored
9
.github/dependabot.yml
vendored
@ -1,36 +1,33 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: npm
|
||||
directory: "/"
|
||||
directory: /
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: sunday
|
||||
time: "01:00"
|
||||
open-pull-requests-limit: 99
|
||||
reviewers:
|
||||
- lipis
|
||||
assignees:
|
||||
- lipis
|
||||
|
||||
- package-ecosystem: npm
|
||||
directory: "/src/packages/excalidraw/"
|
||||
directory: /src/packages/excalidraw/
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: sunday
|
||||
time: "01:00"
|
||||
open-pull-requests-limit: 99
|
||||
reviewers:
|
||||
- ad1992
|
||||
assignees:
|
||||
- ad1992
|
||||
|
||||
- package-ecosystem: npm
|
||||
directory: "/src/packages/utils/"
|
||||
directory: /src/packages/utils/
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: sunday
|
||||
time: "01:00"
|
||||
open-pull-requests-limit: 99
|
||||
reviewers:
|
||||
- ad1992
|
||||
assignees:
|
||||
|
5
.github/workflows/build-docker.yml
vendored
5
.github/workflows/build-docker.yml
vendored
@ -6,9 +6,8 @@ on:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
build-docker:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- run: docker build -t excalidraw .
|
||||
|
20
.github/workflows/build-packages.yml
vendored
20
.github/workflows/build-packages.yml
vendored
@ -7,27 +7,23 @@ on:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
packages:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup Node.js 14.x
|
||||
uses: actions/setup-node@v1
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 14.x
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
npm ci
|
||||
npm ci --prefix src/packages/excalidraw
|
||||
npm ci --prefix src/packages/utils
|
||||
|
||||
yarn --frozen-lockfile
|
||||
yarn --cwd src/packages/excalidraw
|
||||
yarn --cwd src/packages/utils
|
||||
- name: Build @excalidraw/excalidraw
|
||||
run: |
|
||||
npm run pack --prefix src/packages/excalidraw
|
||||
|
||||
yarn --cwd src/packages/excalidraw run pack
|
||||
- name: Build @excalidraw/utils
|
||||
run: |
|
||||
npm run pack --prefix src/packages/utils
|
||||
yarn --cwd src/packages/utils run pack
|
||||
|
1
.github/workflows/cancel.yml
vendored
1
.github/workflows/cancel.yml
vendored
@ -9,7 +9,6 @@ on:
|
||||
jobs:
|
||||
cancel:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
timeout-minutes: 3
|
||||
steps:
|
||||
- uses: styfle/cancel-workflow-action@0.6.0
|
||||
|
12
.github/workflows/lint.yml
vendored
12
.github/workflows/lint.yml
vendored
@ -7,16 +7,16 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup Node.js 14.x
|
||||
uses: actions/setup-node@v1
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 14.x
|
||||
|
||||
- name: Install and lint
|
||||
run: |
|
||||
npm ci
|
||||
npm run test:other
|
||||
npm run test:code
|
||||
npm run test:typecheck
|
||||
yarn --frozen-lockfile
|
||||
yarn test:other
|
||||
yarn test:code
|
||||
yarn test:typecheck
|
||||
|
8
.github/workflows/locales-coverage.yml
vendored
8
.github/workflows/locales-coverage.yml
vendored
@ -3,7 +3,7 @@ name: Build locales coverage
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "l10n_master"
|
||||
- l10n_master
|
||||
|
||||
jobs:
|
||||
locales:
|
||||
@ -15,13 +15,13 @@ jobs:
|
||||
token: ${{ secrets.PUSH_TRANSLATIONS_COVERAGE_PAT }}
|
||||
|
||||
- name: Setup Node.js 14.x
|
||||
uses: actions/setup-node@v1
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 14.x
|
||||
|
||||
- name: Create report file
|
||||
run: |
|
||||
npm run locales-coverage
|
||||
yarn locales-coverage
|
||||
FILE_CHANGED=$(git diff src/locales/percentages.json)
|
||||
if [ ! -z "${FILE_CHANGED}" ]; then
|
||||
git config --global user.name 'Excalidraw Bot'
|
||||
@ -33,7 +33,7 @@ jobs:
|
||||
- name: Construct comment body
|
||||
id: getCommentBody
|
||||
run: |
|
||||
body=$(npm run locales-coverage:description | grep '^[^>]')
|
||||
body=$(yarn locales-coverage:description | grep '^[^>]')
|
||||
body="${body//'%'/'%25'}"
|
||||
body="${body//$'\n'/'%0A'}"
|
||||
body="${body//$'\r'/'%0D'}"
|
||||
|
5
.github/workflows/semantic-pr-title.yml
vendored
5
.github/workflows/semantic-pr-title.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: "Semantic PR title"
|
||||
name: Semantic PR title
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
@ -8,9 +8,8 @@ on:
|
||||
- synchronize
|
||||
|
||||
jobs:
|
||||
main:
|
||||
semantic:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: amannn/action-semantic-pull-request@v3.0.0
|
||||
env:
|
||||
|
17
.github/workflows/sentry-production.yml
vendored
17
.github/workflows/sentry-production.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: New Sentry Production Release
|
||||
name: New Sentry production release
|
||||
|
||||
on:
|
||||
push:
|
||||
@ -6,28 +6,23 @@ on:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
release:
|
||||
sentry:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1.0.0
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup Node.js 14.x
|
||||
uses: actions/setup-node@v1
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 14.x
|
||||
|
||||
- name: Install and build
|
||||
run: |
|
||||
npm ci
|
||||
npm run build:app
|
||||
yarn --frozen-lockfile
|
||||
yarn build:app
|
||||
env:
|
||||
CI: true
|
||||
|
||||
- name: Install Sentry
|
||||
run: |
|
||||
curl -sL https://sentry.io/get-cli/ | bash
|
||||
|
||||
- name: Create new Sentry release
|
||||
run: |
|
||||
export SENTRY_RELEASE=$(sentry-cli releases propose-version)
|
||||
|
11
.github/workflows/test.yml
vendored
11
.github/workflows/test.yml
vendored
@ -5,16 +5,13 @@ on: pull_request
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup Node.js 14.x
|
||||
uses: actions/setup-node@v1
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 14.x
|
||||
|
||||
- name: Install and test
|
||||
run: |
|
||||
npm ci
|
||||
npm run test:app
|
||||
yarn --frozen-lockfile
|
||||
yarn test:app
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -16,7 +16,7 @@ firebase
|
||||
logs
|
||||
node_modules
|
||||
npm-debug.log*
|
||||
package-lock.json
|
||||
static
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
yarn.lock
|
||||
|
@ -1,4 +0,0 @@
|
||||
{
|
||||
"proseWrap": "never",
|
||||
"trailingComma": "all"
|
||||
}
|
@ -2,13 +2,13 @@ FROM node:14-alpine AS build
|
||||
|
||||
WORKDIR /opt/node_app
|
||||
|
||||
COPY package.json package-lock.json ./
|
||||
RUN npm i --no-optional
|
||||
COPY package.json yarn.lock ./
|
||||
RUN yarn --ignore-optional
|
||||
|
||||
ARG NODE_ENV=production
|
||||
|
||||
COPY . .
|
||||
RUN npm run build:app:docker
|
||||
RUN yarn build:app:docker
|
||||
|
||||
FROM nginx:1.17-alpine
|
||||
|
||||
|
22
README.md
22
README.md
@ -86,6 +86,12 @@ 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.
|
||||
|
||||
#### Requirements
|
||||
|
||||
- [Node.js](https://nodejs.org/en/)
|
||||
- [Yarn](https://yarnpkg.com/getting-started/install)
|
||||
- [Git](https://git-scm.com/downloads)
|
||||
|
||||
#### Clone the repo
|
||||
|
||||
```bash
|
||||
@ -94,14 +100,14 @@ git clone https://github.com/excalidraw/excalidraw.git
|
||||
|
||||
#### Commands
|
||||
|
||||
| Command | Description |
|
||||
| --------------------- | --------------------------------- |
|
||||
| `npm install` | Install the dependencies |
|
||||
| `npm start` | Run the project |
|
||||
| `npm run fix` | Reformat all files with Prettier |
|
||||
| `npm test` | Run tests |
|
||||
| `npm run test:update` | Update test snapshots |
|
||||
| `npm run test:code` | Test for formatting with Prettier |
|
||||
| Command | Description |
|
||||
| ------------------ | --------------------------------- |
|
||||
| `yarn` | Install the dependencies |
|
||||
| `yarn start` | Run the project |
|
||||
| `yarn fix` | Reformat all files with Prettier |
|
||||
| `yarn test` | Run tests |
|
||||
| `yarn test:update` | Update test snapshots |
|
||||
| `yarn test:code` | Test for formatting with Prettier |
|
||||
|
||||
#### Docker Compose
|
||||
|
||||
|
@ -18,7 +18,7 @@ services:
|
||||
volumes:
|
||||
- ./:/opt/node_app/app:delegated
|
||||
- ./package.json:/opt/node_app/package.json
|
||||
- ./package-lock.json:/opt/node_app/package-lock.json
|
||||
- ./yarn.lock:/opt/node_app/yarn.lock
|
||||
- notused:/opt/node_app/app/node_modules
|
||||
|
||||
volumes:
|
||||
|
23611
package-lock.json
generated
23611
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
36
package.json
36
package.json
@ -19,21 +19,20 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@sentry/browser": "6.1.0",
|
||||
"@sentry/integrations": "6.1.0",
|
||||
"@sentry/browser": "6.2.0",
|
||||
"@sentry/integrations": "6.2.0",
|
||||
"@testing-library/jest-dom": "5.11.9",
|
||||
"@testing-library/react": "11.2.5",
|
||||
"@types/jest": "26.0.20",
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react-dom": "17.0.1",
|
||||
"@types/socket.io-client": "1.4.35",
|
||||
"browser-fs-access": "0.13.1",
|
||||
"browser-fs-access": "0.14.0",
|
||||
"clsx": "1.1.1",
|
||||
"firebase": "8.2.7",
|
||||
"firebase": "8.2.9",
|
||||
"i18next-browser-languagedetector": "6.0.1",
|
||||
"lodash.throttle": "4.1.1",
|
||||
"nanoid": "3.1.20",
|
||||
"node-sass": "4.14.1",
|
||||
"open-color": "1.8.0",
|
||||
"pako": "1.0.11",
|
||||
"png-chunk-text": "1.0.0",
|
||||
@ -43,18 +42,20 @@
|
||||
"pwacompat": "2.0.17",
|
||||
"react": "17.0.1",
|
||||
"react-dom": "17.0.1",
|
||||
"react-scripts": "4.0.2",
|
||||
"react-scripts": "4.0.3",
|
||||
"roughjs": "4.3.1",
|
||||
"sass": "1.32.8",
|
||||
"socket.io-client": "2.3.1",
|
||||
"typescript": "4.1.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@excalidraw/prettier-config": "1.0.2",
|
||||
"@types/lodash.throttle": "4.1.6",
|
||||
"@types/pako": "1.0.1",
|
||||
"@types/resize-observer-browser": "0.1.5",
|
||||
"eslint-config-prettier": "7.2.0",
|
||||
"eslint-config-prettier": "8.1.0",
|
||||
"eslint-plugin-prettier": "3.3.1",
|
||||
"firebase-tools": "9.3.0",
|
||||
"firebase-tools": "9.5.0",
|
||||
"husky": "4.3.8",
|
||||
"jest-canvas-mock": "2.3.1",
|
||||
"lint-staged": "10.5.4",
|
||||
@ -63,7 +64,7 @@
|
||||
"rewire": "5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"homepage": ".",
|
||||
"husky": {
|
||||
@ -78,28 +79,29 @@
|
||||
"resetMocks": false
|
||||
},
|
||||
"name": "excalidraw",
|
||||
"prettier": "@excalidraw/prettier-config",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build-node": "node ./scripts/build-node.js",
|
||||
"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:version": "node ./scripts/build-version.js",
|
||||
"build": "npm run build:app && npm run build:version",
|
||||
"build": "yarn build:app && yarn build:version",
|
||||
"eject": "react-scripts eject",
|
||||
"fix:code": "npm run test:code -- --fix",
|
||||
"fix:other": "npm run prettier -- --write",
|
||||
"fix": "npm run fix:other && npm run fix:code",
|
||||
"fix:code": "yarn test:code --fix",
|
||||
"fix:other": "yarn prettier --write",
|
||||
"fix": "yarn fix:other && yarn fix:code",
|
||||
"locales-coverage": "node scripts/build-locales-coverage.js",
|
||||
"locales-coverage:description": "node scripts/locales-coverage-description.js",
|
||||
"prettier": "prettier \"**/*.{css,scss,json,md,html,yml}\" --ignore-path=.eslintignore",
|
||||
"start": "react-scripts start",
|
||||
"test:all": "npm run test:typecheck && npm run test:code && npm run test:other && npm run test:app -- --watchAll=false",
|
||||
"test:all": "yarn test:typecheck && yarn test:code && yarn test:other && yarn test:app --watchAll=false",
|
||||
"test:app": "react-scripts test --passWithNoTests",
|
||||
"test:code": "eslint --max-warnings=0 --ignore-path .gitignore --ext .js,.ts,.tsx .",
|
||||
"test:debug": "react-scripts --inspect-brk test --runInBand --no-cache",
|
||||
"test:other": "npm run prettier -- --list-different",
|
||||
"test:other": "yarn prettier --list-different",
|
||||
"test:typecheck": "tsc",
|
||||
"test:update": "npm run test:app -- --updateSnapshot --watchAll=false",
|
||||
"test": "npm run test:app"
|
||||
"test:update": "yarn test:app --updateSnapshot --watchAll=false",
|
||||
"test": "yarn test:app"
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
public/Virgil.woff2
Normal file
BIN
public/Virgil.woff2
Normal file
Binary file not shown.
@ -1,7 +1,7 @@
|
||||
/* http://www.eaglefonts.com/fg-virgil-ttf-131249.htm */
|
||||
@font-face {
|
||||
font-family: "Virgil";
|
||||
src: url("FG_Virgil.woff2");
|
||||
src: url("Virgil.woff2");
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@
|
||||
|
||||
<link
|
||||
rel="preload"
|
||||
href="FG_Virgil.woff2"
|
||||
href="Virgil.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossorigin="anonymous"
|
||||
@ -86,7 +86,9 @@
|
||||
/>
|
||||
|
||||
<link rel="stylesheet" href="fonts.css" type="text/css" />
|
||||
|
||||
<script>
|
||||
window.EXCALIDRAW_ASSET_PATH = "/";
|
||||
</script>
|
||||
<% if (process.env.REACT_APP_GOOGLE_ANALYTICS_ID) { %>
|
||||
<script
|
||||
async
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
// In order to run:
|
||||
// npm install canvas # please do not check it in
|
||||
// npm run build-node
|
||||
// yarn build-node
|
||||
// node build/static/js/build-node.js
|
||||
// open test.png
|
||||
|
||||
|
@ -5,6 +5,7 @@ import { ProjectName } from "../components/ProjectName";
|
||||
import { ToolButton } from "../components/ToolButton";
|
||||
import "../components/ToolIcon.scss";
|
||||
import { Tooltip } from "../components/Tooltip";
|
||||
import { DarkModeToggle, Appearence } from "../components/DarkModeToggle";
|
||||
import { loadFromJSON, saveAsJSON } from "../data";
|
||||
import { t } from "../i18n";
|
||||
import useIsMobile from "../is-mobile";
|
||||
@ -204,3 +205,31 @@ 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>
|
||||
),
|
||||
});
|
||||
|
@ -85,7 +85,8 @@ export type ActionName =
|
||||
| "alignHorizontallyCentered"
|
||||
| "distributeHorizontally"
|
||||
| "distributeVertically"
|
||||
| "viewMode";
|
||||
| "viewMode"
|
||||
| "exportWithDarkMode";
|
||||
|
||||
export interface Action {
|
||||
name: ActionName;
|
||||
|
@ -40,6 +40,7 @@ export const getDefaultAppState = (): Omit<
|
||||
errorMessage: null,
|
||||
exportBackground: true,
|
||||
exportEmbedScene: false,
|
||||
exportWithDarkMode: false,
|
||||
fileHandle: null,
|
||||
gridSize: null,
|
||||
height: window.innerHeight,
|
||||
@ -118,6 +119,7 @@ const APP_STATE_STORAGE_CONF = (<
|
||||
errorMessage: { browser: false, export: false },
|
||||
exportBackground: { browser: true, export: false },
|
||||
exportEmbedScene: { browser: true, export: false },
|
||||
exportWithDarkMode: { browser: true, export: false },
|
||||
fileHandle: { browser: false, export: false },
|
||||
gridSize: { browser: true, export: true },
|
||||
height: { browser: false, export: false },
|
||||
|
@ -672,19 +672,24 @@ class App extends React.Component<ExcalidrawProps, 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,
|
||||
};
|
||||
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.syncActionResult({
|
||||
@ -972,6 +977,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
},
|
||||
{
|
||||
renderOptimizations: true,
|
||||
renderScrollbars: !isMobile(),
|
||||
},
|
||||
);
|
||||
if (scrollBars) {
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
.excalidraw {
|
||||
.CollabButton.is-collaborating {
|
||||
background-color: var(--button-special-active-background-color);
|
||||
background-color: var(--button-special-active-bg-color);
|
||||
|
||||
.ToolIcon__icon svg,
|
||||
.ToolIcon__label {
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
.excalidraw {
|
||||
.color-picker {
|
||||
background: var(--popup-background-color);
|
||||
border: 0px solid transparentize($oc-white, 0.75);
|
||||
box-shadow: transparentize($oc-black, 0.75) 0px 1px 4px;
|
||||
background: var(--popup-bg-color);
|
||||
border: 0 solid transparentize($oc-white, 0.75);
|
||||
box-shadow: transparentize($oc-black, 0.75) 0 1px 4px;
|
||||
border-radius: 4px;
|
||||
position: absolute;
|
||||
|
||||
@ -24,11 +24,11 @@
|
||||
}
|
||||
|
||||
.color-picker-triangle {
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-style: solid;
|
||||
border-width: 0px 9px 10px;
|
||||
border-color: transparent transparent var(--popup-background-color);
|
||||
border-width: 0 9px 10px;
|
||||
border-color: transparent transparent var(--popup-bg-color);
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
|
||||
@ -84,12 +84,12 @@
|
||||
|
||||
.color-picker-transparent {
|
||||
border-radius: 4px;
|
||||
box-shadow: transparentize($oc-black, 0.9) 0px 0px 0px 1px inset;
|
||||
box-shadow: transparentize($oc-black, 0.9) 0 0 0 1px inset;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.color-picker-transparent,
|
||||
@ -104,11 +104,11 @@
|
||||
width: 1.875rem;
|
||||
|
||||
:root[dir="ltr"] & {
|
||||
border-radius: 4px 0px 0px 4px;
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
|
||||
:root[dir="rtl"] & {
|
||||
border-radius: 0px 4px 4px 0px;
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
|
||||
color: var(--input-label-color);
|
||||
@ -144,7 +144,7 @@
|
||||
}
|
||||
|
||||
.color-input-container:focus-within .color-picker-hash::after {
|
||||
background: var(--input-background-color);
|
||||
background: var(--input-bg-color);
|
||||
|
||||
:root[dir="ltr"] & {
|
||||
right: -2px;
|
||||
@ -163,19 +163,19 @@
|
||||
width: 12ch; /* length of `transparent` + 1 */
|
||||
margin: 0;
|
||||
font-size: 1rem;
|
||||
background-color: var(--input-background-color);
|
||||
color: var(--text-color-primary);
|
||||
border: 0px;
|
||||
background-color: var(--input-bg-color);
|
||||
color: var(--text-primary-color);
|
||||
border: 0;
|
||||
outline: none;
|
||||
height: 1.75em;
|
||||
box-shadow: var(--input-border-color) 0px 0px 0px 1px inset;
|
||||
box-shadow: var(--input-border-color) 0 0 0 1px inset;
|
||||
|
||||
:root[dir="ltr"] & {
|
||||
border-radius: 0px 4px 4px 0px;
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
|
||||
:root[dir="rtl"] & {
|
||||
border-radius: 4px 0px 0px 4px;
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
|
||||
float: left;
|
||||
@ -228,7 +228,7 @@
|
||||
}
|
||||
|
||||
.color-picker-type-elementBackground .color-picker-keybinding {
|
||||
color: #fff;
|
||||
color: $oc-white;
|
||||
}
|
||||
|
||||
.color-picker-swatch[aria-label="transparent"] .color-picker-keybinding {
|
||||
@ -241,10 +241,10 @@
|
||||
|
||||
&.Appearance_dark {
|
||||
.color-picker-type-elementBackground .color-picker-keybinding {
|
||||
color: #000;
|
||||
color: $oc-black;
|
||||
}
|
||||
.color-picker-swatch[aria-label="transparent"] .color-picker-keybinding {
|
||||
color: #000;
|
||||
color: $oc-black;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,13 +4,13 @@
|
||||
.context-menu {
|
||||
position: relative;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0px 3px 10px transparentize($oc-black, 0.8);
|
||||
box-shadow: 0 3px 10px transparentize($oc-black, 0.8);
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
user-select: none;
|
||||
margin: -0.25rem 0 0 0.125rem;
|
||||
padding: 0.5rem 0;
|
||||
background-color: var(--popup-secondary-background-color);
|
||||
background-color: var(--popup-secondary-bg-color);
|
||||
border: 1px solid var(--button-gray-3);
|
||||
cursor: default;
|
||||
}
|
||||
@ -61,12 +61,12 @@
|
||||
}
|
||||
|
||||
.context-menu-option:hover {
|
||||
color: var(--popup-background-color);
|
||||
color: var(--popup-bg-color);
|
||||
background-color: var(--select-highlight-color);
|
||||
|
||||
&.dangerous {
|
||||
.context-menu-option__label {
|
||||
color: var(--popup-background-color);
|
||||
color: var(--popup-bg-color);
|
||||
}
|
||||
background-color: $oc-red-6;
|
||||
}
|
||||
|
@ -10,13 +10,18 @@ export type Appearence = "light" | "dark";
|
||||
export const DarkModeToggle = (props: {
|
||||
value: Appearence;
|
||||
onChange: (value: Appearence) => void;
|
||||
title?: string;
|
||||
}) => {
|
||||
const title = props.title
|
||||
? props.title
|
||||
: props.value === "dark"
|
||||
? t("buttons.lightMode")
|
||||
: t("buttons.darkMode");
|
||||
|
||||
return (
|
||||
<label
|
||||
className={`ToolIcon ToolIcon_type_floating ToolIcon_size_M`}
|
||||
title={
|
||||
props.value === "dark" ? t("buttons.lightMode") : t("buttons.darkMode")
|
||||
}
|
||||
title={title}
|
||||
>
|
||||
<input
|
||||
className="ToolIcon_type_checkbox ToolIcon_toggle_opaque"
|
||||
@ -25,11 +30,7 @@ export const DarkModeToggle = (props: {
|
||||
props.onChange(event.target.checked ? "dark" : "light")
|
||||
}
|
||||
checked={props.value === "dark"}
|
||||
aria-label={
|
||||
props.value === "dark"
|
||||
? t("buttons.lightMode")
|
||||
: t("buttons.darkMode")
|
||||
}
|
||||
aria-label={title}
|
||||
/>
|
||||
<div className="ToolIcon__icon">
|
||||
{props.value === "light" ? ICONS.MOON : ICONS.SUN}
|
||||
|
@ -45,7 +45,7 @@
|
||||
position: sticky;
|
||||
top: 0;
|
||||
padding: calc(var(--space-factor) * 2);
|
||||
background: var(--bg-color-island);
|
||||
background: var(--island-bg-color);
|
||||
font-size: 1.25em;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
@ -19,6 +19,9 @@ import { ToolButton } from "./ToolButton";
|
||||
const scales = [1, 2, 3];
|
||||
const defaultScale = scales.includes(devicePixelRatio) ? devicePixelRatio : 1;
|
||||
|
||||
const supportsContextFilters =
|
||||
"filter" in document.createElement("canvas").getContext("2d")!;
|
||||
|
||||
export const ErrorCanvasPreview = () => {
|
||||
return (
|
||||
<div>
|
||||
@ -128,6 +131,8 @@ const ExportModal = ({
|
||||
return (
|
||||
<div className="ExportDialog">
|
||||
<div className="ExportDialog__preview" ref={previewRef} />
|
||||
{supportsContextFilters &&
|
||||
actionManager.renderAction("exportWithDarkMode")}
|
||||
<Stack.Col gap={2} align="center">
|
||||
<div className="ExportDialog__actions">
|
||||
<Stack.Row gap={2}>
|
||||
|
@ -26,7 +26,7 @@ $wide-viewport-width: 1000px;
|
||||
|
||||
> span {
|
||||
padding: 0.2rem 0.4rem;
|
||||
background-color: var(--overlay-background-color);
|
||||
background-color: var(--overlay-bg-color);
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,9 @@
|
||||
}
|
||||
|
||||
.picker {
|
||||
background: var(--popup-background-color);
|
||||
border: 0px solid transparentize($oc-white, 0.75);
|
||||
box-shadow: transparentize($oc-black, 0.75) 0px 1px 4px;
|
||||
background: var(--popup-bg-color);
|
||||
border: 0 solid transparentize($oc-white, 0.75);
|
||||
box-shadow: transparentize($oc-black, 0.75) 0 1px 4px;
|
||||
border-radius: 4px;
|
||||
position: absolute;
|
||||
}
|
||||
@ -56,8 +56,8 @@
|
||||
}
|
||||
|
||||
.picker-triangle {
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
position: relative;
|
||||
top: -10px;
|
||||
:root[dir="ltr"] & {
|
||||
@ -73,7 +73,7 @@
|
||||
content: "";
|
||||
position: absolute;
|
||||
border-style: solid;
|
||||
border-width: 0px 9px 10px;
|
||||
border-width: 0 9px 10px;
|
||||
border-color: transparent transparent transparentize($oc-black, 0.9);
|
||||
top: -1px;
|
||||
}
|
||||
@ -82,8 +82,8 @@
|
||||
content: "";
|
||||
position: absolute;
|
||||
border-style: solid;
|
||||
border-width: 0px 9px 10px;
|
||||
border-color: transparent transparent var(--popup-background-color);
|
||||
border-width: 0 9px 10px;
|
||||
border-color: transparent transparent var(--popup-bg-color);
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,7 +121,7 @@
|
||||
}
|
||||
|
||||
.picker-type-elementBackground .picker-keybinding {
|
||||
color: #fff;
|
||||
color: $oc-white;
|
||||
}
|
||||
|
||||
.picker-swatch[aria-label="transparent"] .picker-keybinding {
|
||||
@ -134,10 +134,10 @@
|
||||
|
||||
&.Appearance_dark {
|
||||
.picker-type-elementBackground .picker-keybinding {
|
||||
color: #000;
|
||||
color: $oc-black;
|
||||
}
|
||||
.picker-swatch[aria-label="transparent"] .picker-keybinding {
|
||||
color: #000;
|
||||
color: $oc-black;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
.excalidraw {
|
||||
.Island {
|
||||
--padding: 0;
|
||||
background-color: var(--bg-color-island);
|
||||
background-color: var(--island-bg-color);
|
||||
backdrop-filter: saturate(100%) blur(10px);
|
||||
box-shadow: var(--shadow-island);
|
||||
border-radius: 4px;
|
||||
|
@ -73,7 +73,7 @@
|
||||
&__footer {
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
bottom: 0px;
|
||||
bottom: 0;
|
||||
|
||||
:root[dir="ltr"] & {
|
||||
right: 0;
|
||||
@ -94,7 +94,7 @@
|
||||
}
|
||||
|
||||
:root[dir="ltr"] &.transition-right {
|
||||
transform: translate(999px, 0px);
|
||||
transform: translate(999px, 0);
|
||||
}
|
||||
|
||||
:root[dir="rtl"] &.transition-left {
|
||||
|
@ -44,10 +44,10 @@
|
||||
overflow-y: auto;
|
||||
|
||||
// for modals, reset blurry bg
|
||||
background: var(--bg-color-island);
|
||||
background: var(--island-bg-color);
|
||||
backdrop-filter: none;
|
||||
|
||||
border: 1px solid var(--dialog-border);
|
||||
border: 1px solid var(--dialog-border-color);
|
||||
box-shadow: 0 2px 10px transparentize($oc-black, 0.75);
|
||||
border-radius: 6px;
|
||||
|
||||
|
@ -1,51 +1,53 @@
|
||||
@import "../css/variables.module";
|
||||
|
||||
.Stats {
|
||||
position: absolute;
|
||||
top: 64px;
|
||||
right: 12px;
|
||||
font-size: 12px;
|
||||
z-index: 999;
|
||||
.excalidraw {
|
||||
.Stats {
|
||||
position: absolute;
|
||||
top: 64px;
|
||||
right: 12px;
|
||||
font-size: 12px;
|
||||
z-index: 999;
|
||||
|
||||
h3 {
|
||||
margin: 0 24px 8px 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
h3 {
|
||||
margin: 0 24px 8px 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.close {
|
||||
float: right;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
cursor: pointer;
|
||||
svg {
|
||||
.close {
|
||||
float: right;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
cursor: pointer;
|
||||
svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
th {
|
||||
border-bottom: 1px solid var(--input-border-color);
|
||||
padding: 4px;
|
||||
}
|
||||
tr {
|
||||
td:nth-child(2) {
|
||||
min-width: 24px;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
th {
|
||||
border-bottom: 1px solid var(--input-border-color);
|
||||
padding: 4px;
|
||||
}
|
||||
tr {
|
||||
td:nth-child(2) {
|
||||
min-width: 24px;
|
||||
text-align: right;
|
||||
:root[dir="rtl"] & {
|
||||
left: 12px;
|
||||
right: initial;
|
||||
|
||||
h3 {
|
||||
margin: 0 0 8px 24px;
|
||||
}
|
||||
.close {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:root[dir="rtl"] & {
|
||||
left: 12px;
|
||||
right: initial;
|
||||
|
||||
h3 {
|
||||
margin: 0 0 8px 24px;
|
||||
}
|
||||
.close {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,18 +2,18 @@
|
||||
|
||||
.excalidraw {
|
||||
.TextInput {
|
||||
color: var(--text-color-primary);
|
||||
color: var(--text-primary-color);
|
||||
display: inline-block;
|
||||
border: 1.5px solid var(--button-gray-1);
|
||||
line-height: 1;
|
||||
padding: 0.75rem;
|
||||
white-space: nowrap;
|
||||
border-radius: var(--space-factor);
|
||||
background-color: var(--input-background-color);
|
||||
background-color: var(--input-bg-color);
|
||||
|
||||
&:not(:focus) {
|
||||
&:hover {
|
||||
background-color: var(--input-hover-background-color);
|
||||
background-color: var(--input-hover-bg-color);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { FontFamily } from "./element/types";
|
||||
import cssVariables from "./css/variables.module.scss";
|
||||
|
||||
export const APP_NAME = "Excalidraw";
|
||||
|
||||
@ -107,3 +108,5 @@ export const MODES = {
|
||||
ZEN: "zenMode",
|
||||
GRID: "gridMode",
|
||||
};
|
||||
|
||||
export const APPEARANCE_FILTER = cssVariables.appearanceFilter;
|
||||
|
@ -8,7 +8,7 @@
|
||||
}
|
||||
|
||||
.excalidraw {
|
||||
color: var(--text-color-primary);
|
||||
color: var(--text-primary-color);
|
||||
display: flex;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
@ -50,10 +50,10 @@
|
||||
}
|
||||
|
||||
.FixedSideContainer {
|
||||
padding-top: var(--sat, 0px);
|
||||
padding-right: var(--sar, 0px);
|
||||
padding-bottom: var(--sab, 0px);
|
||||
padding-left: var(--sal, 0px);
|
||||
padding-top: var(--sat, 0);
|
||||
padding-right: var(--sar, 0);
|
||||
padding-bottom: var(--sab, 0);
|
||||
padding-left: var(--sal, 0);
|
||||
}
|
||||
|
||||
.panelRow {
|
||||
@ -71,7 +71,7 @@
|
||||
margin-top: 0.333rem;
|
||||
margin-bottom: 0.333rem;
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-color-primary);
|
||||
color: var(--text-primary-color);
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
}
|
||||
@ -237,10 +237,10 @@
|
||||
left: 0;
|
||||
right: 0;
|
||||
--bar-padding: calc(4 * var(--space-factor));
|
||||
padding-top: #{"max(var(--bar-padding), var(--sat, 0px))"};
|
||||
padding-right: var(--sar, 0px);
|
||||
padding-bottom: var(--sab, 0px);
|
||||
padding-left: var(--sal, 0px);
|
||||
padding-top: #{"max(var(--bar-padding), var(--sat,0))"};
|
||||
padding-right: var(--sar, 0);
|
||||
padding-bottom: var(--sab, 0);
|
||||
padding-left: var(--sal, 0);
|
||||
z-index: 4;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
@ -257,7 +257,7 @@
|
||||
pointer-events: initial;
|
||||
|
||||
.panelColumn {
|
||||
padding: 8px 8px 0px 8px;
|
||||
padding: 8px 8px 0 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -460,7 +460,7 @@
|
||||
display: none;
|
||||
}
|
||||
.scroll-back-to-content {
|
||||
bottom: calc(80px + var(--sab, 0px));
|
||||
bottom: calc(80px + var(--sab, 0));
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
|
@ -1,43 +1,44 @@
|
||||
@import "open-color/open-color.scss";
|
||||
@import "./variables.module.scss";
|
||||
|
||||
:root {
|
||||
--bg-color-island: rgba(255, 255, 255, 0.9);
|
||||
--popup-background-color: #{$oc-white};
|
||||
--space-factor: 0.25rem;
|
||||
--appearance-filter: none;
|
||||
--button-destructive-bg-color: #{$oc-red-1};
|
||||
--button-destructive-color: #{$oc-red-9};
|
||||
--button-gray-1: #{$oc-gray-2};
|
||||
--button-gray-2: #{$oc-gray-4};
|
||||
--button-gray-3: #{$oc-gray-5};
|
||||
--input-border-color: #{$oc-gray-3};
|
||||
--input-background-color: #{$oc-white};
|
||||
--input-hover-background-color: #{$oc-gray-1};
|
||||
--input-label-color: #{$oc-gray-7};
|
||||
--button-special-active-bg-color: #{$oc-green-0};
|
||||
--dialog-border-color: #{$oc-gray-6};
|
||||
--dropdown-icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="292.4" height="292.4" viewBox="0 0 292 292"><path d="M287 197L159 69c-4-3-8-5-13-5s-9 2-13 5L5 197c-3 4-5 8-5 13s2 9 5 13c4 4 8 5 13 5h256c5 0 9-1 13-5s5-8 5-13-1-9-5-13z"/></svg>');
|
||||
--focus-highlight-color: #{$oc-blue-2};
|
||||
--icon-fill-color: #{$oc-black};
|
||||
--icon-green-fill-color: #{$oc-green-9};
|
||||
--input-bg-color: #{$oc-white};
|
||||
--input-border-color: #{$oc-gray-3};
|
||||
--input-hover-bg-color: #{$oc-gray-1};
|
||||
--input-label-color: #{$oc-gray-7};
|
||||
--island-bg-color: rgba(255, 255, 255, 0.9);
|
||||
--keybinding-color: #{$oc-gray-5};
|
||||
--sat: env(safe-area-inset-top);
|
||||
--link-color: #{$oc-blue-7};
|
||||
--overlay-bg-color: #{transparentize($oc-white, 0.12)};
|
||||
--popup-bg-color: #{$oc-white};
|
||||
--popup-secondary-bg-color: #{$oc-gray-1};
|
||||
--popup-text-color: #{$oc-black};
|
||||
--popup-text-inverted-color: #{$oc-white};
|
||||
--sab: env(safe-area-inset-bottom);
|
||||
--sal: env(safe-area-inset-left);
|
||||
--sar: env(safe-area-inset-right);
|
||||
--text-color-primary: #{$oc-gray-8};
|
||||
--shadow-island: 0 1px 5px #{transparentize($oc-black, 0.85)};
|
||||
--overlay-background-color: #{transparentize($oc-white, 0.12)};
|
||||
--dropdown-icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="292.4" height="292.4" viewBox="0 0 292 292"><path d="M287 197L159 69c-4-3-8-5-13-5s-9 2-13 5L5 197c-3 4-5 8-5 13s2 9 5 13c4 4 8 5 13 5h256c5 0 9-1 13-5s5-8 5-13-1-9-5-13z"/></svg>');
|
||||
--focus-highlight-color: #{$oc-blue-2};
|
||||
--sat: env(safe-area-inset-top);
|
||||
--select-highlight-color: #{$oc-blue-5};
|
||||
--appearance-filter: none;
|
||||
--button-special-active-background-color: #{$oc-green-0};
|
||||
--button-destructive-color: #{$oc-red-9};
|
||||
--button-destructive-background-color: #{$oc-red-1};
|
||||
--popup-secondary-background-color: #{$oc-gray-1};
|
||||
--popup-text-color: #{$oc-black};
|
||||
--popup-text-inverted-color: #{$oc-white};
|
||||
--dialog-border: #{$oc-gray-6};
|
||||
--link-color: #{$oc-blue-7};
|
||||
--shadow-island: 0 1px 5px #{transparentize($oc-black, 0.85)};
|
||||
--space-factor: 0.25rem;
|
||||
--text-primary-color: #{$oc-gray-8};
|
||||
}
|
||||
|
||||
.excalidraw {
|
||||
&.Appearance_dark {
|
||||
background: #000;
|
||||
background: $oc-black;
|
||||
|
||||
&.Appearance_dark-background-none {
|
||||
background: none;
|
||||
@ -45,31 +46,31 @@
|
||||
}
|
||||
|
||||
&.Appearance_dark {
|
||||
--text-color-primary: #{$oc-gray-4};
|
||||
--bg-color-island: #1e1e1e;
|
||||
--popup-background-color: #2c2c2c;
|
||||
--appearance-filter: #{$appearance-filter};
|
||||
--button-destructive-bg-color: #5a0000;
|
||||
--button-destructive-color: #{$oc-red-3};
|
||||
--button-gray-1: #363636;
|
||||
--button-gray-2: #272727;
|
||||
--button-gray-3: #222;
|
||||
--input-border-color: #2e2e2e;
|
||||
--input-background-color: #121212;
|
||||
--input-hover-background-color: #181818;
|
||||
--input-label-color: #{$oc-gray-2};
|
||||
--icon-fill-color: #{$oc-gray-4};
|
||||
--icon-green-fill-color: #{$oc-green-4};
|
||||
--keybinding-color: #{$oc-gray-6};
|
||||
--shadow-island: 0 1px 5px #{transparentize($oc-black, 0.7)};
|
||||
--overlay-background-color: rgba(30, 30, 30, 0.88);
|
||||
--button-special-active-bg-color: #204624;
|
||||
--dialog-border-color: #{$oc-gray-9};
|
||||
--dropdown-icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="292.4" height="292.4" viewBox="0 0 292 292"><path fill="%23ced4da" d="M287 197L159 69c-4-3-8-5-13-5s-9 2-13 5L5 197c-3 4-5 8-5 13s2 9 5 13c4 4 8 5 13 5h256c5 0 9-1 13-5s5-8 5-13-1-9-5-13z"/></svg>');
|
||||
--focus-highlight-color: #{$oc-blue-6};
|
||||
--select-highlight-color: #{$oc-blue-4};
|
||||
--appearance-filter: invert(93%) hue-rotate(180deg);
|
||||
--button-special-active-background-color: #204624;
|
||||
--button-destructive-color: #{$oc-red-3};
|
||||
--button-destructive-background-color: #5a0000;
|
||||
--popup-secondary-background-color: #222;
|
||||
--icon-fill-color: #{$oc-gray-4};
|
||||
--icon-green-fill-color: #{$oc-green-4};
|
||||
--input-bg-color: #121212;
|
||||
--input-border-color: #2e2e2e;
|
||||
--input-hover-bg-color: #181818;
|
||||
--input-label-color: #{$oc-gray-2};
|
||||
--island-bg-color: #1e1e1e;
|
||||
--keybinding-color: #{$oc-gray-6};
|
||||
--overlay-bg-color: #{transparentize($oc-gray-8, 0.88)};
|
||||
--popup-bg-color: #2c2c2c;
|
||||
--popup-secondary-bg-color: #222;
|
||||
--popup-text-color: #{$oc-gray-4};
|
||||
--popup-text-inverted-color: #2c2c2c;
|
||||
--dialog-border: #{$oc-gray-9};
|
||||
--select-highlight-color: #{$oc-blue-4};
|
||||
--shadow-island: 0 1px 5px #{transparentize($oc-black, 0.7)};
|
||||
--text-primary-color: #{$oc-gray-4};
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,9 @@
|
||||
|
||||
// keep up to date with is-mobile.tsx
|
||||
$is-mobile-query: "(max-width: 600px), (max-height: 500px) and (max-width: 1000px)";
|
||||
$appearance-filter: "invert(93%) hue-rotate(180deg)";
|
||||
|
||||
:export {
|
||||
isMobileQuery: unquote($is-mobile-query);
|
||||
appearanceFilter: unquote($appearance-filter);
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ export const exportCanvas = async (
|
||||
if (type === "svg" || type === "clipboard-svg") {
|
||||
const tempSvg = exportToSvg(elements, {
|
||||
exportBackground,
|
||||
exportWithDarkMode: appState.exportWithDarkMode,
|
||||
viewBackgroundColor,
|
||||
exportPadding,
|
||||
scale,
|
||||
|
@ -141,7 +141,7 @@ export const restoreElements = (
|
||||
}, [] as ExcalidrawElement[]);
|
||||
};
|
||||
|
||||
const restoreAppState = (
|
||||
export const restoreAppState = (
|
||||
appState: ImportedDataState["appState"],
|
||||
localAppState: Partial<AppState> | null,
|
||||
): AppState => {
|
||||
|
@ -15,6 +15,7 @@ export interface ImportedDataState {
|
||||
source?: string;
|
||||
elements?: DataState["elements"] | null;
|
||||
appState?: Partial<DataState["appState"]> | null;
|
||||
scrollToCenter?: boolean;
|
||||
}
|
||||
|
||||
export interface LibraryData {
|
||||
|
@ -256,6 +256,7 @@ class CollabWrapper extends PureComponent<Props, CollabState> {
|
||||
if (elements) {
|
||||
scenePromise.resolve({
|
||||
elements,
|
||||
scrollToCenter: true,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
@ -307,7 +308,10 @@ class CollabWrapper extends PureComponent<Props, CollabState> {
|
||||
init: true,
|
||||
});
|
||||
// noop if already resolved via init from firebase
|
||||
scenePromise.resolve({ elements: reconciledElements });
|
||||
scenePromise.resolve({
|
||||
elements: reconciledElements,
|
||||
scrollToCenter: true,
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
}
|
||||
|
||||
.RoomDialog-link {
|
||||
color: var(--text-color-primary);
|
||||
color: var(--text-primary-color);
|
||||
min-width: 0;
|
||||
flex: 1 1 auto;
|
||||
margin-inline-start: 1em;
|
||||
@ -45,7 +45,7 @@
|
||||
}
|
||||
|
||||
.RoomDialog-username {
|
||||
background-color: var(--input-background-color);
|
||||
background-color: var(--input-bg-color);
|
||||
border-color: var(--input-border-color);
|
||||
appearance: none;
|
||||
min-width: 0;
|
||||
@ -67,7 +67,7 @@
|
||||
}
|
||||
|
||||
.Modal .RoomDialog-stopSession {
|
||||
background-color: var(--button-destructive-background-color);
|
||||
background-color: var(--button-destructive-bg-color);
|
||||
|
||||
.ToolIcon__label,
|
||||
.ToolIcon__icon svg {
|
||||
|
@ -13,7 +13,7 @@ import { ExcalidrawImperativeAPI } from "../components/App";
|
||||
import { ErrorDialog } from "../components/ErrorDialog";
|
||||
import { TopErrorBoundary } from "../components/TopErrorBoundary";
|
||||
import { APP_NAME, EVENT, TITLE_TIMEOUT, VERSION_TIMEOUT } from "../constants";
|
||||
import { ImportedDataState } from "../data/types";
|
||||
import { DataState, ImportedDataState } from "../data/types";
|
||||
import {
|
||||
ExcalidrawElement,
|
||||
NonDeletedExcalidrawElement,
|
||||
@ -75,7 +75,11 @@ const initializeScene = async (opts: {
|
||||
|
||||
const initialData = importFromLocalStorage();
|
||||
|
||||
let scene = await loadScene(null, null, initialData);
|
||||
let scene: DataState & { scrollToCenter?: boolean } = await loadScene(
|
||||
null,
|
||||
null,
|
||||
initialData,
|
||||
);
|
||||
|
||||
let roomLinkData = getCollaborationLinkData(window.location.href);
|
||||
const isExternalScene = !!(id || jsonMatch || roomLinkData);
|
||||
@ -94,6 +98,7 @@ const initializeScene = async (opts: {
|
||||
} else if (jsonMatch) {
|
||||
scene = await loadScene(jsonMatch[1], jsonMatch[2], initialData);
|
||||
}
|
||||
scene.scrollToCenter = true;
|
||||
if (!roomLinkData) {
|
||||
window.history.replaceState({}, APP_NAME, window.location.origin);
|
||||
}
|
||||
|
1
src/global.d.ts
vendored
1
src/global.d.ts
vendored
@ -12,6 +12,7 @@ interface Document {
|
||||
interface Window {
|
||||
ClipboardItem: any;
|
||||
__EXCALIDRAW_SHA__: string | undefined;
|
||||
EXCALIDRAW_ASSET_PATH: string | undefined;
|
||||
gtag: Function;
|
||||
}
|
||||
|
||||
|
@ -54,8 +54,8 @@ const elements = [
|
||||
},
|
||||
];
|
||||
|
||||
registerFont("./public/FG_Virgil.ttf", { family: "Virgil" });
|
||||
registerFont("./public/Cascadia.ttf", { family: "Cascadia" });
|
||||
registerFont("./public/Virgil.woff2", { family: "Virgil" });
|
||||
registerFont("./public/Cascadia.woff2", { family: "Cascadia" });
|
||||
|
||||
const canvas = exportToCanvas(
|
||||
elements as any,
|
||||
|
@ -4,7 +4,6 @@ import ExcalidrawApp from "./excalidraw-app";
|
||||
|
||||
import "./excalidraw-app/pwa";
|
||||
import "./excalidraw-app/sentry";
|
||||
|
||||
window.__EXCALIDRAW_SHA__ = process.env.REACT_APP_GIT_SHA;
|
||||
|
||||
ReactDOM.render(<ExcalidrawApp />, document.getElementById("root"));
|
||||
|
@ -92,7 +92,8 @@
|
||||
"centerHorizontally": "Center horizontally",
|
||||
"distributeHorizontally": "Distribute horizontally",
|
||||
"distributeVertically": "Distribute vertically",
|
||||
"viewMode": "View mode"
|
||||
"viewMode": "View mode",
|
||||
"toggleExportColorScheme": "Toggle export color scheme"
|
||||
},
|
||||
"buttons": {
|
||||
"clearReset": "Reset the canvas",
|
||||
|
@ -12,6 +12,34 @@ The change should be grouped under one of the below section and must contain PR
|
||||
Please add the latest change on the top under the correct section.
|
||||
-->
|
||||
|
||||
## 0.4.0
|
||||
|
||||
## Excalidraw API
|
||||
|
||||
### 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).
|
||||
|
||||
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
|
||||
|
||||
- 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
|
||||
|
||||
## Excalidraw API
|
||||
|
@ -20,13 +20,9 @@ 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.
|
||||
|
||||
By default it will try to load the files from `{rootUrl}/excalidraw-assets/`
|
||||
By default it will try to load the files from `https://unpkg.com/@excalidraw/excalidraw/{currentVersion}/dist/`
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
### Demo
|
||||
|
||||
@ -252,51 +248,6 @@ export default function IndexPage() {
|
||||
| [`zenModeEnabled`](#zenModeEnabled) | boolean | | This implies if the zen mode is enabled |
|
||||
| [`gridModeEnabled`](#gridModeEnabled) | boolean | | This implies if the grid mode is enabled |
|
||||
|
||||
### `Extra API's`
|
||||
|
||||
#### `getSceneVersion`
|
||||
|
||||
**How to use**
|
||||
|
||||
<pre>
|
||||
import { getSceneVersion } from "@excalidraw/excalidraw";
|
||||
getSceneVersion(elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>)
|
||||
</pre>
|
||||
|
||||
This function returns the current scene version.
|
||||
|
||||
#### `getSyncableElements`
|
||||
|
||||
**_Signature_**
|
||||
|
||||
<pre>
|
||||
getSyncableElements(elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>):<a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>
|
||||
</pre>
|
||||
|
||||
**How to use**
|
||||
|
||||
```js
|
||||
import { getSyncableElements } from "@excalidraw/excalidraw";
|
||||
```
|
||||
|
||||
This function returns all the deleted elements of the scene.
|
||||
|
||||
### `getElementMap`
|
||||
|
||||
**_Signature_**
|
||||
|
||||
<pre>
|
||||
getElementsMap(elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>): {[id: string]: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement</a>}
|
||||
</pre>
|
||||
|
||||
**How to use**
|
||||
|
||||
```js
|
||||
import { getElementsMap } from "@excalidraw/excalidraw";
|
||||
```
|
||||
|
||||
This function returns an object where each element is mapped to its id.
|
||||
|
||||
#### `width`
|
||||
|
||||
This props defines the `width` of the Excalidraw component. Defaults to `window.innerWidth` if not passed.
|
||||
@ -331,10 +282,11 @@ 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.
|
||||
|
||||
| name | type |
|
||||
| --- | --- |
|
||||
| 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) |
|
||||
| Name | Type | Descrption |
|
||||
| --- | --- | --- |
|
||||
| `elements` | [ExcalidrawElement[]](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78) | The elements with which Excalidraw should be mounted. |
|
||||
| `appState` | [AppState](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L37) | The App state with which Excalidraw should be mounted. |
|
||||
| `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
|
||||
{
|
||||
@ -451,3 +403,98 @@ This prop indicates whether the app is in `zen mode`. When supplied, the value t
|
||||
#### `gridModeEnabled`
|
||||
|
||||
This prop indicates whether the shows the grid. When supplied, the value takes precedence over `intialData.appState.gridModeEnabled`, the grid will be fully controlled by the host app, and users won't be able to toggle it from within the app.
|
||||
|
||||
### Extra API's
|
||||
|
||||
#### `getSceneVersion`
|
||||
|
||||
**How to use**
|
||||
|
||||
<pre>
|
||||
import { getSceneVersion } from "@excalidraw/excalidraw";
|
||||
getSceneVersion(elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>)
|
||||
</pre>
|
||||
|
||||
This function returns the current scene version.
|
||||
|
||||
#### `getSyncableElements`
|
||||
|
||||
**_Signature_**
|
||||
|
||||
<pre>
|
||||
getSyncableElements(elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>):<a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>
|
||||
</pre>
|
||||
|
||||
**How to use**
|
||||
|
||||
```js
|
||||
import { getSyncableElements } from "@excalidraw/excalidraw";
|
||||
```
|
||||
|
||||
This function returns all the deleted elements of the scene.
|
||||
|
||||
#### `getElementMap`
|
||||
|
||||
**_Signature_**
|
||||
|
||||
<pre>
|
||||
getElementsMap(elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>): {[id: string]: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement</a>}
|
||||
</pre>
|
||||
|
||||
**How to use**
|
||||
|
||||
```js
|
||||
import { getElementsMap } from "@excalidraw/excalidraw";
|
||||
```
|
||||
|
||||
This function returns an object where each element is mapped to its id.
|
||||
|
||||
**_The below api's will be available in [next version](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/CHANGELOG.md#unreleased)_**
|
||||
|
||||
#### `restoreAppState`
|
||||
|
||||
**_Signature_**
|
||||
|
||||
<pre>
|
||||
restoreAppState(appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L17">ImportedDataState["appState"]</a>, localAppState: Partial<<a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L37">AppState</a>> | null): <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L37">AppState</a>
|
||||
</pre>
|
||||
|
||||
**_How to use_**
|
||||
|
||||
```js
|
||||
import { restoreAppState } from "@excalidraw/excalidraw";
|
||||
```
|
||||
|
||||
This function will make sure all the keys have appropriate values in [appState](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L37) and if any key is missing, it will be set to default value. If you pass `localAppState`, `localAppState` value will be preferred over the `appState` passed in params.
|
||||
|
||||
#### `restoreElements`
|
||||
|
||||
**_Signature_**
|
||||
|
||||
<pre>
|
||||
restoreElements(elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L16">ImportedDataState["elements"]</a>): <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>
|
||||
</pre>
|
||||
|
||||
**_How to use_**
|
||||
|
||||
```js
|
||||
import { restoreElements } from "@excalidraw/excalidraw";
|
||||
```
|
||||
|
||||
This function will make sure all properties of element is correctly set and if any attribute is missing, it will be set to default value.
|
||||
|
||||
#### `restore`
|
||||
|
||||
**_Signature_**
|
||||
|
||||
<pre>
|
||||
restoreElements(data: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L12">ImportedDataState</a>): <a href="https://github.com/excalidraw/excalidraw/blob/master/src/data/types.ts#L4">DataState</a>
|
||||
</pre>
|
||||
|
||||
**_How to use_**
|
||||
|
||||
```js
|
||||
import { restore } from "@excalidraw/excalidraw";
|
||||
```
|
||||
|
||||
This function makes sure elements and state is set to appropriate values and set to default value if not present. It is combination of [restoreElements](#restoreElements) and [restoreAppState](#restoreAppState)
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React, { useEffect, forwardRef } from "react";
|
||||
import "./publicPath";
|
||||
|
||||
import { InitializeApp } from "../../components/InitializeApp";
|
||||
import App from "../../components/App";
|
||||
@ -106,3 +107,4 @@ export {
|
||||
getElementMap,
|
||||
} from "../../element";
|
||||
export { defaultLang, languages } from "../../i18n";
|
||||
export { restore, restoreAppState, restoreElements } from "../../data/restore";
|
||||
|
4451
src/packages/excalidraw/package-lock.json
generated
4451
src/packages/excalidraw/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@excalidraw/excalidraw",
|
||||
"version": "0.3.1",
|
||||
"version": "0.4.0",
|
||||
"main": "dist/excalidraw.min.js",
|
||||
"files": [
|
||||
"dist/*"
|
||||
@ -41,24 +41,24 @@
|
||||
"react-dom": "^17.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.12.16",
|
||||
"@babel/plugin-transform-arrow-functions": "7.12.13",
|
||||
"@babel/plugin-transform-async-to-generator": "7.12.13",
|
||||
"@babel/plugin-transform-runtime": "7.12.15",
|
||||
"@babel/plugin-transform-typescript": "7.12.16",
|
||||
"@babel/preset-env": "7.12.16",
|
||||
"@babel/core": "7.13.8",
|
||||
"@babel/plugin-transform-arrow-functions": "7.13.0",
|
||||
"@babel/plugin-transform-async-to-generator": "7.13.0",
|
||||
"@babel/plugin-transform-runtime": "7.13.8",
|
||||
"@babel/plugin-transform-typescript": "7.13.0",
|
||||
"@babel/preset-env": "7.13.8",
|
||||
"@babel/preset-react": "7.12.13",
|
||||
"@babel/preset-typescript": "7.12.16",
|
||||
"@babel/preset-typescript": "7.13.0",
|
||||
"babel-loader": "8.2.2",
|
||||
"babel-plugin-transform-class-properties": "6.24.1",
|
||||
"cross-env": "7.0.3",
|
||||
"css-loader": "5.0.2",
|
||||
"css-loader": "5.1.0",
|
||||
"file-loader": "6.2.0",
|
||||
"mini-css-extract-plugin": "1.3.6",
|
||||
"mini-css-extract-plugin": "1.3.9",
|
||||
"sass-loader": "11.0.1",
|
||||
"terser-webpack-plugin": "5.1.1",
|
||||
"ts-loader": "8.0.17",
|
||||
"webpack": "5.21.2",
|
||||
"webpack": "5.24.2",
|
||||
"webpack-bundle-analyzer": "4.4.0",
|
||||
"webpack-cli": "4.5.0"
|
||||
},
|
||||
@ -68,6 +68,6 @@
|
||||
"scripts": {
|
||||
"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",
|
||||
"pack": "npm run build:umd && npm pack"
|
||||
"pack": "yarn build:umd && yarn pack"
|
||||
}
|
||||
}
|
||||
|
9
src/packages/excalidraw/publicPath.js
Normal file
9
src/packages/excalidraw/publicPath.js
Normal file
@ -0,0 +1,9 @@
|
||||
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,7 +13,8 @@ module.exports = {
|
||||
library: "Excalidraw",
|
||||
libraryTarget: "umd",
|
||||
filename: "[name].js",
|
||||
chunkFilename: "excalidraw-assets/[name].js",
|
||||
chunkFilename: "excalidraw-assets/[name]-[contenthash].js",
|
||||
publicPath: "",
|
||||
},
|
||||
resolve: {
|
||||
extensions: [".js", ".ts", ".tsx", ".css", ".scss"],
|
||||
|
2715
src/packages/excalidraw/yarn.lock
Normal file
2715
src/packages/excalidraw/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
3446
src/packages/utils/package-lock.json
generated
3446
src/packages/utils/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -34,19 +34,21 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.12.16",
|
||||
"@babel/plugin-transform-arrow-functions": "7.12.13",
|
||||
"@babel/plugin-transform-async-to-generator": "7.12.13",
|
||||
"@babel/core": "7.13.8",
|
||||
"@babel/plugin-transform-arrow-functions": "7.13.0",
|
||||
"@babel/plugin-transform-async-to-generator": "7.13.0",
|
||||
"@babel/plugin-transform-runtime": "^7.12.10",
|
||||
"@babel/plugin-transform-typescript": "7.12.16",
|
||||
"@babel/preset-env": "7.12.16",
|
||||
"@babel/preset-typescript": "7.12.16",
|
||||
"@babel/plugin-transform-typescript": "7.13.0",
|
||||
"@babel/preset-env": "7.13.8",
|
||||
"@babel/preset-typescript": "7.13.0",
|
||||
"babel-loader": "8.2.2",
|
||||
"babel-plugin-transform-class-properties": "6.24.1",
|
||||
"cross-env": "7.0.3",
|
||||
"css-loader": "5.1.0",
|
||||
"file-loader": "6.2.0",
|
||||
"sass-loader": "11.0.1",
|
||||
"ts-loader": "8.0.17",
|
||||
"webpack": "5.21.2",
|
||||
"webpack": "5.24.2",
|
||||
"webpack-bundle-analyzer": "4.4.0",
|
||||
"webpack-cli": "4.5.0"
|
||||
},
|
||||
@ -55,6 +57,6 @@
|
||||
"scripts": {
|
||||
"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",
|
||||
"pack": "npm run build:umd && npm pack"
|
||||
"pack": "yarn build:umd && npm pack"
|
||||
}
|
||||
}
|
||||
|
@ -13,13 +13,18 @@ module.exports = {
|
||||
libraryTarget: "umd",
|
||||
},
|
||||
resolve: {
|
||||
extensions: [".tsx", ".ts", ".js"],
|
||||
extensions: [".tsx", ".ts", ".js", ".css", ".scss"],
|
||||
},
|
||||
optimization: {
|
||||
runtimeChunk: false,
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(sa|sc|c)ss$/,
|
||||
exclude: /node_modules/,
|
||||
use: ["style-loader", { loader: "css-loader" }, "sass-loader"],
|
||||
},
|
||||
{
|
||||
test: /\.(ts|tsx|js)$/,
|
||||
use: [
|
||||
|
2647
src/packages/utils/yarn.lock
Normal file
2647
src/packages/utils/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
@ -49,6 +49,7 @@ import {
|
||||
} from "../element/transformHandles";
|
||||
import { viewportCoordsToSceneCoords, supportsEmoji } from "../utils";
|
||||
import { UserIdleState } from "../excalidraw-app/collab/types";
|
||||
import { APPEARANCE_FILTER } from "../constants";
|
||||
|
||||
const hasEmojiSupport = supportsEmoji();
|
||||
|
||||
@ -211,6 +212,10 @@ export const renderScene = (
|
||||
const normalizedCanvasWidth = canvas.width / scale;
|
||||
const normalizedCanvasHeight = canvas.height / scale;
|
||||
|
||||
if (sceneState.exportWithDarkMode) {
|
||||
context.filter = APPEARANCE_FILTER;
|
||||
}
|
||||
|
||||
// Paint background
|
||||
if (typeof sceneState.viewBackgroundColor === "string") {
|
||||
const hasTransparence =
|
||||
@ -483,25 +488,20 @@ export const renderScene = (
|
||||
context.stroke();
|
||||
|
||||
const username = sceneState.remotePointerUsernames[clientId];
|
||||
let usernameAndIdleState;
|
||||
if (hasEmojiSupport) {
|
||||
usernameAndIdleState = `${username ? `${username} ` : ""}${
|
||||
userState === UserIdleState.AWAY
|
||||
? "⚫️"
|
||||
: userState === UserIdleState.IDLE
|
||||
? "💤"
|
||||
: "🟢"
|
||||
}`;
|
||||
} else {
|
||||
usernameAndIdleState = `${username ? `${username}` : ""}${
|
||||
userState === UserIdleState.AWAY
|
||||
? ` (${UserIdleState.AWAY})`
|
||||
: userState === UserIdleState.IDLE
|
||||
? ` (${UserIdleState.IDLE})`
|
||||
: ""
|
||||
}`;
|
||||
|
||||
let idleState = "";
|
||||
if (userState === UserIdleState.AWAY) {
|
||||
idleState = hasEmojiSupport ? "⚫️" : ` (${UserIdleState.AWAY})`;
|
||||
} else if (userState === UserIdleState.IDLE) {
|
||||
idleState = hasEmojiSupport ? "💤" : ` (${UserIdleState.IDLE})`;
|
||||
} else if (userState === UserIdleState.ACTIVE) {
|
||||
idleState = hasEmojiSupport ? "🟢" : "";
|
||||
}
|
||||
|
||||
const usernameAndIdleState = `${
|
||||
username ? `${username} ` : ""
|
||||
}${idleState}`;
|
||||
|
||||
if (!isOutOfBounds && usernameAndIdleState) {
|
||||
const offsetX = x + width;
|
||||
const offsetY = y + height;
|
||||
|
@ -7,7 +7,11 @@ import { renderScene, renderSceneToSvg } from "../renderer/renderScene";
|
||||
import { distance, SVG_NS } from "../utils";
|
||||
import { AppState } from "../types";
|
||||
import { t } from "../i18n";
|
||||
import { DEFAULT_FONT_FAMILY, DEFAULT_VERTICAL_ALIGN } from "../constants";
|
||||
import {
|
||||
DEFAULT_FONT_FAMILY,
|
||||
DEFAULT_VERTICAL_ALIGN,
|
||||
APPEARANCE_FILTER,
|
||||
} from "../constants";
|
||||
import { getDefaultAppState } from "../appState";
|
||||
|
||||
export const SVG_EXPORT_TAG = `<!-- svg-source:excalidraw -->`;
|
||||
@ -61,6 +65,7 @@ export const exportToCanvas = (
|
||||
tempCanvas,
|
||||
{
|
||||
viewBackgroundColor: exportBackground ? viewBackgroundColor : null,
|
||||
exportWithDarkMode: appState.exportWithDarkMode,
|
||||
scrollX: -minX + exportPadding,
|
||||
scrollY: -minY + exportPadding,
|
||||
zoom: getDefaultAppState().zoom,
|
||||
@ -87,6 +92,7 @@ export const exportToSvg = (
|
||||
exportBackground,
|
||||
exportPadding = 10,
|
||||
viewBackgroundColor,
|
||||
exportWithDarkMode,
|
||||
scale = 1,
|
||||
shouldAddWatermark,
|
||||
metadata = "",
|
||||
@ -95,6 +101,7 @@ export const exportToSvg = (
|
||||
exportPadding?: number;
|
||||
scale?: number;
|
||||
viewBackgroundColor: string;
|
||||
exportWithDarkMode?: boolean;
|
||||
shouldAddWatermark: boolean;
|
||||
metadata?: string;
|
||||
},
|
||||
@ -114,6 +121,9 @@ export const exportToSvg = (
|
||||
svgRoot.setAttribute("viewBox", `0 0 ${width} ${height}`);
|
||||
svgRoot.setAttribute("width", `${width * scale}`);
|
||||
svgRoot.setAttribute("height", `${height * scale}`);
|
||||
if (exportWithDarkMode) {
|
||||
svgRoot.setAttribute("filter", APPEARANCE_FILTER);
|
||||
}
|
||||
|
||||
svgRoot.innerHTML = `
|
||||
${SVG_EXPORT_TAG}
|
||||
@ -122,7 +132,7 @@ export const exportToSvg = (
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: "Virgil";
|
||||
src: url("https://excalidraw.com/FG_Virgil.woff2");
|
||||
src: url("https://excalidraw.com/Virgil.woff2");
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Cascadia";
|
||||
|
@ -6,6 +6,7 @@ export type SceneState = {
|
||||
scrollY: number;
|
||||
// null indicates transparent bg
|
||||
viewBackgroundColor: string | null;
|
||||
exportWithDarkMode?: boolean;
|
||||
zoom: Zoom;
|
||||
shouldCacheIgnoreZoom: boolean;
|
||||
remotePointerViewportCoords: { [id: string]: { x: number; y: number } };
|
||||
|
@ -29,6 +29,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -489,6 +490,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -955,6 +957,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -1730,6 +1733,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -1933,6 +1937,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -2390,6 +2395,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -2642,6 +2648,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -2805,6 +2812,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -3281,6 +3289,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -3588,6 +3597,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -3791,6 +3801,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -4034,6 +4045,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -4285,6 +4297,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -4667,6 +4680,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -4961,6 +4975,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -5267,6 +5282,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -5474,6 +5490,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -5637,6 +5654,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -6089,6 +6107,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -6406,6 +6425,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -8439,6 +8459,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -8800,6 +8821,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -9054,6 +9076,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -9306,6 +9329,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -9620,6 +9644,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -9783,6 +9808,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -9946,6 +9972,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -10109,6 +10136,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -10302,6 +10330,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -10495,6 +10524,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -10688,6 +10718,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -10881,6 +10912,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -11044,6 +11076,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -11207,6 +11240,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -11400,6 +11434,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -11563,6 +11598,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -11756,6 +11792,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -12471,6 +12508,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -12723,6 +12761,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -12824,6 +12863,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -12923,6 +12963,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -13086,6 +13127,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -13393,6 +13435,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -13700,6 +13743,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -13863,6 +13907,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -14058,6 +14103,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -14306,6 +14352,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -14629,6 +14676,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -15467,6 +15515,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -15774,6 +15823,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -16081,6 +16131,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -16459,6 +16510,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -16625,6 +16677,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -16945,6 +16998,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -17183,6 +17237,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -17437,6 +17492,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -17763,6 +17819,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -17862,6 +17919,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -18025,6 +18083,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -18845,6 +18904,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -18944,6 +19004,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -19697,6 +19758,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -20101,6 +20163,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -20373,6 +20436,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -20474,6 +20538,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -20971,6 +21036,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
@ -21070,6 +21136,7 @@ Object {
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
|
4
src/tests/fixtures/smiley_embedded_v2.svg
vendored
4
src/tests/fixtures/smiley_embedded_v2.svg
vendored
@ -5,7 +5,7 @@
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: "Virgil";
|
||||
src: url("https://excalidraw.com/FG_Virgil.woff2");
|
||||
src: url("https://excalidraw.com/Virgil.woff2");
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Cascadia";
|
||||
@ -13,4 +13,4 @@
|
||||
}
|
||||
</style>
|
||||
</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 |
4
src/tests/fixtures/test_embedded_v1.svg
vendored
4
src/tests/fixtures/test_embedded_v1.svg
vendored
@ -5,7 +5,7 @@
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: "Virgil";
|
||||
src: url("https://excalidraw.com/FG_Virgil.woff2");
|
||||
src: url("https://excalidraw.com/Virgil.woff2");
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Cascadia";
|
||||
@ -13,4 +13,4 @@
|
||||
}
|
||||
</style>
|
||||
</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 |
@ -30,6 +30,7 @@ describe("appState", () => {
|
||||
height: ELEM_HEIGHT,
|
||||
}),
|
||||
],
|
||||
scrollToCenter: true,
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
|
@ -57,6 +57,7 @@ export type AppState = {
|
||||
elementLocked: boolean;
|
||||
exportBackground: boolean;
|
||||
exportEmbedScene: boolean;
|
||||
exportWithDarkMode: boolean;
|
||||
shouldAddWatermark: boolean;
|
||||
currentItemStrokeColor: string;
|
||||
currentItemBackgroundColor: string;
|
||||
|
Reference in New Issue
Block a user