Bump prettier from 1.19.1 to 2.0.1 (#1060)
* Bump prettier from 1.19.1 to 2.0.1 Bumps [prettier](https://github.com/prettier/prettier) from 1.19.1 to 2.0.1. - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/master/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/1.19.1...2.0.1) Signed-off-by: dependabot-preview[bot] <support@dependabot.com> * Update formatting Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> Co-authored-by: Panayiotis Lipiridis <lipiridis@gmail.com>
This commit is contained in:
parent
251fa27c65
commit
722c498abe
6
package-lock.json
generated
6
package-lock.json
generated
@ -12261,9 +12261,9 @@
|
|||||||
"integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw="
|
"integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw="
|
||||||
},
|
},
|
||||||
"prettier": {
|
"prettier": {
|
||||||
"version": "1.19.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz",
|
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.1.tgz",
|
||||||
"integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==",
|
"integrity": "sha512-piXGBcY1zoFOG0MvHpNE5reAGseLmaCRifQ/fmfF49BcYkInEs/naD/unxGNAeOKFA5+JxVrPyMvMlpzcd20UA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"prettier-linter-helpers": {
|
"prettier-linter-helpers": {
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
"lint-staged": "10.0.8",
|
"lint-staged": "10.0.8",
|
||||||
"node-sass": "4.13.1",
|
"node-sass": "4.13.1",
|
||||||
"pepjs": "0.5.2",
|
"pepjs": "0.5.2",
|
||||||
"prettier": "1.19.1",
|
"prettier": "2.0.1",
|
||||||
"rewire": "5.0.0",
|
"rewire": "5.0.0",
|
||||||
"typescript": "3.8.3"
|
"typescript": "3.8.3"
|
||||||
},
|
},
|
||||||
|
@ -159,7 +159,7 @@
|
|||||||
width="40"
|
width="40"
|
||||||
height="40"
|
height="40"
|
||||||
viewBox="0 0 250 250"
|
viewBox="0 0 250 250"
|
||||||
style="position: absolute; top: 0; right: 0"
|
style="position: absolute; top: 0; right: 0;"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
href="https://github.com/excalidraw/excalidraw"
|
href="https://github.com/excalidraw/excalidraw"
|
||||||
@ -170,7 +170,7 @@
|
|||||||
<path
|
<path
|
||||||
class="octo-arm"
|
class="octo-arm"
|
||||||
d="M128 109c-15-9-9-19-9-19 3-7 2-11 2-11-1-7 3-2 3-2 4 5 2 11 2 11-3 10 5 15 9 16"
|
d="M128 109c-15-9-9-19-9-19 3-7 2-11 2-11-1-7 3-2 3-2 4 5 2 11 2 11-3 10 5 15 9 16"
|
||||||
style="transform-origin: 130px 106px"
|
style="transform-origin: 130px 106px;"
|
||||||
fill="#fff"
|
fill="#fff"
|
||||||
/>
|
/>
|
||||||
<path
|
<path
|
||||||
|
@ -29,7 +29,7 @@ config.entry = "./src/index-node";
|
|||||||
// By default, webpack is going to replace the require of the canvas.node file
|
// By default, webpack is going to replace the require of the canvas.node file
|
||||||
// to just a string with the path of the canvas.node file. We need to tell
|
// to just a string with the path of the canvas.node file. We need to tell
|
||||||
// webpack to avoid rewriting that dependency.
|
// webpack to avoid rewriting that dependency.
|
||||||
config.externals = function(context, request, callback) {
|
config.externals = function (context, request, callback) {
|
||||||
if (/\.node$/.test(request)) {
|
if (/\.node$/.test(request)) {
|
||||||
return callback(
|
return callback(
|
||||||
null,
|
null,
|
||||||
|
@ -4,9 +4,9 @@ const fs = require("fs");
|
|||||||
const path = require("path");
|
const path = require("path");
|
||||||
const asar = require("asar");
|
const asar = require("asar");
|
||||||
|
|
||||||
const zero = digit => `0${digit}`.slice(-2);
|
const zero = (digit) => `0${digit}`.slice(-2);
|
||||||
|
|
||||||
const versionDate = date => {
|
const versionDate = (date) => {
|
||||||
const date_ = `${date.getFullYear()}-${zero(date.getMonth() + 1)}-${zero(
|
const date_ = `${date.getFullYear()}-${zero(date.getMonth() + 1)}-${zero(
|
||||||
date.getDate(),
|
date.getDate(),
|
||||||
)}`;
|
)}`;
|
||||||
|
@ -26,7 +26,7 @@ export const actionChangeViewBackgroundColor = register({
|
|||||||
label={t("labels.canvasBackground")}
|
label={t("labels.canvasBackground")}
|
||||||
type="canvasBackground"
|
type="canvasBackground"
|
||||||
color={appState.viewBackgroundColor}
|
color={appState.viewBackgroundColor}
|
||||||
onChange={color => updateData(color)}
|
onChange={(color) => updateData(color)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -35,9 +35,9 @@ export const actionChangeViewBackgroundColor = register({
|
|||||||
|
|
||||||
export const actionClearCanvas = register({
|
export const actionClearCanvas = register({
|
||||||
name: "clearCanvas",
|
name: "clearCanvas",
|
||||||
perform: elements => {
|
perform: (elements) => {
|
||||||
return {
|
return {
|
||||||
elements: elements.map(element =>
|
elements: elements.map((element) =>
|
||||||
newElementWith(element, { isDeleted: true }),
|
newElementWith(element, { isDeleted: true }),
|
||||||
),
|
),
|
||||||
appState: getDefaultAppState(),
|
appState: getDefaultAppState(),
|
||||||
@ -97,7 +97,7 @@ export const actionZoomIn = register({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
keyTest: event =>
|
keyTest: (event) =>
|
||||||
(event.code === KEY_CODES.EQUAL || event.code === KEY_CODES.NUM_ADD) &&
|
(event.code === KEY_CODES.EQUAL || event.code === KEY_CODES.NUM_ADD) &&
|
||||||
(event[KEYS.CTRL_OR_CMD] || event.shiftKey),
|
(event[KEYS.CTRL_OR_CMD] || event.shiftKey),
|
||||||
});
|
});
|
||||||
@ -124,7 +124,7 @@ export const actionZoomOut = register({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
keyTest: event =>
|
keyTest: (event) =>
|
||||||
(event.code === KEY_CODES.MINUS || event.code === KEY_CODES.NUM_SUBTRACT) &&
|
(event.code === KEY_CODES.MINUS || event.code === KEY_CODES.NUM_SUBTRACT) &&
|
||||||
(event[KEYS.CTRL_OR_CMD] || event.shiftKey),
|
(event[KEYS.CTRL_OR_CMD] || event.shiftKey),
|
||||||
});
|
});
|
||||||
@ -151,7 +151,7 @@ export const actionResetZoom = register({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
keyTest: event =>
|
keyTest: (event) =>
|
||||||
(event.code === KEY_CODES.ZERO || event.code === KEY_CODES.NUM_ZERO) &&
|
(event.code === KEY_CODES.ZERO || event.code === KEY_CODES.NUM_ZERO) &&
|
||||||
(event[KEYS.CTRL_OR_CMD] || event.shiftKey),
|
(event[KEYS.CTRL_OR_CMD] || event.shiftKey),
|
||||||
});
|
});
|
||||||
|
@ -25,7 +25,7 @@ export const actionDeleteSelected = register({
|
|||||||
},
|
},
|
||||||
contextItemLabel: "labels.delete",
|
contextItemLabel: "labels.delete",
|
||||||
contextMenuOrder: 3,
|
contextMenuOrder: 3,
|
||||||
keyTest: event => event.key === KEYS.BACKSPACE || event.key === KEYS.DELETE,
|
keyTest: (event) => event.key === KEYS.BACKSPACE || event.key === KEYS.DELETE,
|
||||||
PanelComponent: ({ elements, appState, updateData }) => (
|
PanelComponent: ({ elements, appState, updateData }) => (
|
||||||
<ToolButton
|
<ToolButton
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -27,5 +27,5 @@ export const actionDuplicateSelection = register({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
contextItemLabel: "labels.duplicateSelection",
|
contextItemLabel: "labels.duplicateSelection",
|
||||||
keyTest: event => event[KEYS.CTRL_OR_CMD] && event.key === "d",
|
keyTest: (event) => event[KEYS.CTRL_OR_CMD] && event.key === "d",
|
||||||
});
|
});
|
||||||
|
@ -34,7 +34,7 @@ export const actionChangeExportBackground = register({
|
|||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={appState.exportBackground}
|
checked={appState.exportBackground}
|
||||||
onChange={event => updateData(event.target.checked)}
|
onChange={(event) => updateData(event.target.checked)}
|
||||||
/>{" "}
|
/>{" "}
|
||||||
{t("labels.withBackground")}
|
{t("labels.withBackground")}
|
||||||
</label>
|
</label>
|
||||||
@ -44,7 +44,7 @@ export const actionChangeExportBackground = register({
|
|||||||
export const actionSaveScene = register({
|
export const actionSaveScene = register({
|
||||||
name: "saveScene",
|
name: "saveScene",
|
||||||
perform: (elements, appState, value) => {
|
perform: (elements, appState, value) => {
|
||||||
saveAsJSON(elements, appState).catch(error => console.error(error));
|
saveAsJSON(elements, appState).catch((error) => console.error(error));
|
||||||
return { commitToHistory: false };
|
return { commitToHistory: false };
|
||||||
},
|
},
|
||||||
PanelComponent: ({ updateData }) => (
|
PanelComponent: ({ updateData }) => (
|
||||||
@ -84,7 +84,7 @@ export const actionLoadScene = register({
|
|||||||
.then(({ elements, appState }) => {
|
.then(({ elements, appState }) => {
|
||||||
updateData({ elements: elements, appState: appState });
|
updateData({ elements: elements, appState: appState });
|
||||||
})
|
})
|
||||||
.catch(error => console.error(error));
|
.catch((error) => console.error(error));
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
|
@ -35,7 +35,7 @@ const writeData = (
|
|||||||
const nextElementMap = getElementMap(nextElements);
|
const nextElementMap = getElementMap(nextElements);
|
||||||
return {
|
return {
|
||||||
elements: nextElements
|
elements: nextElements
|
||||||
.map(nextElement =>
|
.map((nextElement) =>
|
||||||
newElementWith(
|
newElementWith(
|
||||||
prevElementMap[nextElement.id] || nextElement,
|
prevElementMap[nextElement.id] || nextElement,
|
||||||
nextElement,
|
nextElement,
|
||||||
@ -44,9 +44,9 @@ const writeData = (
|
|||||||
.concat(
|
.concat(
|
||||||
prevElements
|
prevElements
|
||||||
.filter(
|
.filter(
|
||||||
prevElement => !nextElementMap.hasOwnProperty(prevElement.id),
|
(prevElement) => !nextElementMap.hasOwnProperty(prevElement.id),
|
||||||
)
|
)
|
||||||
.map(prevElement =>
|
.map((prevElement) =>
|
||||||
newElementWith(prevElement, { isDeleted: true }),
|
newElementWith(prevElement, { isDeleted: true }),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -62,7 +62,7 @@ const testUndo = (shift: boolean) => (event: KeyboardEvent) =>
|
|||||||
|
|
||||||
type ActionCreator = (history: SceneHistory) => Action;
|
type ActionCreator = (history: SceneHistory) => Action;
|
||||||
|
|
||||||
export const createUndoAction: ActionCreator = history => ({
|
export const createUndoAction: ActionCreator = (history) => ({
|
||||||
name: "undo",
|
name: "undo",
|
||||||
perform: (elements, appState) =>
|
perform: (elements, appState) =>
|
||||||
writeData(elements, appState, () => history.undoOnce()),
|
writeData(elements, appState, () => history.undoOnce()),
|
||||||
@ -78,7 +78,7 @@ export const createUndoAction: ActionCreator = history => ({
|
|||||||
commitToHistory: () => false,
|
commitToHistory: () => false,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const createRedoAction: ActionCreator = history => ({
|
export const createRedoAction: ActionCreator = (history) => ({
|
||||||
name: "redo",
|
name: "redo",
|
||||||
perform: (elements, appState) =>
|
perform: (elements, appState) =>
|
||||||
writeData(elements, appState, () => history.redoOnce()),
|
writeData(elements, appState, () => history.redoOnce()),
|
||||||
|
@ -18,7 +18,7 @@ const changeProperty = (
|
|||||||
appState: AppState,
|
appState: AppState,
|
||||||
callback: (element: ExcalidrawElement) => ExcalidrawElement,
|
callback: (element: ExcalidrawElement) => ExcalidrawElement,
|
||||||
) => {
|
) => {
|
||||||
return elements.map(element => {
|
return elements.map((element) => {
|
||||||
if (appState.selectedElementIds[element.id]) {
|
if (appState.selectedElementIds[element.id]) {
|
||||||
return callback(element);
|
return callback(element);
|
||||||
}
|
}
|
||||||
@ -26,7 +26,7 @@ const changeProperty = (
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const getFormValue = function<T>(
|
const getFormValue = function <T>(
|
||||||
elements: readonly ExcalidrawElement[],
|
elements: readonly ExcalidrawElement[],
|
||||||
appState: AppState,
|
appState: AppState,
|
||||||
getAttribute: (element: ExcalidrawElement) => T,
|
getAttribute: (element: ExcalidrawElement) => T,
|
||||||
@ -46,7 +46,7 @@ export const actionChangeStrokeColor = register({
|
|||||||
name: "changeStrokeColor",
|
name: "changeStrokeColor",
|
||||||
perform: (elements, appState, value) => {
|
perform: (elements, appState, value) => {
|
||||||
return {
|
return {
|
||||||
elements: changeProperty(elements, appState, el =>
|
elements: changeProperty(elements, appState, (el) =>
|
||||||
newElementWith(el, {
|
newElementWith(el, {
|
||||||
strokeColor: value,
|
strokeColor: value,
|
||||||
}),
|
}),
|
||||||
@ -64,7 +64,7 @@ export const actionChangeStrokeColor = register({
|
|||||||
color={getFormValue(
|
color={getFormValue(
|
||||||
elements,
|
elements,
|
||||||
appState,
|
appState,
|
||||||
element => element.strokeColor,
|
(element) => element.strokeColor,
|
||||||
appState.currentItemStrokeColor,
|
appState.currentItemStrokeColor,
|
||||||
)}
|
)}
|
||||||
onChange={updateData}
|
onChange={updateData}
|
||||||
@ -77,7 +77,7 @@ export const actionChangeBackgroundColor = register({
|
|||||||
name: "changeBackgroundColor",
|
name: "changeBackgroundColor",
|
||||||
perform: (elements, appState, value) => {
|
perform: (elements, appState, value) => {
|
||||||
return {
|
return {
|
||||||
elements: changeProperty(elements, appState, el =>
|
elements: changeProperty(elements, appState, (el) =>
|
||||||
newElementWith(el, {
|
newElementWith(el, {
|
||||||
backgroundColor: value,
|
backgroundColor: value,
|
||||||
}),
|
}),
|
||||||
@ -95,7 +95,7 @@ export const actionChangeBackgroundColor = register({
|
|||||||
color={getFormValue(
|
color={getFormValue(
|
||||||
elements,
|
elements,
|
||||||
appState,
|
appState,
|
||||||
element => element.backgroundColor,
|
(element) => element.backgroundColor,
|
||||||
appState.currentItemBackgroundColor,
|
appState.currentItemBackgroundColor,
|
||||||
)}
|
)}
|
||||||
onChange={updateData}
|
onChange={updateData}
|
||||||
@ -108,7 +108,7 @@ export const actionChangeFillStyle = register({
|
|||||||
name: "changeFillStyle",
|
name: "changeFillStyle",
|
||||||
perform: (elements, appState, value) => {
|
perform: (elements, appState, value) => {
|
||||||
return {
|
return {
|
||||||
elements: changeProperty(elements, appState, el =>
|
elements: changeProperty(elements, appState, (el) =>
|
||||||
newElementWith(el, {
|
newElementWith(el, {
|
||||||
fillStyle: value,
|
fillStyle: value,
|
||||||
}),
|
}),
|
||||||
@ -130,10 +130,10 @@ export const actionChangeFillStyle = register({
|
|||||||
value={getFormValue(
|
value={getFormValue(
|
||||||
elements,
|
elements,
|
||||||
appState,
|
appState,
|
||||||
element => element.fillStyle,
|
(element) => element.fillStyle,
|
||||||
appState.currentItemFillStyle,
|
appState.currentItemFillStyle,
|
||||||
)}
|
)}
|
||||||
onChange={value => {
|
onChange={(value) => {
|
||||||
updateData(value);
|
updateData(value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -145,7 +145,7 @@ export const actionChangeStrokeWidth = register({
|
|||||||
name: "changeStrokeWidth",
|
name: "changeStrokeWidth",
|
||||||
perform: (elements, appState, value) => {
|
perform: (elements, appState, value) => {
|
||||||
return {
|
return {
|
||||||
elements: changeProperty(elements, appState, el =>
|
elements: changeProperty(elements, appState, (el) =>
|
||||||
newElementWith(el, {
|
newElementWith(el, {
|
||||||
strokeWidth: value,
|
strokeWidth: value,
|
||||||
}),
|
}),
|
||||||
@ -167,10 +167,10 @@ export const actionChangeStrokeWidth = register({
|
|||||||
value={getFormValue(
|
value={getFormValue(
|
||||||
elements,
|
elements,
|
||||||
appState,
|
appState,
|
||||||
element => element.strokeWidth,
|
(element) => element.strokeWidth,
|
||||||
appState.currentItemStrokeWidth,
|
appState.currentItemStrokeWidth,
|
||||||
)}
|
)}
|
||||||
onChange={value => updateData(value)}
|
onChange={(value) => updateData(value)}
|
||||||
/>
|
/>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
),
|
),
|
||||||
@ -180,7 +180,7 @@ export const actionChangeSloppiness = register({
|
|||||||
name: "changeSloppiness",
|
name: "changeSloppiness",
|
||||||
perform: (elements, appState, value) => {
|
perform: (elements, appState, value) => {
|
||||||
return {
|
return {
|
||||||
elements: changeProperty(elements, appState, el =>
|
elements: changeProperty(elements, appState, (el) =>
|
||||||
newElementWith(el, {
|
newElementWith(el, {
|
||||||
roughness: value,
|
roughness: value,
|
||||||
}),
|
}),
|
||||||
@ -202,10 +202,10 @@ export const actionChangeSloppiness = register({
|
|||||||
value={getFormValue(
|
value={getFormValue(
|
||||||
elements,
|
elements,
|
||||||
appState,
|
appState,
|
||||||
element => element.roughness,
|
(element) => element.roughness,
|
||||||
appState.currentItemRoughness,
|
appState.currentItemRoughness,
|
||||||
)}
|
)}
|
||||||
onChange={value => updateData(value)}
|
onChange={(value) => updateData(value)}
|
||||||
/>
|
/>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
),
|
),
|
||||||
@ -215,7 +215,7 @@ export const actionChangeOpacity = register({
|
|||||||
name: "changeOpacity",
|
name: "changeOpacity",
|
||||||
perform: (elements, appState, value) => {
|
perform: (elements, appState, value) => {
|
||||||
return {
|
return {
|
||||||
elements: changeProperty(elements, appState, el =>
|
elements: changeProperty(elements, appState, (el) =>
|
||||||
newElementWith(el, {
|
newElementWith(el, {
|
||||||
opacity: value,
|
opacity: value,
|
||||||
}),
|
}),
|
||||||
@ -232,8 +232,8 @@ export const actionChangeOpacity = register({
|
|||||||
min="0"
|
min="0"
|
||||||
max="100"
|
max="100"
|
||||||
step="10"
|
step="10"
|
||||||
onChange={event => updateData(+event.target.value)}
|
onChange={(event) => updateData(+event.target.value)}
|
||||||
onWheel={event => {
|
onWheel={(event) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
const target = event.target as HTMLInputElement;
|
const target = event.target as HTMLInputElement;
|
||||||
const STEP = 10;
|
const STEP = 10;
|
||||||
@ -251,7 +251,7 @@ export const actionChangeOpacity = register({
|
|||||||
getFormValue(
|
getFormValue(
|
||||||
elements,
|
elements,
|
||||||
appState,
|
appState,
|
||||||
element => element.opacity,
|
(element) => element.opacity,
|
||||||
appState.currentItemOpacity,
|
appState.currentItemOpacity,
|
||||||
) ?? undefined
|
) ?? undefined
|
||||||
}
|
}
|
||||||
@ -264,7 +264,7 @@ export const actionChangeFontSize = register({
|
|||||||
name: "changeFontSize",
|
name: "changeFontSize",
|
||||||
perform: (elements, appState, value) => {
|
perform: (elements, appState, value) => {
|
||||||
return {
|
return {
|
||||||
elements: changeProperty(elements, appState, el => {
|
elements: changeProperty(elements, appState, (el) => {
|
||||||
if (isTextElement(el)) {
|
if (isTextElement(el)) {
|
||||||
const element: ExcalidrawTextElement = newElementWith(el, {
|
const element: ExcalidrawTextElement = newElementWith(el, {
|
||||||
font: `${value}px ${el.font.split("px ")[1]}`,
|
font: `${value}px ${el.font.split("px ")[1]}`,
|
||||||
@ -298,10 +298,10 @@ export const actionChangeFontSize = register({
|
|||||||
value={getFormValue(
|
value={getFormValue(
|
||||||
elements,
|
elements,
|
||||||
appState,
|
appState,
|
||||||
element => isTextElement(element) && +element.font.split("px ")[0],
|
(element) => isTextElement(element) && +element.font.split("px ")[0],
|
||||||
+(appState.currentItemFont || DEFAULT_FONT).split("px ")[0],
|
+(appState.currentItemFont || DEFAULT_FONT).split("px ")[0],
|
||||||
)}
|
)}
|
||||||
onChange={value => updateData(value)}
|
onChange={(value) => updateData(value)}
|
||||||
/>
|
/>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
),
|
),
|
||||||
@ -311,7 +311,7 @@ export const actionChangeFontFamily = register({
|
|||||||
name: "changeFontFamily",
|
name: "changeFontFamily",
|
||||||
perform: (elements, appState, value) => {
|
perform: (elements, appState, value) => {
|
||||||
return {
|
return {
|
||||||
elements: changeProperty(elements, appState, el => {
|
elements: changeProperty(elements, appState, (el) => {
|
||||||
if (isTextElement(el)) {
|
if (isTextElement(el)) {
|
||||||
const element: ExcalidrawTextElement = newElementWith(el, {
|
const element: ExcalidrawTextElement = newElementWith(el, {
|
||||||
font: `${el.font.split("px ")[0]}px ${value}`,
|
font: `${el.font.split("px ")[0]}px ${value}`,
|
||||||
@ -344,10 +344,10 @@ export const actionChangeFontFamily = register({
|
|||||||
value={getFormValue(
|
value={getFormValue(
|
||||||
elements,
|
elements,
|
||||||
appState,
|
appState,
|
||||||
element => isTextElement(element) && element.font.split("px ")[1],
|
(element) => isTextElement(element) && element.font.split("px ")[1],
|
||||||
(appState.currentItemFont || DEFAULT_FONT).split("px ")[1],
|
(appState.currentItemFont || DEFAULT_FONT).split("px ")[1],
|
||||||
)}
|
)}
|
||||||
onChange={value => updateData(value)}
|
onChange={(value) => updateData(value)}
|
||||||
/>
|
/>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
),
|
),
|
||||||
|
@ -16,5 +16,5 @@ export const actionSelectAll = register({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
contextItemLabel: "labels.selectAll",
|
contextItemLabel: "labels.selectAll",
|
||||||
keyTest: event => event[KEYS.CTRL_OR_CMD] && event.key === "a",
|
keyTest: (event) => event[KEYS.CTRL_OR_CMD] && event.key === "a",
|
||||||
});
|
});
|
||||||
|
@ -13,7 +13,7 @@ let copiedStyles: string = "{}";
|
|||||||
export const actionCopyStyles = register({
|
export const actionCopyStyles = register({
|
||||||
name: "copyStyles",
|
name: "copyStyles",
|
||||||
perform: (elements, appState) => {
|
perform: (elements, appState) => {
|
||||||
const element = elements.find(el => appState.selectedElementIds[el.id]);
|
const element = elements.find((el) => appState.selectedElementIds[el.id]);
|
||||||
if (element) {
|
if (element) {
|
||||||
copiedStyles = JSON.stringify(element);
|
copiedStyles = JSON.stringify(element);
|
||||||
}
|
}
|
||||||
@ -22,7 +22,7 @@ export const actionCopyStyles = register({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
contextItemLabel: "labels.copyStyles",
|
contextItemLabel: "labels.copyStyles",
|
||||||
keyTest: event =>
|
keyTest: (event) =>
|
||||||
event[KEYS.CTRL_OR_CMD] && event.shiftKey && event.key === "C",
|
event[KEYS.CTRL_OR_CMD] && event.shiftKey && event.key === "C",
|
||||||
contextMenuOrder: 0,
|
contextMenuOrder: 0,
|
||||||
});
|
});
|
||||||
@ -35,7 +35,7 @@ export const actionPasteStyles = register({
|
|||||||
return { elements, commitToHistory: false };
|
return { elements, commitToHistory: false };
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
elements: elements.map(element => {
|
elements: elements.map((element) => {
|
||||||
if (appState.selectedElementIds[element.id]) {
|
if (appState.selectedElementIds[element.id]) {
|
||||||
const newElement = newElementWith(element, {
|
const newElement = newElementWith(element, {
|
||||||
backgroundColor: pastedElement?.backgroundColor,
|
backgroundColor: pastedElement?.backgroundColor,
|
||||||
@ -59,7 +59,7 @@ export const actionPasteStyles = register({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
contextItemLabel: "labels.pasteStyles",
|
contextItemLabel: "labels.pasteStyles",
|
||||||
keyTest: event =>
|
keyTest: (event) =>
|
||||||
event[KEYS.CTRL_OR_CMD] && event.shiftKey && event.key === "V",
|
event[KEYS.CTRL_OR_CMD] && event.shiftKey && event.key === "V",
|
||||||
contextMenuOrder: 1,
|
contextMenuOrder: 1,
|
||||||
});
|
});
|
||||||
|
@ -31,7 +31,7 @@ export const actionSendBackward = register({
|
|||||||
},
|
},
|
||||||
contextItemLabel: "labels.sendBackward",
|
contextItemLabel: "labels.sendBackward",
|
||||||
keyPriority: 40,
|
keyPriority: 40,
|
||||||
keyTest: event =>
|
keyTest: (event) =>
|
||||||
event[KEYS.CTRL_OR_CMD] && !event.shiftKey && event.code === "BracketLeft",
|
event[KEYS.CTRL_OR_CMD] && !event.shiftKey && event.code === "BracketLeft",
|
||||||
PanelComponent: ({ updateData }) => (
|
PanelComponent: ({ updateData }) => (
|
||||||
<button
|
<button
|
||||||
@ -59,7 +59,7 @@ export const actionBringForward = register({
|
|||||||
},
|
},
|
||||||
contextItemLabel: "labels.bringForward",
|
contextItemLabel: "labels.bringForward",
|
||||||
keyPriority: 40,
|
keyPriority: 40,
|
||||||
keyTest: event =>
|
keyTest: (event) =>
|
||||||
event[KEYS.CTRL_OR_CMD] && !event.shiftKey && event.code === "BracketRight",
|
event[KEYS.CTRL_OR_CMD] && !event.shiftKey && event.code === "BracketRight",
|
||||||
PanelComponent: ({ updateData }) => (
|
PanelComponent: ({ updateData }) => (
|
||||||
<button
|
<button
|
||||||
@ -86,7 +86,7 @@ export const actionSendToBack = register({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
contextItemLabel: "labels.sendToBack",
|
contextItemLabel: "labels.sendToBack",
|
||||||
keyTest: event => {
|
keyTest: (event) => {
|
||||||
return isDarwin
|
return isDarwin
|
||||||
? event[KEYS.CTRL_OR_CMD] && event.altKey && event.code === "BracketLeft"
|
? event[KEYS.CTRL_OR_CMD] && event.altKey && event.code === "BracketLeft"
|
||||||
: event[KEYS.CTRL_OR_CMD] &&
|
: event[KEYS.CTRL_OR_CMD] &&
|
||||||
@ -122,7 +122,7 @@ export const actionBringToFront = register({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
contextItemLabel: "labels.bringToFront",
|
contextItemLabel: "labels.bringToFront",
|
||||||
keyTest: event => {
|
keyTest: (event) => {
|
||||||
return isDarwin
|
return isDarwin
|
||||||
? event[KEYS.CTRL_OR_CMD] && event.altKey && event.code === "BracketRight"
|
? event[KEYS.CTRL_OR_CMD] && event.altKey && event.code === "BracketRight"
|
||||||
: event[KEYS.CTRL_OR_CMD] &&
|
: event[KEYS.CTRL_OR_CMD] &&
|
||||||
@ -133,7 +133,7 @@ export const actionBringToFront = register({
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="zIndexButton"
|
className="zIndexButton"
|
||||||
onClick={event => updateData(null)}
|
onClick={(event) => updateData(null)}
|
||||||
title={`${t("labels.bringToFront")} ${
|
title={`${t("labels.bringToFront")} ${
|
||||||
isDarwin
|
isDarwin
|
||||||
? getShortcutKey("CtrlOrCmd+Alt+]")
|
? getShortcutKey("CtrlOrCmd+Alt+]")
|
||||||
|
@ -33,14 +33,14 @@ export class ActionManager implements ActionsManagerInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
registerAll(actions: readonly Action[]) {
|
registerAll(actions: readonly Action[]) {
|
||||||
actions.forEach(action => this.registerAction(action));
|
actions.forEach((action) => this.registerAction(action));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleKeyDown(event: KeyboardEvent) {
|
handleKeyDown(event: KeyboardEvent) {
|
||||||
const data = Object.values(this.actions)
|
const data = Object.values(this.actions)
|
||||||
.sort((a, b) => (b.keyPriority || 0) - (a.keyPriority || 0))
|
.sort((a, b) => (b.keyPriority || 0) - (a.keyPriority || 0))
|
||||||
.filter(
|
.filter(
|
||||||
action =>
|
(action) =>
|
||||||
action.keyTest &&
|
action.keyTest &&
|
||||||
action.keyTest(event, this.getAppState(), this.getElements()),
|
action.keyTest(event, this.getAppState(), this.getElements()),
|
||||||
);
|
);
|
||||||
@ -58,16 +58,16 @@ export class ActionManager implements ActionsManagerInterface {
|
|||||||
this.updater(action.perform(this.getElements(), this.getAppState(), null));
|
this.updater(action.perform(this.getElements(), this.getAppState(), null));
|
||||||
}
|
}
|
||||||
|
|
||||||
getContextMenuItems(actionFilter: ActionFilterFn = action => action) {
|
getContextMenuItems(actionFilter: ActionFilterFn = (action) => action) {
|
||||||
return Object.values(this.actions)
|
return Object.values(this.actions)
|
||||||
.filter(actionFilter)
|
.filter(actionFilter)
|
||||||
.filter(action => "contextItemLabel" in action)
|
.filter((action) => "contextItemLabel" in action)
|
||||||
.sort(
|
.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
(a.contextMenuOrder !== undefined ? a.contextMenuOrder : 999) -
|
(a.contextMenuOrder !== undefined ? a.contextMenuOrder : 999) -
|
||||||
(b.contextMenuOrder !== undefined ? b.contextMenuOrder : 999),
|
(b.contextMenuOrder !== undefined ? b.contextMenuOrder : 999),
|
||||||
)
|
)
|
||||||
.map(action => ({
|
.map((action) => ({
|
||||||
label: action.contextItemLabel ? t(action.contextItemLabel) : "",
|
label: action.contextItemLabel ? t(action.contextItemLabel) : "",
|
||||||
action: () => {
|
action: () => {
|
||||||
this.updater(
|
this.updater(
|
||||||
|
@ -81,7 +81,7 @@ export async function getClipboardContent(
|
|||||||
export async function copyCanvasToClipboardAsPng(canvas: HTMLCanvasElement) {
|
export async function copyCanvasToClipboardAsPng(canvas: HTMLCanvasElement) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
canvas.toBlob(async function(blob: any) {
|
canvas.toBlob(async function (blob: any) {
|
||||||
try {
|
try {
|
||||||
await navigator.clipboard.write([
|
await navigator.clipboard.write([
|
||||||
new window.ClipboardItem({ "image/png": blob }),
|
new window.ClipboardItem({ "image/png": blob }),
|
||||||
|
@ -22,7 +22,7 @@ export function SelectedShapeActions({
|
|||||||
<div className="panelColumn">
|
<div className="panelColumn">
|
||||||
{renderAction("changeStrokeColor")}
|
{renderAction("changeStrokeColor")}
|
||||||
{(hasBackground(elementType) ||
|
{(hasBackground(elementType) ||
|
||||||
targetElements.some(element => hasBackground(element.type))) && (
|
targetElements.some((element) => hasBackground(element.type))) && (
|
||||||
<>
|
<>
|
||||||
{renderAction("changeBackgroundColor")}
|
{renderAction("changeBackgroundColor")}
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ export function SelectedShapeActions({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{(hasStroke(elementType) ||
|
{(hasStroke(elementType) ||
|
||||||
targetElements.some(element => hasStroke(element.type))) && (
|
targetElements.some((element) => hasStroke(element.type))) && (
|
||||||
<>
|
<>
|
||||||
{renderAction("changeStrokeWidth")}
|
{renderAction("changeStrokeWidth")}
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ export function SelectedShapeActions({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{(hasText(elementType) ||
|
{(hasText(elementType) ||
|
||||||
targetElements.some(element => hasText(element.type))) && (
|
targetElements.some((element) => hasText(element.type))) && (
|
||||||
<>
|
<>
|
||||||
{renderAction("changeFontSize")}
|
{renderAction("changeFontSize")}
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ import { actionFinalize } from "../actions";
|
|||||||
function withBatchedUpdates<
|
function withBatchedUpdates<
|
||||||
TFunction extends ((event: any) => void) | (() => void)
|
TFunction extends ((event: any) => void) | (() => void)
|
||||||
>(func: Parameters<TFunction>["length"] extends 0 | 1 ? TFunction : never) {
|
>(func: Parameters<TFunction>["length"] extends 0 | 1 ? TFunction : never) {
|
||||||
return (event => {
|
return ((event) => {
|
||||||
unstable_batchedUpdates(func as TFunction, event);
|
unstable_batchedUpdates(func as TFunction, event);
|
||||||
}) as TFunction;
|
}) as TFunction;
|
||||||
}
|
}
|
||||||
@ -183,7 +183,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
appState={this.state}
|
appState={this.state}
|
||||||
setAppState={this.setAppState}
|
setAppState={this.setAppState}
|
||||||
actionManager={this.actionManager}
|
actionManager={this.actionManager}
|
||||||
elements={globalSceneState.getAllElements().filter(element => {
|
elements={globalSceneState.getAllElements().filter((element) => {
|
||||||
return !element.isDeleted;
|
return !element.isDeleted;
|
||||||
})}
|
})}
|
||||||
setElements={this.setElements}
|
setElements={this.setElements}
|
||||||
@ -201,7 +201,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
}}
|
}}
|
||||||
width={canvasWidth}
|
width={canvasWidth}
|
||||||
height={canvasHeight}
|
height={canvasHeight}
|
||||||
ref={canvas => {
|
ref={(canvas) => {
|
||||||
// canvas is null when unmounting
|
// canvas is null when unmounting
|
||||||
if (canvas !== null) {
|
if (canvas !== null) {
|
||||||
this.canvas = canvas;
|
this.canvas = canvas;
|
||||||
@ -220,7 +220,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
onPointerMove={this.handleCanvasPointerMove}
|
onPointerMove={this.handleCanvasPointerMove}
|
||||||
onPointerUp={this.removePointer}
|
onPointerUp={this.removePointer}
|
||||||
onPointerCancel={this.removePointer}
|
onPointerCancel={this.removePointer}
|
||||||
onDrop={event => {
|
onDrop={(event) => {
|
||||||
const file = event.dataTransfer.files[0];
|
const file = event.dataTransfer.files[0];
|
||||||
if (
|
if (
|
||||||
file?.type === "application/json" ||
|
file?.type === "application/json" ||
|
||||||
@ -234,7 +234,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
commitToHistory: false,
|
commitToHistory: false,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.catch(error => console.error(error));
|
.catch((error) => console.error(error));
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -260,7 +260,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
if (res.commitToHistory) {
|
if (res.commitToHistory) {
|
||||||
history.resumeRecording();
|
history.resumeRecording();
|
||||||
}
|
}
|
||||||
this.setState(state => ({
|
this.setState((state) => ({
|
||||||
...res.appState,
|
...res.appState,
|
||||||
isCollaborating: state.isCollaborating,
|
isCollaborating: state.isCollaborating,
|
||||||
collaborators: state.collaborators,
|
collaborators: state.collaborators,
|
||||||
@ -276,7 +276,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
this.saveDebounced.flush();
|
this.saveDebounced.flush();
|
||||||
});
|
});
|
||||||
|
|
||||||
private disableEvent: EventHandlerNonNull = event => {
|
private disableEvent: EventHandlerNonNull = (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
};
|
};
|
||||||
private unmounted = false;
|
private unmounted = false;
|
||||||
@ -400,7 +400,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
private onResize = withBatchedUpdates(() => {
|
private onResize = withBatchedUpdates(() => {
|
||||||
globalSceneState
|
globalSceneState
|
||||||
.getAllElements()
|
.getAllElements()
|
||||||
.forEach(element => invalidateShapeForElement(element));
|
.forEach((element) => invalidateShapeForElement(element));
|
||||||
this.setState({});
|
this.setState({});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -586,7 +586,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
const dx = x - elementsCenterX;
|
const dx = x - elementsCenterX;
|
||||||
const dy = y - elementsCenterY;
|
const dy = y - elementsCenterY;
|
||||||
|
|
||||||
const newElements = clipboardElements.map(element =>
|
const newElements = clipboardElements.map((element) =>
|
||||||
duplicateElement(element, {
|
duplicateElement(element, {
|
||||||
x: element.x + dx - minX,
|
x: element.x + dx - minX,
|
||||||
y: element.y + dy - minY,
|
y: element.y + dy - minY,
|
||||||
@ -631,7 +631,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
toggleLock = () => {
|
toggleLock = () => {
|
||||||
this.setState(prevState => ({
|
this.setState((prevState) => ({
|
||||||
elementLocked: !prevState.elementLocked,
|
elementLocked: !prevState.elementLocked,
|
||||||
elementType: prevState.elementLocked
|
elementType: prevState.elementLocked
|
||||||
? "selection"
|
? "selection"
|
||||||
@ -767,7 +767,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
break;
|
break;
|
||||||
case "MOUSE_LOCATION":
|
case "MOUSE_LOCATION":
|
||||||
const { socketID, pointerCoords } = decryptedData.payload;
|
const { socketID, pointerCoords } = decryptedData.payload;
|
||||||
this.setState(state => {
|
this.setState((state) => {
|
||||||
if (!state.collaborators.has(socketID)) {
|
if (!state.collaborators.has(socketID)) {
|
||||||
state.collaborators.set(socketID, {});
|
state.collaborators.set(socketID, {});
|
||||||
}
|
}
|
||||||
@ -787,7 +787,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
this.socketInitialized = true;
|
this.socketInitialized = true;
|
||||||
});
|
});
|
||||||
this.socket.on("room-user-change", (clients: string[]) => {
|
this.socket.on("room-user-change", (clients: string[]) => {
|
||||||
this.setState(state => {
|
this.setState((state) => {
|
||||||
const collaborators: typeof state.collaborators = new Map();
|
const collaborators: typeof state.collaborators = new Map();
|
||||||
for (const socketID of clients) {
|
for (const socketID of clients) {
|
||||||
if (state.collaborators.has(socketID)) {
|
if (state.collaborators.has(socketID)) {
|
||||||
@ -901,7 +901,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
? ELEMENT_SHIFT_TRANSLATE_AMOUNT
|
? ELEMENT_SHIFT_TRANSLATE_AMOUNT
|
||||||
: ELEMENT_TRANSLATE_AMOUNT;
|
: ELEMENT_TRANSLATE_AMOUNT;
|
||||||
globalSceneState.replaceAllElements(
|
globalSceneState.replaceAllElements(
|
||||||
globalSceneState.getAllElements().map(el => {
|
globalSceneState.getAllElements().map((el) => {
|
||||||
if (this.state.selectedElementIds[el.id]) {
|
if (this.state.selectedElementIds[el.id]) {
|
||||||
const update: { x?: number; y?: number } = {};
|
const update: { x?: number; y?: number } = {};
|
||||||
if (event.key === KEYS.ARROW_LEFT) {
|
if (event.key === KEYS.ARROW_LEFT) {
|
||||||
@ -1039,7 +1039,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
globalSceneState.replaceAllElements(
|
globalSceneState.replaceAllElements(
|
||||||
globalSceneState
|
globalSceneState
|
||||||
.getAllElements()
|
.getAllElements()
|
||||||
.filter(element => element.id !== elementAtPosition.id),
|
.filter((element) => element.id !== elementAtPosition.id),
|
||||||
);
|
);
|
||||||
|
|
||||||
const centerElementX = elementAtPosition.x + elementAtPosition.width / 2;
|
const centerElementX = elementAtPosition.x + elementAtPosition.width / 2;
|
||||||
@ -1097,7 +1097,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
font: element.font,
|
font: element.font,
|
||||||
opacity: this.state.currentItemOpacity,
|
opacity: this.state.currentItemOpacity,
|
||||||
zoom: this.state.zoom,
|
zoom: this.state.zoom,
|
||||||
onSubmit: text => {
|
onSubmit: (text) => {
|
||||||
if (text) {
|
if (text) {
|
||||||
globalSceneState.replaceAllElements([
|
globalSceneState.replaceAllElements([
|
||||||
...globalSceneState.getAllElements(),
|
...globalSceneState.getAllElements(),
|
||||||
@ -1105,7 +1105,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
newTextElement({ ...element, text, font: element.font }),
|
newTextElement({ ...element, text, font: element.font }),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
this.setState(prevState => ({
|
this.setState((prevState) => ({
|
||||||
selectedElementIds: {
|
selectedElementIds: {
|
||||||
...prevState.selectedElementIds,
|
...prevState.selectedElementIds,
|
||||||
[element.id]: true,
|
[element.id]: true,
|
||||||
@ -1477,7 +1477,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
// otherwise, it will trigger selection based on current
|
// otherwise, it will trigger selection based on current
|
||||||
// state of the box
|
// state of the box
|
||||||
if (!this.state.selectedElementIds[hitElement.id]) {
|
if (!this.state.selectedElementIds[hitElement.id]) {
|
||||||
this.setState(prevState => ({
|
this.setState((prevState) => ({
|
||||||
selectedElementIds: {
|
selectedElementIds: {
|
||||||
...prevState.selectedElementIds,
|
...prevState.selectedElementIds,
|
||||||
[hitElement!.id]: true,
|
[hitElement!.id]: true,
|
||||||
@ -1557,7 +1557,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
opacity: this.state.currentItemOpacity,
|
opacity: this.state.currentItemOpacity,
|
||||||
font: this.state.currentItemFont,
|
font: this.state.currentItemFont,
|
||||||
zoom: this.state.zoom,
|
zoom: this.state.zoom,
|
||||||
onSubmit: text => {
|
onSubmit: (text) => {
|
||||||
if (text) {
|
if (text) {
|
||||||
globalSceneState.replaceAllElements([
|
globalSceneState.replaceAllElements([
|
||||||
...globalSceneState.getAllElements(),
|
...globalSceneState.getAllElements(),
|
||||||
@ -1568,7 +1568,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
this.setState(prevState => ({
|
this.setState((prevState) => ({
|
||||||
selectedElementIds: {
|
selectedElementIds: {
|
||||||
...prevState.selectedElementIds,
|
...prevState.selectedElementIds,
|
||||||
[element.id]: true,
|
[element.id]: true,
|
||||||
@ -1619,7 +1619,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
this.actionManager.executeAction(actionFinalize);
|
this.actionManager.executeAction(actionFinalize);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.setState(prevState => ({
|
this.setState((prevState) => ({
|
||||||
selectedElementIds: {
|
selectedElementIds: {
|
||||||
...prevState.selectedElementIds,
|
...prevState.selectedElementIds,
|
||||||
[multiElement.id]: true,
|
[multiElement.id]: true,
|
||||||
@ -1644,7 +1644,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
roughness: this.state.currentItemRoughness,
|
roughness: this.state.currentItemRoughness,
|
||||||
opacity: this.state.currentItemOpacity,
|
opacity: this.state.currentItemOpacity,
|
||||||
});
|
});
|
||||||
this.setState(prevState => ({
|
this.setState((prevState) => ({
|
||||||
selectedElementIds: {
|
selectedElementIds: {
|
||||||
...prevState.selectedElementIds,
|
...prevState.selectedElementIds,
|
||||||
[element.id]: false,
|
[element.id]: false,
|
||||||
@ -2057,7 +2057,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
window.devicePixelRatio,
|
window.devicePixelRatio,
|
||||||
);
|
);
|
||||||
|
|
||||||
selectedElements.forEach(element => {
|
selectedElements.forEach((element) => {
|
||||||
mutateElement(element, {
|
mutateElement(element, {
|
||||||
x: element.x + x - lastX,
|
x: element.x + x - lastX,
|
||||||
y: element.y + y - lastY,
|
y: element.y + y - lastY,
|
||||||
@ -2139,7 +2139,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
globalSceneState.getAllElements(),
|
globalSceneState.getAllElements(),
|
||||||
draggingElement,
|
draggingElement,
|
||||||
);
|
);
|
||||||
this.setState(prevState => ({
|
this.setState((prevState) => ({
|
||||||
selectedElementIds: {
|
selectedElementIds: {
|
||||||
...prevState.selectedElementIds,
|
...prevState.selectedElementIds,
|
||||||
...elementsWithinSelection.reduce((map, element) => {
|
...elementsWithinSelection.reduce((map, element) => {
|
||||||
@ -2196,7 +2196,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
} else if (draggingOccurred && !multiElement) {
|
} else if (draggingOccurred && !multiElement) {
|
||||||
if (!elementLocked) {
|
if (!elementLocked) {
|
||||||
resetCursor();
|
resetCursor();
|
||||||
this.setState(prevState => ({
|
this.setState((prevState) => ({
|
||||||
draggingElement: null,
|
draggingElement: null,
|
||||||
elementType: "selection",
|
elementType: "selection",
|
||||||
selectedElementIds: {
|
selectedElementIds: {
|
||||||
@ -2205,7 +2205,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
this.setState(prevState => ({
|
this.setState((prevState) => ({
|
||||||
draggingElement: null,
|
draggingElement: null,
|
||||||
selectedElementIds: {
|
selectedElementIds: {
|
||||||
...prevState.selectedElementIds,
|
...prevState.selectedElementIds,
|
||||||
@ -2242,7 +2242,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
globalSceneState.replaceAllElements(
|
globalSceneState.replaceAllElements(
|
||||||
globalSceneState
|
globalSceneState
|
||||||
.getAllElements()
|
.getAllElements()
|
||||||
.filter(el => el.id !== resizingElement.id),
|
.filter((el) => el.id !== resizingElement.id),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2256,14 +2256,14 @@ export class App extends React.Component<any, AppState> {
|
|||||||
// selection unchanged
|
// selection unchanged
|
||||||
if (hitElement && !draggingOccurred && !hitElementWasAddedToSelection) {
|
if (hitElement && !draggingOccurred && !hitElementWasAddedToSelection) {
|
||||||
if (event.shiftKey) {
|
if (event.shiftKey) {
|
||||||
this.setState(prevState => ({
|
this.setState((prevState) => ({
|
||||||
selectedElementIds: {
|
selectedElementIds: {
|
||||||
...prevState.selectedElementIds,
|
...prevState.selectedElementIds,
|
||||||
[hitElement!.id]: false,
|
[hitElement!.id]: false,
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
this.setState(prevState => ({
|
this.setState((prevState) => ({
|
||||||
selectedElementIds: { [hitElement!.id]: true },
|
selectedElementIds: { [hitElement!.id]: true },
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -2276,7 +2276,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!elementLocked) {
|
if (!elementLocked) {
|
||||||
this.setState(prevState => ({
|
this.setState((prevState) => ({
|
||||||
selectedElementIds: {
|
selectedElementIds: {
|
||||||
...prevState.selectedElementIds,
|
...prevState.selectedElementIds,
|
||||||
[draggingElement.id]: true,
|
[draggingElement.id]: true,
|
||||||
@ -2341,7 +2341,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
label: t("labels.copyAsPng"),
|
label: t("labels.copyAsPng"),
|
||||||
action: this.copyToClipboardAsPng,
|
action: this.copyToClipboardAsPng,
|
||||||
},
|
},
|
||||||
...this.actionManager.getContextMenuItems(action =>
|
...this.actionManager.getContextMenuItems((action) =>
|
||||||
this.canvasOnlyActions.includes(action.name),
|
this.canvasOnlyActions.includes(action.name),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -2370,7 +2370,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
action: this.copyToClipboardAsPng,
|
action: this.copyToClipboardAsPng,
|
||||||
},
|
},
|
||||||
...this.actionManager.getContextMenuItems(
|
...this.actionManager.getContextMenuItems(
|
||||||
action => !this.canvasOnlyActions.includes(action.name),
|
(action) => !this.canvasOnlyActions.includes(action.name),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
top: event.clientY,
|
top: event.clientY,
|
||||||
|
@ -13,7 +13,7 @@ export function ButtonSelect<T>({
|
|||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className="buttonList">
|
<div className="buttonList">
|
||||||
{options.map(option => (
|
{options.map((option) => (
|
||||||
<label
|
<label
|
||||||
key={option.text}
|
key={option.text}
|
||||||
className={value === option.value ? "active" : ""}
|
className={value === option.value ? "active" : ""}
|
||||||
|
@ -18,7 +18,7 @@ const keyBindings = [
|
|||||||
["a", "s", "d", "f", "g"],
|
["a", "s", "d", "f", "g"],
|
||||||
].flat();
|
].flat();
|
||||||
|
|
||||||
const Picker = function({
|
const Picker = function ({
|
||||||
colors,
|
colors,
|
||||||
color,
|
color,
|
||||||
onChange,
|
onChange,
|
||||||
@ -114,7 +114,7 @@ const Picker = function({
|
|||||||
<div className="color-picker-triangle"></div>
|
<div className="color-picker-triangle"></div>
|
||||||
<div
|
<div
|
||||||
className="color-picker-content"
|
className="color-picker-content"
|
||||||
ref={el => {
|
ref={(el) => {
|
||||||
if (el) {
|
if (el) {
|
||||||
gallery.current = el;
|
gallery.current = el;
|
||||||
}
|
}
|
||||||
@ -131,7 +131,7 @@ const Picker = function({
|
|||||||
aria-keyshortcuts={keyBindings[i]}
|
aria-keyshortcuts={keyBindings[i]}
|
||||||
style={{ backgroundColor: _color }}
|
style={{ backgroundColor: _color }}
|
||||||
key={_color}
|
key={_color}
|
||||||
ref={el => {
|
ref={(el) => {
|
||||||
if (el && i === 0) {
|
if (el && i === 0) {
|
||||||
firstItem.current = el;
|
firstItem.current = el;
|
||||||
}
|
}
|
||||||
@ -145,9 +145,7 @@ const Picker = function({
|
|||||||
>
|
>
|
||||||
{_color === "transparent" ? (
|
{_color === "transparent" ? (
|
||||||
<div className="color-picker-transparent"></div>
|
<div className="color-picker-transparent"></div>
|
||||||
) : (
|
) : undefined}
|
||||||
undefined
|
|
||||||
)}
|
|
||||||
<span className="color-picker-keybinding">{keyBindings[i]}</span>
|
<span className="color-picker-keybinding">{keyBindings[i]}</span>
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
@ -155,7 +153,7 @@ const Picker = function({
|
|||||||
<ColorInput
|
<ColorInput
|
||||||
color={color}
|
color={color}
|
||||||
label={label}
|
label={label}
|
||||||
onChange={color => {
|
onChange={(color) => {
|
||||||
onChange(color);
|
onChange(color);
|
||||||
}}
|
}}
|
||||||
ref={colorInput}
|
ref={colorInput}
|
||||||
@ -196,7 +194,7 @@ const ColorInput = React.forwardRef(
|
|||||||
spellCheck={false}
|
spellCheck={false}
|
||||||
className="color-picker-input"
|
className="color-picker-input"
|
||||||
aria-label={label}
|
aria-label={label}
|
||||||
onChange={event => {
|
onChange={(event) => {
|
||||||
const value = event.target.value.toLowerCase();
|
const value = event.target.value.toLowerCase();
|
||||||
if (value.match(colorRegex)) {
|
if (value.match(colorRegex)) {
|
||||||
onChange(value === "transparent" ? "transparent" : `#${value}`);
|
onChange(value === "transparent" ? "transparent" : `#${value}`);
|
||||||
@ -204,7 +202,7 @@ const ColorInput = React.forwardRef(
|
|||||||
setInnerValue(value);
|
setInnerValue(value);
|
||||||
}}
|
}}
|
||||||
value={(innerValue || "").replace(/^#/, "")}
|
value={(innerValue || "").replace(/^#/, "")}
|
||||||
onPaste={event => onChange(event.clipboardData.getData("text"))}
|
onPaste={(event) => onChange(event.clipboardData.getData("text"))}
|
||||||
onBlur={() => setInnerValue(color)}
|
onBlur={() => setInnerValue(color)}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
/>
|
/>
|
||||||
@ -244,7 +242,7 @@ export function ColorPicker({
|
|||||||
<ColorInput
|
<ColorInput
|
||||||
color={color}
|
color={color}
|
||||||
label={label}
|
label={label}
|
||||||
onChange={color => {
|
onChange={(color) => {
|
||||||
onChange(color);
|
onChange(color);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -255,7 +253,7 @@ export function ColorPicker({
|
|||||||
<Picker
|
<Picker
|
||||||
colors={colors[type]}
|
colors={colors[type]}
|
||||||
color={color || null}
|
color={color || null}
|
||||||
onChange={changedColor => {
|
onChange={(changedColor) => {
|
||||||
onChange(changedColor);
|
onChange(changedColor);
|
||||||
}}
|
}}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
|
@ -26,7 +26,7 @@ function ContextMenu({ options, onCloseRequest, top, left }: Props) {
|
|||||||
>
|
>
|
||||||
<ul
|
<ul
|
||||||
className="context-menu"
|
className="context-menu"
|
||||||
onContextMenu={event => event.preventDefault()}
|
onContextMenu={(event) => event.preventDefault()}
|
||||||
>
|
>
|
||||||
{options.map((option, idx) => (
|
{options.map((option, idx) => (
|
||||||
<li key={idx} onClick={onCloseRequest}>
|
<li key={idx} onClick={onCloseRequest}>
|
||||||
@ -69,7 +69,7 @@ function handleClose() {
|
|||||||
export default {
|
export default {
|
||||||
push(params: ContextMenuParams) {
|
push(params: ContextMenuParams) {
|
||||||
const options = Array.of<ContextMenuOption>();
|
const options = Array.of<ContextMenuOption>();
|
||||||
params.options.forEach(option => {
|
params.options.forEach((option) => {
|
||||||
if (option) {
|
if (option) {
|
||||||
options.push(option);
|
options.push(option);
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,7 @@ function ExportModal({
|
|||||||
{actionManager.renderAction("changeProjectName")}
|
{actionManager.renderAction("changeProjectName")}
|
||||||
</div>
|
</div>
|
||||||
<Stack.Row gap={2}>
|
<Stack.Row gap={2}>
|
||||||
{scales.map(s => (
|
{scales.map((s) => (
|
||||||
<ToolButton
|
<ToolButton
|
||||||
key={s}
|
key={s}
|
||||||
size="s"
|
size="s"
|
||||||
@ -174,7 +174,7 @@ function ExportModal({
|
|||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={exportSelected}
|
checked={exportSelected}
|
||||||
onChange={event =>
|
onChange={(event) =>
|
||||||
setExportSelected(event.currentTarget.checked)
|
setExportSelected(event.currentTarget.checked)
|
||||||
}
|
}
|
||||||
ref={onlySelectedInput}
|
ref={onlySelectedInput}
|
||||||
|
@ -22,7 +22,7 @@ export function LanguageList({
|
|||||||
value={currentLanguage}
|
value={currentLanguage}
|
||||||
aria-label={i18n.t("buttons.selectLanguage")}
|
aria-label={i18n.t("buttons.selectLanguage")}
|
||||||
>
|
>
|
||||||
{languages.map(language => (
|
{languages.map((language) => (
|
||||||
<option key={language.lng} value={language.lng}>
|
<option key={language.lng} value={language.lng}>
|
||||||
{language.label}
|
{language.label}
|
||||||
</option>
|
</option>
|
||||||
|
@ -73,7 +73,7 @@ export const LayerUI = React.memo(
|
|||||||
onExportToPng={createExporter("png")}
|
onExportToPng={createExporter("png")}
|
||||||
onExportToSvg={createExporter("svg")}
|
onExportToSvg={createExporter("svg")}
|
||||||
onExportToClipboard={createExporter("clipboard")}
|
onExportToClipboard={createExporter("clipboard")}
|
||||||
onExportToBackend={exportedElements => {
|
onExportToBackend={(exportedElements) => {
|
||||||
if (canvas) {
|
if (canvas) {
|
||||||
exportCanvas(
|
exportCanvas(
|
||||||
"backend",
|
"backend",
|
||||||
@ -143,7 +143,7 @@ export const LayerUI = React.memo(
|
|||||||
)}
|
)}
|
||||||
</Stack.Col>
|
</Stack.Col>
|
||||||
<Section heading="shapes">
|
<Section heading="shapes">
|
||||||
{heading => (
|
{(heading) => (
|
||||||
<Stack.Col gap={4} align="start">
|
<Stack.Col gap={4} align="start">
|
||||||
<Stack.Row gap={1}>
|
<Stack.Row gap={1}>
|
||||||
<Island padding={1}>
|
<Island padding={1}>
|
||||||
@ -184,7 +184,7 @@ export const LayerUI = React.memo(
|
|||||||
</FixedSideContainer>
|
</FixedSideContainer>
|
||||||
<footer role="contentinfo">
|
<footer role="contentinfo">
|
||||||
<LanguageList
|
<LanguageList
|
||||||
onChange={lng => {
|
onChange={(lng) => {
|
||||||
setLanguage(lng);
|
setLanguage(lng);
|
||||||
setAppState({});
|
setAppState({});
|
||||||
}}
|
}}
|
||||||
@ -228,7 +228,7 @@ export const LayerUI = React.memo(
|
|||||||
return (
|
return (
|
||||||
prev.language === next.language &&
|
prev.language === next.language &&
|
||||||
prev.elements === next.elements &&
|
prev.elements === next.elements &&
|
||||||
keys.every(key => prevAppState[key] === nextAppState[key])
|
keys.every((key) => prevAppState[key] === nextAppState[key])
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -40,7 +40,7 @@ export function MobileMenu({
|
|||||||
<>
|
<>
|
||||||
<FixedSideContainer side="top">
|
<FixedSideContainer side="top">
|
||||||
<Section heading="shapes">
|
<Section heading="shapes">
|
||||||
{heading => (
|
{(heading) => (
|
||||||
<Stack.Col gap={4} align="center">
|
<Stack.Col gap={4} align="center">
|
||||||
<Stack.Row gap={1}>
|
<Stack.Row gap={1}>
|
||||||
<Island padding={1}>
|
<Island padding={1}>
|
||||||
@ -87,7 +87,7 @@ export function MobileMenu({
|
|||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>{t("labels.language")}</legend>
|
<legend>{t("labels.language")}</legend>
|
||||||
<LanguageList
|
<LanguageList
|
||||||
onChange={lng => {
|
onChange={(lng) => {
|
||||||
setLanguage(lng);
|
setLanguage(lng);
|
||||||
setAppState({});
|
setAppState({});
|
||||||
}}
|
}}
|
||||||
|
@ -35,7 +35,7 @@ type ToolButtonProps =
|
|||||||
|
|
||||||
const DEFAULT_SIZE: ToolIconSize = "m";
|
const DEFAULT_SIZE: ToolIconSize = "m";
|
||||||
|
|
||||||
export const ToolButton = React.forwardRef(function(
|
export const ToolButton = React.forwardRef(function (
|
||||||
props: ToolButtonProps,
|
props: ToolButtonProps,
|
||||||
ref,
|
ref,
|
||||||
) {
|
) {
|
||||||
|
@ -34,7 +34,7 @@ export class TopErrorBoundary extends React.Component<
|
|||||||
_localStorage[key] = value;
|
_localStorage[key] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.setState(state => ({
|
this.setState((state) => ({
|
||||||
hasError: true,
|
hasError: true,
|
||||||
unresolvedError: state.unresolvedError
|
unresolvedError: state.unresolvedError
|
||||||
? state.unresolvedError.concat(error)
|
? state.unresolvedError.concat(error)
|
||||||
@ -60,7 +60,7 @@ export class TopErrorBoundary extends React.Component<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState(state => ({
|
this.setState((state) => ({
|
||||||
unresolvedError: null,
|
unresolvedError: null,
|
||||||
stack: `${
|
stack: `${
|
||||||
state.stack ? `${state.stack}\n\n================\n\n${stack}` : stack
|
state.stack ? `${state.stack}\n\n================\n\n${stack}` : stack
|
||||||
|
@ -27,7 +27,7 @@ export async function loadFromBlob(blob: any) {
|
|||||||
if ("text" in Blob) {
|
if ("text" in Blob) {
|
||||||
contents = await blob.text();
|
contents = await blob.text();
|
||||||
} else {
|
} else {
|
||||||
contents = await new Promise(resolve => {
|
contents = await new Promise((resolve) => {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.readAsText(blob, "utf8");
|
reader.readAsText(blob, "utf8");
|
||||||
reader.onloadend = () => {
|
reader.onloadend = () => {
|
||||||
@ -41,7 +41,7 @@ export async function loadFromBlob(blob: any) {
|
|||||||
if (!elements.length) {
|
if (!elements.length) {
|
||||||
return Promise.reject("Cannot load invalid json");
|
return Promise.reject("Cannot load invalid json");
|
||||||
}
|
}
|
||||||
return new Promise<DataState>(resolve => {
|
return new Promise<DataState>((resolve) => {
|
||||||
resolve(restore(elements, appState, { scrollToContent: true }));
|
resolve(restore(elements, appState, { scrollToContent: true }));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ export function serializeAsJSON(
|
|||||||
type: "excalidraw",
|
type: "excalidraw",
|
||||||
version: 1,
|
version: 1,
|
||||||
source: window.location.origin,
|
source: window.location.origin,
|
||||||
elements: elements.filter(element => !element.isDeleted),
|
elements: elements.filter((element) => !element.isDeleted),
|
||||||
appState: cleanAppStateForExport(appState),
|
appState: cleanAppStateForExport(appState),
|
||||||
},
|
},
|
||||||
null,
|
null,
|
||||||
|
@ -12,7 +12,7 @@ export function saveToLocalStorage(
|
|||||||
) {
|
) {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
LOCAL_STORAGE_KEY,
|
LOCAL_STORAGE_KEY,
|
||||||
JSON.stringify(elements.filter(element => !element.isDeleted)),
|
JSON.stringify(elements.filter((element) => !element.isDeleted)),
|
||||||
);
|
);
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
LOCAL_STORAGE_KEY_STATE,
|
LOCAL_STORAGE_KEY_STATE,
|
||||||
|
@ -15,12 +15,12 @@ export function restore(
|
|||||||
opts?: { scrollToContent: boolean },
|
opts?: { scrollToContent: boolean },
|
||||||
): DataState {
|
): DataState {
|
||||||
const elements = savedElements
|
const elements = savedElements
|
||||||
.filter(el => {
|
.filter((el) => {
|
||||||
// filtering out selection, which is legacy, no longer kept in elements,
|
// filtering out selection, which is legacy, no longer kept in elements,
|
||||||
// and causing issues if retained
|
// and causing issues if retained
|
||||||
return el.type !== "selection" && !isInvisiblySmallElement(el);
|
return el.type !== "selection" && !isInvisiblySmallElement(el);
|
||||||
})
|
})
|
||||||
.map(element => {
|
.map((element) => {
|
||||||
let points: Point[] = [];
|
let points: Point[] = [];
|
||||||
if (element.type === "arrow") {
|
if (element.type === "arrow") {
|
||||||
if (Array.isArray(element.points)) {
|
if (Array.isArray(element.points)) {
|
||||||
|
@ -192,7 +192,7 @@ export function getCommonBounds(elements: readonly ExcalidrawElement[]) {
|
|||||||
let minY = Infinity;
|
let minY = Infinity;
|
||||||
let maxY = -Infinity;
|
let maxY = -Infinity;
|
||||||
|
|
||||||
elements.forEach(element => {
|
elements.forEach((element) => {
|
||||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
|
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
|
||||||
minX = Math.min(minX, x1);
|
minX = Math.min(minX, x1);
|
||||||
minY = Math.min(minY, y1);
|
minY = Math.min(minY, y1);
|
||||||
|
@ -45,7 +45,7 @@ export function hitTest(
|
|||||||
const a = Math.abs(element.width) / 2;
|
const a = Math.abs(element.width) / 2;
|
||||||
const b = Math.abs(element.height) / 2;
|
const b = Math.abs(element.height) / 2;
|
||||||
|
|
||||||
[0, 1, 2, 3].forEach(x => {
|
[0, 1, 2, 3].forEach((x) => {
|
||||||
const xx = a * tx;
|
const xx = a * tx;
|
||||||
const yy = b * ty;
|
const yy = b * ty;
|
||||||
|
|
||||||
@ -179,7 +179,7 @@ export function hitTest(
|
|||||||
const relY = y - element.y;
|
const relY = y - element.y;
|
||||||
|
|
||||||
// hit thest all "subshapes" of the linear element
|
// hit thest all "subshapes" of the linear element
|
||||||
return shape.some(subshape =>
|
return shape.some((subshape) =>
|
||||||
hitTestRoughShape(subshape.sets, relX, relY, lineThreshold),
|
hitTestRoughShape(subshape.sets, relX, relY, lineThreshold),
|
||||||
);
|
);
|
||||||
} else if (element.type === "text") {
|
} else if (element.type === "text") {
|
||||||
|
@ -37,7 +37,7 @@ export function getSyncableElements(elements: readonly ExcalidrawElement[]) {
|
|||||||
// There are places in Excalidraw where synthetic invisibly small elements are added and removed.
|
// There are places in Excalidraw where synthetic invisibly small elements are added and removed.
|
||||||
// It's probably best to keep those local otherwise there might be a race condition that
|
// It's probably best to keep those local otherwise there might be a race condition that
|
||||||
// gets the app into an invalid state. I've never seen it happen but I'm worried about it :)
|
// gets the app into an invalid state. I've never seen it happen but I'm worried about it :)
|
||||||
return elements.filter(el => !isInvisiblySmallElement(el));
|
return elements.filter((el) => !isInvisiblySmallElement(el));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getElementMap(elements: readonly ExcalidrawElement[]) {
|
export function getElementMap(elements: readonly ExcalidrawElement[]) {
|
||||||
@ -55,5 +55,5 @@ export function getDrawingVersion(elements: readonly ExcalidrawElement[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function hasNonDeletedElements(elements: readonly ExcalidrawElement[]) {
|
export function hasNonDeletedElements(elements: readonly ExcalidrawElement[]) {
|
||||||
return elements.some(element => !element.isDeleted);
|
return elements.some((element) => !element.isDeleted);
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ export function resizeTest(
|
|||||||
|
|
||||||
const handlers = handlerRectangles(element, zoom, pointerType);
|
const handlers = handlerRectangles(element, zoom, pointerType);
|
||||||
|
|
||||||
const filter = Object.keys(handlers).filter(key => {
|
const filter = Object.keys(handlers).filter((key) => {
|
||||||
const handler = handlers[key as HandlerRectanglesRet]!;
|
const handler = handlers[key as HandlerRectanglesRet]!;
|
||||||
if (!handler) {
|
if (!handler) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -64,7 +64,7 @@ export function textWysiwyg({
|
|||||||
backfaceVisibility: "hidden",
|
backfaceVisibility: "hidden",
|
||||||
});
|
});
|
||||||
|
|
||||||
editable.onpaste = ev => {
|
editable.onpaste = (ev) => {
|
||||||
try {
|
try {
|
||||||
const selection = window.getSelection();
|
const selection = window.getSelection();
|
||||||
if (!selection?.rangeCount) {
|
if (!selection?.rangeCount) {
|
||||||
@ -91,7 +91,7 @@ export function textWysiwyg({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
editable.onkeydown = ev => {
|
editable.onkeydown = (ev) => {
|
||||||
if (ev.key === KEYS.ESCAPE) {
|
if (ev.key === KEYS.ESCAPE) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
handleSubmit();
|
handleSubmit();
|
||||||
|
@ -4,8 +4,8 @@ import { normalizeScroll } from "./scene";
|
|||||||
export function getCenter(pointers: Map<number, PointerCoords>) {
|
export function getCenter(pointers: Map<number, PointerCoords>) {
|
||||||
const allCoords = Array.from(pointers.values());
|
const allCoords = Array.from(pointers.values());
|
||||||
return {
|
return {
|
||||||
x: normalizeScroll(sum(allCoords, coords => coords.x) / allCoords.length),
|
x: normalizeScroll(sum(allCoords, (coords) => coords.x) / allCoords.length),
|
||||||
y: normalizeScroll(sum(allCoords, coords => coords.y) / allCoords.length),
|
y: normalizeScroll(sum(allCoords, (coords) => coords.y) / allCoords.length),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ const fallbackLanguage = languages[0];
|
|||||||
|
|
||||||
export function setLanguage(newLng: string | undefined) {
|
export function setLanguage(newLng: string | undefined) {
|
||||||
currentLanguage =
|
currentLanguage =
|
||||||
languages.find(language => language.lng === newLng) || fallbackLanguage;
|
languages.find((language) => language.lng === newLng) || fallbackLanguage;
|
||||||
|
|
||||||
languageDetector.cacheUserLanguage(currentLanguage.lng);
|
languageDetector.cacheUserLanguage(currentLanguage.lng);
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ export function t(path: string, replacement?: { [key: string]: string }) {
|
|||||||
const languageDetector = new LanguageDetector();
|
const languageDetector = new LanguageDetector();
|
||||||
languageDetector.init({
|
languageDetector.init({
|
||||||
languageUtils: {
|
languageUtils: {
|
||||||
formatLanguageCode: function(lng: string) {
|
formatLanguageCode: function (lng: string) {
|
||||||
return lng;
|
return lng;
|
||||||
},
|
},
|
||||||
isWhitelisted: () => true,
|
isWhitelisted: () => true,
|
||||||
|
@ -8,7 +8,7 @@ import "./styles.scss";
|
|||||||
// Block pinch-zooming on iOS outside of the content area
|
// Block pinch-zooming on iOS outside of the content area
|
||||||
document.addEventListener(
|
document.addEventListener(
|
||||||
"touchmove",
|
"touchmove",
|
||||||
function(event) {
|
function (event) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
if (event.scale !== 1) {
|
if (event.scale !== 1) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { Point } from "./types";
|
import { Point } from "./types";
|
||||||
|
|
||||||
export function getSizeFromPoints(points: readonly Point[]) {
|
export function getSizeFromPoints(points: readonly Point[]) {
|
||||||
const xs = points.map(point => point[0]);
|
const xs = points.map((point) => point[0]);
|
||||||
const ys = points.map(point => point[1]);
|
const ys = points.map((point) => point[1]);
|
||||||
return {
|
return {
|
||||||
width: Math.max(...xs) - Math.min(...xs),
|
width: Math.max(...xs) - Math.min(...xs),
|
||||||
height: Math.max(...ys) - Math.min(...ys),
|
height: Math.max(...ys) - Math.min(...ys),
|
||||||
@ -13,7 +13,7 @@ export function rescalePoints(
|
|||||||
nextDimensionSize: number,
|
nextDimensionSize: number,
|
||||||
prevPoints: readonly Point[],
|
prevPoints: readonly Point[],
|
||||||
): Point[] {
|
): Point[] {
|
||||||
const prevDimValues = prevPoints.map(point => point[dimension]);
|
const prevDimValues = prevPoints.map((point) => point[dimension]);
|
||||||
const prevMaxDimension = Math.max(...prevDimValues);
|
const prevMaxDimension = Math.max(...prevDimValues);
|
||||||
const prevMinDimension = Math.min(...prevDimValues);
|
const prevMinDimension = Math.min(...prevDimValues);
|
||||||
const prevDimensionSize = prevMaxDimension - prevMinDimension;
|
const prevDimensionSize = prevMaxDimension - prevMinDimension;
|
||||||
@ -22,7 +22,7 @@ export function rescalePoints(
|
|||||||
|
|
||||||
let nextMinDimension = Infinity;
|
let nextMinDimension = Infinity;
|
||||||
|
|
||||||
const scaledPoints = prevPoints.map(prevPoint =>
|
const scaledPoints = prevPoints.map((prevPoint) =>
|
||||||
prevPoint.map((value, currentDimension) => {
|
prevPoint.map((value, currentDimension) => {
|
||||||
if (currentDimension !== dimension) {
|
if (currentDimension !== dimension) {
|
||||||
return value;
|
return value;
|
||||||
@ -36,7 +36,7 @@ export function rescalePoints(
|
|||||||
const translation = prevMinDimension - nextMinDimension;
|
const translation = prevMinDimension - nextMinDimension;
|
||||||
|
|
||||||
const nextPoints = scaledPoints.map(
|
const nextPoints = scaledPoints.map(
|
||||||
scaledPoint =>
|
(scaledPoint) =>
|
||||||
scaledPoint.map((value, currentDimension) => {
|
scaledPoint.map((value, currentDimension) => {
|
||||||
return currentDimension === dimension ? value + translation : value;
|
return currentDimension === dimension ? value + translation : value;
|
||||||
}) as [number, number],
|
}) as [number, number],
|
||||||
|
@ -86,7 +86,7 @@ function drawElementOnCanvas(
|
|||||||
}
|
}
|
||||||
case "arrow":
|
case "arrow":
|
||||||
case "line": {
|
case "line": {
|
||||||
(getShapeForElement(element) as Drawable[]).forEach(shape =>
|
(getShapeForElement(element) as Drawable[]).forEach((shape) =>
|
||||||
rc.draw(shape),
|
rc.draw(shape),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@ -372,7 +372,7 @@ export function renderElementToSvg(
|
|||||||
generateElement(element, generator);
|
generateElement(element, generator);
|
||||||
const group = svgRoot.ownerDocument!.createElementNS(SVG_NS, "g");
|
const group = svgRoot.ownerDocument!.createElementNS(SVG_NS, "g");
|
||||||
const opacity = element.opacity / 100;
|
const opacity = element.opacity / 100;
|
||||||
(getShapeForElement(element) as Drawable[]).forEach(shape => {
|
(getShapeForElement(element) as Drawable[]).forEach((shape) => {
|
||||||
const node = rsvg.draw(shape);
|
const node = rsvg.draw(shape);
|
||||||
if (opacity !== 1) {
|
if (opacity !== 1) {
|
||||||
node.setAttribute("stroke-opacity", `${opacity}`);
|
node.setAttribute("stroke-opacity", `${opacity}`);
|
||||||
@ -402,7 +402,7 @@ export function renderElementToSvg(
|
|||||||
const lines = element.text.replace(/\r\n?/g, "\n").split("\n");
|
const lines = element.text.replace(/\r\n?/g, "\n").split("\n");
|
||||||
const lineHeight = element.height / lines.length;
|
const lineHeight = element.height / lines.length;
|
||||||
const offset = element.height - element.baseline;
|
const offset = element.height - element.baseline;
|
||||||
const fontSplit = element.font.split(" ").filter(d => !!d.trim());
|
const fontSplit = element.font.split(" ").filter((d) => !!d.trim());
|
||||||
let fontFamily = fontSplit[0];
|
let fontFamily = fontSplit[0];
|
||||||
let fontSize = "20px";
|
let fontSize = "20px";
|
||||||
if (fontSplit.length > 1) {
|
if (fontSplit.length > 1) {
|
||||||
|
@ -52,7 +52,7 @@ export function renderScene(
|
|||||||
return { atLeastOneVisibleElement: false };
|
return { atLeastOneVisibleElement: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
const elements = allElements.filter(element => !element.isDeleted);
|
const elements = allElements.filter((element) => !element.isDeleted);
|
||||||
|
|
||||||
const context = canvas.getContext("2d")!;
|
const context = canvas.getContext("2d")!;
|
||||||
context.scale(scale, scale);
|
context.scale(scale, scale);
|
||||||
@ -86,7 +86,7 @@ export function renderScene(
|
|||||||
context.scale(sceneState.zoom, sceneState.zoom);
|
context.scale(sceneState.zoom, sceneState.zoom);
|
||||||
|
|
||||||
// Paint visible elements
|
// Paint visible elements
|
||||||
const visibleElements = elements.filter(element =>
|
const visibleElements = elements.filter((element) =>
|
||||||
isVisibleElement(
|
isVisibleElement(
|
||||||
element,
|
element,
|
||||||
normalizedCanvasWidth,
|
normalizedCanvasWidth,
|
||||||
@ -95,7 +95,7 @@ export function renderScene(
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
visibleElements.forEach(element => {
|
visibleElements.forEach((element) => {
|
||||||
renderElement(element, rc, context, renderOptimizations, sceneState);
|
renderElement(element, rc, context, renderOptimizations, sceneState);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -116,7 +116,7 @@ export function renderScene(
|
|||||||
const dashledLinePadding = 4 / sceneState.zoom;
|
const dashledLinePadding = 4 / sceneState.zoom;
|
||||||
|
|
||||||
context.translate(sceneState.scrollX, sceneState.scrollY);
|
context.translate(sceneState.scrollX, sceneState.scrollY);
|
||||||
selectedElements.forEach(element => {
|
selectedElements.forEach((element) => {
|
||||||
const [
|
const [
|
||||||
elementX1,
|
elementX1,
|
||||||
elementY1,
|
elementY1,
|
||||||
@ -148,8 +148,8 @@ export function renderScene(
|
|||||||
context.fillStyle = "#fff";
|
context.fillStyle = "#fff";
|
||||||
const handlers = handlerRectangles(selectedElements[0], sceneState.zoom);
|
const handlers = handlerRectangles(selectedElements[0], sceneState.zoom);
|
||||||
Object.values(handlers)
|
Object.values(handlers)
|
||||||
.filter(handler => handler !== undefined)
|
.filter((handler) => handler !== undefined)
|
||||||
.forEach(handler => {
|
.forEach((handler) => {
|
||||||
const lineWidth = context.lineWidth;
|
const lineWidth = context.lineWidth;
|
||||||
context.lineWidth = 1 / sceneState.zoom;
|
context.lineWidth = 1 / sceneState.zoom;
|
||||||
context.fillRect(handler[0], handler[1], handler[2], handler[3]);
|
context.fillRect(handler[0], handler[1], handler[2], handler[3]);
|
||||||
@ -219,7 +219,7 @@ export function renderScene(
|
|||||||
const strokeStyle = context.strokeStyle;
|
const strokeStyle = context.strokeStyle;
|
||||||
context.fillStyle = SCROLLBAR_COLOR;
|
context.fillStyle = SCROLLBAR_COLOR;
|
||||||
context.strokeStyle = "rgba(255,255,255,0.8)";
|
context.strokeStyle = "rgba(255,255,255,0.8)";
|
||||||
[scrollBars.horizontal, scrollBars.vertical].forEach(scrollBar => {
|
[scrollBars.horizontal, scrollBars.vertical].forEach((scrollBar) => {
|
||||||
if (scrollBar) {
|
if (scrollBar) {
|
||||||
roundRect(
|
roundRect(
|
||||||
context,
|
context,
|
||||||
@ -288,7 +288,7 @@ export function renderSceneToSvg(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// render elements
|
// render elements
|
||||||
elements.forEach(element => {
|
elements.forEach((element) => {
|
||||||
if (!element.isDeleted) {
|
if (!element.isDeleted) {
|
||||||
renderElementToSvg(
|
renderElementToSvg(
|
||||||
element,
|
element,
|
||||||
|
@ -20,7 +20,7 @@ export function exportToCanvas(
|
|||||||
scale?: number;
|
scale?: number;
|
||||||
viewBackgroundColor: string;
|
viewBackgroundColor: string;
|
||||||
},
|
},
|
||||||
createCanvas: (width: number, height: number) => any = function(
|
createCanvas: (width: number, height: number) => any = function (
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
) {
|
) {
|
||||||
|
@ -102,7 +102,7 @@ export function isOverScrollBars(scrollBars: ScrollBars, x: number, y: number) {
|
|||||||
const [isOverHorizontalScrollBar, isOverVerticalScrollBar] = [
|
const [isOverHorizontalScrollBar, isOverVerticalScrollBar] = [
|
||||||
scrollBars.horizontal,
|
scrollBars.horizontal,
|
||||||
scrollBars.vertical,
|
scrollBars.vertical,
|
||||||
].map(scrollBar => {
|
].map((scrollBar) => {
|
||||||
return (
|
return (
|
||||||
scrollBar &&
|
scrollBar &&
|
||||||
scrollBar.x <= x &&
|
scrollBar.x <= x &&
|
||||||
|
@ -13,7 +13,7 @@ export function getElementsWithinSelection(
|
|||||||
selectionX2,
|
selectionX2,
|
||||||
selectionY2,
|
selectionY2,
|
||||||
] = getElementAbsoluteCoords(selection);
|
] = getElementAbsoluteCoords(selection);
|
||||||
return elements.filter(element => {
|
return elements.filter((element) => {
|
||||||
const [
|
const [
|
||||||
elementX1,
|
elementX1,
|
||||||
elementY1,
|
elementY1,
|
||||||
@ -36,7 +36,7 @@ export function deleteSelectedElements(
|
|||||||
appState: AppState,
|
appState: AppState,
|
||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
elements: elements.map(el => {
|
elements: elements.map((el) => {
|
||||||
if (appState.selectedElementIds[el.id]) {
|
if (appState.selectedElementIds[el.id]) {
|
||||||
return newElementWith(el, { isDeleted: true });
|
return newElementWith(el, { isDeleted: true });
|
||||||
}
|
}
|
||||||
@ -66,7 +66,7 @@ export function isSomeElementSelected(
|
|||||||
elements: readonly ExcalidrawElement[],
|
elements: readonly ExcalidrawElement[],
|
||||||
appState: AppState,
|
appState: AppState,
|
||||||
): boolean {
|
): boolean {
|
||||||
return elements.some(element => appState.selectedElementIds[element.id]);
|
return elements.some((element) => appState.selectedElementIds[element.id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -80,7 +80,7 @@ export function getCommonAttributeOfSelectedElements<T>(
|
|||||||
): T | null {
|
): T | null {
|
||||||
const attributes = Array.from(
|
const attributes = Array.from(
|
||||||
new Set(
|
new Set(
|
||||||
getSelectedElements(elements, appState).map(element =>
|
getSelectedElements(elements, appState).map((element) =>
|
||||||
getAttribute(element),
|
getAttribute(element),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -92,7 +92,7 @@ export function getSelectedElements(
|
|||||||
elements: readonly ExcalidrawElement[],
|
elements: readonly ExcalidrawElement[],
|
||||||
appState: AppState,
|
appState: AppState,
|
||||||
): readonly ExcalidrawElement[] {
|
): readonly ExcalidrawElement[] {
|
||||||
return elements.filter(element => appState.selectedElementIds[element.id]);
|
return elements.filter((element) => appState.selectedElementIds[element.id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTargetElement(
|
export function getTargetElement(
|
||||||
|
@ -90,7 +90,7 @@ export function moveAllLeft<T>(elements: T[], indicesToMove: number[]) {
|
|||||||
indicesToMove.sort((a: number, b: number) => a - b);
|
indicesToMove.sort((a: number, b: number) => a - b);
|
||||||
|
|
||||||
// Copy the elements to move
|
// Copy the elements to move
|
||||||
const leftMostElements = indicesToMove.map(index => elements[index]);
|
const leftMostElements = indicesToMove.map((index) => elements[index]);
|
||||||
|
|
||||||
const reversedIndicesToMove = indicesToMove
|
const reversedIndicesToMove = indicesToMove
|
||||||
// We go from right to left to avoid overriding elements.
|
// We go from right to left to avoid overriding elements.
|
||||||
@ -170,7 +170,9 @@ export function moveAllRight<T>(elements: T[], indicesToMove: number[]) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Copy the elements to move
|
// Copy the elements to move
|
||||||
const rightMostElements = reversedIndicesToMove.map(index => elements[index]);
|
const rightMostElements = reversedIndicesToMove.map(
|
||||||
|
(index) => elements[index],
|
||||||
|
);
|
||||||
|
|
||||||
indicesToMove = reversedIndicesToMove
|
indicesToMove = reversedIndicesToMove
|
||||||
// We go from left to right to avoid overriding elements.
|
// We go from left to right to avoid overriding elements.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user