mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
fix popup component lifecycle
This commit is contained in:
parent
86281329b5
commit
865328457f
5 changed files with 43 additions and 33 deletions
|
@ -25,8 +25,6 @@ export const actionToggleShapeSwitch = register({
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
appState,
|
|
||||||
commitToHistory: false,
|
|
||||||
captureUpdate: CaptureUpdateAction.NEVER,
|
captureUpdate: CaptureUpdateAction.NEVER,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
@ -431,7 +431,7 @@ import {
|
||||||
} from "../components/hyperlink/Hyperlink";
|
} from "../components/hyperlink/Hyperlink";
|
||||||
|
|
||||||
import { Fonts } from "../fonts";
|
import { Fonts } from "../fonts";
|
||||||
import { editorJotaiStore } from "../editor-jotai";
|
import { editorJotaiStore, type WritableAtom } from "../editor-jotai";
|
||||||
import { ImageSceneDataError } from "../errors";
|
import { ImageSceneDataError } from "../errors";
|
||||||
import {
|
import {
|
||||||
getSnapLinesAtPointer,
|
getSnapLinesAtPointer,
|
||||||
|
@ -821,6 +821,15 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateEditorAtom = <Value, Args extends unknown[], Result>(
|
||||||
|
atom: WritableAtom<Value, Args, Result>,
|
||||||
|
...args: Args
|
||||||
|
): Result => {
|
||||||
|
const result = editorJotaiStore.set(atom, ...args);
|
||||||
|
this.triggerRender();
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
private onWindowMessage(event: MessageEvent) {
|
private onWindowMessage(event: MessageEvent) {
|
||||||
if (
|
if (
|
||||||
event.origin !== "https://player.vimeo.com" &&
|
event.origin !== "https://player.vimeo.com" &&
|
||||||
|
@ -2148,7 +2157,7 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
};
|
};
|
||||||
|
|
||||||
private openEyeDropper = ({ type }: { type: "stroke" | "background" }) => {
|
private openEyeDropper = ({ type }: { type: "stroke" | "background" }) => {
|
||||||
editorJotaiStore.set(activeEyeDropperAtom, {
|
this.updateEditorAtom(activeEyeDropperAtom, {
|
||||||
swapPreviewOnAlt: true,
|
swapPreviewOnAlt: true,
|
||||||
colorPickerType:
|
colorPickerType:
|
||||||
type === "stroke" ? "elementStroke" : "elementBackground",
|
type === "stroke" ? "elementStroke" : "elementBackground",
|
||||||
|
@ -4169,7 +4178,7 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
|
|
||||||
// Shape switching
|
// Shape switching
|
||||||
if (event.key === KEYS.ESCAPE) {
|
if (event.key === KEYS.ESCAPE) {
|
||||||
editorJotaiStore.set(shapeSwitchAtom, null);
|
this.updateEditorAtom(shapeSwitchAtom, null);
|
||||||
} else if (
|
} else if (
|
||||||
event.key === KEYS.TAB &&
|
event.key === KEYS.TAB &&
|
||||||
(document.activeElement === this.excalidrawContainerRef?.current ||
|
(document.activeElement === this.excalidrawContainerRef?.current ||
|
||||||
|
@ -4193,10 +4202,9 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (switchCategory) {
|
if (switchCategory) {
|
||||||
editorJotaiStore.set(shapeSwitchAtom, {
|
this.updateEditorAtom(shapeSwitchAtom, {
|
||||||
type: "panel",
|
type: "panel",
|
||||||
});
|
});
|
||||||
this.triggerRender();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4658,7 +4666,7 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
event[KEYS.CTRL_OR_CMD] &&
|
event[KEYS.CTRL_OR_CMD] &&
|
||||||
(event.key === KEYS.BACKSPACE || event.key === KEYS.DELETE)
|
(event.key === KEYS.BACKSPACE || event.key === KEYS.DELETE)
|
||||||
) {
|
) {
|
||||||
editorJotaiStore.set(activeConfirmDialogAtom, "clearCanvas");
|
this.updateEditorAtom(activeConfirmDialogAtom, "clearCanvas");
|
||||||
}
|
}
|
||||||
|
|
||||||
// eye dropper
|
// eye dropper
|
||||||
|
@ -6407,11 +6415,11 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
focus: false,
|
focus: false,
|
||||||
})),
|
})),
|
||||||
}));
|
}));
|
||||||
editorJotaiStore.set(searchItemInFocusAtom, null);
|
this.updateEditorAtom(searchItemInFocusAtom, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (editorJotaiStore.get(shapeSwitchAtom)) {
|
if (editorJotaiStore.get(shapeSwitchAtom)) {
|
||||||
editorJotaiStore.set(shapeSwitchAtom, null);
|
this.updateEditorAtom(shapeSwitchAtom, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// since contextMenu options are potentially evaluated on each render,
|
// since contextMenu options are potentially evaluated on each render,
|
||||||
|
|
|
@ -68,7 +68,7 @@ import {
|
||||||
sceneCoordsToViewportCoords,
|
sceneCoordsToViewportCoords,
|
||||||
} from "..";
|
} from "..";
|
||||||
import { trackEvent } from "../analytics";
|
import { trackEvent } from "../analytics";
|
||||||
import { atom, editorJotaiStore, useAtom } from "../editor-jotai";
|
import { atom, editorJotaiStore, useSetAtom } from "../editor-jotai";
|
||||||
|
|
||||||
import "./ShapeSwitch.scss";
|
import "./ShapeSwitch.scss";
|
||||||
import { ToolButton } from "./ToolButton";
|
import { ToolButton } from "./ToolButton";
|
||||||
|
@ -94,6 +94,7 @@ export const shapeSwitchAtom = atom<{
|
||||||
type: "panel";
|
type: "panel";
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
|
|
||||||
|
// NOTE doesn't need to be an atom. Review once we integrate with properties panel.
|
||||||
export const shapeSwitchFontSizeAtom = atom<{
|
export const shapeSwitchFontSizeAtom = atom<{
|
||||||
[id: string]: {
|
[id: string]: {
|
||||||
fontSize: number;
|
fontSize: number;
|
||||||
|
@ -101,6 +102,7 @@ export const shapeSwitchFontSizeAtom = atom<{
|
||||||
};
|
};
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
|
|
||||||
|
// NOTE doesn't need to be an atom. Review once we integrate with properties panel.
|
||||||
export const shapeSwitchLinearAtom = atom<{
|
export const shapeSwitchLinearAtom = atom<{
|
||||||
[id: string]: {
|
[id: string]: {
|
||||||
properties:
|
properties:
|
||||||
|
@ -111,18 +113,19 @@ export const shapeSwitchLinearAtom = atom<{
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
|
|
||||||
const ShapeSwitch = ({ app }: { app: App }) => {
|
const ShapeSwitch = ({ app }: { app: App }) => {
|
||||||
const [shapeSwitch, setShapeSwitch] = useAtom(shapeSwitchAtom);
|
const setShapeSwitchFontSize = useSetAtom(shapeSwitchFontSizeAtom);
|
||||||
const [, setShapeSwitchFontSize] = useAtom(shapeSwitchFontSizeAtom);
|
const setShapeSwitchLinear = useSetAtom(shapeSwitchLinearAtom);
|
||||||
const [, setShapeSwitchLinear] = useAtom(shapeSwitchLinearAtom);
|
|
||||||
|
|
||||||
const selectedElements = useMemo(
|
const selectedElements = app.scene.getSelectedElements(app.state);
|
||||||
() => app.scene.getSelectedElements(app.state),
|
|
||||||
[app.scene, app.state],
|
|
||||||
);
|
|
||||||
const elementsCategoryRef = useRef<SwitchShapeCategory>(null);
|
const elementsCategoryRef = useRef<SwitchShapeCategory>(null);
|
||||||
|
|
||||||
// close shape switch panel if selecting different "types" of elements
|
// close shape switch panel if selecting different "types" of elements
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (selectedElements.length === 0) {
|
||||||
|
app.updateEditorAtom(shapeSwitchAtom, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const switchCategory = getSwitchCategoryFromElements(selectedElements);
|
const switchCategory = getSwitchCategoryFromElements(selectedElements);
|
||||||
|
|
||||||
if (switchCategory && !elementsCategoryRef.current) {
|
if (switchCategory && !elementsCategoryRef.current) {
|
||||||
|
@ -132,22 +135,17 @@ const ShapeSwitch = ({ app }: { app: App }) => {
|
||||||
(elementsCategoryRef.current &&
|
(elementsCategoryRef.current &&
|
||||||
switchCategory !== elementsCategoryRef.current)
|
switchCategory !== elementsCategoryRef.current)
|
||||||
) {
|
) {
|
||||||
setShapeSwitch(null);
|
app.updateEditorAtom(shapeSwitchAtom, null);
|
||||||
elementsCategoryRef.current = null;
|
elementsCategoryRef.current = null;
|
||||||
}
|
}
|
||||||
}, [selectedElements, app.state.selectedElementIds, setShapeSwitch]);
|
}, [selectedElements, app]);
|
||||||
|
|
||||||
// clear if not active
|
useEffect(() => {
|
||||||
if (!shapeSwitch) {
|
return () => {
|
||||||
setShapeSwitchFontSize(null);
|
setShapeSwitchFontSize(null);
|
||||||
setShapeSwitchLinear(null);
|
setShapeSwitchLinear(null);
|
||||||
return null;
|
};
|
||||||
}
|
}, [setShapeSwitchFontSize, setShapeSwitchLinear]);
|
||||||
|
|
||||||
if (selectedElements.length === 0) {
|
|
||||||
setShapeSwitch(null);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <Panel app={app} elements={selectedElements} />;
|
return <Panel app={app} elements={selectedElements} />;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
// eslint-disable-next-line no-restricted-imports
|
// eslint-disable-next-line no-restricted-imports
|
||||||
import { atom, createStore, type PrimitiveAtom } from "jotai";
|
import {
|
||||||
|
atom,
|
||||||
|
createStore,
|
||||||
|
type PrimitiveAtom,
|
||||||
|
type WritableAtom,
|
||||||
|
} from "jotai";
|
||||||
import { createIsolation } from "jotai-scope";
|
import { createIsolation } from "jotai-scope";
|
||||||
|
|
||||||
const jotai = createIsolation();
|
const jotai = createIsolation();
|
||||||
|
|
||||||
export { atom, PrimitiveAtom };
|
export { atom, PrimitiveAtom, WritableAtom };
|
||||||
export const { useAtom, useSetAtom, useAtomValue, useStore } = jotai;
|
export const { useAtom, useSetAtom, useAtomValue, useStore } = jotai;
|
||||||
export const EditorJotaiProvider: ReturnType<
|
export const EditorJotaiProvider: ReturnType<
|
||||||
typeof createIsolation
|
typeof createIsolation
|
||||||
|
|
|
@ -714,6 +714,7 @@ export type AppClassProperties = {
|
||||||
excalidrawContainerValue: App["excalidrawContainerValue"];
|
excalidrawContainerValue: App["excalidrawContainerValue"];
|
||||||
|
|
||||||
onPointerUpEmitter: App["onPointerUpEmitter"];
|
onPointerUpEmitter: App["onPointerUpEmitter"];
|
||||||
|
updateEditorAtom: App["updateEditorAtom"];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PointerDownState = Readonly<{
|
export type PointerDownState = Readonly<{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue