PoC: Expose wysiwyg element to manipulate from outside (#1356)
* expose wysiwyg element to manipulate from outside * keep focus after changing style * update editingElement correctly * remove mistake * update text only * proper check for element * udpate snapshots * add error log * remove try catch handler * remove blur event * add proper types * merge if condition * simplify if condition Co-Authored-By: Lipis <lipiridis@gmail.com> Co-authored-by: dwelle <luzar.david@gmail.com> Co-authored-by: Lipis <lipiridis@gmail.com> Co-authored-by: Fausto95 <faustino.kialungila@gmail.com>
This commit is contained in:
parent
d2246bfb30
commit
5e2f164026
@ -27,7 +27,10 @@ const changeProperty = (
|
|||||||
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] ||
|
||||||
|
element.id === appState.editingElement?.id
|
||||||
|
) {
|
||||||
return callback(element);
|
return callback(element);
|
||||||
}
|
}
|
||||||
return element;
|
return element;
|
||||||
|
@ -8,6 +8,7 @@ export const DEFAULT_TEXT_ALIGN = "left";
|
|||||||
|
|
||||||
export function getDefaultAppState(): AppState {
|
export function getDefaultAppState(): AppState {
|
||||||
return {
|
return {
|
||||||
|
wysiwygElement: null,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
draggingElement: null,
|
draggingElement: null,
|
||||||
|
@ -25,6 +25,7 @@ import {
|
|||||||
getElementWithResizeHandler,
|
getElementWithResizeHandler,
|
||||||
canResizeMutlipleElements,
|
canResizeMutlipleElements,
|
||||||
getResizeHandlerFromCoords,
|
getResizeHandlerFromCoords,
|
||||||
|
isNonDeletedElement,
|
||||||
} from "../element";
|
} from "../element";
|
||||||
import {
|
import {
|
||||||
deleteSelectedElements,
|
deleteSelectedElements,
|
||||||
@ -269,19 +270,31 @@ export class App extends React.Component<any, AppState> {
|
|||||||
if (this.unmounted) {
|
if (this.unmounted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let editingElement: AppState["editingElement"] | null = null;
|
||||||
if (res.elements) {
|
if (res.elements) {
|
||||||
|
res.elements.forEach((element) => {
|
||||||
|
if (
|
||||||
|
this.state.editingElement?.id === element.id &&
|
||||||
|
this.state.editingElement !== element &&
|
||||||
|
isNonDeletedElement(element)
|
||||||
|
) {
|
||||||
|
editingElement = element;
|
||||||
|
}
|
||||||
|
});
|
||||||
globalSceneState.replaceAllElements(res.elements);
|
globalSceneState.replaceAllElements(res.elements);
|
||||||
if (res.commitToHistory) {
|
if (res.commitToHistory) {
|
||||||
history.resumeRecording();
|
history.resumeRecording();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res.appState) {
|
if (res.appState || editingElement) {
|
||||||
if (res.commitToHistory) {
|
if (res.commitToHistory) {
|
||||||
history.resumeRecording();
|
history.resumeRecording();
|
||||||
}
|
}
|
||||||
this.setState((state) => ({
|
this.setState((state) => ({
|
||||||
...res.appState,
|
...res.appState,
|
||||||
|
editingElement: editingElement || state.editingElement,
|
||||||
isCollaborating: state.isCollaborating,
|
isCollaborating: state.isCollaborating,
|
||||||
collaborators: state.collaborators,
|
collaborators: state.collaborators,
|
||||||
}));
|
}));
|
||||||
@ -1186,9 +1199,6 @@ export class App extends React.Component<any, AppState> {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// deselect all other elements when inserting text
|
|
||||||
this.setState({ selectedElementIds: {} });
|
|
||||||
|
|
||||||
const deleteElement = () => {
|
const deleteElement = () => {
|
||||||
globalSceneState.replaceAllElements([
|
globalSceneState.replaceAllElements([
|
||||||
...globalSceneState.getElementsIncludingDeleted().map((_element) => {
|
...globalSceneState.getElementsIncludingDeleted().map((_element) => {
|
||||||
@ -1216,7 +1226,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
textWysiwyg({
|
const wysiwygElement = textWysiwyg({
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
initText: element.text,
|
initText: element.text,
|
||||||
@ -1236,6 +1246,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
onSubmit: withBatchedUpdates((text) => {
|
onSubmit: withBatchedUpdates((text) => {
|
||||||
updateElement(text);
|
updateElement(text);
|
||||||
this.setState((prevState) => ({
|
this.setState((prevState) => ({
|
||||||
|
wysiwygElement: null,
|
||||||
selectedElementIds: {
|
selectedElementIds: {
|
||||||
...prevState.selectedElementIds,
|
...prevState.selectedElementIds,
|
||||||
[element.id]: true,
|
[element.id]: true,
|
||||||
@ -1255,6 +1266,8 @@ export class App extends React.Component<any, AppState> {
|
|||||||
resetSelection();
|
resetSelection();
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
// deselect all other elements when inserting text
|
||||||
|
this.setState({ selectedElementIds: {}, wysiwygElement });
|
||||||
|
|
||||||
// do an initial update to re-initialize element position since we were
|
// do an initial update to re-initialize element position since we were
|
||||||
// modifying element's x/y for sake of editor (case: syncing to remote)
|
// modifying element's x/y for sake of editor (case: syncing to remote)
|
||||||
@ -1564,6 +1577,9 @@ export class App extends React.Component<any, AppState> {
|
|||||||
private handleCanvasPointerDown = (
|
private handleCanvasPointerDown = (
|
||||||
event: React.PointerEvent<HTMLCanvasElement>,
|
event: React.PointerEvent<HTMLCanvasElement>,
|
||||||
) => {
|
) => {
|
||||||
|
if (this.state.wysiwygElement && this.state.wysiwygElement.submit) {
|
||||||
|
this.state.wysiwygElement.submit();
|
||||||
|
}
|
||||||
if (lastPointerUp !== null) {
|
if (lastPointerUp !== null) {
|
||||||
// Unfortunately, sometimes we don't get a pointerup after a pointerdown,
|
// Unfortunately, sometimes we don't get a pointerup after a pointerdown,
|
||||||
// this can happen when a contextual menu or alert is triggered. In order to avoid
|
// this can happen when a contextual menu or alert is triggered. In order to avoid
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
import { ExcalidrawElement, NonDeletedExcalidrawElement } from "./types";
|
import {
|
||||||
|
ExcalidrawElement,
|
||||||
|
NonDeletedExcalidrawElement,
|
||||||
|
NonDeleted,
|
||||||
|
} from "./types";
|
||||||
import { isInvisiblySmallElement } from "./sizeHelpers";
|
import { isInvisiblySmallElement } from "./sizeHelpers";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -68,3 +72,9 @@ export function getNonDeletedElements(elements: readonly ExcalidrawElement[]) {
|
|||||||
readonly NonDeletedExcalidrawElement[]
|
readonly NonDeletedExcalidrawElement[]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isNonDeletedElement<T extends ExcalidrawElement>(
|
||||||
|
element: T,
|
||||||
|
): element is NonDeleted<T> {
|
||||||
|
return !element.isDeleted;
|
||||||
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { KEYS } from "../keys";
|
import { KEYS } from "../keys";
|
||||||
import { selectNode } from "../utils";
|
import { selectNode } from "../utils";
|
||||||
|
import { WysiwigElement } from "./types";
|
||||||
|
|
||||||
function trimText(text: string) {
|
function trimText(text: string) {
|
||||||
// whitespace only → trim all because we'd end up inserting invisible element
|
// whitespace only → trim all because we'd end up inserting invisible element
|
||||||
@ -40,7 +41,7 @@ export function textWysiwyg({
|
|||||||
textAlign,
|
textAlign,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
onCancel,
|
onCancel,
|
||||||
}: TextWysiwygParams) {
|
}: TextWysiwygParams): WysiwigElement {
|
||||||
const editable = document.createElement("div");
|
const editable = document.createElement("div");
|
||||||
try {
|
try {
|
||||||
editable.contentEditable = "plaintext-only";
|
editable.contentEditable = "plaintext-only";
|
||||||
@ -120,7 +121,6 @@ export function textWysiwyg({
|
|||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
editable.onblur = handleSubmit;
|
|
||||||
|
|
||||||
function stopEvent(event: Event) {
|
function stopEvent(event: Event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
@ -137,7 +137,6 @@ export function textWysiwyg({
|
|||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
// remove events to ensure they don't late-fire
|
// remove events to ensure they don't late-fire
|
||||||
editable.onblur = null;
|
|
||||||
editable.onpaste = null;
|
editable.onpaste = null;
|
||||||
editable.oninput = null;
|
editable.oninput = null;
|
||||||
editable.onkeydown = null;
|
editable.onkeydown = null;
|
||||||
@ -150,4 +149,12 @@ export function textWysiwyg({
|
|||||||
document.body.appendChild(editable);
|
document.body.appendChild(editable);
|
||||||
editable.focus();
|
editable.focus();
|
||||||
selectNode(editable);
|
selectNode(editable);
|
||||||
|
|
||||||
|
return {
|
||||||
|
submit: handleSubmit,
|
||||||
|
changeStyle: (style: any) => {
|
||||||
|
Object.assign(editable.style, style);
|
||||||
|
editable.focus();
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -68,3 +68,8 @@ export type ResizeArrowFnType = (
|
|||||||
pointerY: number,
|
pointerY: number,
|
||||||
perfect: boolean,
|
perfect: boolean,
|
||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
|
export type WysiwigElement = {
|
||||||
|
submit: () => void;
|
||||||
|
changeStyle: (style: Record<string, any>) => void;
|
||||||
|
};
|
||||||
|
@ -14,6 +14,7 @@ import {
|
|||||||
handlerRectangles,
|
handlerRectangles,
|
||||||
getCommonBounds,
|
getCommonBounds,
|
||||||
canResizeMutlipleElements,
|
canResizeMutlipleElements,
|
||||||
|
isTextElement,
|
||||||
} from "../element";
|
} from "../element";
|
||||||
|
|
||||||
import { roundRect } from "./roundRect";
|
import { roundRect } from "./roundRect";
|
||||||
@ -103,6 +104,18 @@ export function renderScene(
|
|||||||
return { atLeastOneVisibleElement: false };
|
return { atLeastOneVisibleElement: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
appState.wysiwygElement?.changeStyle &&
|
||||||
|
isTextElement(appState.editingElement)
|
||||||
|
) {
|
||||||
|
appState.wysiwygElement.changeStyle({
|
||||||
|
font: appState.editingElement.font,
|
||||||
|
textAlign: appState.editingElement.textAlign,
|
||||||
|
color: appState.editingElement.strokeColor,
|
||||||
|
opacity: appState.editingElement.opacity,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const context = canvas.getContext("2d")!;
|
const context = canvas.getContext("2d")!;
|
||||||
context.scale(scale, scale);
|
context.scale(scale, scale);
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -240,6 +241,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -358,6 +360,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -633,6 +636,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -793,6 +797,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -993,6 +998,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -1252,6 +1258,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -1603,7 +1610,32 @@ Object {
|
|||||||
"cursorX": 0,
|
"cursorX": 0,
|
||||||
"cursorY": 0,
|
"cursorY": 0,
|
||||||
"draggingElement": null,
|
"draggingElement": null,
|
||||||
"editingElement": null,
|
"editingElement": Object {
|
||||||
|
"angle": 0,
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"height": 0,
|
||||||
|
"id": "id6",
|
||||||
|
"isDeleted": false,
|
||||||
|
"lastCommittedPoint": null,
|
||||||
|
"opacity": 100,
|
||||||
|
"points": Array [
|
||||||
|
Array [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
"roughness": 1,
|
||||||
|
"seed": 845789479,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"strokeWidth": 1,
|
||||||
|
"type": "line",
|
||||||
|
"version": 6,
|
||||||
|
"versionNonce": 745419401,
|
||||||
|
"width": 0,
|
||||||
|
"x": 30,
|
||||||
|
"y": 30,
|
||||||
|
},
|
||||||
"elementLocked": false,
|
"elementLocked": false,
|
||||||
"elementType": "selection",
|
"elementType": "selection",
|
||||||
"errorMessage": null,
|
"errorMessage": null,
|
||||||
@ -1626,6 +1658,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -2250,6 +2283,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -2368,6 +2402,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -2486,6 +2521,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -2604,6 +2640,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -2744,6 +2781,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -2884,6 +2922,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -3024,6 +3063,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -3142,6 +3182,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -3260,6 +3301,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -3400,6 +3442,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -3518,6 +3561,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -3590,6 +3634,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -4475,6 +4520,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -4899,6 +4945,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -5230,6 +5277,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -5472,6 +5520,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -5645,6 +5694,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -6481,6 +6531,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -7208,6 +7259,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -7830,6 +7882,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -8352,6 +8405,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -8824,6 +8878,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -9201,6 +9256,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -9487,6 +9543,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -9702,6 +9759,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -10594,6 +10652,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -11375,6 +11434,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -12049,6 +12109,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -12616,6 +12677,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -12994,6 +13056,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -13050,6 +13113,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -13106,6 +13170,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -13402,6 +13467,7 @@ Object {
|
|||||||
"showShortcutsDialog": false,
|
"showShortcutsDialog": false,
|
||||||
"username": "",
|
"username": "",
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
|
"wysiwygElement": null,
|
||||||
"zoom": 1,
|
"zoom": 1,
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
NonDeletedExcalidrawElement,
|
NonDeletedExcalidrawElement,
|
||||||
NonDeleted,
|
NonDeleted,
|
||||||
TextAlign,
|
TextAlign,
|
||||||
|
WysiwigElement,
|
||||||
} from "./element/types";
|
} from "./element/types";
|
||||||
import { SHAPES } from "./shapes";
|
import { SHAPES } from "./shapes";
|
||||||
import { Point as RoughPoint } from "roughjs/bin/geometry";
|
import { Point as RoughPoint } from "roughjs/bin/geometry";
|
||||||
@ -12,6 +13,7 @@ export type FlooredNumber = number & { _brand: "FlooredNumber" };
|
|||||||
export type Point = Readonly<RoughPoint>;
|
export type Point = Readonly<RoughPoint>;
|
||||||
|
|
||||||
export type AppState = {
|
export type AppState = {
|
||||||
|
wysiwygElement: WysiwigElement | null;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
errorMessage: string | null;
|
errorMessage: string | null;
|
||||||
draggingElement: NonDeletedExcalidrawElement | null;
|
draggingElement: NonDeletedExcalidrawElement | null;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user