@blocklet/editor 2.0.94 → 2.0.96

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,9 @@ type OnChange = (editorState: EditorState, editor: LexicalEditor) => void;
3
3
  /**
4
4
  * 检听内容变化
5
5
  * - 忽略 selection 事件
6
- * - 默认忽略首次 onChange 事件 (editor 初始化时的 onChange)
6
+ * - 默认忽略首次 onChange 事件 (autofocus 开启时 editor 初始化后会自动触发 onChange)
7
+ *
8
+ * 注意: Editor#autofocus 与 OnChangePlugin 行为有关系: https://github.com/facebook/lexical/issues/4493
7
9
  */
8
10
  export declare function OnContentChangePlugin({ onChange, ignoreInitialChange, }: {
9
11
  onChange: OnChange;
@@ -1,19 +1,35 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin';
3
- import { useRef } from 'react';
3
+ import { useLayoutEffect, useRef } from 'react';
4
+ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
4
5
  /**
5
6
  * 检听内容变化
6
7
  * - 忽略 selection 事件
7
- * - 默认忽略首次 onChange 事件 (editor 初始化时的 onChange)
8
+ * - 默认忽略首次 onChange 事件 (autofocus 开启时 editor 初始化后会自动触发 onChange)
9
+ *
10
+ * 注意: Editor#autofocus 与 OnChangePlugin 行为有关系: https://github.com/facebook/lexical/issues/4493
8
11
  */
9
12
  export function OnContentChangePlugin({ onChange, ignoreInitialChange = true, }) {
10
- const initialChangeRef = useRef(false);
11
- const handleOnChange = (editorState, editor) => {
12
- if (ignoreInitialChange && !initialChangeRef.current) {
13
- initialChangeRef.current = true;
14
- return;
13
+ const [editor] = useLexicalComposerContext();
14
+ const initialContentRef = useRef();
15
+ const changedRef = useRef(false);
16
+ useLayoutEffect(() => {
17
+ if (initialContentRef.current === undefined) {
18
+ const editorState = editor.getEditorState();
19
+ initialContentRef.current = editorState ? JSON.stringify(editorState) : '';
20
+ }
21
+ }, [editor]);
22
+ const handleOnChange = (editorState, lexicalEditor) => {
23
+ if (changedRef.current) {
24
+ onChange(editorState, lexicalEditor);
25
+ }
26
+ else {
27
+ const content = editorState ? JSON.stringify(editorState) : '';
28
+ if (content !== initialContentRef.current || !ignoreInitialChange) {
29
+ onChange(editorState, lexicalEditor);
30
+ changedRef.current = true;
31
+ }
15
32
  }
16
- onChange(editorState, editor);
17
33
  };
18
34
  return _jsx(OnChangePlugin, { onChange: handleOnChange, ignoreSelectionChange: true });
19
35
  }
@@ -37,6 +37,12 @@ export default function ExcalidrawModal({ closeOnClickOutside = false, onSave, i
37
37
  const [loading, setLoading] = useState(false);
38
38
  const [saveText, setSaveText] = useState('Save');
39
39
  const [fullScreen, setFullScreen] = useState(false);
40
+ const markBlockletDirtyState = () => {
41
+ window.dispatchEvent(new CustomEvent('blocklet:markDirty', { detail: { key: 'excalidraw' } }));
42
+ };
43
+ const resetBlockletDirtyState = () => {
44
+ window.dispatchEvent(new CustomEvent('blocklet:resetDirty', { detail: { key: 'excalidraw' } }));
45
+ };
40
46
  useEffect(() => {
41
47
  // @ts-ignore set window.name to add library target
42
48
  window.name = window.location.href;
@@ -127,12 +133,14 @@ export default function ExcalidrawModal({ closeOnClickOutside = false, onSave, i
127
133
  finally {
128
134
  setLoading(false);
129
135
  setSaveText('Save');
136
+ resetBlockletDirtyState();
130
137
  }
131
138
  };
132
139
  const discard = () => {
133
140
  if (elements.filter((el) => !el.isDeleted).length === 0) {
134
141
  // delete node if the scene is clear
135
142
  onDelete();
143
+ resetBlockletDirtyState();
136
144
  }
137
145
  else {
138
146
  // Otherwise, show confirmation dialog before closing
@@ -144,6 +152,7 @@ export default function ExcalidrawModal({ closeOnClickOutside = false, onSave, i
144
152
  return (_jsxs(Modal, { title: "Discard", onClose: () => {
145
153
  setDiscardModalOpen(false);
146
154
  }, closeOnClickOutside: false, children: ["Are you sure you want to discard the changes?", _jsxs("div", { className: "ExcalidrawModal__discardModal", children: [_jsx(Button, { onClick: () => {
155
+ resetBlockletDirtyState();
147
156
  setDiscardModalOpen(false);
148
157
  onClose();
149
158
  }, children: "Discard" }), ' ', _jsx(Button, { onClick: () => {
@@ -154,6 +163,7 @@ export default function ExcalidrawModal({ closeOnClickOutside = false, onSave, i
154
163
  return null;
155
164
  }
156
165
  const onChange = (els, _, fls) => {
166
+ markBlockletDirtyState();
157
167
  setElements(els);
158
168
  setFiles(fls);
159
169
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocklet/editor",
3
- "version": "2.0.94",
3
+ "version": "2.0.96",
4
4
  "main": "lib/index.js",
5
5
  "scripts": {
6
6
  "dev": "npm run storybook",
@@ -40,7 +40,7 @@
40
40
  "@arcblock/ux": "^2.10.12",
41
41
  "@blocklet/embed": "^0.1.11",
42
42
  "@blocklet/pages-kit": "^0.2.390",
43
- "@blocklet/pdf": "2.0.94",
43
+ "@blocklet/pdf": "2.0.96",
44
44
  "@excalidraw/excalidraw": "^0.14.2",
45
45
  "@iconify/iconify": "^3.0.1",
46
46
  "@iconify/icons-tabler": "^1.2.95",
@@ -113,5 +113,5 @@
113
113
  "react": "*",
114
114
  "react-dom": "*"
115
115
  },
116
- "gitHead": "02ab63096d5ce531d390d4a3e600d4812e212d57"
116
+ "gitHead": "ee7ea575137f9253ee9292ad6dc3763192118791"
117
117
  }