From 08c4dd9659fb694f5e324390021671306327a3a5 Mon Sep 17 00:00:00 2001 From: neysanfoo Date: Wed, 25 Sep 2024 00:36:29 +0800 Subject: [PATCH 1/6] dont create node if discard --- .../src/nodes/ExcalidrawNode/ExcalidrawComponent.tsx | 9 ++++++++- .../src/nodes/ExcalidrawNode/ExcalidrawModal.tsx | 8 +------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawComponent.tsx b/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawComponent.tsx index fcf2186ee19..da9236c570f 100644 --- a/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawComponent.tsx +++ b/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawComponent.tsx @@ -195,6 +195,13 @@ export default function ExcalidrawComponent({ return [nodeWidth, nodeHeight]; }, [editor, nodeKey]); + const closeModal = useCallback(() => { + setModalOpen(false); + if (elements.length === 0) { + deleteNode(); + } + }, [deleteNode, elements.length]); + return ( <> setModalOpen(false)} + onClose={closeModal} onSave={(els, aps, fls) => { editor.setEditable(true); setData(els, aps, fls); diff --git a/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawModal.tsx b/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawModal.tsx index af46993ee06..28272fdab29 100644 --- a/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawModal.tsx +++ b/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawModal.tsx @@ -171,13 +171,7 @@ export default function ExcalidrawModal({ }; const discard = () => { - if (elements && elements.filter((el) => !el.isDeleted).length === 0) { - // delete node if the scene is clear - onDelete(); - } else { - //Otherwise, show confirmation dialog before closing - setDiscardModalOpen(true); - } + setDiscardModalOpen(true); }; function ShowDiscardDialog(): JSX.Element { From e24325cae9ba7ebf3a2c65ef86e24246f7e05abe Mon Sep 17 00:00:00 2001 From: neysanfoo Date: Wed, 25 Sep 2024 01:13:01 +0800 Subject: [PATCH 2/6] don't add modal to undo stack --- .../ExcalidrawNode/ExcalidrawComponent.tsx | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawComponent.tsx b/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawComponent.tsx index da9236c570f..75c036fa4f1 100644 --- a/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawComponent.tsx +++ b/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawComponent.tsx @@ -129,22 +129,25 @@ export default function ExcalidrawComponent({ if (!editor.isEditable()) { return; } - return editor.update(() => { - const node = $getNodeByKey(nodeKey); - if ($isExcalidrawNode(node)) { - if ((els && els.length > 0) || Object.keys(fls).length > 0) { - node.setData( - JSON.stringify({ - appState: aps, - elements: els, - files: fls, - }), - ); - } else { - node.remove(); + return editor.update( + () => { + const node = $getNodeByKey(nodeKey); + if ($isExcalidrawNode(node)) { + if ((els && els.length > 0) || Object.keys(fls).length > 0) { + node.setData( + JSON.stringify({ + appState: aps, + elements: els, + files: fls, + }), + ); + } else { + node.remove(); + } } - } - }); + }, + {tag: 'history-merge'}, + ); }; const onResizeStart = () => { From e8b0b63e71ae1ff6b11e631c2dca9dba3ff8877f Mon Sep 17 00:00:00 2001 From: neysanfoo Date: Wed, 25 Sep 2024 16:02:57 +0800 Subject: [PATCH 3/6] decorator node has no exportJSON method --- packages/lexical-playground/src/nodes/ExcalidrawNode/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/lexical-playground/src/nodes/ExcalidrawNode/index.tsx b/packages/lexical-playground/src/nodes/ExcalidrawNode/index.tsx index 606cea0d7e8..6299d1d32c1 100644 --- a/packages/lexical-playground/src/nodes/ExcalidrawNode/index.tsx +++ b/packages/lexical-playground/src/nodes/ExcalidrawNode/index.tsx @@ -84,7 +84,6 @@ export class ExcalidrawNode extends DecoratorNode { exportJSON(): SerializedExcalidrawNode { return { - ...super.exportJSON(), data: this.__data, height: this.__height === 'inherit' ? undefined : this.__height, type: 'excalidraw', From b39a1b2d2aad65d13f06677612b0fc09625bd25b Mon Sep 17 00:00:00 2001 From: neysanfoo Date: Wed, 25 Sep 2024 16:11:29 +0800 Subject: [PATCH 4/6] add tag for close and delete --- .../ExcalidrawNode/ExcalidrawComponent.tsx | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawComponent.tsx b/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawComponent.tsx index 75c036fa4f1..85653499043 100644 --- a/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawComponent.tsx +++ b/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawComponent.tsx @@ -113,12 +113,15 @@ export default function ExcalidrawComponent({ const deleteNode = useCallback(() => { setModalOpen(false); - return editor.update(() => { - const node = $getNodeByKey(nodeKey); - if (node) { - node.remove(); - } - }); + return editor.update( + () => { + const node = $getNodeByKey(nodeKey); + if (node) { + node.remove(); + } + }, + {tag: 'history-merge'}, + ); }, [editor, nodeKey]); const setData = ( @@ -201,9 +204,17 @@ export default function ExcalidrawComponent({ const closeModal = useCallback(() => { setModalOpen(false); if (elements.length === 0) { - deleteNode(); + editor.update( + () => { + const node = $getNodeByKey(nodeKey); + if (node) { + node.remove(); + } + }, + {tag: 'history-merge'}, + ); } - }, [deleteNode, elements.length]); + }, [editor, nodeKey, elements.length]); return ( <> From 92d883b37e86c32f96c3011b26ceecff96a5c261 Mon Sep 17 00:00:00 2001 From: neysanfoo Date: Thu, 26 Sep 2024 15:26:09 +0800 Subject: [PATCH 5/6] revert uhistory-merge tags --- .../ExcalidrawNode/ExcalidrawComponent.tsx | 63 ++++++++----------- 1 file changed, 27 insertions(+), 36 deletions(-) diff --git a/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawComponent.tsx b/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawComponent.tsx index 85653499043..1feb846b4e2 100644 --- a/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawComponent.tsx +++ b/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawComponent.tsx @@ -113,15 +113,12 @@ export default function ExcalidrawComponent({ const deleteNode = useCallback(() => { setModalOpen(false); - return editor.update( - () => { - const node = $getNodeByKey(nodeKey); - if (node) { - node.remove(); - } - }, - {tag: 'history-merge'}, - ); + return editor.update(() => { + const node = $getNodeByKey(nodeKey); + if (node) { + node.remove(); + } + }); }, [editor, nodeKey]); const setData = ( @@ -132,25 +129,22 @@ export default function ExcalidrawComponent({ if (!editor.isEditable()) { return; } - return editor.update( - () => { - const node = $getNodeByKey(nodeKey); - if ($isExcalidrawNode(node)) { - if ((els && els.length > 0) || Object.keys(fls).length > 0) { - node.setData( - JSON.stringify({ - appState: aps, - elements: els, - files: fls, - }), - ); - } else { - node.remove(); - } + return editor.update(() => { + const node = $getNodeByKey(nodeKey); + if ($isExcalidrawNode(node)) { + if ((els && els.length > 0) || Object.keys(fls).length > 0) { + node.setData( + JSON.stringify({ + appState: aps, + elements: els, + files: fls, + }), + ); + } else { + node.remove(); } - }, - {tag: 'history-merge'}, - ); + } + }); }; const onResizeStart = () => { @@ -204,15 +198,12 @@ export default function ExcalidrawComponent({ const closeModal = useCallback(() => { setModalOpen(false); if (elements.length === 0) { - editor.update( - () => { - const node = $getNodeByKey(nodeKey); - if (node) { - node.remove(); - } - }, - {tag: 'history-merge'}, - ); + editor.update(() => { + const node = $getNodeByKey(nodeKey); + if (node) { + node.remove(); + } + }); } }, [editor, nodeKey, elements.length]); From f6eb5414af4a0cb46f9fbe01aec6b51db68acbab Mon Sep 17 00:00:00 2001 From: neysanfoo Date: Mon, 30 Sep 2024 19:01:22 +0800 Subject: [PATCH 6/6] move modal into ui --- .../ExcalidrawNode/ExcalidrawComponent.tsx | 4 +- .../src/plugins/ExcalidrawPlugin/index.ts | 55 ----------- .../src/plugins/ExcalidrawPlugin/index.tsx | 96 +++++++++++++++++++ .../ExcalidrawNode => ui}/ExcalidrawModal.css | 0 .../ExcalidrawNode => ui}/ExcalidrawModal.tsx | 4 +- 5 files changed, 100 insertions(+), 59 deletions(-) delete mode 100644 packages/lexical-playground/src/plugins/ExcalidrawPlugin/index.ts create mode 100644 packages/lexical-playground/src/plugins/ExcalidrawPlugin/index.tsx rename packages/lexical-playground/src/{nodes/ExcalidrawNode => ui}/ExcalidrawModal.css (100%) rename packages/lexical-playground/src/{nodes/ExcalidrawNode => ui}/ExcalidrawModal.tsx (98%) diff --git a/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawComponent.tsx b/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawComponent.tsx index 1feb846b4e2..becee621de9 100644 --- a/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawComponent.tsx +++ b/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawComponent.tsx @@ -6,7 +6,7 @@ * */ -import type {ExcalidrawInitialElements} from './ExcalidrawModal'; +import type {ExcalidrawInitialElements} from '../../ui/ExcalidrawModal'; import type {NodeKey} from 'lexical'; import {AppState, BinaryFiles} from '@excalidraw/excalidraw/types/types'; @@ -23,10 +23,10 @@ import { import {useCallback, useEffect, useMemo, useRef, useState} from 'react'; import * as React from 'react'; +import ExcalidrawModal from '../../ui/ExcalidrawModal'; import ImageResizer from '../../ui/ImageResizer'; import {$isExcalidrawNode} from '.'; import ExcalidrawImage from './ExcalidrawImage'; -import ExcalidrawModal from './ExcalidrawModal'; export default function ExcalidrawComponent({ nodeKey, diff --git a/packages/lexical-playground/src/plugins/ExcalidrawPlugin/index.ts b/packages/lexical-playground/src/plugins/ExcalidrawPlugin/index.ts deleted file mode 100644 index 0746bd14dca..00000000000 --- a/packages/lexical-playground/src/plugins/ExcalidrawPlugin/index.ts +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - */ -import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext'; -import {$wrapNodeInElement} from '@lexical/utils'; -import { - $createParagraphNode, - $insertNodes, - $isRootOrShadowRoot, - COMMAND_PRIORITY_EDITOR, - createCommand, - LexicalCommand, -} from 'lexical'; -import {useEffect} from 'react'; - -import { - $createExcalidrawNode, - ExcalidrawNode, -} from '../../nodes/ExcalidrawNode'; - -export const INSERT_EXCALIDRAW_COMMAND: LexicalCommand = createCommand( - 'INSERT_EXCALIDRAW_COMMAND', -); - -export default function ExcalidrawPlugin(): null { - const [editor] = useLexicalComposerContext(); - useEffect(() => { - if (!editor.hasNodes([ExcalidrawNode])) { - throw new Error( - 'ExcalidrawPlugin: ExcalidrawNode not registered on editor', - ); - } - - return editor.registerCommand( - INSERT_EXCALIDRAW_COMMAND, - () => { - const excalidrawNode = $createExcalidrawNode(); - - $insertNodes([excalidrawNode]); - if ($isRootOrShadowRoot(excalidrawNode.getParentOrThrow())) { - $wrapNodeInElement(excalidrawNode, $createParagraphNode).selectEnd(); - } - - return true; - }, - COMMAND_PRIORITY_EDITOR, - ); - }, [editor]); - - return null; -} diff --git a/packages/lexical-playground/src/plugins/ExcalidrawPlugin/index.tsx b/packages/lexical-playground/src/plugins/ExcalidrawPlugin/index.tsx new file mode 100644 index 00000000000..4bcc00c4b8f --- /dev/null +++ b/packages/lexical-playground/src/plugins/ExcalidrawPlugin/index.tsx @@ -0,0 +1,96 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ +import type {ExcalidrawInitialElements} from '../../ui/ExcalidrawModal'; +import type {AppState, BinaryFiles} from '@excalidraw/excalidraw/types/types'; + +import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext'; +import {$wrapNodeInElement} from '@lexical/utils'; +import { + $createParagraphNode, + $insertNodes, + $isRootOrShadowRoot, + COMMAND_PRIORITY_EDITOR, + createCommand, + LexicalCommand, +} from 'lexical'; +import {useEffect, useState} from 'react'; + +import { + $createExcalidrawNode, + ExcalidrawNode, +} from '../../nodes/ExcalidrawNode'; +import ExcalidrawModal from '../../ui/ExcalidrawModal'; + +export const INSERT_EXCALIDRAW_COMMAND: LexicalCommand = createCommand( + 'INSERT_EXCALIDRAW_COMMAND', +); + +export default function ExcalidrawPlugin(): JSX.Element | null { + const [editor] = useLexicalComposerContext(); + const [isModalOpen, setModalOpen] = useState(false); + + useEffect(() => { + if (!editor.hasNodes([ExcalidrawNode])) { + throw new Error( + 'ExcalidrawPlugin: ExcalidrawNode not registered on editor', + ); + } + + return editor.registerCommand( + INSERT_EXCALIDRAW_COMMAND, + () => { + setModalOpen(true); + return true; + }, + COMMAND_PRIORITY_EDITOR, + ); + }, [editor]); + + const onClose = () => { + setModalOpen(false); + }; + + const onDelete = () => { + setModalOpen(false); + }; + + const onSave = ( + elements: ExcalidrawInitialElements, + appState: Partial, + files: BinaryFiles, + ) => { + editor.update(() => { + const excalidrawNode = $createExcalidrawNode(); + excalidrawNode.setData( + JSON.stringify({ + appState, + elements, + files, + }), + ); + $insertNodes([excalidrawNode]); + if ($isRootOrShadowRoot(excalidrawNode.getParentOrThrow())) { + $wrapNodeInElement(excalidrawNode, $createParagraphNode).selectEnd(); + } + }); + setModalOpen(false); + }; + + return isModalOpen ? ( + + ) : null; +} diff --git a/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawModal.css b/packages/lexical-playground/src/ui/ExcalidrawModal.css similarity index 100% rename from packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawModal.css rename to packages/lexical-playground/src/ui/ExcalidrawModal.css diff --git a/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawModal.tsx b/packages/lexical-playground/src/ui/ExcalidrawModal.tsx similarity index 98% rename from packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawModal.tsx rename to packages/lexical-playground/src/ui/ExcalidrawModal.tsx index 28272fdab29..8b3c3939ca0 100644 --- a/packages/lexical-playground/src/nodes/ExcalidrawNode/ExcalidrawModal.tsx +++ b/packages/lexical-playground/src/ui/ExcalidrawModal.tsx @@ -19,8 +19,8 @@ import * as React from 'react'; import {ReactPortal, useEffect, useLayoutEffect, useRef, useState} from 'react'; import {createPortal} from 'react-dom'; -import Button from '../../ui/Button'; -import Modal from '../../ui/Modal'; +import Button from './Button'; +import Modal from './Modal'; export type ExcalidrawInitialElements = ExcalidrawInitialDataState['elements'];