Compare commits
66 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c12dab7a60 | |||
| 39e7b8cf4f | |||
| e0ece680a6 | |||
| 8dfea49ec1 | |||
| d7f314cda8 | |||
| 6adb45ef5a | |||
| b0eeb8e6e6 | |||
| c3c20b6087 | |||
| 0faec7efb6 | |||
| aff817c667 | |||
| 9a3a3ecb44 | |||
| 81f8039ec7 | |||
| 14759d5b72 | |||
| b997e69ebc | |||
| 4a89aba682 | |||
| 34dcf998bd | |||
| 325d1bec91 | |||
| b917e42694 | |||
| eb9e67e36a | |||
| f14ae52e94 | |||
| f93eb658d6 | |||
| 9bac44ee75 | |||
| 91b4109f67 | |||
| 6e45cb95db | |||
| 5edf82898b | |||
| 60b82e3055 | |||
| 5d6590c200 | |||
| d3bebbc68d | |||
| 4ff8f3b006 | |||
| abbc756887 | |||
| 10e07e434c | |||
| fb582b45db | |||
| 23f21434ff | |||
| 7e9fdf85a0 | |||
| 98c26642d0 | |||
| 2b434db062 | |||
| f919907855 | |||
| bfeb3c7dfd | |||
| 8729ab3c54 | |||
| 37f53bccbf | |||
| c783763307 | |||
| f151f45df8 | |||
| f33880e005 | |||
| 29ed50f6ea | |||
| ce52c18382 | |||
| 7c3e1d8d1b | |||
| 0d15934a96 | |||
| a0069d04f0 | |||
| 3b86944365 | |||
| 4c7b1a2269 | |||
| 60864ace54 | |||
| 4b32c03994 | |||
| 222dbdcc00 | |||
| 1346227d30 | |||
| ecbddd214c | |||
| 4999ca5c82 | |||
| 174638889d | |||
| 480998582e | |||
| 94544e458c | |||
| f664ba9e1e | |||
| 015a60638e | |||
| 7abb80530f | |||
| 5abe9b93e8 | |||
| 59cff0f219 | |||
| 81c17a56fb | |||
| 802b8c50d5 |
@@ -0,0 +1,37 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: npm
|
||||
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/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: sunday
|
||||
time: "01:00"
|
||||
open-pull-requests-limit: 99
|
||||
reviewers:
|
||||
- ad1992
|
||||
assignees:
|
||||
- ad1992
|
||||
|
||||
- package-ecosystem: npm
|
||||
directory: "/src/packages/utils/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: sunday
|
||||
time: "01:00"
|
||||
open-pull-requests-limit: 99
|
||||
reviewers:
|
||||
- ad1992
|
||||
assignees:
|
||||
- ad1992
|
||||
@@ -4,7 +4,6 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
build-docker:
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
schedule:
|
||||
- cron: "18 7 * * 0"
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: ["typescript"]
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
@@ -30,3 +30,18 @@ jobs:
|
||||
git commit -am "Auto commit: Calculate translation coverage"
|
||||
git push
|
||||
fi
|
||||
- name: Construct comment body
|
||||
id: getCommentBody
|
||||
run: |
|
||||
body=$(npm run locales-coverage:description | grep '^[^>]')
|
||||
body="${body//'%'/'%25'}"
|
||||
body="${body//$'\n'/'%0A'}"
|
||||
body="${body//$'\r'/'%0D'}"
|
||||
echo ::set-output name=body::$body
|
||||
|
||||
- name: Update description with coverage
|
||||
uses: kt3k/update-pr-description@v1.0.1
|
||||
with:
|
||||
pr_body: ${{ steps.getCommentBody.outputs.body }}
|
||||
pr_title: "chore: New Crowdin updates"
|
||||
github_token: ${{ secrets.PUSH_TRANSLATIONS_COVERAGE_PAT }}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
name: "Semantic PR title"
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- synchronize
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: amannn/action-semantic-pull-request@v2.1.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
Generated
+383
-586
File diff suppressed because it is too large
Load Diff
+14
-14
@@ -19,18 +19,18 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@sentry/browser": "5.28.0",
|
||||
"@sentry/integrations": "5.28.0",
|
||||
"@sentry/browser": "5.29.0",
|
||||
"@sentry/integrations": "5.29.0",
|
||||
"@testing-library/jest-dom": "5.11.6",
|
||||
"@testing-library/react": "11.2.2",
|
||||
"@types/jest": "26.0.16",
|
||||
"@types/jest": "26.0.19",
|
||||
"@types/nanoid": "2.1.0",
|
||||
"@types/react": "17.0.0",
|
||||
"@types/react-dom": "17.0.0",
|
||||
"@types/socket.io-client": "1.4.34",
|
||||
"browser-nativefs": "0.11.1",
|
||||
"browser-nativefs": "0.12.0",
|
||||
"clsx": "1.1.1",
|
||||
"firebase": "8.1.2",
|
||||
"firebase": "8.2.1",
|
||||
"i18next-browser-languagedetector": "6.0.1",
|
||||
"lodash.throttle": "4.1.1",
|
||||
"nanoid": "2.1.11",
|
||||
@@ -47,19 +47,18 @@
|
||||
"react-scripts": "4.0.1",
|
||||
"roughjs": "4.3.1",
|
||||
"socket.io-client": "2.3.1",
|
||||
"typescript": "4.0.5"
|
||||
"typescript": "4.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/lodash.throttle": "4.1.6",
|
||||
"@types/pako": "1.0.1",
|
||||
"asar": "3.0.3",
|
||||
"eslint-config-prettier": "7.0.0",
|
||||
"eslint-plugin-prettier": "3.1.4",
|
||||
"firebase-tools": "8.17.0",
|
||||
"husky": "4.3.0",
|
||||
"eslint-config-prettier": "7.1.0",
|
||||
"eslint-plugin-prettier": "3.3.0",
|
||||
"firebase-tools": "9.0.1",
|
||||
"husky": "4.3.6",
|
||||
"jest-canvas-mock": "2.3.0",
|
||||
"lint-staged": "10.5.3",
|
||||
"pepjs": "0.5.2",
|
||||
"pepjs": "0.5.3",
|
||||
"prettier": "2.2.1",
|
||||
"rewire": "5.0.0"
|
||||
},
|
||||
@@ -84,13 +83,14 @@
|
||||
"build-node": "node ./scripts/build-node.js",
|
||||
"build:app:docker": "REACT_APP_INCLUDE_GTAG=false REACT_APP_DISABLE_SENTRY=true react-scripts build",
|
||||
"build:app": "REACT_APP_INCLUDE_GTAG=true REACT_APP_GIT_SHA=$NOW_GITHUB_COMMIT_SHA react-scripts build",
|
||||
"build:zip": "node ./scripts/build-version.js",
|
||||
"build": "npm run build:app && npm run build:zip",
|
||||
"build:version": "node ./scripts/build-version.js",
|
||||
"build": "npm run build:app && npm run 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",
|
||||
"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",
|
||||
|
||||
@@ -55,6 +55,8 @@
|
||||
<meta name="twitter:image" content="https://excalidraw.com/og-image.png" />
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
|
||||
|
||||
<!-- Excalidraw version -->
|
||||
<meta name="version" content="{version}" />
|
||||
<link
|
||||
rel="preload"
|
||||
href="FG_Virgil.woff2"
|
||||
|
||||
@@ -25,5 +25,6 @@
|
||||
"application/vnd.excalidraw+json": [".excalidraw"]
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"capture_links": "new_client"
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const asar = require("asar");
|
||||
const versionFile = path.join("build", "version.json");
|
||||
const indexFile = path.join("build", "index.html");
|
||||
|
||||
const zero = (digit) => `0${digit}`.slice(-2);
|
||||
|
||||
@@ -20,18 +21,24 @@ const now = new Date();
|
||||
|
||||
const data = JSON.stringify(
|
||||
{
|
||||
asar: "excalidraw.asar",
|
||||
version: versionDate(now),
|
||||
},
|
||||
undefined,
|
||||
2,
|
||||
);
|
||||
|
||||
fs.writeFileSync(path.join("build", "version.json"), data);
|
||||
fs.writeFileSync(versionFile, data);
|
||||
|
||||
(async () => {
|
||||
const src = "build/";
|
||||
const dest = path.join("build", `excalidraw.asar`);
|
||||
// https://stackoverflow.com/a/14181136/8418
|
||||
fs.readFile(indexFile, "utf8", (error, data) => {
|
||||
if (error) {
|
||||
return console.error(error);
|
||||
}
|
||||
const result = data.replace(/{version}/g, versionDate(now));
|
||||
|
||||
await asar.createPackage(src, dest);
|
||||
})();
|
||||
fs.writeFile(indexFile, result, "utf8", (error) => {
|
||||
if (error) {
|
||||
return console.error(error);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
const fs = require("fs");
|
||||
|
||||
const THRESSHOLD = 85;
|
||||
|
||||
const crowdinMap = {
|
||||
"ar-SA": "en-ar",
|
||||
"el-GR": "en-el",
|
||||
"fi-FI": "en-fi",
|
||||
"ja-JP": "en-ja",
|
||||
"bg-BG": "en-bg",
|
||||
"ca-ES": "en-ca",
|
||||
"de-DE": "en-de",
|
||||
"es-ES": "en-es",
|
||||
"fa-IR": "en-fa",
|
||||
"fr-FR": "en-fr",
|
||||
"he-IL": "en-he",
|
||||
"hi-IN": "en-hi",
|
||||
"hu-HU": "en-hu",
|
||||
"id-ID": "en-id",
|
||||
"it-IT": "en-it",
|
||||
"ko-KR": "en-ko",
|
||||
"my-MM": "en-my",
|
||||
"nb-NO": "en-nb",
|
||||
"nl-NL": "en-nl",
|
||||
"nn-NO": "en-nnno",
|
||||
"pl-PL": "en-pl",
|
||||
"pt-PT": "en-pt",
|
||||
"ro-RO": "en-ro",
|
||||
"ru-RU": "en-ru",
|
||||
"sk-SK": "en-sk",
|
||||
"sv-SE": "en-sv",
|
||||
"tr-TR": "en-tr",
|
||||
"uk-UA": "en-uk",
|
||||
"zh-CN": "en-zhcn",
|
||||
"zh-TW": "en-zhtw",
|
||||
};
|
||||
|
||||
const flags = {
|
||||
"ar-SA": "🇸🇦",
|
||||
"bg-BG": "🇧🇬",
|
||||
"ca-ES": "🇪🇸",
|
||||
"de-DE": "🇩🇪",
|
||||
"el-GR": "🇬🇷",
|
||||
"es-ES": "🇪🇸",
|
||||
"fa-IR": "🇮🇷",
|
||||
"fi-FI": "🇫🇮",
|
||||
"fr-FR": "🇫🇷",
|
||||
"he-IL": "🇮🇱",
|
||||
"hi-IN": "🇮🇳",
|
||||
"hu-HU": "🇭🇺",
|
||||
"id-ID": "🇮🇩",
|
||||
"it-IT": "🇮🇹",
|
||||
"ja-JP": "🇯🇵",
|
||||
"ko-KR": "🇰🇷",
|
||||
"my-MM": "🇲🇲",
|
||||
"nb-NO": "🇳🇴",
|
||||
"nl-NL": "🇳🇱",
|
||||
"nn-NO": "🇳🇴",
|
||||
"pl-PL": "🇵🇱",
|
||||
"pt-PT": "🇵🇹",
|
||||
"ro-RO": "🇷🇴",
|
||||
"ru-RU": "🇷🇺",
|
||||
"sk-SK": "🇸🇰",
|
||||
"sv-SE": "🇸🇪",
|
||||
"tr-TR": "🇹🇷",
|
||||
"uk-UA": "🇺🇦",
|
||||
"zh-CN": "🇨🇳",
|
||||
"zh-TW": "🇹🇼",
|
||||
};
|
||||
|
||||
const languages = {
|
||||
"ar-SA": "العربية",
|
||||
"bg-BG": "Български",
|
||||
"ca-ES": "Catalan",
|
||||
"de-DE": "Deutsch",
|
||||
"el-GR": "Ελληνικά",
|
||||
"es-ES": "Español",
|
||||
"fa-IR": "فارسی",
|
||||
"fi-FI": "Suomi",
|
||||
"fr-FR": "Français",
|
||||
"he-IL": "עברית",
|
||||
"hi-IN": "हिन्दी",
|
||||
"hu-HU": "Magyar",
|
||||
"id-ID": "Bahasa Indonesia",
|
||||
"it-IT": "Italiano",
|
||||
"ja-JP": "日本語",
|
||||
"ko-KR": "한국어",
|
||||
"my-MM": "Burmese",
|
||||
"nb-NO": "Norsk bokmål",
|
||||
"nl-NL": "Nederlands",
|
||||
"nn-NO": "Norsk nynorsk",
|
||||
"pl-PL": "Polski",
|
||||
"pt-PT": "Português",
|
||||
"ro-RO": "Română",
|
||||
"ru-RU": "Русский",
|
||||
"sk-SK": "Slovenčina",
|
||||
"sv-SE": "Svenska",
|
||||
"tr-TR": "Türkçe",
|
||||
"uk-UA": "Українська",
|
||||
"zh-CN": "简体中文",
|
||||
"zh-TW": "繁體中文",
|
||||
};
|
||||
|
||||
const percentages = fs.readFileSync(
|
||||
`${__dirname}/../src/locales/percentages.json`,
|
||||
);
|
||||
const rowData = JSON.parse(percentages);
|
||||
|
||||
const coverages = Object.entries(rowData)
|
||||
.sort(([, a], [, b]) => b - a)
|
||||
.reduce((r, [k, v]) => ({ ...r, [k]: v }), {});
|
||||
|
||||
const boldIf = (text, condition) => (condition ? `**${text}**` : text);
|
||||
|
||||
const printHeader = () => {
|
||||
let result = "| | Flag | Locale | % |\n";
|
||||
result += "| --: | :--: | -- | --: |";
|
||||
return result;
|
||||
};
|
||||
|
||||
const printRow = (id, locale, coverage) => {
|
||||
const isOver = coverage > THRESSHOLD;
|
||||
let result = `| ${boldIf(id, isOver)} | `;
|
||||
|
||||
result += `${locale in flags ? flags[locale] : ""} | `;
|
||||
|
||||
const language = locale in languages ? languages[locale] : locale;
|
||||
if (locale in crowdinMap && crowdinMap[locale]) {
|
||||
result += `[${boldIf(
|
||||
language,
|
||||
isOver,
|
||||
)}](https://crowdin.com/translate/excalidraw/10/${crowdinMap[locale]}) | `;
|
||||
} else {
|
||||
result += `${boldIf(language, isOver)} | `;
|
||||
}
|
||||
result += `${boldIf(coverage, isOver)} |`;
|
||||
return result;
|
||||
};
|
||||
|
||||
console.info("## Languages check");
|
||||
console.info("\n\r");
|
||||
console.info(
|
||||
`Our translations for every languages should be at least **${THRESSHOLD}%** to appear on Excalidraw. Join our project in [Crowdin](https://crowdin.com/project/excalidraw) and help us translate it in your language. **Can't find your own?** Open an [issue](https://github.com/excalidraw/excalidraw/issues/new) and we'll add it to the list.`,
|
||||
);
|
||||
console.info("\n\r");
|
||||
console.info(printHeader());
|
||||
let index = 1;
|
||||
for (const coverage in coverages) {
|
||||
if (coverage === "en") {
|
||||
continue;
|
||||
}
|
||||
console.info(printRow(index, coverage, coverages[coverage]));
|
||||
index++;
|
||||
}
|
||||
console.info("\n\r");
|
||||
console.info("\\* Languages in **bold** are going to appear on production.");
|
||||
@@ -4,12 +4,14 @@ import { getDefaultAppState } from "../appState";
|
||||
import { trash, zoomIn, zoomOut, resetZoom } from "../components/icons";
|
||||
import { ToolButton } from "../components/ToolButton";
|
||||
import { t } from "../i18n";
|
||||
import { getNormalizedZoom } from "../scene";
|
||||
import { getNormalizedZoom, getSelectedElements } from "../scene";
|
||||
import { getNonDeletedElements } from "../element";
|
||||
import { CODES, KEYS } from "../keys";
|
||||
import { getShortcutKey } from "../utils";
|
||||
import useIsMobile from "../is-mobile";
|
||||
import { register } from "./register";
|
||||
import { newElementWith } from "../element/mutateElement";
|
||||
import { ExcalidrawElement } from "../element/types";
|
||||
import { AppState, NormalizedZoomValue } from "../types";
|
||||
import { getCommonBounds } from "../element";
|
||||
import { getNewZoom } from "../scene/zoom";
|
||||
@@ -62,7 +64,7 @@ export const actionClearCanvas = register({
|
||||
elementLocked: appState.elementLocked,
|
||||
exportBackground: appState.exportBackground,
|
||||
exportEmbedScene: appState.exportEmbedScene,
|
||||
gridSize: appState.gridSize,
|
||||
showGrid: appState.showGrid,
|
||||
shouldAddWatermark: appState.shouldAddWatermark,
|
||||
showStats: appState.showStats,
|
||||
},
|
||||
@@ -93,6 +95,7 @@ export const actionZoomIn = register({
|
||||
const zoom = getNewZoom(
|
||||
getNormalizedZoom(appState.zoom.value + ZOOM_STEP),
|
||||
appState.zoom,
|
||||
{ left: appState.offsetLeft, top: appState.offsetTop },
|
||||
{ x: appState.width / 2, y: appState.height / 2 },
|
||||
);
|
||||
trackEvent(EVENT_ACTION, "zoom", "in", zoom.value * 100);
|
||||
@@ -126,6 +129,7 @@ export const actionZoomOut = register({
|
||||
const zoom = getNewZoom(
|
||||
getNormalizedZoom(appState.zoom.value - ZOOM_STEP),
|
||||
appState.zoom,
|
||||
{ left: appState.offsetLeft, top: appState.offsetTop },
|
||||
{ x: appState.width / 2, y: appState.height / 2 },
|
||||
);
|
||||
|
||||
@@ -161,10 +165,15 @@ export const actionResetZoom = register({
|
||||
return {
|
||||
appState: {
|
||||
...appState,
|
||||
zoom: getNewZoom(1 as NormalizedZoomValue, appState.zoom, {
|
||||
x: appState.width / 2,
|
||||
y: appState.height / 2,
|
||||
}),
|
||||
zoom: getNewZoom(
|
||||
1 as NormalizedZoomValue,
|
||||
appState.zoom,
|
||||
{ left: appState.offsetLeft, top: appState.offsetTop },
|
||||
{
|
||||
x: appState.width / 2,
|
||||
y: appState.height / 2,
|
||||
},
|
||||
),
|
||||
},
|
||||
commitToHistory: false,
|
||||
};
|
||||
@@ -204,38 +213,63 @@ const zoomValueToFitBoundsOnViewport = (
|
||||
return clampedZoomValueToFitElements as NormalizedZoomValue;
|
||||
};
|
||||
|
||||
const zoomToFitElements = (
|
||||
elements: readonly ExcalidrawElement[],
|
||||
appState: Readonly<AppState>,
|
||||
zoomToSelection: boolean,
|
||||
) => {
|
||||
const nonDeletedElements = getNonDeletedElements(elements);
|
||||
const selectedElements = getSelectedElements(nonDeletedElements, appState);
|
||||
|
||||
const commonBounds =
|
||||
zoomToSelection && selectedElements.length > 0
|
||||
? getCommonBounds(selectedElements)
|
||||
: getCommonBounds(nonDeletedElements);
|
||||
|
||||
const zoomValue = zoomValueToFitBoundsOnViewport(commonBounds, {
|
||||
width: appState.width,
|
||||
height: appState.height,
|
||||
});
|
||||
const newZoom = getNewZoom(zoomValue, appState.zoom, {
|
||||
left: appState.offsetLeft,
|
||||
top: appState.offsetTop,
|
||||
});
|
||||
const action = zoomToSelection ? "selection" : "fit";
|
||||
|
||||
const [x1, y1, x2, y2] = commonBounds;
|
||||
const centerX = (x1 + x2) / 2;
|
||||
const centerY = (y1 + y2) / 2;
|
||||
trackEvent(EVENT_ACTION, "zoom", action, newZoom.value * 100);
|
||||
return {
|
||||
appState: {
|
||||
...appState,
|
||||
...centerScrollOn({
|
||||
scenePoint: { x: centerX, y: centerY },
|
||||
viewportDimensions: {
|
||||
width: appState.width,
|
||||
height: appState.height,
|
||||
},
|
||||
zoom: newZoom,
|
||||
}),
|
||||
zoom: newZoom,
|
||||
},
|
||||
commitToHistory: false,
|
||||
};
|
||||
};
|
||||
|
||||
export const actionZoomToSelected = register({
|
||||
name: "zoomToSelection",
|
||||
perform: (elements, appState) => zoomToFitElements(elements, appState, true),
|
||||
keyTest: (event) =>
|
||||
event.code === CODES.TWO &&
|
||||
event.shiftKey &&
|
||||
!event.altKey &&
|
||||
!event[KEYS.CTRL_OR_CMD],
|
||||
});
|
||||
|
||||
export const actionZoomToFit = register({
|
||||
name: "zoomToFit",
|
||||
perform: (elements, appState) => {
|
||||
const nonDeletedElements = elements.filter((element) => !element.isDeleted);
|
||||
const commonBounds = getCommonBounds(nonDeletedElements);
|
||||
|
||||
const zoomValue = zoomValueToFitBoundsOnViewport(commonBounds, {
|
||||
width: appState.width,
|
||||
height: appState.height,
|
||||
});
|
||||
const newZoom = getNewZoom(zoomValue, appState.zoom);
|
||||
|
||||
const [x1, y1, x2, y2] = commonBounds;
|
||||
const centerX = (x1 + x2) / 2;
|
||||
const centerY = (y1 + y2) / 2;
|
||||
trackEvent(EVENT_ACTION, "zoom", "fit", newZoom.value * 100);
|
||||
return {
|
||||
appState: {
|
||||
...appState,
|
||||
...centerScrollOn({
|
||||
scenePoint: { x: centerX, y: centerY },
|
||||
viewportDimensions: {
|
||||
width: appState.width,
|
||||
height: appState.height,
|
||||
},
|
||||
zoom: newZoom,
|
||||
}),
|
||||
zoom: newZoom,
|
||||
},
|
||||
commitToHistory: false,
|
||||
};
|
||||
},
|
||||
perform: (elements, appState) => zoomToFitElements(elements, appState, false),
|
||||
keyTest: (event) =>
|
||||
event.code === CODES.ONE &&
|
||||
event.shiftKey &&
|
||||
|
||||
@@ -136,7 +136,7 @@ export const actionDeleteSelected = register({
|
||||
};
|
||||
},
|
||||
contextItemLabel: "labels.delete",
|
||||
contextMenuOrder: 3,
|
||||
contextMenuOrder: 999999,
|
||||
keyTest: (event) => event.key === KEYS.BACKSPACE || event.key === KEYS.DELETE,
|
||||
PanelComponent: ({ elements, appState, updateData }) => (
|
||||
<ToolButton
|
||||
|
||||
@@ -3,12 +3,15 @@ import { EVENT_CHANGE, EVENT_IO, trackEvent } from "../analytics";
|
||||
import { load, save, saveAs } from "../components/icons";
|
||||
import { ProjectName } from "../components/ProjectName";
|
||||
import { ToolButton } from "../components/ToolButton";
|
||||
import { Tooltip } from "../components/Tooltip";
|
||||
import { questionCircle } from "../components/icons";
|
||||
import { loadFromJSON, saveAsJSON } from "../data";
|
||||
import { t } from "../i18n";
|
||||
import useIsMobile from "../is-mobile";
|
||||
import { KEYS } from "../keys";
|
||||
import { muteFSAbortError } from "../utils";
|
||||
import { register } from "./register";
|
||||
import "../components/ToolIcon.scss";
|
||||
|
||||
export const actionChangeProjectName = register({
|
||||
name: "changeProjectName",
|
||||
@@ -54,13 +57,20 @@ export const actionChangeExportEmbedScene = register({
|
||||
};
|
||||
},
|
||||
PanelComponent: ({ appState, updateData }) => (
|
||||
<label title={t("labels.exportEmbedScene_details")}>
|
||||
<label style={{ display: "flex" }}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={appState.exportEmbedScene}
|
||||
onChange={(event) => updateData(event.target.checked)}
|
||||
/>{" "}
|
||||
{t("labels.exportEmbedScene")}
|
||||
<Tooltip
|
||||
label={t("labels.exportEmbedScene_details")}
|
||||
position="above"
|
||||
long={true}
|
||||
>
|
||||
<div className="TooltipIcon">{questionCircle}</div>
|
||||
</Tooltip>
|
||||
</label>
|
||||
),
|
||||
});
|
||||
|
||||
@@ -19,8 +19,8 @@ export type ShortcutName =
|
||||
| "copyAsSvg"
|
||||
| "group"
|
||||
| "ungroup"
|
||||
| "toggleGridMode"
|
||||
| "toggleStats"
|
||||
| "gridMode"
|
||||
| "stats"
|
||||
| "addToLibrary";
|
||||
|
||||
const shortcutMap: Record<ShortcutName, string[]> = {
|
||||
@@ -51,8 +51,8 @@ const shortcutMap: Record<ShortcutName, string[]> = {
|
||||
copyAsSvg: [],
|
||||
group: [getShortcutKey("CtrlOrCmd+G")],
|
||||
ungroup: [getShortcutKey("CtrlOrCmd+Shift+G")],
|
||||
toggleGridMode: [getShortcutKey("CtrlOrCmd+'")],
|
||||
toggleStats: [],
|
||||
gridMode: [getShortcutKey("CtrlOrCmd+'")],
|
||||
stats: [],
|
||||
addToLibrary: [],
|
||||
};
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ export type ActionName =
|
||||
| "zoomOut"
|
||||
| "resetZoom"
|
||||
| "zoomToFit"
|
||||
| "zoomToSelection"
|
||||
| "changeFontFamily"
|
||||
| "changeTextAlign"
|
||||
| "toggleFullScreen"
|
||||
|
||||
+14
-11
@@ -11,14 +11,17 @@ export const EVENT_SHAPE = "shape";
|
||||
export const EVENT_SHARE = "share";
|
||||
export const EVENT_MAGIC = "magic";
|
||||
|
||||
export const trackEvent = window.gtag
|
||||
? (category: string, name: string, label?: string, value?: number) => {
|
||||
window.gtag("event", name, {
|
||||
event_category: category,
|
||||
event_label: label,
|
||||
value,
|
||||
});
|
||||
}
|
||||
: (category: string, name: string, label?: string, value?: number) => {
|
||||
console.info("Track Event", category, name, label, value);
|
||||
};
|
||||
export const trackEvent =
|
||||
typeof window !== "undefined" && window.gtag
|
||||
? (category: string, name: string, label?: string, value?: number) => {
|
||||
window.gtag("event", name, {
|
||||
event_category: category,
|
||||
event_label: label,
|
||||
value,
|
||||
});
|
||||
}
|
||||
: typeof process !== "undefined" && process?.env?.JEST_WORKER_ID
|
||||
? (category: string, name: string, label?: string, value?: number) => {}
|
||||
: (category: string, name: string, label?: string, value?: number) => {
|
||||
console.info("Track Event", category, name, label, value);
|
||||
};
|
||||
|
||||
+2
-7
@@ -65,7 +65,7 @@ export const getDefaultAppState = (): Omit<
|
||||
showShortcutsDialog: false,
|
||||
suggestedBindings: [],
|
||||
zenModeEnabled: false,
|
||||
gridSize: null,
|
||||
showGrid: false,
|
||||
editingGroupId: null,
|
||||
selectedGroupIds: {},
|
||||
width: window.innerWidth,
|
||||
@@ -120,7 +120,7 @@ const APP_STATE_STORAGE_CONF = (<
|
||||
errorMessage: { browser: false, export: false },
|
||||
exportBackground: { browser: true, export: false },
|
||||
exportEmbedScene: { browser: true, export: false },
|
||||
gridSize: { browser: true, export: true },
|
||||
showGrid: { browser: true, export: false },
|
||||
height: { browser: false, export: false },
|
||||
isBindingEnabled: { browser: false, export: false },
|
||||
isLibraryOpen: { browser: false, export: false },
|
||||
@@ -166,11 +166,6 @@ const _clearAppStateForStorage = <ExportType extends "export" | "browser">(
|
||||
const stateForExport = {} as { [K in ExportableKeys]?: typeof appState[K] };
|
||||
for (const key of Object.keys(appState) as (keyof typeof appState)[]) {
|
||||
const propConfig = APP_STATE_STORAGE_CONF[key];
|
||||
if (!propConfig) {
|
||||
console.error(
|
||||
`_clearAppStateForStorage: appState key "${key}" config doesn't exist for "${exportType}" export type`,
|
||||
);
|
||||
}
|
||||
if (propConfig?.[exportType]) {
|
||||
// @ts-ignore see https://github.com/microsoft/TypeScript/issues/31445
|
||||
stateForExport[key] = appState[key];
|
||||
|
||||
+18
-12
@@ -19,15 +19,15 @@ export const NOT_SPREADSHEET = "NOT_SPREADSHEET";
|
||||
export const VALID_SPREADSHEET = "VALID_SPREADSHEET";
|
||||
|
||||
type ParseSpreadsheetResult =
|
||||
| { type: typeof NOT_SPREADSHEET }
|
||||
| { type: typeof NOT_SPREADSHEET; reason: string }
|
||||
| { type: typeof VALID_SPREADSHEET; spreadsheet: Spreadsheet };
|
||||
|
||||
const tryParseNumber = (s: string): number | null => {
|
||||
const match = /^[$€£¥₩]?([0-9]+(\.[0-9]+)?)$/.exec(s);
|
||||
const match = /^[$€£¥₩]?([0-9,]+(\.[0-9]+)?)$/.exec(s);
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
return parseFloat(match[1]);
|
||||
return parseFloat(match[1].replace(/,/g, ""));
|
||||
};
|
||||
|
||||
const isNumericColumn = (lines: string[][], columnIndex: number) =>
|
||||
@@ -37,12 +37,12 @@ const tryParseCells = (cells: string[][]): ParseSpreadsheetResult => {
|
||||
const numCols = cells[0].length;
|
||||
|
||||
if (numCols > 2) {
|
||||
return { type: NOT_SPREADSHEET };
|
||||
return { type: NOT_SPREADSHEET, reason: "More than 2 columns" };
|
||||
}
|
||||
|
||||
if (numCols === 1) {
|
||||
if (!isNumericColumn(cells, 0)) {
|
||||
return { type: NOT_SPREADSHEET };
|
||||
return { type: NOT_SPREADSHEET, reason: "Value is not numeric" };
|
||||
}
|
||||
|
||||
const hasHeader = tryParseNumber(cells[0][0]) === null;
|
||||
@@ -51,7 +51,7 @@ const tryParseCells = (cells: string[][]): ParseSpreadsheetResult => {
|
||||
);
|
||||
|
||||
if (values.length < 2) {
|
||||
return { type: NOT_SPREADSHEET };
|
||||
return { type: NOT_SPREADSHEET, reason: "Less than two rows" };
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -67,7 +67,7 @@ const tryParseCells = (cells: string[][]): ParseSpreadsheetResult => {
|
||||
const valueColumnIndex = isNumericColumn(cells, 0) ? 0 : 1;
|
||||
|
||||
if (!isNumericColumn(cells, valueColumnIndex)) {
|
||||
return { type: NOT_SPREADSHEET };
|
||||
return { type: NOT_SPREADSHEET, reason: "Value is not numeric" };
|
||||
}
|
||||
|
||||
const labelColumnIndex = (valueColumnIndex + 1) % 2;
|
||||
@@ -75,7 +75,7 @@ const tryParseCells = (cells: string[][]): ParseSpreadsheetResult => {
|
||||
const rows = hasHeader ? cells.slice(1) : cells;
|
||||
|
||||
if (rows.length < 2) {
|
||||
return { type: NOT_SPREADSHEET };
|
||||
return { type: NOT_SPREADSHEET, reason: "Less than 2 rows" };
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -104,13 +104,13 @@ export const tryParseSpreadsheet = (text: string): ParseSpreadsheetResult => {
|
||||
// Copy/paste from excel, spreadhseets, tsv, csv.
|
||||
// For now we only accept 2 columns with an optional header
|
||||
|
||||
// Check for tab separeted values
|
||||
// Check for tab separated values
|
||||
let lines = text
|
||||
.trim()
|
||||
.split("\n")
|
||||
.map((line) => line.trim().split("\t"));
|
||||
|
||||
// Check for comma separeted files
|
||||
// Check for comma separated files
|
||||
if (lines.length && lines[0].length !== 2) {
|
||||
lines = text
|
||||
.trim()
|
||||
@@ -119,14 +119,17 @@ export const tryParseSpreadsheet = (text: string): ParseSpreadsheetResult => {
|
||||
}
|
||||
|
||||
if (lines.length === 0) {
|
||||
return { type: NOT_SPREADSHEET };
|
||||
return { type: NOT_SPREADSHEET, reason: "No values" };
|
||||
}
|
||||
|
||||
const numColsFirstLine = lines[0].length;
|
||||
const isSpreadsheet = lines.every((line) => line.length === numColsFirstLine);
|
||||
|
||||
if (!isSpreadsheet) {
|
||||
return { type: NOT_SPREADSHEET };
|
||||
return {
|
||||
type: NOT_SPREADSHEET,
|
||||
reason: "All rows don't have same number of columns",
|
||||
};
|
||||
}
|
||||
|
||||
const result = tryParseCells(lines);
|
||||
@@ -192,6 +195,7 @@ export const renderSpreadsheet = (
|
||||
y,
|
||||
startArrowhead: null,
|
||||
endArrowhead: null,
|
||||
width: chartWidth,
|
||||
points: [
|
||||
[0, 0],
|
||||
[chartWidth, 0],
|
||||
@@ -205,6 +209,7 @@ export const renderSpreadsheet = (
|
||||
y,
|
||||
startArrowhead: null,
|
||||
endArrowhead: null,
|
||||
height: chartHeight,
|
||||
points: [
|
||||
[0, 0],
|
||||
[0, -chartHeight],
|
||||
@@ -220,6 +225,7 @@ export const renderSpreadsheet = (
|
||||
endArrowhead: null,
|
||||
...commonProps,
|
||||
strokeStyle: "dotted",
|
||||
width: chartWidth,
|
||||
points: [
|
||||
[0, 0],
|
||||
[chartWidth, 0],
|
||||
|
||||
+80
-41
@@ -124,6 +124,7 @@ import {
|
||||
MIME_TYPES,
|
||||
TAP_TWICE_TIMEOUT,
|
||||
TOUCH_CTX_MENU_TIMEOUT,
|
||||
APP_NAME,
|
||||
} from "../constants";
|
||||
|
||||
import LayerUI from "./LayerUI";
|
||||
@@ -345,12 +346,15 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
offsetLeft,
|
||||
} = this.state;
|
||||
|
||||
const { onCollabButtonClick } = this.props;
|
||||
const { onCollabButtonClick, onExportToBackend } = this.props;
|
||||
const canvasScale = window.devicePixelRatio;
|
||||
|
||||
const canvasWidth = canvasDOMWidth * canvasScale;
|
||||
const canvasHeight = canvasDOMHeight * canvasScale;
|
||||
|
||||
const DEFAULT_PASTE_X = canvasDOMWidth / 2;
|
||||
const DEFAULT_PASTE_Y = canvasDOMHeight / 2;
|
||||
|
||||
return (
|
||||
<div
|
||||
className="excalidraw"
|
||||
@@ -371,12 +375,17 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
onCollabButtonClick={onCollabButtonClick}
|
||||
onLockToggle={this.toggleLock}
|
||||
onInsertShape={(elements) =>
|
||||
this.addElementsFromPasteOrLibrary(elements)
|
||||
this.addElementsFromPasteOrLibrary(
|
||||
elements,
|
||||
DEFAULT_PASTE_X,
|
||||
DEFAULT_PASTE_Y,
|
||||
)
|
||||
}
|
||||
zenModeEnabled={zenModeEnabled}
|
||||
toggleZenMode={this.toggleZenMode}
|
||||
lng={getLanguage().lng}
|
||||
isCollaborating={this.props.isCollaborating || false}
|
||||
onExportToBackend={onExportToBackend}
|
||||
/>
|
||||
{this.state.showStats && (
|
||||
<Stats
|
||||
@@ -494,7 +503,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
};
|
||||
|
||||
private importLibraryFromUrl = async (url: string) => {
|
||||
window.history.replaceState({}, "Excalidraw", window.location.origin);
|
||||
window.history.replaceState({}, APP_NAME, window.location.origin);
|
||||
try {
|
||||
const request = await fetch(url);
|
||||
const blob = await request.blob();
|
||||
@@ -586,6 +595,8 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
scene.elements,
|
||||
{
|
||||
...scene.appState,
|
||||
width: this.state.width,
|
||||
height: this.state.height,
|
||||
offsetTop: this.state.offsetTop,
|
||||
offsetLeft: this.state.offsetLeft,
|
||||
},
|
||||
@@ -1025,7 +1036,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
const dy = y - elementsCenterY;
|
||||
const groupIdMap = new Map();
|
||||
|
||||
const [gridX, gridY] = getGridPoint(dx, dy, this.state.gridSize);
|
||||
const [gridX, gridY] = getGridPoint(dx, dy, this.state.showGrid);
|
||||
|
||||
const oldIdToDuplicatedId = new Map();
|
||||
const newElements = clipboardElements.map((element) => {
|
||||
@@ -1138,7 +1149,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
|
||||
toggleGridMode = () => {
|
||||
this.setState({
|
||||
gridSize: this.state.gridSize ? null : GRID_SIZE,
|
||||
showGrid: !this.state.showGrid,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1264,8 +1275,8 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
|
||||
if (isArrowKey(event.key)) {
|
||||
const step =
|
||||
(this.state.gridSize &&
|
||||
(event.shiftKey ? ELEMENT_TRANSLATE_AMOUNT : this.state.gridSize)) ||
|
||||
(this.state.showGrid &&
|
||||
(event.shiftKey ? ELEMENT_TRANSLATE_AMOUNT : GRID_SIZE)) ||
|
||||
(event.shiftKey
|
||||
? ELEMENT_SHIFT_TRANSLATE_AMOUNT
|
||||
: ELEMENT_TRANSLATE_AMOUNT);
|
||||
@@ -1416,13 +1427,27 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
|
||||
private onGestureChange = withBatchedUpdates((event: GestureEvent) => {
|
||||
event.preventDefault();
|
||||
this.setState(({ zoom }) => ({
|
||||
zoom: getNewZoom(
|
||||
getNormalizedZoom(gesture.initialScale! * event.scale),
|
||||
zoom,
|
||||
{ x: cursorX, y: cursorY },
|
||||
),
|
||||
}));
|
||||
|
||||
// onGestureChange only has zoom factor but not the center.
|
||||
// If we're on iPad or iPhone, then we recognize multi-touch and will
|
||||
// zoom in at the right location on the touchMove handler already.
|
||||
// On Macbook, we don't have those events so will zoom in at the
|
||||
// current location instead.
|
||||
if (gesture.pointers.size === 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
const initialScale = gesture.initialScale;
|
||||
if (initialScale) {
|
||||
this.setState(({ zoom, offsetLeft, offsetTop }) => ({
|
||||
zoom: getNewZoom(
|
||||
getNormalizedZoom(initialScale * event.scale),
|
||||
zoom,
|
||||
{ left: offsetLeft, top: offsetTop },
|
||||
{ x: cursorX, y: cursorY },
|
||||
),
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
private onGestureEnd = withBatchedUpdates((event: GestureEvent) => {
|
||||
@@ -1734,21 +1759,28 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
});
|
||||
}
|
||||
|
||||
if (gesture.pointers.size === 2) {
|
||||
const initialScale = gesture.initialScale;
|
||||
if (
|
||||
gesture.pointers.size === 2 &&
|
||||
gesture.lastCenter &&
|
||||
initialScale &&
|
||||
gesture.initialDistance
|
||||
) {
|
||||
const center = getCenter(gesture.pointers);
|
||||
const deltaX = center.x - gesture.lastCenter!.x;
|
||||
const deltaY = center.y - gesture.lastCenter!.y;
|
||||
const deltaX = center.x - gesture.lastCenter.x;
|
||||
const deltaY = center.y - gesture.lastCenter.y;
|
||||
gesture.lastCenter = center;
|
||||
|
||||
const distance = getDistance(Array.from(gesture.pointers.values()));
|
||||
const scaleFactor = distance / gesture.initialDistance!;
|
||||
const scaleFactor = distance / gesture.initialDistance;
|
||||
|
||||
this.setState(({ zoom, scrollX, scrollY }) => ({
|
||||
this.setState(({ zoom, scrollX, scrollY, offsetLeft, offsetTop }) => ({
|
||||
scrollX: normalizeScroll(scrollX + deltaX / zoom.value),
|
||||
scrollY: normalizeScroll(scrollY + deltaY / zoom.value),
|
||||
zoom: getNewZoom(
|
||||
getNormalizedZoom(gesture.initialScale! * scaleFactor),
|
||||
getNormalizedZoom(initialScale * scaleFactor),
|
||||
zoom,
|
||||
{ left: offsetLeft, top: offsetTop },
|
||||
center,
|
||||
),
|
||||
shouldCacheIgnoreZoom: true,
|
||||
@@ -1787,7 +1819,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
scenePointerX,
|
||||
scenePointerY,
|
||||
this.state.editingLinearElement,
|
||||
this.state.gridSize,
|
||||
this.state.showGrid,
|
||||
);
|
||||
if (editingLinearElement !== this.state.editingLinearElement) {
|
||||
this.setState({ editingLinearElement });
|
||||
@@ -2217,7 +2249,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
return {
|
||||
origin,
|
||||
originInGrid: tupleToCoors(
|
||||
getGridPoint(origin.x, origin.y, this.state.gridSize),
|
||||
getGridPoint(origin.x, origin.y, this.state.showGrid),
|
||||
),
|
||||
scrollbars: isOverScrollBars(
|
||||
currentScrollBars,
|
||||
@@ -2575,13 +2607,13 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
const [gridX, gridY] = getGridPoint(
|
||||
pointerDownState.origin.x,
|
||||
pointerDownState.origin.y,
|
||||
elementType === "draw" ? null : this.state.gridSize,
|
||||
elementType === "draw" ? false : this.state.showGrid,
|
||||
);
|
||||
|
||||
/* If arrow is pre-arrowheads, it will have undefined for both start and end arrowheads.
|
||||
If so, we want it to be null for start and "arrow" for end. If the linear item is not
|
||||
an arrow, we want it to be null for both. Otherwise, we want it to use the
|
||||
values from appState. */
|
||||
If so, we want it to be null for start and "arrow" for end. If the linear item is not
|
||||
an arrow, we want it to be null for both. Otherwise, we want it to use the
|
||||
values from appState. */
|
||||
|
||||
const { currentItemStartArrowhead, currentItemEndArrowhead } = this.state;
|
||||
const [startArrowhead, endArrowhead] =
|
||||
@@ -2637,7 +2669,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
const [gridX, gridY] = getGridPoint(
|
||||
pointerDownState.origin.x,
|
||||
pointerDownState.origin.y,
|
||||
this.state.gridSize,
|
||||
this.state.showGrid,
|
||||
);
|
||||
const element = newElement({
|
||||
type: elementType,
|
||||
@@ -2726,7 +2758,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
const [gridX, gridY] = getGridPoint(
|
||||
pointerCoords.x,
|
||||
pointerCoords.y,
|
||||
this.state.gridSize,
|
||||
this.state.showGrid,
|
||||
);
|
||||
|
||||
// for arrows/lines, don't start dragging until a given threshold
|
||||
@@ -2798,7 +2830,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
const [dragX, dragY] = getGridPoint(
|
||||
pointerCoords.x - pointerDownState.drag.offset.x,
|
||||
pointerCoords.y - pointerDownState.drag.offset.y,
|
||||
this.state.gridSize,
|
||||
this.state.showGrid,
|
||||
);
|
||||
|
||||
const [dragDistanceX, dragDistanceY] = [
|
||||
@@ -2850,7 +2882,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
const [originDragX, originDragY] = getGridPoint(
|
||||
pointerDownState.origin.x - pointerDownState.drag.offset.x,
|
||||
pointerDownState.origin.y - pointerDownState.drag.offset.y,
|
||||
this.state.gridSize,
|
||||
this.state.showGrid,
|
||||
);
|
||||
mutateElement(duplicatedElement, {
|
||||
x: duplicatedElement.x + (originDragX - dragX),
|
||||
@@ -3510,7 +3542,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
const [gridX, gridY] = getGridPoint(
|
||||
pointerCoords.x,
|
||||
pointerCoords.y,
|
||||
this.state.gridSize,
|
||||
this.state.showGrid,
|
||||
);
|
||||
dragNewElement(
|
||||
draggingElement,
|
||||
@@ -3548,7 +3580,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
const [resizeX, resizeY] = getGridPoint(
|
||||
pointerCoords.x - pointerDownState.resize.offset.x,
|
||||
pointerCoords.y - pointerDownState.resize.offset.y,
|
||||
this.state.gridSize,
|
||||
this.state.showGrid,
|
||||
);
|
||||
if (
|
||||
transformElements(
|
||||
@@ -3612,13 +3644,15 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
CANVAS_ONLY_ACTIONS.includes(action.name),
|
||||
),
|
||||
{
|
||||
shortcutName: "toggleGridMode",
|
||||
label: t("labels.toggleGridMode"),
|
||||
checked: this.state.showGrid,
|
||||
shortcutName: "gridMode",
|
||||
label: t("labels.gridMode"),
|
||||
action: this.toggleGridMode,
|
||||
},
|
||||
{
|
||||
shortcutName: "toggleStats",
|
||||
label: t("labels.toggleStats"),
|
||||
checked: this.state.showStats,
|
||||
shortcutName: "stats",
|
||||
label: t("stats.title"),
|
||||
action: this.toggleStats,
|
||||
},
|
||||
],
|
||||
@@ -3695,11 +3729,16 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
this.setState(({ zoom }) => ({
|
||||
zoom: getNewZoom(getNormalizedZoom(zoom.value - delta / 100), zoom, {
|
||||
x: cursorX,
|
||||
y: cursorY,
|
||||
}),
|
||||
this.setState(({ zoom, offsetLeft, offsetTop }) => ({
|
||||
zoom: getNewZoom(
|
||||
getNormalizedZoom(zoom.value - delta / 100),
|
||||
zoom,
|
||||
{ left: offsetLeft, top: offsetTop },
|
||||
{
|
||||
x: cursorX,
|
||||
y: cursorY,
|
||||
},
|
||||
),
|
||||
selectedElementIds: {},
|
||||
previousSelectedElementIds:
|
||||
Object.keys(selectedElementIds).length !== 0
|
||||
|
||||
@@ -32,6 +32,21 @@
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 0.2fr;
|
||||
align-items: center;
|
||||
|
||||
&.checkmark::before {
|
||||
position: absolute;
|
||||
left: 6px;
|
||||
margin-bottom: 1px;
|
||||
content: "\2713";
|
||||
}
|
||||
|
||||
&.dangerous {
|
||||
div:nth-child(1) {
|
||||
color: $oc-red-7;
|
||||
}
|
||||
}
|
||||
|
||||
div:nth-child(1) {
|
||||
justify-self: start;
|
||||
margin-inline-end: 20px;
|
||||
@@ -46,6 +61,13 @@
|
||||
.context-menu-option:hover {
|
||||
color: var(--popup-background-color);
|
||||
background-color: var(--select-highlight-color);
|
||||
|
||||
&.dangerous {
|
||||
div:nth-child(1) {
|
||||
color: var(--popup-background-color);
|
||||
}
|
||||
background-color: $oc-red-6;
|
||||
}
|
||||
}
|
||||
|
||||
.context-menu-option:focus {
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
} from "../actions/shortcuts";
|
||||
|
||||
type ContextMenuOption = {
|
||||
checked?: boolean;
|
||||
shortcutName: ShortcutName;
|
||||
label: string;
|
||||
action(): void;
|
||||
@@ -26,7 +27,6 @@ const ContextMenu = ({ options, onCloseRequest, top, left }: Props) => {
|
||||
const isDarkTheme = !!document
|
||||
.querySelector(".excalidraw")
|
||||
?.classList.contains("Appearance_dark");
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx("excalidraw", {
|
||||
@@ -43,9 +43,14 @@ const ContextMenu = ({ options, onCloseRequest, top, left }: Props) => {
|
||||
className="context-menu"
|
||||
onContextMenu={(event) => event.preventDefault()}
|
||||
>
|
||||
{options.map(({ action, shortcutName, label }, idx) => (
|
||||
{options.map(({ action, checked, shortcutName, label }, idx) => (
|
||||
<li data-testid={shortcutName} key={idx} onClick={onCloseRequest}>
|
||||
<button className="context-menu-option" onClick={action}>
|
||||
<button
|
||||
className={`context-menu-option
|
||||
${shortcutName === "delete" ? "dangerous" : ""}
|
||||
${checked ? "checkmark" : ""}`}
|
||||
onClick={action}
|
||||
>
|
||||
<div>{label}</div>
|
||||
<div>
|
||||
{shortcutName
|
||||
|
||||
@@ -14,7 +14,9 @@ export const DarkModeToggle = (props: {
|
||||
return (
|
||||
<label
|
||||
className={`ToolIcon ToolIcon_type_floating ToolIcon_size_M`}
|
||||
title={t("buttons.toggleDarkMode")}
|
||||
title={
|
||||
props.value === "dark" ? t("buttons.lightMode") : t("buttons.darkMode")
|
||||
}
|
||||
>
|
||||
<input
|
||||
className="ToolIcon_type_checkbox ToolIcon_toggle_opaque"
|
||||
@@ -23,7 +25,11 @@ export const DarkModeToggle = (props: {
|
||||
props.onChange(event.target.checked ? "dark" : "light")
|
||||
}
|
||||
checked={props.value === "dark"}
|
||||
aria-label={t("buttons.toggleDarkMode")}
|
||||
aria-label={
|
||||
props.value === "dark"
|
||||
? t("buttons.lightMode")
|
||||
: t("buttons.darkMode")
|
||||
}
|
||||
/>
|
||||
<div className="ToolIcon__icon">
|
||||
{props.value === "light" ? ICONS.MOON : ICONS.SUN}
|
||||
|
||||
@@ -28,7 +28,14 @@ export const ErrorDialog = ({
|
||||
onCloseRequest={handleClose}
|
||||
title={t("errorDialog.title")}
|
||||
>
|
||||
<div>{message}</div>
|
||||
<div>
|
||||
{message.split("\n").map((line) => (
|
||||
<>
|
||||
{line}
|
||||
<br />
|
||||
</>
|
||||
))}
|
||||
</div>
|
||||
</Dialog>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -67,7 +67,7 @@ const ExportModal = ({
|
||||
onExportToPng: ExportCB;
|
||||
onExportToSvg: ExportCB;
|
||||
onExportToClipboard: ExportCB;
|
||||
onExportToBackend: ExportCB;
|
||||
onExportToBackend?: ExportCB;
|
||||
onCloseRequest: () => void;
|
||||
}) => {
|
||||
const someElementIsSelected = isSomeElementSelected(elements, appState);
|
||||
@@ -155,13 +155,15 @@ const ExportModal = ({
|
||||
onClick={() => onExportToClipboard(exportedElements, scale)}
|
||||
/>
|
||||
)}
|
||||
<ToolButton
|
||||
type="button"
|
||||
icon={link}
|
||||
title={t("buttons.getShareableLink")}
|
||||
aria-label={t("buttons.getShareableLink")}
|
||||
onClick={() => onExportToBackend(exportedElements)}
|
||||
/>
|
||||
{onExportToBackend && (
|
||||
<ToolButton
|
||||
type="button"
|
||||
icon={link}
|
||||
title={t("buttons.getShareableLink")}
|
||||
aria-label={t("buttons.getShareableLink")}
|
||||
onClick={() => onExportToBackend(exportedElements)}
|
||||
/>
|
||||
)}
|
||||
</Stack.Row>
|
||||
<div className="ExportDialog__name">
|
||||
{actionManager.renderAction("changeProjectName")}
|
||||
@@ -235,7 +237,7 @@ export const ExportDialog = ({
|
||||
onExportToPng: ExportCB;
|
||||
onExportToSvg: ExportCB;
|
||||
onExportToClipboard: ExportCB;
|
||||
onExportToBackend: ExportCB;
|
||||
onExportToBackend?: ExportCB;
|
||||
}) => {
|
||||
const [modalIsShown, setModalIsShown] = useState(false);
|
||||
const triggerButton = useRef<HTMLButtonElement>(null);
|
||||
|
||||
@@ -38,8 +38,8 @@ const getHints = ({ appState, elements }: Hint) => {
|
||||
selectedElements.length === 1
|
||||
) {
|
||||
const targetElement = selectedElements[0];
|
||||
if (isLinearElement(targetElement) && targetElement.points.length > 2) {
|
||||
return null;
|
||||
if (isLinearElement(targetElement) && targetElement.points.length === 2) {
|
||||
return t("hints.lockAngle");
|
||||
}
|
||||
return t("hints.resize");
|
||||
}
|
||||
|
||||
@@ -93,6 +93,9 @@
|
||||
grid-auto-flow: column;
|
||||
grid-gap: 0.5rem;
|
||||
border-radius: 4px;
|
||||
:root[dir="rtl"] & {
|
||||
padding: 0.4rem;
|
||||
}
|
||||
}
|
||||
|
||||
.picker-keybinding {
|
||||
|
||||
@@ -39,64 +39,6 @@
|
||||
width: 1.2rem;
|
||||
height: 1.2rem;
|
||||
}
|
||||
|
||||
&.tooltip .tooltip-text {
|
||||
visibility: hidden;
|
||||
width: 20rem;
|
||||
bottom: calc(50% + 0.8rem + 6px);
|
||||
|
||||
:root[dir="ltr"] & {
|
||||
left: -5px;
|
||||
}
|
||||
|
||||
:root[dir="rtl"] & {
|
||||
right: -5px;
|
||||
}
|
||||
|
||||
background-color: $oc-black;
|
||||
color: $oc-white;
|
||||
text-align: center;
|
||||
border-radius: 6px;
|
||||
padding: 5px;
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
white-space: pre-wrap;
|
||||
|
||||
&::after {
|
||||
--size: 6px;
|
||||
content: "";
|
||||
border: var(--size) solid transparent;
|
||||
border-top-color: $oc-black;
|
||||
position: absolute;
|
||||
bottom: calc(-2 * var(--size));
|
||||
|
||||
:root[dir="ltr"] & {
|
||||
left: calc(5px + var(--size) / 2);
|
||||
}
|
||||
|
||||
:root[dir="rtl"] & {
|
||||
right: calc(5px + var(--size) / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the following 3 rules ensure that the tooltip doesn't show (nor affect
|
||||
// the cursor) when you drag over when you draw on canvas, but at the same
|
||||
// time it still works when clicking on the link/shield
|
||||
|
||||
body:active &.tooltip:not(:hover) {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
body:not(:active) &.tooltip:hover .tooltip-text {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.tooltip-text:hover {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
&__github-corner {
|
||||
|
||||
+17
-26
@@ -65,6 +65,11 @@ interface LayerUIProps {
|
||||
toggleZenMode: () => void;
|
||||
lng: string;
|
||||
isCollaborating: boolean;
|
||||
onExportToBackend?: (
|
||||
exportedElements: readonly NonDeletedExcalidrawElement[],
|
||||
appState: AppState,
|
||||
canvas: HTMLCanvasElement | null,
|
||||
) => void;
|
||||
}
|
||||
|
||||
const useOnClickOutside = (
|
||||
@@ -317,10 +322,10 @@ const LayerUI = ({
|
||||
zenModeEnabled,
|
||||
toggleZenMode,
|
||||
isCollaborating,
|
||||
onExportToBackend,
|
||||
}: LayerUIProps) => {
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
// TODO: Extend tooltip component and use here.
|
||||
const renderEncryptedIcon = () => (
|
||||
<a
|
||||
className={clsx("encrypted-icon tooltip zen-mode-visibility", {
|
||||
@@ -333,10 +338,9 @@ const LayerUI = ({
|
||||
trackEvent(EVENT_EXIT, "e2ee shield");
|
||||
}}
|
||||
>
|
||||
<span className="tooltip-text" dir="auto">
|
||||
{t("encrypted.tooltip")}
|
||||
</span>
|
||||
{shield}
|
||||
<Tooltip label={t("encrypted.tooltip")} position="above" long={true}>
|
||||
{shield}
|
||||
</Tooltip>
|
||||
</a>
|
||||
);
|
||||
|
||||
@@ -360,6 +364,7 @@ const LayerUI = ({
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<ExportDialog
|
||||
elements={elements}
|
||||
@@ -368,28 +373,14 @@ const LayerUI = ({
|
||||
onExportToPng={createExporter("png")}
|
||||
onExportToSvg={createExporter("svg")}
|
||||
onExportToClipboard={createExporter("clipboard")}
|
||||
onExportToBackend={async (exportedElements) => {
|
||||
if (canvas) {
|
||||
try {
|
||||
await exportCanvas(
|
||||
"backend",
|
||||
exportedElements,
|
||||
{
|
||||
...appState,
|
||||
selectedElementIds: {},
|
||||
},
|
||||
canvas,
|
||||
appState,
|
||||
);
|
||||
} catch (error) {
|
||||
if (error.name !== "AbortError") {
|
||||
const { width, height } = canvas;
|
||||
console.error(error, { width, height });
|
||||
setAppState({ errorMessage: error.message });
|
||||
onExportToBackend={
|
||||
onExportToBackend
|
||||
? (elements) => {
|
||||
onExportToBackend &&
|
||||
onExportToBackend(elements, appState, canvas);
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -207,15 +207,16 @@ export const ShortcutsDialog = ({ onClose }: { onClose?: () => void }) => {
|
||||
shortcuts={["Shift+1"]}
|
||||
/>
|
||||
<Shortcut
|
||||
label={t("buttons.toggleFullScreen")}
|
||||
shortcuts={["F"]}
|
||||
label={t("shortcutsDialog.zoomToSelection")}
|
||||
shortcuts={["Shift+2"]}
|
||||
/>
|
||||
<Shortcut label={t("buttons.fullScreen")} shortcuts={["F"]} />
|
||||
<Shortcut
|
||||
label={t("buttons.toggleZenMode")}
|
||||
label={t("buttons.zenMode")}
|
||||
shortcuts={[getShortcutKey("Alt+Z")]}
|
||||
/>
|
||||
<Shortcut
|
||||
label={t("labels.toggleGridMode")}
|
||||
label={t("labels.gridMode")}
|
||||
shortcuts={[getShortcutKey("CtrlOrCmd+'")]}
|
||||
/>
|
||||
</ShortcutIsland>
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
right: 12px;
|
||||
font-size: 12px;
|
||||
z-index: 999;
|
||||
|
||||
h3 {
|
||||
margin: 0 24px 8px 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.close {
|
||||
@@ -29,9 +31,21 @@
|
||||
}
|
||||
tr {
|
||||
td:nth-child(2) {
|
||||
min-width: 48px;
|
||||
min-width: 24px;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:root[dir="rtl"] & {
|
||||
left: 12px;
|
||||
right: initial;
|
||||
|
||||
h3 {
|
||||
margin: 0 0 8px 24px;
|
||||
}
|
||||
.close {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
@import "open-color/open-color.scss";
|
||||
@import "../css/variables";
|
||||
|
||||
.excalidraw {
|
||||
.ToolIcon {
|
||||
display: inline-flex;
|
||||
@@ -181,6 +183,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
.TooltipIcon {
|
||||
width: 0.9em;
|
||||
height: 0.9em;
|
||||
margin-left: 5px;
|
||||
margin-top: 1px;
|
||||
|
||||
@media #{$media-query} {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.unlocked-icon {
|
||||
:root[dir="ltr"] & {
|
||||
left: 2px;
|
||||
|
||||
+27
-10
@@ -7,39 +7,56 @@
|
||||
.Tooltip__label {
|
||||
--arrow-size: 4px;
|
||||
visibility: hidden;
|
||||
width: 10ch;
|
||||
background: $oc-black;
|
||||
color: $oc-white;
|
||||
text-align: center;
|
||||
border-radius: 4px;
|
||||
padding: 4px;
|
||||
border-radius: 6px;
|
||||
padding: 8px;
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
font-size: 0.7rem;
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
top: calc(100% + var(--arrow-size) + 3px);
|
||||
font-weight: 500;
|
||||
// extra pixel offset for unknown reasons
|
||||
left: calc(-50% + var(--arrow-size) / 2 - 1px);
|
||||
left: calc(50% + var(--arrow-size) / 2 - 1px);
|
||||
transform: translateX(-50%);
|
||||
word-wrap: break-word;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
border: var(--arrow-size) solid transparent;
|
||||
border-bottom-color: $oc-black;
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
left: calc(50% - var(--arrow-size));
|
||||
}
|
||||
|
||||
&--above {
|
||||
bottom: calc(100% + var(--arrow-size) + 3px);
|
||||
|
||||
&::after {
|
||||
border-top-color: $oc-black;
|
||||
top: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&--below {
|
||||
top: calc(100% + var(--arrow-size) + 3px);
|
||||
|
||||
&::after {
|
||||
border-bottom-color: $oc-black;
|
||||
bottom: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the following 3 rules ensure that the tooltip doesn't show (nor affect
|
||||
// the cursor) when you drag over when you draw on canvas, but at the same
|
||||
// time it still works when clicking on the link/shield
|
||||
body:active .Tooltip:not(:hover) {
|
||||
|
||||
body:active & .Tooltip:not(:hover) {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
body:not(:active) .Tooltip:hover .Tooltip__label {
|
||||
body:not(:active) & .Tooltip:hover .Tooltip__label {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,11 +5,27 @@ import React from "react";
|
||||
type TooltipProps = {
|
||||
children: React.ReactNode;
|
||||
label: string;
|
||||
position?: "above" | "below";
|
||||
long?: boolean;
|
||||
};
|
||||
|
||||
export const Tooltip = ({ children, label }: TooltipProps) => (
|
||||
export const Tooltip = ({
|
||||
children,
|
||||
label,
|
||||
position = "below",
|
||||
long = false,
|
||||
}: TooltipProps) => (
|
||||
<div className="Tooltip">
|
||||
<span className="Tooltip__label">{label}</span>
|
||||
<span
|
||||
className={
|
||||
position === "above"
|
||||
? "Tooltip__label Tooltip__label--above"
|
||||
: "Tooltip__label Tooltip__label--below"
|
||||
}
|
||||
style={{ width: long ? "50ch" : "10ch" }}
|
||||
>
|
||||
{label}
|
||||
</span>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -108,6 +108,11 @@ export const redo = createIcon(
|
||||
{ mirror: true },
|
||||
);
|
||||
|
||||
export const questionCircle = createIcon(
|
||||
"M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zM262.655 90c-54.497 0-89.255 22.957-116.549 63.758-3.536 5.286-2.353 12.415 2.715 16.258l34.699 26.31c5.205 3.947 12.621 3.008 16.665-2.122 17.864-22.658 30.113-35.797 57.303-35.797 20.429 0 45.698 13.148 45.698 32.958 0 14.976-12.363 22.667-32.534 33.976C247.128 238.528 216 254.941 216 296v4c0 6.627 5.373 12 12 12h56c6.627 0 12-5.373 12-12v-1.333c0-28.462 83.186-29.647 83.186-106.667 0-58.002-60.165-102-116.531-102zM256 338c-25.365 0-46 20.635-46 46 0 25.364 20.635 46 46 46s46-20.636 46-46c0-25.365-20.635-46-46-46z",
|
||||
{ mirror: true },
|
||||
);
|
||||
|
||||
// Icon imported form Storybook
|
||||
// Storybook is licensed under MIT https://github.com/storybookjs/storybook/blob/next/LICENSE
|
||||
export const resetZoom = createIcon(
|
||||
|
||||
+4
-1
@@ -1,5 +1,7 @@
|
||||
import { FontFamily } from "./element/types";
|
||||
|
||||
export const APP_NAME = "Excalidraw";
|
||||
|
||||
export const DRAGGING_THRESHOLD = 10; // 10px
|
||||
export const LINE_CONFIRM_THRESHOLD = 10; // 10px
|
||||
export const ELEMENT_SHIFT_TRANSLATE_AMOUNT = 5;
|
||||
@@ -71,7 +73,7 @@ export const DEFAULT_VERTICAL_ALIGN = "top";
|
||||
|
||||
export const CANVAS_ONLY_ACTIONS = ["selectAll"];
|
||||
|
||||
export const GRID_SIZE = 20; // TODO make it configurable?
|
||||
export const GRID_SIZE = 20;
|
||||
|
||||
export const MIME_TYPES = {
|
||||
excalidraw: "application/vnd.excalidraw+json",
|
||||
@@ -85,3 +87,4 @@ export const STORAGE_KEYS = {
|
||||
// time in milliseconds
|
||||
export const TAP_TWICE_TIMEOUT = 300;
|
||||
export const TOUCH_CTX_MENU_TIMEOUT = 500;
|
||||
export const TITLE_TIMEOUT = 10000;
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ import { AppState } from "../types";
|
||||
import { restore } from "./restore";
|
||||
import { ImportedDataState, LibraryData } from "./types";
|
||||
|
||||
export const parseFileContents = async (blob: Blob | File) => {
|
||||
const parseFileContents = async (blob: Blob | File) => {
|
||||
let contents: string;
|
||||
|
||||
if (blob.type === "image/png") {
|
||||
|
||||
+1
-71
@@ -1,14 +1,10 @@
|
||||
import { fileSave } from "browser-nativefs";
|
||||
import { EVENT_IO, trackEvent } from "../analytics";
|
||||
import { getDefaultAppState } from "../appState";
|
||||
import {
|
||||
copyCanvasToClipboardAsPng,
|
||||
copyTextToSystemClipboard,
|
||||
} from "../clipboard";
|
||||
import {
|
||||
ExcalidrawElement,
|
||||
NonDeletedExcalidrawElement,
|
||||
} from "../element/types";
|
||||
import { NonDeletedExcalidrawElement } from "../element/types";
|
||||
import { t } from "../i18n";
|
||||
import { exportToCanvas, exportToSvg } from "../scene/export";
|
||||
import { ExportType } from "../scene/types";
|
||||
@@ -19,65 +15,6 @@ import { serializeAsJSON } from "./json";
|
||||
export { loadFromBlob } from "./blob";
|
||||
export { loadFromJSON, saveAsJSON } from "./json";
|
||||
|
||||
const BACKEND_V2_POST = process.env.REACT_APP_BACKEND_V2_POST_URL;
|
||||
|
||||
export const exportToBackend = async (
|
||||
elements: readonly ExcalidrawElement[],
|
||||
appState: AppState,
|
||||
) => {
|
||||
const json = serializeAsJSON(elements, appState);
|
||||
const encoded = new TextEncoder().encode(json);
|
||||
|
||||
const key = await window.crypto.subtle.generateKey(
|
||||
{
|
||||
name: "AES-GCM",
|
||||
length: 128,
|
||||
},
|
||||
true, // extractable
|
||||
["encrypt", "decrypt"],
|
||||
);
|
||||
// The iv is set to 0. We are never going to reuse the same key so we don't
|
||||
// need to have an iv. (I hope that's correct...)
|
||||
const iv = new Uint8Array(12);
|
||||
// We use symmetric encryption. AES-GCM is the recommended algorithm and
|
||||
// includes checks that the ciphertext has not been modified by an attacker.
|
||||
const encrypted = await window.crypto.subtle.encrypt(
|
||||
{
|
||||
name: "AES-GCM",
|
||||
iv,
|
||||
},
|
||||
key,
|
||||
encoded,
|
||||
);
|
||||
// We use jwk encoding to be able to extract just the base64 encoded key.
|
||||
// We will hardcode the rest of the attributes when importing back the key.
|
||||
const exportedKey = await window.crypto.subtle.exportKey("jwk", key);
|
||||
|
||||
try {
|
||||
const response = await fetch(BACKEND_V2_POST, {
|
||||
method: "POST",
|
||||
body: encrypted,
|
||||
});
|
||||
const json = await response.json();
|
||||
if (json.id) {
|
||||
const url = new URL(window.location.href);
|
||||
// We need to store the key (and less importantly the id) as hash instead
|
||||
// of queryParam in order to never send it to the server
|
||||
url.hash = `json=${json.id},${exportedKey.k!}`;
|
||||
const urlString = url.toString();
|
||||
window.prompt(`🔒${t("alerts.uploadedSecurly")}`, urlString);
|
||||
trackEvent(EVENT_IO, "export", "backend");
|
||||
} else if (json.error_class === "RequestTooLargeError") {
|
||||
window.alert(t("alerts.couldNotCreateShareableLinkTooBig"));
|
||||
} else {
|
||||
window.alert(t("alerts.couldNotCreateShareableLink"));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
window.alert(t("alerts.couldNotCreateShareableLink"));
|
||||
}
|
||||
};
|
||||
|
||||
export const exportCanvas = async (
|
||||
type: ExportType,
|
||||
elements: readonly NonDeletedExcalidrawElement[],
|
||||
@@ -169,13 +106,6 @@ export const exportCanvas = async (
|
||||
}
|
||||
throw new Error(t("alerts.couldNotCopyToClipboard"));
|
||||
}
|
||||
} else if (type === "backend") {
|
||||
exportToBackend(elements, {
|
||||
...appState,
|
||||
viewBackgroundColor: exportBackground
|
||||
? appState.viewBackgroundColor
|
||||
: getDefaultAppState().viewBackgroundColor,
|
||||
});
|
||||
}
|
||||
|
||||
// clean up the DOM
|
||||
|
||||
@@ -102,7 +102,7 @@ export class LinearElementEditor {
|
||||
element,
|
||||
scenePointerX - editingLinearElement.pointerOffset.x,
|
||||
scenePointerY - editingLinearElement.pointerOffset.y,
|
||||
appState.gridSize,
|
||||
appState.showGrid,
|
||||
);
|
||||
LinearElementEditor.movePoint(element, activePointIndex, newPoint);
|
||||
if (isBindingElement(element)) {
|
||||
@@ -198,7 +198,7 @@ export class LinearElementEditor {
|
||||
element,
|
||||
scenePointer.x,
|
||||
scenePointer.y,
|
||||
appState.gridSize,
|
||||
appState.showGrid,
|
||||
),
|
||||
],
|
||||
});
|
||||
@@ -282,7 +282,7 @@ export class LinearElementEditor {
|
||||
scenePointerX: number,
|
||||
scenePointerY: number,
|
||||
editingLinearElement: LinearElementEditor,
|
||||
gridSize: number | null,
|
||||
isGridOn: boolean,
|
||||
): LinearElementEditor {
|
||||
const { elementId, lastUncommittedPoint } = editingLinearElement;
|
||||
const element = LinearElementEditor.getElement(elementId);
|
||||
@@ -304,7 +304,7 @@ export class LinearElementEditor {
|
||||
element,
|
||||
scenePointerX - editingLinearElement.pointerOffset.x,
|
||||
scenePointerY - editingLinearElement.pointerOffset.y,
|
||||
gridSize,
|
||||
isGridOn,
|
||||
);
|
||||
|
||||
if (lastPoint === lastUncommittedPoint) {
|
||||
@@ -398,9 +398,9 @@ export class LinearElementEditor {
|
||||
element: NonDeleted<ExcalidrawLinearElement>,
|
||||
scenePointerX: number,
|
||||
scenePointerY: number,
|
||||
gridSize: number | null,
|
||||
isGridOn: boolean,
|
||||
): Point {
|
||||
const pointerOnGrid = getGridPoint(scenePointerX, scenePointerY, gridSize);
|
||||
const pointerOnGrid = getGridPoint(scenePointerX, scenePointerY, isGridOn);
|
||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
|
||||
const cx = (x1 + x2) / 2;
|
||||
const cy = (y1 + y2) / 2;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { PureComponent } from "react";
|
||||
import throttle from "lodash.throttle";
|
||||
|
||||
import { ENV, EVENT } from "../../constants";
|
||||
import { APP_NAME, ENV, EVENT } from "../../constants";
|
||||
|
||||
import {
|
||||
decryptAESGEM,
|
||||
@@ -157,11 +157,7 @@ class CollabWrapper extends PureComponent<Props, CollabState> {
|
||||
};
|
||||
|
||||
openPortal = async () => {
|
||||
window.history.pushState(
|
||||
{},
|
||||
"Excalidraw",
|
||||
await generateCollaborationLink(),
|
||||
);
|
||||
window.history.pushState({}, APP_NAME, await generateCollaborationLink());
|
||||
const elements = this.excalidrawRef.current!.getSceneElements();
|
||||
// remove deleted elements from elements array & history to ensure we don't
|
||||
// expose potentially sensitive user data in case user manually deletes
|
||||
@@ -178,7 +174,7 @@ class CollabWrapper extends PureComponent<Props, CollabState> {
|
||||
|
||||
closePortal = () => {
|
||||
this.saveCollabRoomToFirebase();
|
||||
window.history.pushState({}, "Excalidraw", window.location.origin);
|
||||
window.history.pushState({}, APP_NAME, window.location.origin);
|
||||
this.destroySocketClient();
|
||||
trackEvent(EVENT_SHARE, "session end");
|
||||
};
|
||||
|
||||
@@ -3,12 +3,14 @@ import { ExcalidrawElement } from "../../element/types";
|
||||
import { AppState } from "../../types";
|
||||
import { ImportedDataState } from "../../data/types";
|
||||
import { restore } from "../../data/restore";
|
||||
import { EVENT_ACTION, trackEvent } from "../../analytics";
|
||||
import { EVENT_ACTION, EVENT_IO, trackEvent } from "../../analytics";
|
||||
import { serializeAsJSON } from "../../data/json";
|
||||
|
||||
const byteToHex = (byte: number): string => `0${byte.toString(16)}`.slice(-2);
|
||||
|
||||
const BACKEND_GET = process.env.REACT_APP_BACKEND_V1_GET_URL;
|
||||
const BACKEND_V2_GET = process.env.REACT_APP_BACKEND_V2_GET_URL;
|
||||
const BACKEND_V2_POST = process.env.REACT_APP_BACKEND_V2_POST_URL;
|
||||
|
||||
const generateRandomID = async () => {
|
||||
const arr = new Uint8Array(10);
|
||||
@@ -228,3 +230,60 @@ export const loadScene = async (
|
||||
commitToHistory: false,
|
||||
};
|
||||
};
|
||||
|
||||
export const exportToBackend = async (
|
||||
elements: readonly ExcalidrawElement[],
|
||||
appState: AppState,
|
||||
) => {
|
||||
const json = serializeAsJSON(elements, appState);
|
||||
const encoded = new TextEncoder().encode(json);
|
||||
|
||||
const key = await window.crypto.subtle.generateKey(
|
||||
{
|
||||
name: "AES-GCM",
|
||||
length: 128,
|
||||
},
|
||||
true, // extractable
|
||||
["encrypt", "decrypt"],
|
||||
);
|
||||
// The iv is set to 0. We are never going to reuse the same key so we don't
|
||||
// need to have an iv. (I hope that's correct...)
|
||||
const iv = new Uint8Array(12);
|
||||
// We use symmetric encryption. AES-GCM is the recommended algorithm and
|
||||
// includes checks that the ciphertext has not been modified by an attacker.
|
||||
const encrypted = await window.crypto.subtle.encrypt(
|
||||
{
|
||||
name: "AES-GCM",
|
||||
iv,
|
||||
},
|
||||
key,
|
||||
encoded,
|
||||
);
|
||||
// We use jwk encoding to be able to extract just the base64 encoded key.
|
||||
// We will hardcode the rest of the attributes when importing back the key.
|
||||
const exportedKey = await window.crypto.subtle.exportKey("jwk", key);
|
||||
|
||||
try {
|
||||
const response = await fetch(BACKEND_V2_POST, {
|
||||
method: "POST",
|
||||
body: encrypted,
|
||||
});
|
||||
const json = await response.json();
|
||||
if (json.id) {
|
||||
const url = new URL(window.location.href);
|
||||
// We need to store the key (and less importantly the id) as hash instead
|
||||
// of queryParam in order to never send it to the server
|
||||
url.hash = `json=${json.id},${exportedKey.k!}`;
|
||||
const urlString = url.toString();
|
||||
window.prompt(`🔒${t("alerts.uploadedSecurly")}`, urlString);
|
||||
trackEvent(EVENT_IO, "export", "backend");
|
||||
} else if (json.error_class === "RequestTooLargeError") {
|
||||
window.alert(t("alerts.couldNotCreateShareableLinkTooBig"));
|
||||
} else {
|
||||
window.alert(t("alerts.couldNotCreateShareableLink"));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
window.alert(t("alerts.couldNotCreateShareableLink"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -13,16 +13,22 @@ import { ImportedDataState } from "../data/types";
|
||||
import CollabWrapper, { CollabAPI } from "./collab/CollabWrapper";
|
||||
import { TopErrorBoundary } from "../components/TopErrorBoundary";
|
||||
import { t } from "../i18n";
|
||||
import { loadScene } from "./data";
|
||||
import { exportToBackend, loadScene } from "./data";
|
||||
import { getCollaborationLinkData } from "./data";
|
||||
import { EVENT } from "../constants";
|
||||
import { loadFromFirebase } from "./data/firebase";
|
||||
import { ExcalidrawImperativeAPI } from "../components/App";
|
||||
import { debounce, ResolvablePromise, resolvablePromise } from "../utils";
|
||||
import { AppState, ExcalidrawAPIRefValue } from "../types";
|
||||
import { ExcalidrawElement } from "../element/types";
|
||||
import {
|
||||
ExcalidrawElement,
|
||||
NonDeletedExcalidrawElement,
|
||||
} from "../element/types";
|
||||
import { SAVE_TO_LOCAL_STORAGE_TIMEOUT } from "./app_constants";
|
||||
import { EVENT_LOAD, EVENT_SHARE, trackEvent } from "../analytics";
|
||||
import { ErrorDialog } from "../components/ErrorDialog";
|
||||
import { getDefaultAppState } from "../appState";
|
||||
import { APP_NAME, TITLE_TIMEOUT } from "../constants";
|
||||
|
||||
const excalidrawRef: React.MutableRefObject<
|
||||
MarkRequired<ExcalidrawAPIRefValue, "ready" | "readyPromise">
|
||||
@@ -113,7 +119,7 @@ const initializeScene = async (opts: {
|
||||
scene = await loadScene(jsonMatch[1], jsonMatch[2], initialData);
|
||||
}
|
||||
if (!isCollabScene) {
|
||||
window.history.replaceState({}, "Excalidraw", window.location.origin);
|
||||
window.history.replaceState({}, APP_NAME, window.location.origin);
|
||||
}
|
||||
} else {
|
||||
// https://github.com/excalidraw/excalidraw/issues/1919
|
||||
@@ -132,7 +138,7 @@ const initializeScene = async (opts: {
|
||||
}
|
||||
|
||||
isCollabScene = false;
|
||||
window.history.replaceState({}, "Excalidraw", window.location.origin);
|
||||
window.history.replaceState({}, APP_NAME, window.location.origin);
|
||||
}
|
||||
}
|
||||
if (isCollabScene) {
|
||||
@@ -178,6 +184,7 @@ function ExcalidrawWrapper(props: { collab: CollabAPI }) {
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight,
|
||||
});
|
||||
const [errorMessage, setErrorMessage] = useState("");
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const onResize = () => {
|
||||
@@ -240,6 +247,10 @@ function ExcalidrawWrapper(props: { collab: CollabAPI }) {
|
||||
}
|
||||
};
|
||||
|
||||
const titleTimeout = setTimeout(
|
||||
() => (document.title = APP_NAME),
|
||||
TITLE_TIMEOUT,
|
||||
);
|
||||
window.addEventListener(EVENT.HASHCHANGE, onHashChange, false);
|
||||
window.addEventListener(EVENT.UNLOAD, onBlur, false);
|
||||
window.addEventListener(EVENT.BLUR, onBlur, false);
|
||||
@@ -247,6 +258,7 @@ function ExcalidrawWrapper(props: { collab: CollabAPI }) {
|
||||
window.removeEventListener(EVENT.HASHCHANGE, onHashChange, false);
|
||||
window.removeEventListener(EVENT.UNLOAD, onBlur, false);
|
||||
window.removeEventListener(EVENT.BLUR, onBlur, false);
|
||||
clearTimeout(titleTimeout);
|
||||
};
|
||||
}, [collab.initializeSocketClient]);
|
||||
|
||||
@@ -260,18 +272,52 @@ function ExcalidrawWrapper(props: { collab: CollabAPI }) {
|
||||
}
|
||||
};
|
||||
|
||||
const onExportToBackend = async (
|
||||
exportedElements: readonly NonDeletedExcalidrawElement[],
|
||||
appState: AppState,
|
||||
canvas: HTMLCanvasElement | null,
|
||||
) => {
|
||||
if (exportedElements.length === 0) {
|
||||
return window.alert(t("alerts.cannotExportEmptyCanvas"));
|
||||
}
|
||||
if (canvas) {
|
||||
try {
|
||||
await exportToBackend(exportedElements, {
|
||||
...appState,
|
||||
viewBackgroundColor: appState.exportBackground
|
||||
? appState.viewBackgroundColor
|
||||
: getDefaultAppState().viewBackgroundColor,
|
||||
});
|
||||
} catch (error) {
|
||||
if (error.name !== "AbortError") {
|
||||
const { width, height } = canvas;
|
||||
console.error(error, { width, height });
|
||||
setErrorMessage(error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
return (
|
||||
<Excalidraw
|
||||
ref={excalidrawRef}
|
||||
onChange={onChange}
|
||||
width={dimensions.width}
|
||||
height={dimensions.height}
|
||||
initialData={initialStatePromiseRef.current.promise}
|
||||
user={{ name: collab.username }}
|
||||
onCollabButtonClick={collab.onCollabButtonClick}
|
||||
isCollaborating={collab.isCollaborating}
|
||||
onPointerUpdate={collab.onPointerUpdate}
|
||||
/>
|
||||
<>
|
||||
<Excalidraw
|
||||
ref={excalidrawRef}
|
||||
onChange={onChange}
|
||||
width={dimensions.width}
|
||||
height={dimensions.height}
|
||||
initialData={initialStatePromiseRef.current.promise}
|
||||
user={{ name: collab.username }}
|
||||
onCollabButtonClick={collab.onCollabButtonClick}
|
||||
isCollaborating={collab.isCollaborating}
|
||||
onPointerUpdate={collab.onPointerUpdate}
|
||||
onExportToBackend={onExportToBackend}
|
||||
/>
|
||||
{errorMessage && (
|
||||
<ErrorDialog
|
||||
message={errorMessage}
|
||||
onClose={() => setErrorMessage("")}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ export const CODES = {
|
||||
BRACKET_RIGHT: "BracketRight",
|
||||
BRACKET_LEFT: "BracketLeft",
|
||||
ONE: "Digit1",
|
||||
TWO: "Digit2",
|
||||
NINE: "Digit9",
|
||||
QUOTE: "Quote",
|
||||
ZERO: "Digit0",
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "تحديد الكل",
|
||||
"multiSelect": "إضافة عنصر للتحديد",
|
||||
"moveCanvas": "نقل لوح رسم",
|
||||
"cut": "",
|
||||
"copy": "نسخ",
|
||||
"copyAsPng": "نسخ إلى الحافظة بصيغة PNG",
|
||||
"copyAsSvg": "نسخ بصيغة SVG",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "الحواف",
|
||||
"sharp": "حادة",
|
||||
"round": "دائرية",
|
||||
"arrowheads": "",
|
||||
"arrowhead_none": "",
|
||||
"arrowhead_arrow": "",
|
||||
"arrowhead_bar": "",
|
||||
"arrowhead_dot": "",
|
||||
"fontSize": "حجم الخط",
|
||||
"fontFamily": "نوع الخط",
|
||||
"onlySelected": "المحدد فقط",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "إلغاء تحديد مجموعة",
|
||||
"collaborators": "المتعاونون",
|
||||
"toggleGridMode": "التبديل إلى وضع الشبكة",
|
||||
"toggleStats": "",
|
||||
"addToLibrary": "أضف إلى المكتبة",
|
||||
"removeFromLibrary": "حذف من المكتبة",
|
||||
"libraryLoadingMessage": "جارٍ تحميل المكتبة...",
|
||||
"libraries": "",
|
||||
"loadingScene": "جاري تحميل المشهد...",
|
||||
"align": "محاذاة",
|
||||
"alignTop": "محاذاة إلى اﻷعلى",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "إضافة سطر جديد (نص)",
|
||||
"textFinish": "الانتهاء من تحرير (النص)",
|
||||
"zoomToFit": "تكبير لتلائم جميع العناصر",
|
||||
"zoomToSelection": "",
|
||||
"preventBinding": "منع ربط السهم"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "رسوماتك مشفرة من النهاية إلى النهاية حتى أن خوادم Excalidraw لن تراها أبدا."
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "قمت بلصق جدول بيانات دون عمود رقمي.",
|
||||
"tooManyColumns": "قمت بلصق جدول بيانات دون عمود رقمي."
|
||||
"stats": {
|
||||
"angle": "",
|
||||
"element": "",
|
||||
"elements": "",
|
||||
"height": "",
|
||||
"scene": "",
|
||||
"selected": "",
|
||||
"storage": "",
|
||||
"title": "",
|
||||
"total": "",
|
||||
"width": ""
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "Маркирай всичко",
|
||||
"multiSelect": "",
|
||||
"moveCanvas": "",
|
||||
"cut": "",
|
||||
"copy": "Копирай",
|
||||
"copyAsPng": "Копиране в клипборда",
|
||||
"copyAsSvg": "Копиране в клипборда",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "",
|
||||
"sharp": "",
|
||||
"round": "",
|
||||
"arrowheads": "",
|
||||
"arrowhead_none": "",
|
||||
"arrowhead_arrow": "",
|
||||
"arrowhead_bar": "",
|
||||
"arrowhead_dot": "",
|
||||
"fontSize": "Размер на шрифта",
|
||||
"fontFamily": "Семейство шрифтове",
|
||||
"onlySelected": "Само избраното",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "",
|
||||
"collaborators": "",
|
||||
"toggleGridMode": "",
|
||||
"toggleStats": "",
|
||||
"addToLibrary": "",
|
||||
"removeFromLibrary": "",
|
||||
"libraryLoadingMessage": "",
|
||||
"libraries": "",
|
||||
"loadingScene": "",
|
||||
"align": "",
|
||||
"alignTop": "",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "Добавяне на нов ред (текст)",
|
||||
"textFinish": "Завършете редактиране (текст)",
|
||||
"zoomToFit": "",
|
||||
"zoomToSelection": "",
|
||||
"preventBinding": ""
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": ""
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "",
|
||||
"tooManyColumns": ""
|
||||
"stats": {
|
||||
"angle": "",
|
||||
"element": "",
|
||||
"elements": "",
|
||||
"height": "",
|
||||
"scene": "",
|
||||
"selected": "",
|
||||
"storage": "",
|
||||
"title": "",
|
||||
"total": "",
|
||||
"width": ""
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "Seleccionar tot",
|
||||
"multiSelect": "Afegir element a la selecció",
|
||||
"moveCanvas": "Moure el llenç",
|
||||
"cut": "",
|
||||
"copy": "Copiar",
|
||||
"copyAsPng": "Copiar al porta-retalls com a PNG",
|
||||
"copyAsSvg": "Copiar al porta-retalls com a SVG",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "Vores",
|
||||
"sharp": "Agut",
|
||||
"round": "Arrodonit",
|
||||
"arrowheads": "",
|
||||
"arrowhead_none": "",
|
||||
"arrowhead_arrow": "",
|
||||
"arrowhead_bar": "",
|
||||
"arrowhead_dot": "",
|
||||
"fontSize": "Mida de lletra",
|
||||
"fontFamily": "Tipus de lletra",
|
||||
"onlySelected": "Només seleccionats",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "Desagrupar la selecció",
|
||||
"collaborators": "Col·laboradors",
|
||||
"toggleGridMode": "Commutar línies de graella",
|
||||
"toggleStats": "",
|
||||
"addToLibrary": "Afegir a la biblioteca",
|
||||
"removeFromLibrary": "Eliminar de la biblioteca",
|
||||
"libraryLoadingMessage": "Carregant la biblioteca...",
|
||||
"libraries": "",
|
||||
"loadingScene": "Carregant escena ...",
|
||||
"align": "",
|
||||
"alignTop": "",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "Afegir línea nova (text)",
|
||||
"textFinish": "Acabar d'editar (text)",
|
||||
"zoomToFit": "Zoom per veure tots els elements",
|
||||
"zoomToSelection": "",
|
||||
"preventBinding": "Prevenir vinculació de la fletxa"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "Els vostres dibuixos estan xifrats de punta a punta de manera que els servidors d’Excalidraw no els veuran mai."
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "Has enganxat un full de càlcul sense columna numèrica.",
|
||||
"tooManyColumns": "Has enganxat un full de càlcul amb més de dues columnes."
|
||||
"stats": {
|
||||
"angle": "",
|
||||
"element": "",
|
||||
"elements": "",
|
||||
"height": "",
|
||||
"scene": "",
|
||||
"selected": "",
|
||||
"storage": "",
|
||||
"title": "",
|
||||
"total": "",
|
||||
"width": ""
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "Alle auswählen",
|
||||
"multiSelect": "Element zur Auswahl hinzufügen",
|
||||
"moveCanvas": "Leinwand verschieben",
|
||||
"cut": "Ausschneiden",
|
||||
"copy": "Kopieren",
|
||||
"copyAsPng": "In Zwischenablage kopieren (PNG)",
|
||||
"copyAsSvg": "In Zwischenablage kopieren (SVG)",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "Kanten",
|
||||
"sharp": "Eckig",
|
||||
"round": "Rund",
|
||||
"arrowheads": "Pfeilspitzen",
|
||||
"arrowhead_none": "Keine",
|
||||
"arrowhead_arrow": "Pfeil",
|
||||
"arrowhead_bar": "Balken",
|
||||
"arrowhead_dot": "Punkt",
|
||||
"fontSize": "Schriftgröße",
|
||||
"fontFamily": "Schriftfamilie",
|
||||
"onlySelected": "Nur ausgewählte",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "Gruppierung aufheben",
|
||||
"collaborators": "Mitarbeitende",
|
||||
"toggleGridMode": "Gitterlinien ein-/ausschalten",
|
||||
"toggleStats": "Statistiken für Nerds ein-/ausschalten",
|
||||
"addToLibrary": "Zur Bibliothek hinzufügen",
|
||||
"removeFromLibrary": "Aus Bibliothek entfernen",
|
||||
"libraryLoadingMessage": "Lade Bibliothek...",
|
||||
"libraries": "Bibliotheken durchsuchen",
|
||||
"loadingScene": "Lade Zeichnung...",
|
||||
"align": "Ausrichten",
|
||||
"alignTop": "Obere Kanten",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "Neue Zeile hinzufügen (Text)",
|
||||
"textFinish": "Bearbeiten beenden (Text)",
|
||||
"zoomToFit": "Zoomen um alle Elemente einzupassen",
|
||||
"zoomToSelection": "",
|
||||
"preventBinding": "Pfeil-Bindung verhindern"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "Da deine Zeichnungen Ende-zu-Ende verschlüsselt werden, sehen auch unsere Excalidraw-Server sie niemals."
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "Du hast eine Tabelle ohne numerische Spalte eingefügt.",
|
||||
"tooManyColumns": "Du hast eine Tabelle mit mehr als zwei Spalten eingefügt."
|
||||
"stats": {
|
||||
"angle": "Winkel",
|
||||
"element": "Element",
|
||||
"elements": "Elemente",
|
||||
"height": "Höhe",
|
||||
"scene": "Zeichnung",
|
||||
"selected": "Ausgewählt",
|
||||
"storage": "Speicher",
|
||||
"title": "Statistiken für Nerds",
|
||||
"total": "Gesamt",
|
||||
"width": "Breite"
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "Επιλογή όλων",
|
||||
"multiSelect": "Προσθέστε το στοιχείο στην επιλογή",
|
||||
"moveCanvas": "Μετακίνηση καμβά",
|
||||
"cut": "Αποκοπή",
|
||||
"copy": "Αντιγραφή",
|
||||
"copyAsPng": "Αντιγραφή στο πρόχειρο ως PNG",
|
||||
"copyAsSvg": "Αντιγραφή στο πρόχειρο ως SVG",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "Άκρες",
|
||||
"sharp": "Οξύ",
|
||||
"round": "Στρογγυλό",
|
||||
"arrowheads": "Σύμβολα βελών",
|
||||
"arrowhead_none": "Κανένα",
|
||||
"arrowhead_arrow": "Βέλος",
|
||||
"arrowhead_bar": "Μπάρα",
|
||||
"arrowhead_dot": "Τελεία",
|
||||
"fontSize": "Μέγεθος γραμματοσειράς",
|
||||
"fontFamily": "Γραμματοσειρά",
|
||||
"onlySelected": "Μόνο τα Επιλεγμένα",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "Κατάργηση ομάδας από επιλογή",
|
||||
"collaborators": "Συνεργάτες",
|
||||
"toggleGridMode": "Εναλλαγή λειτουργίας πλέγματος",
|
||||
"toggleStats": "",
|
||||
"addToLibrary": "Προσθήκη στη βιβλιοθήκη",
|
||||
"removeFromLibrary": "Αφαίρεση από τη βιβλιοθήκη",
|
||||
"libraryLoadingMessage": "Φόρτωση βιβλιοθήκης...",
|
||||
"libraries": "Άλλες βιβλιοθήκες",
|
||||
"loadingScene": "Φόρτωση σκηνής...",
|
||||
"align": "Στοίχιση",
|
||||
"alignTop": "Στοίχιση πάνω",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "Προσθήκη νέας γραμμής (κείμενο)",
|
||||
"textFinish": "Ολοκλήρωση επεξεργασίας (κείμενο)",
|
||||
"zoomToFit": "Zoom ώστε να χωρέσουν όλα τα στοιχεία",
|
||||
"zoomToSelection": "",
|
||||
"preventBinding": "Αποτροπή δέσμευσης βέλων"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "Τα σχέδιά σου είναι κρυπτογραφημένα από άκρο σε άκρο, έτσι δεν θα έιναι ποτέ ορατά μέσα από τους διακομιστές του Excalidraw."
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "Επικόλλησες ένα υπολογιστικό φύλλο χωρίς αριθμητική στήλη.",
|
||||
"tooManyColumns": "Επικόλλησες ένα υπολογιστικό φύλλο με περισσότερες από δύο στήλες."
|
||||
"stats": {
|
||||
"angle": "Γωνία",
|
||||
"element": "Στοιχείο",
|
||||
"elements": "Στοιχεία",
|
||||
"height": "Ύψος",
|
||||
"scene": "",
|
||||
"selected": "Επιλεγμένα",
|
||||
"storage": "Χώρος",
|
||||
"title": "",
|
||||
"total": "Σύνολο ",
|
||||
"width": "Πλάτος"
|
||||
}
|
||||
}
|
||||
|
||||
+9
-7
@@ -37,7 +37,7 @@
|
||||
"fontSize": "Font size",
|
||||
"fontFamily": "Font family",
|
||||
"onlySelected": "Only selected",
|
||||
"withBackground": "With Background",
|
||||
"withBackground": "With background",
|
||||
"exportEmbedScene": "Embed scene into exported file",
|
||||
"exportEmbedScene_details": "Scene data will be saved into the exported PNG/SVG file so that the scene can be restored from it.\nWill increase exported file size.",
|
||||
"addWatermark": "Add \"Made with Excalidraw\"",
|
||||
@@ -76,8 +76,7 @@
|
||||
"group": "Group selection",
|
||||
"ungroup": "Ungroup selection",
|
||||
"collaborators": "Collaborators",
|
||||
"toggleGridMode": "Toggle grid mode",
|
||||
"toggleStats": "Toggle stats for nerds",
|
||||
"gridMode": "Grid mode",
|
||||
"addToLibrary": "Add to library",
|
||||
"removeFromLibrary": "Remove from library",
|
||||
"libraryLoadingMessage": "Loading library...",
|
||||
@@ -118,9 +117,10 @@
|
||||
"redo": "Redo",
|
||||
"roomDialog": "Start live collaboration",
|
||||
"createNewRoom": "Create new room",
|
||||
"toggleFullScreen": "Toggle full screen",
|
||||
"toggleDarkMode": "Toggle dark mode",
|
||||
"toggleZenMode": "Toggle zen mode",
|
||||
"fullScreen": "Full screen",
|
||||
"darkMode": "Dark mode",
|
||||
"lightMode": "Light mode",
|
||||
"zenMode": "Zen mode",
|
||||
"exitZenMode": "Exit zen mode"
|
||||
},
|
||||
"alerts": {
|
||||
@@ -136,7 +136,7 @@
|
||||
"loadSceneOverridePrompt": "Loading external drawing will replace your existing content. Do you wish to continue?",
|
||||
"errorLoadingLibrary": "There was an error loading the third party library.",
|
||||
"confirmAddLibrary": "This will add {{numShapes}} shape(s) to your library. Are you sure?",
|
||||
"imageDoesNotContainScene": "Image file doesn't contain scene data. Have you enabled this during export?",
|
||||
"imageDoesNotContainScene": "Importing images isn't supported at the moment.\n\nDid you want to import a scene? This image does not seem to contain any scene data. Have you enabled this during export?",
|
||||
"cannotRestoreFromImage": "Scene couldn't be restored from this image file"
|
||||
},
|
||||
"toolBar": {
|
||||
@@ -161,6 +161,7 @@
|
||||
"freeDraw": "Click and drag, release when you're finished",
|
||||
"text": "Tip: you can also add text by double-clicking anywhere with the selection tool",
|
||||
"linearElementMulti": "Click on last point or press Escape or Enter to finish",
|
||||
"lockAngle": "You can constrain angle by holding SHIFT",
|
||||
"resize": "You can constrain proportions by holding SHIFT while resizing,\nhold ALT to resize from the center",
|
||||
"rotate": "You can constrain angles by holding SHIFT while rotating",
|
||||
"lineEditor_info": "Double-click or press Enter to edit points",
|
||||
@@ -213,6 +214,7 @@
|
||||
"textNewLine": "Add new line (text)",
|
||||
"textFinish": "Finish editing (text)",
|
||||
"zoomToFit": "Zoom to fit all elements",
|
||||
"zoomToSelection": "Zoom to selection",
|
||||
"preventBinding": "Prevent arrow binding"
|
||||
},
|
||||
"encrypted": {
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "Seleccionar todo",
|
||||
"multiSelect": "Añadir elemento a la selección",
|
||||
"moveCanvas": "Mover el lienzo",
|
||||
"cut": "",
|
||||
"copy": "Copiar",
|
||||
"copyAsPng": "Copiar al portapapeles como PNG",
|
||||
"copyAsSvg": "Copiar al portapapeles como SVG",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "Bordes",
|
||||
"sharp": "Afilado",
|
||||
"round": "Redondo",
|
||||
"arrowheads": "",
|
||||
"arrowhead_none": "",
|
||||
"arrowhead_arrow": "",
|
||||
"arrowhead_bar": "",
|
||||
"arrowhead_dot": "",
|
||||
"fontSize": "Tamaño de la fuente",
|
||||
"fontFamily": "Tipo de fuente",
|
||||
"onlySelected": "Sólo seleccionados",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "Desagrupar",
|
||||
"collaborators": "Colaboradores",
|
||||
"toggleGridMode": "Alternar modo cuadrícula",
|
||||
"toggleStats": "",
|
||||
"addToLibrary": "Añadir a la biblioteca",
|
||||
"removeFromLibrary": "Eliminar de la biblioteca",
|
||||
"libraryLoadingMessage": "Cargando biblioteca...",
|
||||
"libraries": "",
|
||||
"loadingScene": "Cargando escena...",
|
||||
"align": "",
|
||||
"alignTop": "",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "Añadir nueva línea (texto)",
|
||||
"textFinish": "Finalizar edición (texto)",
|
||||
"zoomToFit": "Ajustar para mostrar todos los elementos",
|
||||
"zoomToSelection": "",
|
||||
"preventBinding": "Evitar enlace de flecha"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "Tus dibujos están cifrados de punto a punto, por lo que los servidores de Excalidraw nunca los verán."
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "Pegaste una hoja de cálculo sin una columna numérica.",
|
||||
"tooManyColumns": "Pegaste una hoja de cálculo con más de dos columnas."
|
||||
"stats": {
|
||||
"angle": "",
|
||||
"element": "",
|
||||
"elements": "",
|
||||
"height": "",
|
||||
"scene": "",
|
||||
"selected": "",
|
||||
"storage": "",
|
||||
"title": "",
|
||||
"total": "",
|
||||
"width": ""
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "انتخاب همه",
|
||||
"multiSelect": "یک ایتم به انتخاب شده ها اضافه کنید.",
|
||||
"moveCanvas": "بوم را حرکت بدهید",
|
||||
"cut": "",
|
||||
"copy": "کپی",
|
||||
"copyAsPng": "کپی در حافطه موقت به صورت PNG",
|
||||
"copyAsSvg": "کپی در حافطه موقت به صورت SVG",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "لبه ها",
|
||||
"sharp": "تیز",
|
||||
"round": "دور",
|
||||
"arrowheads": "",
|
||||
"arrowhead_none": "",
|
||||
"arrowhead_arrow": "",
|
||||
"arrowhead_bar": "",
|
||||
"arrowhead_dot": "",
|
||||
"fontSize": "اندازه قلم",
|
||||
"fontFamily": "نوع قلم",
|
||||
"onlySelected": "فقط انتخاب شده ها",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "حذف گروهبندی انتخابها",
|
||||
"collaborators": "همکاران",
|
||||
"toggleGridMode": "سويچ خطوط راهنما",
|
||||
"toggleStats": "",
|
||||
"addToLibrary": "افزودن به کتابخانه",
|
||||
"removeFromLibrary": "حذف از کتابخانه",
|
||||
"libraryLoadingMessage": "بارگذاری کتابخانه...",
|
||||
"libraries": "",
|
||||
"loadingScene": "باگذاری صحنه...",
|
||||
"align": "تراز",
|
||||
"alignTop": "تراز به بالا",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "یک خط جدید اضافه کنید (متن)",
|
||||
"textFinish": "پایان ویرایش (متن)",
|
||||
"zoomToFit": "بزرگنمایی برای دیدن تمام آیتم ها",
|
||||
"zoomToSelection": "",
|
||||
"preventBinding": "مانع شدن از چسبیدن فلش ها"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "شما در یک محیط رمزگزاری شده دو طرفه در حال طراحی هستید پس Excalidraw هرگز طرح های شما را نمیبند."
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "شما یک صفحه گسترده را بدون ستون عددی کپی کرده اید.",
|
||||
"tooManyColumns": "شما یک صفحه گسترده را با بیش از دو ستون کپی کرده اید."
|
||||
"stats": {
|
||||
"angle": "",
|
||||
"element": "",
|
||||
"elements": "",
|
||||
"height": "",
|
||||
"scene": "",
|
||||
"selected": "",
|
||||
"storage": "",
|
||||
"title": "",
|
||||
"total": "",
|
||||
"width": ""
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "Valitse kaikki",
|
||||
"multiSelect": "Lisää kohde valintaan",
|
||||
"moveCanvas": "Siirrä piirtoaluetta",
|
||||
"cut": "Leikkaa",
|
||||
"copy": "Kopioi",
|
||||
"copyAsPng": "Kopioi leikepöydälle PNG-tiedostona",
|
||||
"copyAsSvg": "Kopioi leikepöydälle SVG-tiedostona",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "Reunat",
|
||||
"sharp": "Terävä",
|
||||
"round": "Pyöreä",
|
||||
"arrowheads": "Nuolenkärjet",
|
||||
"arrowhead_none": "Ei mitään",
|
||||
"arrowhead_arrow": "Nuoli",
|
||||
"arrowhead_bar": "Tasapää",
|
||||
"arrowhead_dot": "Piste",
|
||||
"fontSize": "Kirjasinkoko",
|
||||
"fontFamily": "Kirjasintyyppi",
|
||||
"onlySelected": "Vain valitut",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "Pura valittu ryhmä",
|
||||
"collaborators": "Yhteistyökumppanit",
|
||||
"toggleGridMode": "Ruudukko päälle/pois",
|
||||
"toggleStats": "Nörttien tilastot päälle/pois",
|
||||
"addToLibrary": "Lisää kirjastoon",
|
||||
"removeFromLibrary": "Poista kirjastosta",
|
||||
"libraryLoadingMessage": "Ladataan kirjastoa...",
|
||||
"libraries": "Selaa kirjastoja",
|
||||
"loadingScene": "Ladataan työtä...",
|
||||
"align": "Tasaa",
|
||||
"alignTop": "Tasaa ylös",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "Lisää uusi rivi (teksti)",
|
||||
"textFinish": "Lopeta muokkaus (teksti)",
|
||||
"zoomToFit": "Zoomaa kaikki elementit näkyviin",
|
||||
"zoomToSelection": "Zoomaa valintaan",
|
||||
"preventBinding": "Estä nuolten sitominen"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "Piirroksesi ovat päästä päähän salattuja, joten Excalidrawin palvelimet eivät koskaan näe niitä."
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "Liitit taulukon ilman lukuja sisältävää saraketta.",
|
||||
"tooManyColumns": "Liitit taulukon, jossa on enemmän kuin kaksi saraketta."
|
||||
"stats": {
|
||||
"angle": "Kulma",
|
||||
"element": "Elementti",
|
||||
"elements": "Elementit",
|
||||
"height": "Korkeus",
|
||||
"scene": "Teos",
|
||||
"selected": "Valitut",
|
||||
"storage": "Tallennustila",
|
||||
"title": "Nörttien tilastot",
|
||||
"total": "Yhteensä",
|
||||
"width": "Leveys"
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "Tout sélectionner",
|
||||
"multiSelect": "Ajouter l'élément à la sélection",
|
||||
"moveCanvas": "Déplacer le canvas",
|
||||
"cut": "Couper",
|
||||
"copy": "Copier",
|
||||
"copyAsPng": "Copier dans le presse-papier en PNG",
|
||||
"copyAsSvg": "Copier dans le presse-papier en SVG",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "Angles",
|
||||
"sharp": "Aigu",
|
||||
"round": "Rond",
|
||||
"arrowheads": "Extrémités de ligne",
|
||||
"arrowhead_none": "Aucun",
|
||||
"arrowhead_arrow": "Flèche",
|
||||
"arrowhead_bar": "Barre",
|
||||
"arrowhead_dot": "Point",
|
||||
"fontSize": "Taille de la police",
|
||||
"fontFamily": "Police",
|
||||
"onlySelected": "Uniquement la sélection",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "Dégrouper la sélection",
|
||||
"collaborators": "Collaborateurs",
|
||||
"toggleGridMode": "Basculer le mode grille",
|
||||
"toggleStats": "Activer/désactiver les stats pour les nerds",
|
||||
"addToLibrary": "Ajouter à la bibliothèque",
|
||||
"removeFromLibrary": "Supprimer de la bibliothèque",
|
||||
"libraryLoadingMessage": "Chargement de la bibliothèque...",
|
||||
"libraries": "Explorer les bibliothèques",
|
||||
"loadingScene": "Chargement de la scène...",
|
||||
"align": "Aligner",
|
||||
"alignTop": "Aligner en haut",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "Ajouter une nouvelle ligne (texte)",
|
||||
"textFinish": "Terminer l'édition (texte)",
|
||||
"zoomToFit": "Zoomer pour visualiser tous les éléments",
|
||||
"zoomToSelection": "Zoom sur la sélection",
|
||||
"preventBinding": "Empêcher la liaison de la flèche"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "Vos dessins sont chiffrés de bout en bout, les serveurs d'Excalidraw ne les verront jamais."
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "Vous avez collé une feuille de calcul sans données numérique.",
|
||||
"tooManyColumns": "Vous avez collé une feuille de calcul avec plus de deux colonnes."
|
||||
"stats": {
|
||||
"angle": "Angle",
|
||||
"element": "Élément",
|
||||
"elements": "Éléments",
|
||||
"height": "Hauteur",
|
||||
"scene": "Scène",
|
||||
"selected": "Sélectionné",
|
||||
"storage": "Stockage",
|
||||
"title": "Stats pour nerds",
|
||||
"total": "Total",
|
||||
"width": "Largeur"
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "בחר הכל",
|
||||
"multiSelect": "",
|
||||
"moveCanvas": "",
|
||||
"cut": "",
|
||||
"copy": "העתק",
|
||||
"copyAsPng": "העתק ללוח כ PNG",
|
||||
"copyAsSvg": "העתק ללוח כ SVG",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "",
|
||||
"sharp": "",
|
||||
"round": "",
|
||||
"arrowheads": "",
|
||||
"arrowhead_none": "",
|
||||
"arrowhead_arrow": "",
|
||||
"arrowhead_bar": "",
|
||||
"arrowhead_dot": "",
|
||||
"fontSize": "גודל גופן",
|
||||
"fontFamily": "סוג הגופן",
|
||||
"onlySelected": "רק מה שנבחר",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "פרק קבוצה",
|
||||
"collaborators": "",
|
||||
"toggleGridMode": "",
|
||||
"toggleStats": "",
|
||||
"addToLibrary": "",
|
||||
"removeFromLibrary": "",
|
||||
"libraryLoadingMessage": "",
|
||||
"libraries": "",
|
||||
"loadingScene": "",
|
||||
"align": "",
|
||||
"alignTop": "",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "הוסף שורה חדשה (טקסט)",
|
||||
"textFinish": "סיים עריכה (טקסט)",
|
||||
"zoomToFit": "זום להתאמת כל האלמנטים למסך",
|
||||
"zoomToSelection": "",
|
||||
"preventBinding": ""
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "הרישומים שלך מוצפנים מקצה לקצה כך שהשרתים של Excalidraw לא יראו אותם לעולם."
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "",
|
||||
"tooManyColumns": ""
|
||||
"stats": {
|
||||
"angle": "",
|
||||
"element": "",
|
||||
"elements": "",
|
||||
"height": "",
|
||||
"scene": "",
|
||||
"selected": "",
|
||||
"storage": "",
|
||||
"title": "",
|
||||
"total": "",
|
||||
"width": ""
|
||||
}
|
||||
}
|
||||
|
||||
+21
-4
@@ -4,6 +4,7 @@
|
||||
"selectAll": "सभी चुनें",
|
||||
"multiSelect": "आकार को चयन में जोड़ें",
|
||||
"moveCanvas": "कैनवास को स्थानांतरित करें",
|
||||
"cut": "काटें",
|
||||
"copy": "प्रतिलिपि",
|
||||
"copyAsPng": "क्लिपबोर्ड पर कॉपी करें ,पीएनजी के रूप में",
|
||||
"copyAsSvg": "क्लिपबोर्ड पर कॉपी करें,एसवीजी के रूप में",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "किनारा",
|
||||
"sharp": "नुकीला",
|
||||
"round": "गोल",
|
||||
"arrowheads": "",
|
||||
"arrowhead_none": "",
|
||||
"arrowhead_arrow": "तीर",
|
||||
"arrowhead_bar": "",
|
||||
"arrowhead_dot": "",
|
||||
"fontSize": "फ़ॉन्ट का आकार",
|
||||
"fontFamily": "फ़ॉन्ट का परिवार",
|
||||
"onlySelected": "केवल चयनित",
|
||||
@@ -63,7 +69,7 @@
|
||||
"language": "भाषा",
|
||||
"createRoom": "अधिवेशन",
|
||||
"duplicateSelection": "डुप्लिकेट",
|
||||
"untitled": "",
|
||||
"untitled": "अशीर्षित",
|
||||
"name": "नाम",
|
||||
"yourName": "आपका नाम",
|
||||
"madeWithExcalidraw": "मेड विथ एक्सकैलिडराव",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "समूह चयन असमूहीकृत करें",
|
||||
"collaborators": "सहयोगी",
|
||||
"toggleGridMode": "टॉगल ग्रिड मोड",
|
||||
"toggleStats": "",
|
||||
"addToLibrary": "लाइब्रेरी से जोड़ें",
|
||||
"removeFromLibrary": "लाइब्रेरी से निकालें",
|
||||
"libraryLoadingMessage": "लाइब्रेरी खुल रही है",
|
||||
"libraries": "",
|
||||
"loadingScene": "दृश्य खुल रहा है",
|
||||
"align": "",
|
||||
"alignTop": "",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "नई पंक्ति (पाठ) जोड़ें",
|
||||
"textFinish": "संपादन समाप्त करें (पाठ)",
|
||||
"zoomToFit": "सभी तत्वों को फिट करने के लिए ज़ूम करें",
|
||||
"zoomToSelection": "",
|
||||
"preventBinding": ""
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "आपके चित्र अंत-से-अंत एन्क्रिप्टेड हैं, इसलिए एक्सक्लूसिव्रॉव के सर्वर उन्हें कभी नहीं देखेंगे।"
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "आपने एक संख्यात्मक कॉलम के बिना एक स्प्रेडशीट चिपकाई।",
|
||||
"tooManyColumns": "आपने दो से अधिक कॉलम के साथ एक स्प्रेडशीट चिपकाई।"
|
||||
"stats": {
|
||||
"angle": "कोण",
|
||||
"element": "",
|
||||
"elements": "",
|
||||
"height": "ऊंचाई",
|
||||
"scene": "दृश्य",
|
||||
"selected": "चयनित",
|
||||
"storage": "संग्रह",
|
||||
"title": "",
|
||||
"total": "कुल",
|
||||
"width": "चौड़ाई"
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "Összes kijelölése",
|
||||
"multiSelect": "",
|
||||
"moveCanvas": "",
|
||||
"cut": "",
|
||||
"copy": "Másolás",
|
||||
"copyAsPng": "Vágólapra másolás mint PNG",
|
||||
"copyAsSvg": "Vágólapra másolás mint SVG",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "",
|
||||
"sharp": "",
|
||||
"round": "",
|
||||
"arrowheads": "",
|
||||
"arrowhead_none": "",
|
||||
"arrowhead_arrow": "",
|
||||
"arrowhead_bar": "",
|
||||
"arrowhead_dot": "",
|
||||
"fontSize": "",
|
||||
"fontFamily": "",
|
||||
"onlySelected": "Csak a kiválasztott",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "",
|
||||
"collaborators": "",
|
||||
"toggleGridMode": "",
|
||||
"toggleStats": "",
|
||||
"addToLibrary": "",
|
||||
"removeFromLibrary": "",
|
||||
"libraryLoadingMessage": "",
|
||||
"libraries": "",
|
||||
"loadingScene": "",
|
||||
"align": "",
|
||||
"alignTop": "",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "",
|
||||
"textFinish": "",
|
||||
"zoomToFit": "",
|
||||
"zoomToSelection": "",
|
||||
"preventBinding": ""
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": ""
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "",
|
||||
"tooManyColumns": ""
|
||||
"stats": {
|
||||
"angle": "",
|
||||
"element": "",
|
||||
"elements": "",
|
||||
"height": "",
|
||||
"scene": "",
|
||||
"selected": "",
|
||||
"storage": "",
|
||||
"title": "",
|
||||
"total": "",
|
||||
"width": ""
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "Pilih semua",
|
||||
"multiSelect": "Tambahkan elemen ke pilihan",
|
||||
"moveCanvas": "Pindahkan kanvas",
|
||||
"cut": "Potong",
|
||||
"copy": "Salin",
|
||||
"copyAsPng": "Salin ke papan klip sebagai PNG",
|
||||
"copyAsSvg": "Salin ke papan klip sebagai SVG",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "Tepi",
|
||||
"sharp": "Tajam",
|
||||
"round": "Bulat",
|
||||
"arrowheads": "Mata panah",
|
||||
"arrowhead_none": "Tidak ada",
|
||||
"arrowhead_arrow": "Panah",
|
||||
"arrowhead_bar": "Batang",
|
||||
"arrowhead_dot": "Titik",
|
||||
"fontSize": "Ukuran font",
|
||||
"fontFamily": "Jenis font",
|
||||
"onlySelected": "Hanya yang Dipilih",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "Pisahkan pilihan",
|
||||
"collaborators": "Kolaborator",
|
||||
"toggleGridMode": "Aktifkan/Matikan mode kisi",
|
||||
"toggleStats": "Aktifkan statistik untuk nerd",
|
||||
"addToLibrary": "Tambahkan ke pustaka",
|
||||
"removeFromLibrary": "Hapus dari pustaka",
|
||||
"libraryLoadingMessage": "Memuat pustaka...",
|
||||
"libraries": "Telusur pustaka",
|
||||
"loadingScene": "Memuat pemandangan...",
|
||||
"align": "Perataan",
|
||||
"alignTop": "Rata atas",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "Tambahkan baris baru (teks)",
|
||||
"textFinish": "Selesai mengedit (teks)",
|
||||
"zoomToFit": "Perbesar agar sesuai dengan semua elemen",
|
||||
"zoomToSelection": "",
|
||||
"preventBinding": "Cegah pengikatan panah"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "Gambar anda terenkripsi end-to-end sehingga server Excalidraw tidak akan pernah dapat melihatnya."
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "Anda menempelkan sebuah lembar bentang tanpa sebuah kolom numerik.",
|
||||
"tooManyColumns": "Anda menempelkan sebuah lembar bentang dengan lebih dari dua kolom."
|
||||
"stats": {
|
||||
"angle": "Sudut",
|
||||
"element": "Elemen",
|
||||
"elements": "Elemen",
|
||||
"height": "Tinggi",
|
||||
"scene": "Pemandangan",
|
||||
"selected": "Terpilih",
|
||||
"storage": "Penyimpanan",
|
||||
"title": "Statistik untuk nerd",
|
||||
"total": "Total",
|
||||
"width": "Lebar"
|
||||
}
|
||||
}
|
||||
|
||||
+22
-5
@@ -4,6 +4,7 @@
|
||||
"selectAll": "Seleziona tutto",
|
||||
"multiSelect": "Aggiungi elemento alla selezione",
|
||||
"moveCanvas": "Sposta tela",
|
||||
"cut": "Taglia",
|
||||
"copy": "Copia",
|
||||
"copyAsPng": "Copia negli appunti come PNG",
|
||||
"copyAsSvg": "Copia negli appunti come SVG",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "Bordi",
|
||||
"sharp": "Acuto",
|
||||
"round": "Rotondo",
|
||||
"arrowheads": "Punta della freccia",
|
||||
"arrowhead_none": "Nessuno",
|
||||
"arrowhead_arrow": "Freccia",
|
||||
"arrowhead_bar": "Barra",
|
||||
"arrowhead_dot": "Punto",
|
||||
"fontSize": "Dimensione carattere",
|
||||
"fontFamily": "Carattere",
|
||||
"onlySelected": "Solo selezionati",
|
||||
@@ -70,10 +76,12 @@
|
||||
"group": "Crea gruppo da selezione",
|
||||
"ungroup": "Dividi gruppo da selezione",
|
||||
"collaborators": "Collaboratori",
|
||||
"toggleGridMode": "Attiva/disattiva modalità quadrícula",
|
||||
"toggleGridMode": "Attiva/disattiva modalità griglia",
|
||||
"toggleStats": "Attiva/disattiva statistiche per nerd",
|
||||
"addToLibrary": "Aggiungi alla biblioteca",
|
||||
"removeFromLibrary": "Rimuovi dalla biblioteca",
|
||||
"libraryLoadingMessage": "Caricamento della biblioteca...",
|
||||
"libraries": "Sfoglia librerie",
|
||||
"loadingScene": "Caricamento della scena...",
|
||||
"align": "Allinea",
|
||||
"alignTop": "Allinea in alto",
|
||||
@@ -116,7 +124,7 @@
|
||||
"exitZenMode": "Uscire dalla modalità zen"
|
||||
},
|
||||
"alerts": {
|
||||
"clearReset": "Questo cancellerà l'intera tela. Sei sicuro?",
|
||||
"clearReset": "Questa azione cancellerà l'intera tela. Sei sicuro?",
|
||||
"couldNotCreateShareableLink": "Non riesco a creare un link condivisibile.",
|
||||
"couldNotCreateShareableLinkTooBig": "Impossibile creare il link condivisibile: la scena è troppo grande",
|
||||
"couldNotLoadInvalidFile": "Impossibile caricare un file no valido",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "Aggiungi nuova riga (testo)",
|
||||
"textFinish": "Completa la modifica (testo)",
|
||||
"zoomToFit": "Adatta zoom per mostrare tutti gli elementi",
|
||||
"zoomToSelection": "Zoom alla selezione",
|
||||
"preventBinding": "Prevenire l'associazione freccia"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "I tuoi disegni sono crittografati end-to-end in modo che i server di Excalidraw non li possano mai vedere."
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "Hai incollato un foglio di calcolo senza una colonna numerica.",
|
||||
"tooManyColumns": "Hai incollato un foglio di calcolo con più di due colonne."
|
||||
"stats": {
|
||||
"angle": "Angolo",
|
||||
"element": "Elemento",
|
||||
"elements": "Elementi",
|
||||
"height": "Altezza",
|
||||
"scene": "Scena",
|
||||
"selected": "Selezionato",
|
||||
"storage": "Memoria",
|
||||
"title": "Statistiche per nerd",
|
||||
"total": "Totale",
|
||||
"width": "Larghezza"
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "すべて選択",
|
||||
"multiSelect": "複数選択",
|
||||
"moveCanvas": "キャンバスを移動",
|
||||
"cut": "",
|
||||
"copy": "コピー",
|
||||
"copyAsPng": "PNGとしてクリップボードへコピー",
|
||||
"copyAsSvg": "SVGとしてクリップボードへコピー",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "角",
|
||||
"sharp": "四角",
|
||||
"round": "丸",
|
||||
"arrowheads": "",
|
||||
"arrowhead_none": "",
|
||||
"arrowhead_arrow": "",
|
||||
"arrowhead_bar": "",
|
||||
"arrowhead_dot": "",
|
||||
"fontSize": "フォントの大きさ",
|
||||
"fontFamily": "フォントの種類",
|
||||
"onlySelected": "選択中のみ",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "グループ化を解除",
|
||||
"collaborators": "共同編集者",
|
||||
"toggleGridMode": "グリッドモードに切り替える",
|
||||
"toggleStats": "",
|
||||
"addToLibrary": "ライブラリに追加",
|
||||
"removeFromLibrary": "ライブラリから削除",
|
||||
"libraryLoadingMessage": "ライブラリを読み込み中...",
|
||||
"libraries": "",
|
||||
"loadingScene": "シーンを読み込み中...",
|
||||
"align": "整列",
|
||||
"alignTop": "上揃え",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "テキストの改行",
|
||||
"textFinish": "テキストの編集を終える",
|
||||
"zoomToFit": "すべての図形が収まるよう拡大/縮小",
|
||||
"zoomToSelection": "",
|
||||
"preventBinding": "矢印を結合しない"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "描画内容はエンドツーエンド暗号化が施されており、Excalidrawサーバーが内容を見ることはできません。"
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "数値の列が存在しないスプレッドシートをペーストしました。",
|
||||
"tooManyColumns": "2列以上のスプレッドシートを貼り付けました."
|
||||
"stats": {
|
||||
"angle": "",
|
||||
"element": "",
|
||||
"elements": "",
|
||||
"height": "",
|
||||
"scene": "",
|
||||
"selected": "",
|
||||
"storage": "",
|
||||
"title": "",
|
||||
"total": "",
|
||||
"width": ""
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "전체 선택",
|
||||
"multiSelect": "선택 영역에 추가하기",
|
||||
"moveCanvas": "캔버스 이동",
|
||||
"cut": "",
|
||||
"copy": "복사하기",
|
||||
"copyAsPng": "클립보드로 PNG 이미지 복사",
|
||||
"copyAsSvg": "클립보드로 SVG 이미지 복사",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "가장자리",
|
||||
"sharp": "선명하게",
|
||||
"round": "둥글게",
|
||||
"arrowheads": "",
|
||||
"arrowhead_none": "",
|
||||
"arrowhead_arrow": "",
|
||||
"arrowhead_bar": "",
|
||||
"arrowhead_dot": "",
|
||||
"fontSize": "폰트 크기",
|
||||
"fontFamily": "폰트 스타일",
|
||||
"onlySelected": "선택한 항목만",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "그룹 해제",
|
||||
"collaborators": "공동 작업자",
|
||||
"toggleGridMode": "격자 모드 켜기/끄기",
|
||||
"toggleStats": "",
|
||||
"addToLibrary": "라이브러리에 추가",
|
||||
"removeFromLibrary": "라이브러리에서 제거",
|
||||
"libraryLoadingMessage": "라이브러리 불러오는 중...",
|
||||
"libraries": "",
|
||||
"loadingScene": "화면 불러오는 중...",
|
||||
"align": "",
|
||||
"alignTop": "",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "줄바꾸기",
|
||||
"textFinish": "편집 완료",
|
||||
"zoomToFit": "",
|
||||
"zoomToSelection": "",
|
||||
"preventBinding": ""
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": ""
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "",
|
||||
"tooManyColumns": ""
|
||||
"stats": {
|
||||
"angle": "",
|
||||
"element": "",
|
||||
"elements": "",
|
||||
"height": "",
|
||||
"scene": "",
|
||||
"selected": "",
|
||||
"storage": "",
|
||||
"title": "",
|
||||
"total": "",
|
||||
"width": ""
|
||||
}
|
||||
}
|
||||
|
||||
+24
-7
@@ -4,6 +4,7 @@
|
||||
"selectAll": "အကုန်ရွေး",
|
||||
"multiSelect": "ရွေးထားသည့်ထဲပုံထည့်",
|
||||
"moveCanvas": "ကားချပ်ရွှေ့",
|
||||
"cut": "",
|
||||
"copy": "ကူး",
|
||||
"copyAsPng": "PNG အနေဖြင့်ကူး",
|
||||
"copyAsSvg": "SVG အနေဖြင့်ကူး",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "အစွန်း",
|
||||
"sharp": "ထောင့်ချွန်",
|
||||
"round": "ထောင့်ဝိုင်း",
|
||||
"arrowheads": "မြှားခေါင်း",
|
||||
"arrowhead_none": "ဘာမျှမရှိ",
|
||||
"arrowhead_arrow": "မြှား",
|
||||
"arrowhead_bar": "",
|
||||
"arrowhead_dot": "",
|
||||
"fontSize": "စာလုံးအရွယ်",
|
||||
"fontFamily": "စာလုံးပုံစံ",
|
||||
"onlySelected": "ရွေးထားသလောက်",
|
||||
@@ -54,7 +60,7 @@
|
||||
"architect": "ဗိသုကာ",
|
||||
"artist": "ပန်းချီ",
|
||||
"cartoonist": "ကာတွန်း",
|
||||
"fileTitle": "",
|
||||
"fileTitle": "ခေါင်းစဉ်",
|
||||
"colorPicker": "အရောင်ရွေး",
|
||||
"canvasBackground": "ကားချပ်နောက်ခံ",
|
||||
"drawingCanvas": "ပုံဆွဲကားချပ်",
|
||||
@@ -63,7 +69,7 @@
|
||||
"language": "ဘာသာစကား",
|
||||
"createRoom": "တိုက်ရိုက်ပူးပေါင်းဆောင်ရွက်ရန်အဖွဲ့ဖွဲ့",
|
||||
"duplicateSelection": "ပွား",
|
||||
"untitled": "",
|
||||
"untitled": "အမည်မရှိ",
|
||||
"name": "အမည်",
|
||||
"yourName": "သင့်အမည်",
|
||||
"madeWithExcalidraw": "Excalidraw ဖြင့်ဖန်တီးသည်။",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "အုပ်စုဖျက်သိမ်း",
|
||||
"collaborators": "ပူးပေါင်းပါဝင်သူများ",
|
||||
"toggleGridMode": "ဇယားကွက်ဖော်/ဖျောက်",
|
||||
"toggleStats": "",
|
||||
"addToLibrary": "မှတ်တမ်းတင်",
|
||||
"removeFromLibrary": "မှတ်တမ်းမှထုတ်",
|
||||
"libraryLoadingMessage": "မှတ်တမ်းအား တင်သွင်းနေသည်...",
|
||||
"libraries": "စာကြည့်တိုက်တွင်ရှာဖွေပါ",
|
||||
"loadingScene": "မြင်ကွင်းဖော်နေသည်...",
|
||||
"align": "ချိန်ညှိ",
|
||||
"alignTop": "ထိပ်ညှိ",
|
||||
@@ -82,8 +90,8 @@
|
||||
"alignRight": "ညာညှိ",
|
||||
"centerVertically": "ဒေါင်လိုက်အလယ်ညှိ",
|
||||
"centerHorizontally": "အလျားလိုက်အလယ်ညှိ",
|
||||
"distributeHorizontally": "",
|
||||
"distributeVertically": ""
|
||||
"distributeHorizontally": "အလျားလိုက်",
|
||||
"distributeVertically": "ထောင်လိုက်"
|
||||
},
|
||||
"buttons": {
|
||||
"clearReset": "ကားချပ်ရှင်းလင်း",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "စာသားဖြည့်သွင်း",
|
||||
"textFinish": "စာသားဖြည့်သွင်းပြီး",
|
||||
"zoomToFit": "ကားချပ်အပြည့်ဖေါ်",
|
||||
"zoomToSelection": "",
|
||||
"preventBinding": "မြှားများမပေါင်းစေရန်"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "ရေးဆွဲထားသောပုံများအား နှစ်ဘက်စွန်းတိုင်လျှို့ဝှက်ထားသဖြင့် Excalidraw ၏ဆာဗာများပင်လျှင်မြင်တွေ့ရမည်မဟုတ်ပါ။"
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "အမှတ်စဉ်ကော်လံမပါဝင်သောဇယားအားထည့်သွင်းလိုက်သည်။",
|
||||
"tooManyColumns": "ကော်လံနှစ်ခုထက်ပိုပါနေသောဇယားအားထည့်သွင်းလိုက်သည်။"
|
||||
"stats": {
|
||||
"angle": "ထောင့်",
|
||||
"element": "",
|
||||
"elements": "",
|
||||
"height": "အမြင့်",
|
||||
"scene": "မြင်ကွင်း",
|
||||
"selected": "ရွေးချယ်သည်",
|
||||
"storage": "သိုလှောင်ခန်း",
|
||||
"title": "အက္ခရာများအတွက်အချက်အလက်များ",
|
||||
"total": "စုစုပေါင်း",
|
||||
"width": "အကျယ်"
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "Velg alt",
|
||||
"multiSelect": "Legg til element i utvalg",
|
||||
"moveCanvas": "Flytt lerretet",
|
||||
"cut": "Klipp ut",
|
||||
"copy": "Kopier",
|
||||
"copyAsPng": "Kopier til PNG",
|
||||
"copyAsSvg": "Kopier til utklippstavlen som SVG",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "Kanter",
|
||||
"sharp": "Skarp",
|
||||
"round": "Rund",
|
||||
"arrowheads": "Pilspisser",
|
||||
"arrowhead_none": "Ingen",
|
||||
"arrowhead_arrow": "Pil",
|
||||
"arrowhead_bar": "Søyle",
|
||||
"arrowhead_dot": "Prikk",
|
||||
"fontSize": "Skriftstørrelse",
|
||||
"fontFamily": "Fontfamilie",
|
||||
"onlySelected": "Kun valgte",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "Avgruppér utvalg",
|
||||
"collaborators": "Samarbeidspartnere",
|
||||
"toggleGridMode": "Slå av/på rutenett",
|
||||
"toggleStats": "Skru av/på statistikk for nerder",
|
||||
"addToLibrary": "Legg til i bibliotek",
|
||||
"removeFromLibrary": "Fjern fra bibliotek",
|
||||
"libraryLoadingMessage": "Laster bibliotek...",
|
||||
"libraries": "Bla gjennom biblioteker",
|
||||
"loadingScene": "Laster inn scene...",
|
||||
"align": "Juster",
|
||||
"alignTop": "Juster øverst",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "Legg til ny linje (tekst)",
|
||||
"textFinish": "Fullfør redigering (tekst)",
|
||||
"zoomToFit": "Zoom for å passe alle elementene",
|
||||
"zoomToSelection": "Zoom til utvalg",
|
||||
"preventBinding": "Forhindre pilbinding"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "Dine tegninger er ende-til-ende-krypterte slik at Excalidraw sine servere aldri vil se dem."
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "Du limte inn et regneark uten en numerisk kolonne.",
|
||||
"tooManyColumns": "Du limte inn et regneark med mer enn to kolonner."
|
||||
"stats": {
|
||||
"angle": "Vinkel",
|
||||
"element": "Element",
|
||||
"elements": "Elementer",
|
||||
"height": "Høyde",
|
||||
"scene": "Scene",
|
||||
"selected": "Valgt",
|
||||
"storage": "Lagring",
|
||||
"title": "Statistikk for nerder",
|
||||
"total": "Totalt",
|
||||
"width": "Bredde"
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "Alles selecteren",
|
||||
"multiSelect": "Voeg element toe aan selectie",
|
||||
"moveCanvas": "Canvas verplaatsen",
|
||||
"cut": "",
|
||||
"copy": "Kopiëren",
|
||||
"copyAsPng": "Kopieer als PNG",
|
||||
"copyAsSvg": "Kopieer als SVG",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "Randen",
|
||||
"sharp": "Hoekig",
|
||||
"round": "Rond",
|
||||
"arrowheads": "",
|
||||
"arrowhead_none": "",
|
||||
"arrowhead_arrow": "",
|
||||
"arrowhead_bar": "",
|
||||
"arrowhead_dot": "",
|
||||
"fontSize": "Tekstgrootte",
|
||||
"fontFamily": "Lettertype",
|
||||
"onlySelected": "Enkel geselecteerde",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "Groep opheffen",
|
||||
"collaborators": "Deelnemers",
|
||||
"toggleGridMode": "Rasterlijnen in-/uitschakelen",
|
||||
"toggleStats": "",
|
||||
"addToLibrary": "Voeg toe aan bibliotheek",
|
||||
"removeFromLibrary": "Verwijder uit bibliotheek",
|
||||
"libraryLoadingMessage": "Bibliotheek laden...",
|
||||
"libraries": "",
|
||||
"loadingScene": "Scène laden...",
|
||||
"align": "",
|
||||
"alignTop": "",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "Nieuwe regel toevoegen (tekst)",
|
||||
"textFinish": "Voltooi bewerken (tekst)",
|
||||
"zoomToFit": "Zoom in op alle elementen",
|
||||
"zoomToSelection": "",
|
||||
"preventBinding": ""
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "Je tekeningen zijn beveiligd met end-to-end encryptie, dus Excalidraw's servers zullen nooit zien wat je tekent."
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "Je hebt een werkblad geplakt zonder een numerieke kolom.",
|
||||
"tooManyColumns": "Je hebt een werkblad geplakt met meer dan twee kolommen."
|
||||
"stats": {
|
||||
"angle": "",
|
||||
"element": "",
|
||||
"elements": "",
|
||||
"height": "",
|
||||
"scene": "",
|
||||
"selected": "",
|
||||
"storage": "",
|
||||
"title": "",
|
||||
"total": "",
|
||||
"width": ""
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "Vel alt",
|
||||
"multiSelect": "Legg til element i utval",
|
||||
"moveCanvas": "Flytt lerretet",
|
||||
"cut": "",
|
||||
"copy": "Kopier",
|
||||
"copyAsPng": "Kopier til utklippstavla som PNG",
|
||||
"copyAsSvg": "Kopier til utklippstavla som SVG",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "Kanter",
|
||||
"sharp": "Skarp",
|
||||
"round": "Rund",
|
||||
"arrowheads": "",
|
||||
"arrowhead_none": "",
|
||||
"arrowhead_arrow": "",
|
||||
"arrowhead_bar": "",
|
||||
"arrowhead_dot": "",
|
||||
"fontSize": "Skriftstorleik",
|
||||
"fontFamily": "Skrifttype",
|
||||
"onlySelected": "Kun valde",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "Avgrupper utval",
|
||||
"collaborators": "Samarbeidarar",
|
||||
"toggleGridMode": "Sla på/av rutenett",
|
||||
"toggleStats": "",
|
||||
"addToLibrary": "Legg til i bibliotek",
|
||||
"removeFromLibrary": "Fjern frå bibliotek",
|
||||
"libraryLoadingMessage": "Laster bibliotek...",
|
||||
"libraries": "",
|
||||
"loadingScene": "Laster scene...",
|
||||
"align": "",
|
||||
"alignTop": "",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "Legg til ny linje (tekst)",
|
||||
"textFinish": "Fullfør redigering (tekst)",
|
||||
"zoomToFit": "Zoom for å sjå alle elementa",
|
||||
"zoomToSelection": "",
|
||||
"preventBinding": "Hindre pilkobling"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "Teikningane dine er ende-til-ende-krypterte slik at Excalidraw sine serverar aldri får sjå dei."
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "Du limte inn eit rekneark utan ei numerisk kolonne.",
|
||||
"tooManyColumns": "Du limte inn eit rekneark med meir enn to kolonnar."
|
||||
"stats": {
|
||||
"angle": "",
|
||||
"element": "",
|
||||
"elements": "",
|
||||
"height": "",
|
||||
"scene": "",
|
||||
"selected": "",
|
||||
"storage": "",
|
||||
"title": "",
|
||||
"total": "",
|
||||
"width": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
{
|
||||
"ar-SA": 98,
|
||||
"bg-BG": 67,
|
||||
"ca-ES": 89,
|
||||
"de-DE": 100,
|
||||
"el-GR": 96,
|
||||
"ar-SA": 89,
|
||||
"bg-BG": 61,
|
||||
"ca-ES": 81,
|
||||
"de-DE": 99,
|
||||
"el-GR": 95,
|
||||
"en": 100,
|
||||
"es-ES": 89,
|
||||
"fa-IR": 98,
|
||||
"es-ES": 81,
|
||||
"fa-IR": 89,
|
||||
"fi-FI": 100,
|
||||
"fr-FR": 100,
|
||||
"he-IL": 76,
|
||||
"hi-IN": 85,
|
||||
"hu-HU": 48,
|
||||
"id-ID": 100,
|
||||
"he-IL": 69,
|
||||
"hi-IN": 82,
|
||||
"hu-HU": 44,
|
||||
"id-ID": 99,
|
||||
"it-IT": 100,
|
||||
"ja-JP": 98,
|
||||
"ko-KR": 75,
|
||||
"my-MM": 97,
|
||||
"ja-JP": 89,
|
||||
"ko-KR": 68,
|
||||
"my-MM": 96,
|
||||
"nb-NO": 100,
|
||||
"nl-NL": 88,
|
||||
"nn-NO": 89,
|
||||
"pl-PL": 88,
|
||||
"pt-PT": 92,
|
||||
"nl-NL": 80,
|
||||
"nn-NO": 80,
|
||||
"pl-PL": 79,
|
||||
"pt-PT": 83,
|
||||
"ro-RO": 100,
|
||||
"ru-RU": 85,
|
||||
"ru-RU": 81,
|
||||
"sk-SK": 100,
|
||||
"sv-SE": 100,
|
||||
"tr-TR": 90,
|
||||
"uk-UA": 100,
|
||||
"zh-CN": 100,
|
||||
"zh-TW": 100
|
||||
"tr-TR": 81,
|
||||
"uk-UA": 98,
|
||||
"zh-CN": 95,
|
||||
"zh-TW": 99
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "Zaznacz wszystko",
|
||||
"multiSelect": "Dodaj element do zaznaczenia",
|
||||
"moveCanvas": "Przesuń obszar roboczy",
|
||||
"cut": "",
|
||||
"copy": "Kopiuj",
|
||||
"copyAsPng": "Skopiuj do schowka jako plik PNG",
|
||||
"copyAsSvg": "Skopiuj do schowka jako plik SVG",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "Krawędzie",
|
||||
"sharp": "Ostry",
|
||||
"round": "Zaokrąglij",
|
||||
"arrowheads": "",
|
||||
"arrowhead_none": "",
|
||||
"arrowhead_arrow": "",
|
||||
"arrowhead_bar": "",
|
||||
"arrowhead_dot": "",
|
||||
"fontSize": "Rozmiar tekstu",
|
||||
"fontFamily": "Krój pisma",
|
||||
"onlySelected": "Tylko wybrane",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "Rozgrupuj wybrane",
|
||||
"collaborators": "Współtwórcy",
|
||||
"toggleGridMode": "Włącz siatkę",
|
||||
"toggleStats": "",
|
||||
"addToLibrary": "Dodaj do biblioteki",
|
||||
"removeFromLibrary": "Usuń z biblioteki",
|
||||
"libraryLoadingMessage": "Wczytywanie biblioteki...",
|
||||
"libraries": "",
|
||||
"loadingScene": "Ładowanie sceny...",
|
||||
"align": "",
|
||||
"alignTop": "",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "Dodaj nową linię (tekst)",
|
||||
"textFinish": "Zakończ edycję (tekst)",
|
||||
"zoomToFit": "Powiększ, aby wyświetlić wszystkie elementy",
|
||||
"zoomToSelection": "",
|
||||
"preventBinding": "Zablokuj przywiązanie strzałek do obiektu"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "Twoje rysunki są zabezpieczone szyfrowaniem end-to-end, tak więc nawet w Excalidraw nie jesteśmy w stanie zobaczyć tego co tworzysz."
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "Wklejono arkusz kalkulacyjny bez kolumny numerycznej.",
|
||||
"tooManyColumns": "Wklejono arkusz kalkulacyjny z więcej niż dwoma kolumnami."
|
||||
"stats": {
|
||||
"angle": "",
|
||||
"element": "",
|
||||
"elements": "",
|
||||
"height": "",
|
||||
"scene": "",
|
||||
"selected": "",
|
||||
"storage": "",
|
||||
"title": "",
|
||||
"total": "",
|
||||
"width": ""
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "Selecionar tudo",
|
||||
"multiSelect": "Adicionar elemento à seleção",
|
||||
"moveCanvas": "Mover tela",
|
||||
"cut": "",
|
||||
"copy": "Copiar",
|
||||
"copyAsPng": "Copiar para a área de transferência como PNG",
|
||||
"copyAsSvg": "Copiar para a área de transferência como SVG",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "Arestas",
|
||||
"sharp": "Aguçado",
|
||||
"round": "Redondo",
|
||||
"arrowheads": "",
|
||||
"arrowhead_none": "",
|
||||
"arrowhead_arrow": "",
|
||||
"arrowhead_bar": "",
|
||||
"arrowhead_dot": "",
|
||||
"fontSize": "Tamanho da fonte",
|
||||
"fontFamily": "Família da fontes",
|
||||
"onlySelected": "Somente a seleção",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "Desagrupar seleção",
|
||||
"collaborators": "Colaboradores",
|
||||
"toggleGridMode": "Alternar modo de grade",
|
||||
"toggleStats": "",
|
||||
"addToLibrary": "Adicionar à biblioteca",
|
||||
"removeFromLibrary": "Remover da biblioteca",
|
||||
"libraryLoadingMessage": "Carregando biblioteca...",
|
||||
"libraries": "",
|
||||
"loadingScene": "Carregando cena...",
|
||||
"align": "",
|
||||
"alignTop": "",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "Adicionar nova linha (texto)",
|
||||
"textFinish": "Finalizar edição (texto)",
|
||||
"zoomToFit": "Ajustar para caber todos os elementos",
|
||||
"zoomToSelection": "",
|
||||
"preventBinding": "Prevenir fixação de seta"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "Seus desenhos são criptografados de ponta a ponta, então os servidores do Excalidraw nunca os verão."
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "Você colou uma planilha sem uma coluna numérica.",
|
||||
"tooManyColumns": "Você colou uma planilha com mais de duas colunas."
|
||||
"stats": {
|
||||
"angle": "",
|
||||
"element": "",
|
||||
"elements": "",
|
||||
"height": "",
|
||||
"scene": "",
|
||||
"selected": "",
|
||||
"storage": "",
|
||||
"title": "",
|
||||
"total": "",
|
||||
"width": ""
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "Selectare totală",
|
||||
"multiSelect": "Adaugă element la selecție",
|
||||
"moveCanvas": "Mutare pânză",
|
||||
"cut": "Decupare",
|
||||
"copy": "Copiere",
|
||||
"copyAsPng": "Copiere în memoria temporară ca PNG",
|
||||
"copyAsSvg": "Copiere în memoria temporară ca SVG",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "Margini",
|
||||
"sharp": "Ascuțite",
|
||||
"round": "Rotunde",
|
||||
"arrowheads": "Vârfuri de săgeată",
|
||||
"arrowhead_none": "Niciunul",
|
||||
"arrowhead_arrow": "Săgeată",
|
||||
"arrowhead_bar": "Bară",
|
||||
"arrowhead_dot": "Bulină",
|
||||
"fontSize": "Dimensiune font",
|
||||
"fontFamily": "Familia de fonturi",
|
||||
"onlySelected": "Numai selecția",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "Degrupare selecție",
|
||||
"collaborators": "Colaboratori",
|
||||
"toggleGridMode": "Comută modul grilă",
|
||||
"toggleStats": "Comută statisticile pentru pasionați",
|
||||
"addToLibrary": "Adăugare la bibliotecă",
|
||||
"removeFromLibrary": "Eliminare din bibliotecă",
|
||||
"libraryLoadingMessage": "Se încarcă biblioteca...",
|
||||
"libraries": "Răsfoiește bibliotecile",
|
||||
"loadingScene": "Se încarcă scena...",
|
||||
"align": "Aliniere",
|
||||
"alignTop": "Aliniere sus",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "Adaugă o linie nouă (text)",
|
||||
"textFinish": "Finalizează editarea (text)",
|
||||
"zoomToFit": "Apropiere/depărtare pentru a cuprinde totul",
|
||||
"zoomToSelection": "Panoramare la selecție",
|
||||
"preventBinding": "Împiedică legarea săgeții"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "Desenele tale sunt criptate integral, astfel că serverele Excalidraw nu le vor vedea niciodată."
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "Ai inserat o foaie de calcul fără o coloană numerică.",
|
||||
"tooManyColumns": "Ai inserat o foaie de calcul cu mai mult de două coloane."
|
||||
"stats": {
|
||||
"angle": "Unghi",
|
||||
"element": "Element",
|
||||
"elements": "Elemente",
|
||||
"height": "Înălțime",
|
||||
"scene": "Scenă",
|
||||
"selected": "Selectate",
|
||||
"storage": "Stocare",
|
||||
"title": "Statistici pentru pasionați",
|
||||
"total": "Total",
|
||||
"width": "Lățime"
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "Выбрать все",
|
||||
"multiSelect": "Добавить элемент к выбору",
|
||||
"moveCanvas": "Переместить холст",
|
||||
"cut": "",
|
||||
"copy": "Копировать",
|
||||
"copyAsPng": "Скопировать в буфер обмена как PNG",
|
||||
"copyAsSvg": "Скопировать в буфер обмена как SVG",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "Края",
|
||||
"sharp": "Острые",
|
||||
"round": "Скругленные",
|
||||
"arrowheads": "",
|
||||
"arrowhead_none": "",
|
||||
"arrowhead_arrow": "Cтрелка",
|
||||
"arrowhead_bar": "",
|
||||
"arrowhead_dot": "Точка",
|
||||
"fontSize": "Размер шрифта",
|
||||
"fontFamily": "Семейство шрифтов",
|
||||
"onlySelected": "Только выбранные",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "Разделить выделение",
|
||||
"collaborators": "Сотрудники",
|
||||
"toggleGridMode": "Переключить режим сетки",
|
||||
"toggleStats": "",
|
||||
"addToLibrary": "Добавить в библиотеку",
|
||||
"removeFromLibrary": "Удалить из библиотеки",
|
||||
"libraryLoadingMessage": "Загрузка библиотеки...",
|
||||
"libraries": "",
|
||||
"loadingScene": "Загрузка сцены...",
|
||||
"align": "",
|
||||
"alignTop": "",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "Добавить новую строку (текст)",
|
||||
"textFinish": "Закончить редактирование (текст)",
|
||||
"zoomToFit": "",
|
||||
"zoomToSelection": "",
|
||||
"preventBinding": "Предотвратить привязку стрелок"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": ""
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "",
|
||||
"tooManyColumns": "Вы вставили таблицу с более чем двумя столбцами."
|
||||
"stats": {
|
||||
"angle": "Угол",
|
||||
"element": "Элемент",
|
||||
"elements": "Элементы",
|
||||
"height": "Высота",
|
||||
"scene": "",
|
||||
"selected": "",
|
||||
"storage": "",
|
||||
"title": "",
|
||||
"total": "",
|
||||
"width": "Ширина"
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "Vybrať všetko",
|
||||
"multiSelect": "Pridať prvok do výberu",
|
||||
"moveCanvas": "Pohyb plátna",
|
||||
"cut": "Vystrihnúť",
|
||||
"copy": "Kopírovať",
|
||||
"copyAsPng": "Kopírovať do schránky ako PNG",
|
||||
"copyAsSvg": "Kopírovať do schránky ako SVG",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "Okraje",
|
||||
"sharp": "Ostré",
|
||||
"round": "Zaokrúhlené",
|
||||
"arrowheads": "Zakončenie šípky",
|
||||
"arrowhead_none": "Žiadne",
|
||||
"arrowhead_arrow": "Šípka",
|
||||
"arrowhead_bar": "Čiara",
|
||||
"arrowhead_dot": "Bod",
|
||||
"fontSize": "Veľkosť písma",
|
||||
"fontFamily": "Písmo",
|
||||
"onlySelected": "Iba vybrané",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "Zrušiť zoskupenie",
|
||||
"collaborators": "Spolupracovníci",
|
||||
"toggleGridMode": "Prepnúť mriežku",
|
||||
"toggleStats": "Prepnúť štatistiky",
|
||||
"addToLibrary": "Pridať do knižnice",
|
||||
"removeFromLibrary": "Odstrániť z knižnice",
|
||||
"libraryLoadingMessage": "Načítavanie knižnice...",
|
||||
"libraries": "Prehliadať knižnice",
|
||||
"loadingScene": "Načítavanie scény...",
|
||||
"align": "Zarovnanie",
|
||||
"alignTop": "Zarovnať nahor",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "Vložiť nový riadok (text)",
|
||||
"textFinish": "Ukončenie editovania (text)",
|
||||
"zoomToFit": "Priblížiť aby boli zahrnuté všetky prvky",
|
||||
"zoomToSelection": "Priblížiť na výber",
|
||||
"preventBinding": "Zakázať pripájanie šípky"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "Vaše kresby používajú end-to-end šifrovanie, takže ich Excalidraw server nedokáže prečítať."
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "Prilepili ste tabuľku bez číselného stĺpca.",
|
||||
"tooManyColumns": "Prilepili ste tabuľku s viac ako dvoma stĺpcami."
|
||||
"stats": {
|
||||
"angle": "Uhol",
|
||||
"element": "Prvok",
|
||||
"elements": "Prvky",
|
||||
"height": "Výška",
|
||||
"scene": "Scéna",
|
||||
"selected": "Vybrané",
|
||||
"storage": "Úložisko",
|
||||
"title": "Štatistiky",
|
||||
"total": "Celkom",
|
||||
"width": "Šírka"
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "Markera alla",
|
||||
"multiSelect": "Lägg till element till markering",
|
||||
"moveCanvas": "Flytta canvas",
|
||||
"cut": "Klipp ut",
|
||||
"copy": "Kopiera",
|
||||
"copyAsPng": "Kopiera till urklipp som PNG",
|
||||
"copyAsSvg": "Kopiera till urklipp som SVG",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "Kanter",
|
||||
"sharp": "Skarp",
|
||||
"round": "Rund",
|
||||
"arrowheads": "Pilhuvuden",
|
||||
"arrowhead_none": "Inga",
|
||||
"arrowhead_arrow": "Pil",
|
||||
"arrowhead_bar": "Stolpe",
|
||||
"arrowhead_dot": "Punkt",
|
||||
"fontSize": "Teckenstorlek",
|
||||
"fontFamily": "Teckensnitt",
|
||||
"onlySelected": "Endast markering",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "Avgruppera markering",
|
||||
"collaborators": "Medarbetare",
|
||||
"toggleGridMode": "Växla rutnätsläge",
|
||||
"toggleStats": "Visa/dölj statistik för nördar",
|
||||
"addToLibrary": "Lägg till i biblioteket",
|
||||
"removeFromLibrary": "Ta bort från bibliotek",
|
||||
"libraryLoadingMessage": "Laddar bibliotek...",
|
||||
"libraries": "Bläddra i bibliotek",
|
||||
"loadingScene": "Laddar scen...",
|
||||
"align": "Justera",
|
||||
"alignTop": "Justera överkant",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "Lägg till ny rad (text)",
|
||||
"textFinish": "Slutför redigering (text)",
|
||||
"zoomToFit": "Zooma för att rymma alla element",
|
||||
"zoomToSelection": "Zooma till markering",
|
||||
"preventBinding": "Förhindra pilbindning"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "Dina skisser är krypterade från ände till ände så Excalidraws servrar kommer aldrig att se dem."
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "Du klistrade in ett kalkylblad utan en numerisk kolumn.",
|
||||
"tooManyColumns": "Du klistrade in ett kalkylblad med mer än två kolumner."
|
||||
"stats": {
|
||||
"angle": "Vinkel",
|
||||
"element": "Element",
|
||||
"elements": "Element",
|
||||
"height": "Höjd",
|
||||
"scene": "Skiss",
|
||||
"selected": "Valda",
|
||||
"storage": "Lagring",
|
||||
"title": "Statistik för nördar",
|
||||
"total": "Totalt",
|
||||
"width": "Bredd"
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "Tümünü seç",
|
||||
"multiSelect": "Seçime öge ekle",
|
||||
"moveCanvas": "Tuvali taşı",
|
||||
"cut": "",
|
||||
"copy": "Kopyala",
|
||||
"copyAsPng": "Panoya PNG olarak kopyala",
|
||||
"copyAsSvg": "Panoya SVG olarak kopyala",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "Kenarlar",
|
||||
"sharp": "Keskin",
|
||||
"round": "Yuvarlak",
|
||||
"arrowheads": "",
|
||||
"arrowhead_none": "",
|
||||
"arrowhead_arrow": "",
|
||||
"arrowhead_bar": "",
|
||||
"arrowhead_dot": "",
|
||||
"fontSize": "Yazı tipi boyutu",
|
||||
"fontFamily": "Yazı tipi ailesi",
|
||||
"onlySelected": "Sadece seçilen",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "Seçilen grubu dağıt",
|
||||
"collaborators": "Ortaklar",
|
||||
"toggleGridMode": "Izgara modunu aç",
|
||||
"toggleStats": "",
|
||||
"addToLibrary": "Kütüphaneye ekle",
|
||||
"removeFromLibrary": "Kütüphaneden kaldır",
|
||||
"libraryLoadingMessage": "Kütüphane yükleniyor...",
|
||||
"libraries": "",
|
||||
"loadingScene": "Çalışma alanı yükleniyor...",
|
||||
"align": "",
|
||||
"alignTop": "",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "Yeni satır ekle (yazı)",
|
||||
"textFinish": "(Yazıyı) düzenlemeyi bitir",
|
||||
"zoomToFit": "Tüm öğeleri sığdırmak için yakınlaştır",
|
||||
"zoomToSelection": "",
|
||||
"preventBinding": "Ok bağlamayı önleyin"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "Çizimleriniz uçtan-uca şifrelenmiştir, Excalidraw'ın sunucuları bile onları göremez."
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "Sayısal sütunu olmayan bir tablo yapıştırdın.",
|
||||
"tooManyColumns": "İkiden daha fazla sütuna sahip bir tablo yapıştırdın."
|
||||
"stats": {
|
||||
"angle": "",
|
||||
"element": "",
|
||||
"elements": "",
|
||||
"height": "",
|
||||
"scene": "",
|
||||
"selected": "",
|
||||
"storage": "",
|
||||
"title": "",
|
||||
"total": "",
|
||||
"width": ""
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "Вибрати все",
|
||||
"multiSelect": "Додати елемент до вибраного",
|
||||
"moveCanvas": "Перемістити полотно",
|
||||
"cut": "Вирізати",
|
||||
"copy": "Копіювати",
|
||||
"copyAsPng": "Копіювати як PNG",
|
||||
"copyAsSvg": "Копіювати як SVG",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "Краї",
|
||||
"sharp": "Гострі",
|
||||
"round": "Круглі",
|
||||
"arrowheads": "",
|
||||
"arrowhead_none": "Жоден",
|
||||
"arrowhead_arrow": "Стрілка",
|
||||
"arrowhead_bar": "Колона",
|
||||
"arrowhead_dot": "Точка",
|
||||
"fontSize": "Розмір шрифту",
|
||||
"fontFamily": "Шрифт",
|
||||
"onlySelected": "Тільки вибране",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "Розгрупувати виділене",
|
||||
"collaborators": "Співавтори",
|
||||
"toggleGridMode": "Режим сітки",
|
||||
"toggleStats": "",
|
||||
"addToLibrary": "Додати до бібліотеки",
|
||||
"removeFromLibrary": "Видалити з бібліотеки",
|
||||
"libraryLoadingMessage": "Завантажити бібліотеку...",
|
||||
"libraries": "Огляд бібліотек",
|
||||
"loadingScene": "Завантаження сцени...",
|
||||
"align": "Вирівнювання",
|
||||
"alignTop": "Вирівняти по верхньому краю",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "Додати новий рядок (текст)",
|
||||
"textFinish": "Завершити редагування (текст)",
|
||||
"zoomToFit": "Збільшити щоб умістити все",
|
||||
"zoomToSelection": "Перейти до виділеного",
|
||||
"preventBinding": "Запобігти зв'язування зі стрілками"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "Ваші креслення захищені наскрізним шифруванням — сервери Excalidraw ніколи їх не побачать."
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "Ви вставили таблицю без числової колонки.",
|
||||
"tooManyColumns": "Ви вставляли таблицю з більш ніж двома колонками."
|
||||
"stats": {
|
||||
"angle": "Кут",
|
||||
"element": "Елемент",
|
||||
"elements": "Елементи",
|
||||
"height": "Висота",
|
||||
"scene": "Сцена",
|
||||
"selected": "Вибраний",
|
||||
"storage": "Сховище",
|
||||
"title": "",
|
||||
"total": "Всього",
|
||||
"width": "Ширина"
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "全部选中",
|
||||
"multiSelect": "添加元素到选区",
|
||||
"moveCanvas": "移动画布",
|
||||
"cut": "",
|
||||
"copy": "复制",
|
||||
"copyAsPng": "复制为 PNG 到剪贴板",
|
||||
"copyAsSvg": "复制为 SVG 到剪贴板",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "边角",
|
||||
"sharp": "尖锐",
|
||||
"round": "圆润",
|
||||
"arrowheads": "",
|
||||
"arrowhead_none": "",
|
||||
"arrowhead_arrow": "",
|
||||
"arrowhead_bar": "",
|
||||
"arrowhead_dot": "",
|
||||
"fontSize": "字体大小",
|
||||
"fontFamily": "字体",
|
||||
"onlySelected": "仅被选中",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "取消组选",
|
||||
"collaborators": "协作者",
|
||||
"toggleGridMode": "切换网格模式",
|
||||
"toggleStats": "",
|
||||
"addToLibrary": "添加到库中",
|
||||
"removeFromLibrary": "从库中移除",
|
||||
"libraryLoadingMessage": "正在加载库...",
|
||||
"libraries": "",
|
||||
"loadingScene": "正在加载绘图...",
|
||||
"align": "对齐",
|
||||
"alignTop": "顶部对齐",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "文本换行",
|
||||
"textFinish": "完成编辑文本",
|
||||
"zoomToFit": "缩放以适应所有元素",
|
||||
"zoomToSelection": "缩放至选择部分",
|
||||
"preventBinding": "防止箭头吸附"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "您的绘图采用的端到端加密,因此Excalidraw服务器永远不会收集。"
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "您粘贴了一个没有数字列的表格。",
|
||||
"tooManyColumns": "您粘贴了两列以上的表格。"
|
||||
"stats": {
|
||||
"angle": "角度",
|
||||
"element": "元素",
|
||||
"elements": "元素",
|
||||
"height": "高度",
|
||||
"scene": "场景",
|
||||
"selected": "选中",
|
||||
"storage": "存储",
|
||||
"title": "",
|
||||
"total": "总计",
|
||||
"width": "宽度"
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -4,6 +4,7 @@
|
||||
"selectAll": "全選",
|
||||
"multiSelect": "將物件加入選取範圍",
|
||||
"moveCanvas": "移動畫布",
|
||||
"cut": "剪下",
|
||||
"copy": "複製",
|
||||
"copyAsPng": "複製 PNG 至剪貼簿",
|
||||
"copyAsSvg": "複製 SVG 至剪貼簿",
|
||||
@@ -28,6 +29,11 @@
|
||||
"edges": "邊緣",
|
||||
"sharp": "尖銳",
|
||||
"round": "平滑",
|
||||
"arrowheads": "箭頭",
|
||||
"arrowhead_none": "無",
|
||||
"arrowhead_arrow": "箭頭",
|
||||
"arrowhead_bar": "塊",
|
||||
"arrowhead_dot": "點",
|
||||
"fontSize": "字型大小",
|
||||
"fontFamily": "字體",
|
||||
"onlySelected": "僅選取物件",
|
||||
@@ -71,9 +77,11 @@
|
||||
"ungroup": "取消群組",
|
||||
"collaborators": "協作者",
|
||||
"toggleGridMode": "切換格線模式",
|
||||
"toggleStats": "切換詳細統計",
|
||||
"addToLibrary": "加入資料庫",
|
||||
"removeFromLibrary": "從資料庫中移除",
|
||||
"libraryLoadingMessage": "資料庫讀取中…",
|
||||
"libraries": "",
|
||||
"loadingScene": "場景讀取中…",
|
||||
"align": "對齊",
|
||||
"alignTop": "對齊頂部",
|
||||
@@ -205,13 +213,22 @@
|
||||
"textNewLine": "換行(文字)",
|
||||
"textFinish": "完成編輯(文字)",
|
||||
"zoomToFit": "放大至填滿畫面",
|
||||
"zoomToSelection": "縮放至選取區",
|
||||
"preventBinding": "防止箭頭綁定"
|
||||
},
|
||||
"encrypted": {
|
||||
"tooltip": "你的作品已使用 end-to-end 方式加密,Excalidraw 的伺服器也無法取得其內容。"
|
||||
},
|
||||
"charts": {
|
||||
"noNumericColumn": "你貼上的 spreadsheet 沒有數字欄。",
|
||||
"tooManyColumns": "你貼上的 spreadsheet 超過兩欄。"
|
||||
"stats": {
|
||||
"angle": "角度",
|
||||
"element": "元素",
|
||||
"elements": "元素",
|
||||
"height": "高度",
|
||||
"scene": "場景",
|
||||
"selected": "已選",
|
||||
"storage": "儲存",
|
||||
"title": "詳細統計",
|
||||
"total": "合計",
|
||||
"width": "寬度"
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
import { Point } from "./types";
|
||||
import { LINE_CONFIRM_THRESHOLD } from "./constants";
|
||||
import { GRID_SIZE, LINE_CONFIRM_THRESHOLD } from "./constants";
|
||||
import { ExcalidrawLinearElement } from "./element/types";
|
||||
|
||||
export const rotate = (
|
||||
@@ -307,12 +307,12 @@ const doSegmentsIntersect = (p1: Point, q1: Point, p2: Point, q2: Point) => {
|
||||
export const getGridPoint = (
|
||||
x: number,
|
||||
y: number,
|
||||
gridSize: number | null,
|
||||
isGridOn: boolean,
|
||||
): [number, number] => {
|
||||
if (gridSize) {
|
||||
if (isGridOn) {
|
||||
return [
|
||||
Math.round(x / gridSize) * gridSize,
|
||||
Math.round(y / gridSize) * gridSize,
|
||||
Math.round(x / GRID_SIZE) * GRID_SIZE,
|
||||
Math.round(y / GRID_SIZE) * GRID_SIZE,
|
||||
];
|
||||
}
|
||||
return [x, y];
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
# Changelog
|
||||
|
||||
## 0.1.0
|
||||
|
||||
First release of `@excalidraw/excalidraw`
|
||||
|
||||
## 0.1.1
|
||||
|
||||
#### Fix
|
||||
- Update the homepage URL so it redirects to correct readme [#2498](https://github.com/excalidraw/excalidraw/pull/2498)
|
||||
@@ -0,0 +1,62 @@
|
||||
# Changelog
|
||||
|
||||
<!--
|
||||
Guidelines for changelog:
|
||||
The change should be grouped under one of the below section and must contain PR link.
|
||||
- Features: For new features.
|
||||
- Fixes: For bug fixes.
|
||||
- Chore: Changes for non src files example package.json.
|
||||
- Improvements: For any improvements.
|
||||
- Refactor: For any refactoring.
|
||||
|
||||
Please add the latest change on the top under the correct section.
|
||||
-->
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Features
|
||||
|
||||
- Add support for `exportToBackend` prop to allow host apps to implement shareable links [#2612](https://github.com/excalidraw/excalidraw/pull/2612/files)
|
||||
- Add zoom to selection [#2522](https://github.com/excalidraw/excalidraw/pull/2522)
|
||||
- Insert Library items in the middle of the screen [#2527](https://github.com/excalidraw/excalidraw/pull/2527)
|
||||
- Show shortcut context menu [#2501](https://github.com/excalidraw/excalidraw/pull/2501)
|
||||
- Aligns arrowhead schemas [#2517](https://github.com/excalidraw/excalidraw/pull/2517)
|
||||
- Add Cut to menus [#2511](https://github.com/excalidraw/excalidraw/pull/2511)
|
||||
- More Arrowheads: dot, bar [#2486](https://github.com/excalidraw/excalidraw/pull/2486)
|
||||
- Support CSV graphs and improve the look and feel [#2495](https://github.com/excalidraw/excalidraw/pull/2495)
|
||||
|
||||
### Fixes
|
||||
|
||||
- Consistent case for export locale strings [#2622](https://github.com/excalidraw/excalidraw/pull/2622)
|
||||
- Remove unnecessary console.error as it was polluting Sentry [#2637](https://github.com/excalidraw/excalidraw/pull/2637)
|
||||
- Fix scroll-to-center on init for non-zero canvas offsets [#2445](https://github.com/excalidraw/excalidraw/pull/2445)
|
||||
- Hide collab button when onCollabButtonClick not supplied [#2598](https://github.com/excalidraw/excalidraw/pull/2598)
|
||||
- Fix resizing the pasted charts [#2586](https://github.com/excalidraw/excalidraw/pull/2586)
|
||||
- Fix element visibility and zoom on cursor when canvas offset isn't 0. [#2534](https://github.com/excalidraw/excalidraw/pull/2534)
|
||||
- Fix Library Menu Layout [#2502](https://github.com/excalidraw/excalidraw/pull/2502)
|
||||
- Support number with commas in charts [#2636](https://github.com/excalidraw/excalidraw/pull/2636)
|
||||
- Don't break zoom when zooming in on UI [#2638](https://github.com/excalidraw/excalidraw/pull/2638)
|
||||
|
||||
### Improvements
|
||||
|
||||
- Display proper tooltip for 2-point lines during resize, and normalize modifier key labels in hints [#2655](https://github.com/excalidraw/excalidraw/pull/2655)
|
||||
- Improve error message around importing images [#2619](https://github.com/excalidraw/excalidraw/pull/2619)
|
||||
- Add tooltip with icon for embedding scenes [#2532](https://github.com/excalidraw/excalidraw/pull/2532)
|
||||
- RTL support for the stats dialog [#2530](https://github.com/excalidraw/excalidraw/pull/2530)
|
||||
- Expand canvas padding based on zoom. [#2515](https://github.com/excalidraw/excalidraw/pull/2515)
|
||||
- Hide shortcuts on pickers for mobile [#2508](https://github.com/excalidraw/excalidraw/pull/2508)
|
||||
- Hide stats and scrollToContent-button when mobile menus open [#2509](https://github.com/excalidraw/excalidraw/pull/2509)
|
||||
|
||||
### Chore
|
||||
|
||||
- Bump ini from 1.3.5 to 1.3.7 in /src/packages/excalidraw [#2500](https://github.com/excalidraw/excalidraw/pull/2500)
|
||||
|
||||
## 0.1.1
|
||||
|
||||
#### Fix
|
||||
|
||||
- Update the homepage URL so it redirects to correct readme [#2498](https://github.com/excalidraw/excalidraw/pull/2498)
|
||||
|
||||
## 0.1.0
|
||||
|
||||
First release of `@excalidraw/excalidraw`
|
||||
@@ -39,26 +39,19 @@ import "./styles.css";
|
||||
export default function App() {
|
||||
const excalidrawRef = createRef();
|
||||
|
||||
const onChange = (elements, state) => {
|
||||
console.log(excalidrawRef.current);
|
||||
console.log("Elements :", elements, "State : ", state);
|
||||
};
|
||||
|
||||
const [dimensions, setDimensions] = useState({
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight,
|
||||
});
|
||||
|
||||
const onResize = () => {
|
||||
setDimensions({
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight,
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const onResize = () => {
|
||||
setDimensions({
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight,
|
||||
});
|
||||
};
|
||||
window.addEventListener("resize", onResize);
|
||||
|
||||
return () => window.removeEventListener("resize", onResize);
|
||||
}, []);
|
||||
|
||||
@@ -94,7 +87,6 @@ export default function App() {
|
||||
excalidrawRef.current.updateScene(sceneData);
|
||||
};
|
||||
|
||||
const { width, height } = dimensions;
|
||||
return (
|
||||
<div className="App">
|
||||
<button className="update-scene" onClick={updateScene}>
|
||||
@@ -111,12 +103,17 @@ export default function App() {
|
||||
<div className="excalidraw-wrapper">
|
||||
<Excalidraw
|
||||
ref={excalidrawRef}
|
||||
width={width}
|
||||
height={height}
|
||||
width={dimensions.width}
|
||||
height={dimensions.height}
|
||||
initialData={InitialData}
|
||||
onChange={onChange}
|
||||
onChange={(elements, state) => {
|
||||
console.log("Latest elements:", elements, "Latest state:", state);
|
||||
}}
|
||||
user={{ name: "Excalidraw User" }}
|
||||
onPointerUpdate={(payload) => console.log(payload)}
|
||||
onPointerUpdate={(pointerData) => console.log(pointerData)}
|
||||
onCollabButtonClick={() => {
|
||||
window.alert("You clicked on collab button");
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -141,6 +138,7 @@ export default function App() {
|
||||
| [`onCollabButtonClick`](#onCollabButtonClick) | Function | | Callback to be triggered when the collab button is clicked |
|
||||
| [`isCollaborating`](#isCollaborating) | `boolean` | | This implies if the app is in collaboration mode |
|
||||
| [`onPointerUpdate`](#onPointerUpdate) | Function | | Callback triggered when mouse pointer is updated. |
|
||||
| [`onExportToBackend`](#onExportToBackend) | Function | | Callback triggered when link button is clicked on export dialog |
|
||||
|
||||
#### `width`
|
||||
|
||||
@@ -219,8 +217,8 @@ This is the user name which shows during collaboration. Defaults to `{name: ''}`
|
||||
|
||||
#### `excalidrawRef`
|
||||
|
||||
You can pass a ref when you want to access some excalidraw API's.
|
||||
We expose the below API's
|
||||
You can pass a `ref` when you want to access some excalidraw APIs.
|
||||
We expose the below APIs:
|
||||
|
||||
| API | signature | Usage |
|
||||
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
@@ -241,15 +239,15 @@ const excalidrawRef = { current: { readyPromise: <a href="https://github.com/exc
|
||||
|
||||
#### `onCollabButtonClick`
|
||||
|
||||
This callback is triggered when clicked on the collab button in excalidraw
|
||||
This callback is triggered when clicked on the collab button in excalidraw. If not supplied, the collab dialog button is not rendered.
|
||||
|
||||
#### `isCollaborating`
|
||||
|
||||
This props implies if the app is in collaboration mode
|
||||
This prop indicates if the app is in collaboration mode.
|
||||
|
||||
#### `onPointerUpdate`
|
||||
|
||||
This callback is triggered when mouse pointer is updated
|
||||
This callback is triggered when mouse pointer is updated.
|
||||
|
||||
```js
|
||||
({ x, y }, button, pointersMap}) => void;
|
||||
@@ -260,3 +258,15 @@ This callback is triggered when mouse pointer is updated
|
||||
2.`button`: The position of the button. This will be one of `["down", "up"]`
|
||||
|
||||
3.`pointersMap`: [`pointers map`](https://github.com/excalidraw/excalidraw/blob/182a3e39e1362d73d2a565c870eb2fb72071fdcc/src/types.ts#L122) of the scene
|
||||
|
||||
#### `onExportToBackend`
|
||||
|
||||
This callback is triggered when the shareable-link button is clicked in the export dialog. The link button will only be shown if this callback is passed.
|
||||
|
||||
```js
|
||||
(exportedElements, appState, canvas) => void
|
||||
```
|
||||
|
||||
1. `exportedElements`: An array of [non deleted elements](https://github.com/excalidraw/excalidraw/blob/6e45cb95dbd7a8be1859c7055b06957298e3097c/src/element/types.ts#L76) which needs to be exported.
|
||||
2. `appState`: [AppState](https://github.com/excalidraw/excalidraw/blob/4c90ea5667d29effe8ec4a115e49efc7c340cdb3/src/types.ts#L33) of the scene.
|
||||
3. `canvas`: The `HTMLCanvasElement` of the scene.
|
||||
|
||||
@@ -8,7 +8,6 @@ import "../../css/styles.scss";
|
||||
|
||||
import { ExcalidrawAPIRefValue, ExcalidrawProps } from "../../types";
|
||||
import { IsMobileProvider } from "../../is-mobile";
|
||||
import { noop } from "../../utils";
|
||||
|
||||
const Excalidraw = (props: ExcalidrawProps) => {
|
||||
const {
|
||||
@@ -20,9 +19,10 @@ const Excalidraw = (props: ExcalidrawProps) => {
|
||||
initialData,
|
||||
user,
|
||||
excalidrawRef,
|
||||
onCollabButtonClick = noop,
|
||||
onCollabButtonClick,
|
||||
isCollaborating,
|
||||
onPointerUpdate,
|
||||
onExportToBackend,
|
||||
} = props;
|
||||
|
||||
useEffect(() => {
|
||||
@@ -58,6 +58,7 @@ const Excalidraw = (props: ExcalidrawProps) => {
|
||||
onCollabButtonClick={onCollabButtonClick}
|
||||
isCollaborating={isCollaborating}
|
||||
onPointerUpdate={onPointerUpdate}
|
||||
onExportToBackend={onExportToBackend}
|
||||
/>
|
||||
</IsMobileProvider>
|
||||
</InitializeApp>
|
||||
|
||||
+1414
-4809
File diff suppressed because it is too large
Load Diff
@@ -37,30 +37,30 @@
|
||||
]
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1"
|
||||
"react": "^17.0.1",
|
||||
"react-dom": "^17.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.9.0",
|
||||
"@babel/plugin-transform-arrow-functions": "7.8.3",
|
||||
"@babel/plugin-transform-async-to-generator": "7.8.3",
|
||||
"@babel/plugin-transform-runtime": "7.12.1",
|
||||
"@babel/plugin-transform-typescript": "7.9.4",
|
||||
"@babel/preset-env": "7.9.5",
|
||||
"@babel/preset-react": "7.9.4",
|
||||
"@babel/preset-typescript": "7.9.0",
|
||||
"babel-loader": "8.1.0",
|
||||
"@babel/core": "7.12.10",
|
||||
"@babel/plugin-transform-arrow-functions": "7.12.1",
|
||||
"@babel/plugin-transform-async-to-generator": "7.12.1",
|
||||
"@babel/plugin-transform-runtime": "7.12.10",
|
||||
"@babel/plugin-transform-typescript": "7.12.1",
|
||||
"@babel/preset-env": "7.12.11",
|
||||
"@babel/preset-react": "7.12.10",
|
||||
"@babel/preset-typescript": "7.12.7",
|
||||
"babel-loader": "8.2.2",
|
||||
"babel-plugin-transform-class-properties": "6.24.1",
|
||||
"cross-env": "7.0.2",
|
||||
"css-loader": "3.5.2",
|
||||
"file-loader": "6.0.0",
|
||||
"mini-css-extract-plugin": "0.8.0",
|
||||
"sass-loader": "8.0.2",
|
||||
"terser-webpack-plugin": "2.3.5",
|
||||
"ts-loader": "7.0.0",
|
||||
"webpack": "4.42.0",
|
||||
"webpack-bundle-analyzer": "3.9.0",
|
||||
"webpack-cli": "3.3.11"
|
||||
"cross-env": "7.0.3",
|
||||
"css-loader": "5.0.1",
|
||||
"file-loader": "6.2.0",
|
||||
"mini-css-extract-plugin": "1.3.3",
|
||||
"sass-loader": "10.1.0",
|
||||
"terser-webpack-plugin": "5.0.3",
|
||||
"ts-loader": "8.0.12",
|
||||
"webpack": "5.11.0",
|
||||
"webpack-bundle-analyzer": "4.3.0",
|
||||
"webpack-cli": "4.2.0"
|
||||
},
|
||||
"bugs": "https://github.com/excalidraw/excalidraw/issues",
|
||||
"repository": "https://github.com/excalidraw/excalidraw",
|
||||
|
||||
@@ -16,7 +16,7 @@ type ExportOpts = {
|
||||
) => { width: number; height: number; scale: number };
|
||||
};
|
||||
|
||||
const exportToCanvas = ({
|
||||
export const exportToCanvas = ({
|
||||
elements,
|
||||
appState = getDefaultAppState(),
|
||||
getDimensions = (width, height) => ({ width, height, scale: 1 }),
|
||||
|
||||
@@ -75,7 +75,6 @@ const excalidrawDiagram = {
|
||||
],
|
||||
appState: {
|
||||
viewBackgroundColor: "#ffffff",
|
||||
gridSize: null,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { exportToBlob, exportToSvg } from "../utils.ts";
|
||||
export { exportToBlob, exportToSvg, exportToCanvas } from "../utils.ts";
|
||||
|
||||
Generated
+968
-4264
File diff suppressed because it is too large
Load Diff
@@ -34,21 +34,21 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.9.0",
|
||||
"@babel/plugin-transform-arrow-functions": "7.8.3",
|
||||
"@babel/plugin-transform-async-to-generator": "7.8.3",
|
||||
"@babel/plugin-transform-runtime": "^7.12.1",
|
||||
"@babel/plugin-transform-typescript": "7.9.4",
|
||||
"@babel/preset-env": "7.9.5",
|
||||
"@babel/preset-typescript": "7.9.0",
|
||||
"babel-loader": "8.1.0",
|
||||
"@babel/core": "7.12.10",
|
||||
"@babel/plugin-transform-arrow-functions": "7.12.1",
|
||||
"@babel/plugin-transform-async-to-generator": "7.12.1",
|
||||
"@babel/plugin-transform-runtime": "^7.12.10",
|
||||
"@babel/plugin-transform-typescript": "7.12.1",
|
||||
"@babel/preset-env": "7.12.11",
|
||||
"@babel/preset-typescript": "7.12.7",
|
||||
"babel-loader": "8.2.2",
|
||||
"babel-plugin-transform-class-properties": "6.24.1",
|
||||
"cross-env": "7.0.2",
|
||||
"file-loader": "6.0.0",
|
||||
"ts-loader": "7.0.0",
|
||||
"webpack": "4.42.0",
|
||||
"webpack-bundle-analyzer": "3.9.0",
|
||||
"webpack-cli": "3.3.11"
|
||||
"cross-env": "7.0.3",
|
||||
"file-loader": "6.2.0",
|
||||
"ts-loader": "8.0.12",
|
||||
"webpack": "5.11.0",
|
||||
"webpack-bundle-analyzer": "4.3.0",
|
||||
"webpack-cli": "4.2.0"
|
||||
},
|
||||
"bugs": "https://github.com/excalidraw/excalidraw/issues",
|
||||
"repository": "https://github.com/excalidraw/excalidraw",
|
||||
|
||||
+23
-17
@@ -48,6 +48,7 @@ import {
|
||||
TransformHandleType,
|
||||
} from "../element/transformHandles";
|
||||
import { viewportCoordsToSceneCoords } from "../utils";
|
||||
import { GRID_SIZE } from "../constants";
|
||||
|
||||
const strokeRectWithRotation = (
|
||||
context: CanvasRenderingContext2D,
|
||||
@@ -118,7 +119,6 @@ const fillCircle = (
|
||||
|
||||
const strokeGrid = (
|
||||
context: CanvasRenderingContext2D,
|
||||
gridSize: number,
|
||||
offsetX: number,
|
||||
offsetY: number,
|
||||
width: number,
|
||||
@@ -127,13 +127,13 @@ const strokeGrid = (
|
||||
const origStrokeStyle = context.strokeStyle;
|
||||
context.strokeStyle = "rgba(0,0,0,0.1)";
|
||||
context.beginPath();
|
||||
for (let x = offsetX; x < offsetX + width + gridSize * 2; x += gridSize) {
|
||||
context.moveTo(x, offsetY - gridSize);
|
||||
context.lineTo(x, offsetY + height + gridSize * 2);
|
||||
for (let x = offsetX; x < offsetX + width + GRID_SIZE * 2; x += GRID_SIZE) {
|
||||
context.moveTo(x, offsetY - GRID_SIZE);
|
||||
context.lineTo(x, offsetY + height + GRID_SIZE * 2);
|
||||
}
|
||||
for (let y = offsetY; y < offsetY + height + gridSize * 2; y += gridSize) {
|
||||
context.moveTo(offsetX - gridSize, y);
|
||||
context.lineTo(offsetX + width + gridSize * 2, y);
|
||||
for (let y = offsetY; y < offsetY + height + GRID_SIZE * 2; y += GRID_SIZE) {
|
||||
context.moveTo(offsetX - GRID_SIZE, y);
|
||||
context.lineTo(offsetX + width + GRID_SIZE * 2, y);
|
||||
}
|
||||
context.stroke();
|
||||
context.strokeStyle = origStrokeStyle;
|
||||
@@ -233,16 +233,15 @@ export const renderScene = (
|
||||
context.scale(sceneState.zoom.value, sceneState.zoom.value);
|
||||
|
||||
// Grid
|
||||
if (renderGrid && appState.gridSize) {
|
||||
if (renderGrid && appState.showGrid) {
|
||||
strokeGrid(
|
||||
context,
|
||||
appState.gridSize,
|
||||
-Math.ceil(zoomTranslationX / sceneState.zoom.value / appState.gridSize) *
|
||||
appState.gridSize +
|
||||
(sceneState.scrollX % appState.gridSize),
|
||||
-Math.ceil(zoomTranslationY / sceneState.zoom.value / appState.gridSize) *
|
||||
appState.gridSize +
|
||||
(sceneState.scrollY % appState.gridSize),
|
||||
-Math.ceil(zoomTranslationX / sceneState.zoom.value / GRID_SIZE) *
|
||||
GRID_SIZE +
|
||||
(sceneState.scrollX % GRID_SIZE),
|
||||
-Math.ceil(zoomTranslationY / sceneState.zoom.value / GRID_SIZE) *
|
||||
GRID_SIZE +
|
||||
(sceneState.scrollY % GRID_SIZE),
|
||||
normalizedCanvasWidth / sceneState.zoom.value,
|
||||
normalizedCanvasHeight / sceneState.zoom.value,
|
||||
);
|
||||
@@ -763,13 +762,20 @@ const isVisibleElement = (
|
||||
) => {
|
||||
const [x1, y1, x2, y2] = getElementBounds(element); // scene coordinates
|
||||
const topLeftSceneCoords = viewportCoordsToSceneCoords(
|
||||
{ clientX: 0, clientY: 0 },
|
||||
{
|
||||
clientX: viewTransformations.offsetLeft,
|
||||
clientY: viewTransformations.offsetTop,
|
||||
},
|
||||
viewTransformations,
|
||||
);
|
||||
const bottomRightSceneCoords = viewportCoordsToSceneCoords(
|
||||
{ clientX: canvasWidth, clientY: canvasHeight },
|
||||
{
|
||||
clientX: viewTransformations.offsetLeft + canvasWidth,
|
||||
clientY: viewTransformations.offsetTop + canvasHeight,
|
||||
},
|
||||
viewTransformations,
|
||||
);
|
||||
|
||||
return (
|
||||
topLeftSceneCoords.x <= x2 &&
|
||||
topLeftSceneCoords.y <= y2 &&
|
||||
|
||||
+5
-2
@@ -3,6 +3,7 @@ import { NormalizedZoomValue, PointerCoords, Zoom } from "../types";
|
||||
export const getNewZoom = (
|
||||
newZoomValue: NormalizedZoomValue,
|
||||
prevZoom: Zoom,
|
||||
canvasOffset: { left: number; top: number },
|
||||
zoomOnViewportPoint: PointerCoords = { x: 0, y: 0 },
|
||||
): Zoom => {
|
||||
return {
|
||||
@@ -10,11 +11,13 @@ export const getNewZoom = (
|
||||
translation: {
|
||||
x:
|
||||
zoomOnViewportPoint.x -
|
||||
(zoomOnViewportPoint.x - prevZoom.translation.x) *
|
||||
canvasOffset.left -
|
||||
(zoomOnViewportPoint.x - canvasOffset.left - prevZoom.translation.x) *
|
||||
(newZoomValue / prevZoom.value),
|
||||
y:
|
||||
zoomOnViewportPoint.y -
|
||||
(zoomOnViewportPoint.y - prevZoom.translation.y) *
|
||||
canvasOffset.top -
|
||||
(zoomOnViewportPoint.y - canvasOffset.top - prevZoom.translation.y) *
|
||||
(newZoomValue / prevZoom.value),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`tryParseSpreadsheet works for numbers with comma in them 1`] = `
|
||||
Object {
|
||||
"spreadsheet": Object {
|
||||
"labels": Array [
|
||||
"Week 1",
|
||||
"Week 2",
|
||||
"Week 3",
|
||||
],
|
||||
"title": "Users",
|
||||
"values": Array [
|
||||
814,
|
||||
10301,
|
||||
4264,
|
||||
],
|
||||
},
|
||||
"type": "VALID_SPREADSHEET",
|
||||
}
|
||||
`;
|
||||
@@ -31,7 +31,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -67,6 +66,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -486,7 +486,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -529,6 +528,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -947,7 +947,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": false,
|
||||
"isLibraryOpen": false,
|
||||
@@ -973,6 +972,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -1717,7 +1717,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -1745,6 +1744,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -1915,7 +1915,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -1948,6 +1947,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -2367,7 +2367,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -2395,6 +2394,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -2614,7 +2614,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -2639,6 +2638,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -2772,7 +2772,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -2800,6 +2799,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -3243,7 +3243,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -3268,6 +3267,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -3545,7 +3545,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -3573,6 +3572,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -3743,7 +3743,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -3773,6 +3772,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -3981,7 +3981,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -4009,6 +4008,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -4227,7 +4227,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -4256,6 +4255,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -4604,7 +4604,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -4653,6 +4652,7 @@ Object {
|
||||
},
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -4893,7 +4893,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -4920,6 +4919,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -5194,7 +5194,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -5241,6 +5240,7 @@ Object {
|
||||
},
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -5396,7 +5396,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -5421,6 +5420,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -5554,7 +5554,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -5579,6 +5578,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -6001,7 +6001,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -6033,6 +6032,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -6313,7 +6313,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -6338,6 +6337,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -8341,7 +8341,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -8371,6 +8370,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -8697,7 +8697,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -8728,6 +8727,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -8946,7 +8946,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -8975,6 +8974,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -9193,7 +9193,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -9223,6 +9222,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -9502,7 +9502,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -9527,6 +9526,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -9660,7 +9660,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -9685,6 +9684,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -9818,7 +9818,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -9843,6 +9842,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -9976,7 +9976,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -10001,6 +10000,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -10164,7 +10164,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -10189,6 +10188,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -10352,7 +10352,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -10377,6 +10376,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -10540,7 +10540,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -10565,6 +10564,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -10728,7 +10728,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -10753,6 +10752,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -10886,7 +10886,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -10911,6 +10910,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -11044,7 +11044,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -11069,6 +11068,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -11232,7 +11232,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -11257,6 +11256,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -11390,7 +11390,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -11415,6 +11414,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -11578,7 +11578,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -11614,6 +11613,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -12288,7 +12288,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -12317,6 +12316,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -12535,7 +12535,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -12560,6 +12559,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": true,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -12631,7 +12631,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -12654,6 +12653,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -12725,7 +12725,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -12750,6 +12749,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -12883,7 +12883,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -12908,6 +12907,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -13185,7 +13185,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -13210,6 +13209,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -13487,7 +13487,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -13512,6 +13511,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -13645,7 +13645,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -13668,6 +13667,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -13835,7 +13835,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -13860,6 +13859,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -14078,7 +14078,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -14109,6 +14108,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -14396,7 +14396,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -14421,6 +14420,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -15229,7 +15229,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -15254,6 +15253,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -15531,7 +15531,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -15556,6 +15555,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -15833,7 +15833,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -15862,6 +15861,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -16206,7 +16206,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -16234,6 +16233,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -16367,7 +16367,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -16401,6 +16400,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -16682,7 +16682,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -16710,6 +16709,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -16915,7 +16915,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -16946,6 +16945,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -17164,7 +17164,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -17197,6 +17196,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -17485,7 +17485,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -17508,6 +17507,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -17579,7 +17579,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -17604,6 +17603,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -17737,7 +17737,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -17773,6 +17772,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -18552,7 +18552,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -18575,6 +18574,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -18646,7 +18646,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -18671,6 +18670,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -19392,7 +19392,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -19443,6 +19442,7 @@ Object {
|
||||
},
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -19791,7 +19791,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -19840,6 +19839,7 @@ Object {
|
||||
},
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -20058,7 +20058,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -20083,6 +20082,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": true,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -20154,7 +20154,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -20179,6 +20178,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -20646,7 +20646,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -20669,6 +20668,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
@@ -20740,7 +20740,6 @@ Object {
|
||||
"exportBackground": true,
|
||||
"exportEmbedScene": false,
|
||||
"fileHandle": null,
|
||||
"gridSize": null,
|
||||
"height": 768,
|
||||
"isBindingEnabled": true,
|
||||
"isLibraryOpen": false,
|
||||
@@ -20763,6 +20762,7 @@ Object {
|
||||
"selectionElement": null,
|
||||
"shouldAddWatermark": false,
|
||||
"shouldCacheIgnoreZoom": false,
|
||||
"showGrid": false,
|
||||
"showShortcutsDialog": false,
|
||||
"showStats": false,
|
||||
"startBoundElement": null,
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { tryParseSpreadsheet } from "../charts";
|
||||
|
||||
describe("tryParseSpreadsheet", () => {
|
||||
it("works for numbers with comma in them", () => {
|
||||
const result = tryParseSpreadsheet(
|
||||
`Week Index${"\t"}Users
|
||||
Week 1${"\t"}814
|
||||
Week 2${"\t"}10,301
|
||||
Week 3${"\t"}4,264`,
|
||||
);
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,4 @@
|
||||
import { queryByText } from "@testing-library/react";
|
||||
import { queryAllByText, queryByText } from "@testing-library/react";
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { copiedStyles } from "../actions/actionStyles";
|
||||
@@ -635,8 +635,8 @@ describe("regression tests", () => {
|
||||
const contextMenu = document.querySelector(".context-menu");
|
||||
const expectedShortcutNames: ShortcutName[] = [
|
||||
"selectAll",
|
||||
"toggleGridMode",
|
||||
"toggleStats",
|
||||
"gridMode",
|
||||
"stats",
|
||||
];
|
||||
|
||||
expect(contextMenu).not.toBeNull();
|
||||
@@ -864,7 +864,7 @@ describe("regression tests", () => {
|
||||
clientY: 1,
|
||||
});
|
||||
const contextMenu = document.querySelector(".context-menu");
|
||||
fireEvent.click(queryByText(contextMenu as HTMLElement, "Delete")!);
|
||||
fireEvent.click(queryAllByText(contextMenu as HTMLElement, "Delete")[0]);
|
||||
expect(API.getSelectedElements()).toHaveLength(0);
|
||||
expect(h.elements[0].isDeleted).toBe(true);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import React from "react";
|
||||
import { render, waitFor } from "./test-utils";
|
||||
import Excalidraw from "../packages/excalidraw/index";
|
||||
import { API } from "./helpers/api";
|
||||
|
||||
const { h } = window;
|
||||
|
||||
describe("appState", () => {
|
||||
it("scroll-to-center on init works with non-zero offsets", async () => {
|
||||
const WIDTH = 600;
|
||||
const HEIGHT = 700;
|
||||
const OFFSET_LEFT = 200;
|
||||
const OFFSET_TOP = 100;
|
||||
|
||||
const ELEM_WIDTH = 100;
|
||||
const ELEM_HEIGHT = 60;
|
||||
|
||||
await render(
|
||||
<Excalidraw
|
||||
width={WIDTH}
|
||||
height={HEIGHT}
|
||||
offsetLeft={OFFSET_LEFT}
|
||||
offsetTop={OFFSET_TOP}
|
||||
initialData={{
|
||||
elements: [
|
||||
API.createElement({
|
||||
type: "rectangle",
|
||||
id: "A",
|
||||
width: ELEM_WIDTH,
|
||||
height: ELEM_HEIGHT,
|
||||
}),
|
||||
],
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(h.state.width).toBe(WIDTH);
|
||||
expect(h.state.height).toBe(HEIGHT);
|
||||
expect(h.state.offsetLeft).toBe(OFFSET_LEFT);
|
||||
expect(h.state.offsetTop).toBe(OFFSET_TOP);
|
||||
|
||||
// assert scroll is in center
|
||||
expect(h.state.scrollX).toBe(WIDTH / 2 - ELEM_WIDTH / 2);
|
||||
expect(h.state.scrollY).toBe(HEIGHT / 2 - ELEM_HEIGHT / 2);
|
||||
});
|
||||
});
|
||||
});
|
||||
+6
-1
@@ -83,7 +83,7 @@ export type AppState = {
|
||||
showShortcutsDialog: boolean;
|
||||
zenModeEnabled: boolean;
|
||||
appearance: "light" | "dark";
|
||||
gridSize: number | null;
|
||||
showGrid: boolean;
|
||||
|
||||
/** top-most selected groups (i.e. does not include nested groups) */
|
||||
selectedGroupIds: { [groupId: string]: boolean };
|
||||
@@ -166,6 +166,11 @@ export interface ExcalidrawProps {
|
||||
button: "down" | "up";
|
||||
pointersMap: Gesture["pointers"];
|
||||
}) => void;
|
||||
onExportToBackend?: (
|
||||
exportedElements: readonly NonDeletedExcalidrawElement[],
|
||||
appState: AppState,
|
||||
canvas: HTMLCanvasElement | null,
|
||||
) => void;
|
||||
}
|
||||
|
||||
export type SceneData = {
|
||||
|
||||
+11
-9
@@ -7,6 +7,7 @@ import {
|
||||
import { FontFamily, FontString } from "./element/types";
|
||||
import { Zoom } from "./types";
|
||||
import { unstable_batchedUpdates } from "react-dom";
|
||||
import { isDarwin } from "./keys";
|
||||
|
||||
export const SVG_NS = "http://www.w3.org/2000/svg";
|
||||
|
||||
@@ -179,15 +180,18 @@ export const allowFullScreen = () =>
|
||||
export const exitFullScreen = () => document.exitFullscreen();
|
||||
|
||||
export const getShortcutKey = (shortcut: string): string => {
|
||||
const isMac = /Mac|iPod|iPhone|iPad/.test(window.navigator.platform);
|
||||
if (isMac) {
|
||||
return `${shortcut
|
||||
shortcut = shortcut
|
||||
.replace(/\bAlt\b/i, "Alt")
|
||||
.replace(/\bShift\b/i, "Shift")
|
||||
.replace(/\b(Enter|Return)\b/i, "Enter")
|
||||
.replace(/\bDel\b/i, "Delete");
|
||||
|
||||
if (isDarwin) {
|
||||
return shortcut
|
||||
.replace(/\bCtrlOrCmd\b/i, "Cmd")
|
||||
.replace(/\bAlt\b/i, "Option")
|
||||
.replace(/\bDel\b/i, "Delete")
|
||||
.replace(/\b(Enter|Return)\b/i, "Enter")}`;
|
||||
.replace(/\bAlt\b/i, "Option");
|
||||
}
|
||||
return `${shortcut.replace(/\bCtrlOrCmd\b/i, "Ctrl")}`;
|
||||
return shortcut.replace(/\bCtrlOrCmd\b/i, "Ctrl");
|
||||
};
|
||||
|
||||
export const viewportCoordsToSceneCoords = (
|
||||
@@ -310,8 +314,6 @@ export const isTransparent = (color: string) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const noop = () => ({});
|
||||
|
||||
export type ResolvablePromise<T> = Promise<T> & {
|
||||
resolve: [T] extends [undefined] ? (value?: T) => void : (value: T) => void;
|
||||
reject: (error: Error) => void;
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react"
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user