@lobehub/editor 1.4.2 → 1.4.3
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.
- package/README.md +10 -8
- package/es/editor-kernel/kernel.d.ts +3 -0
- package/es/editor-kernel/kernel.js +32 -1
- package/es/editor-kernel/react/react-editor.d.ts +5 -2
- package/es/editor-kernel/react/react-editor.js +12 -17
- package/es/react/ChatInputActions/ChatInputActions.js +2 -2
- package/es/react/Editor/Editor.js +4 -2
- package/es/react/Editor/type.d.ts +3 -2
- package/es/react/hooks/useEditor.d.ts +1 -2
- package/es/react/hooks/useEditor.js +6 -4
- package/es/react/hooks/useEditorState/index.d.ts +10 -7
- package/es/react/hooks/useEditorState/index.js +85 -69
- package/es/types/kernel.d.ts +14 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -99,20 +99,21 @@ The simplest way to get started with a fully-featured editor:
|
|
|
99
99
|
|
|
100
100
|
```tsx
|
|
101
101
|
import {
|
|
102
|
+
INSERT_HEADING_COMMAND,
|
|
102
103
|
ReactCodeblockPlugin,
|
|
103
104
|
ReactImagePlugin,
|
|
104
105
|
ReactLinkPlugin,
|
|
105
106
|
ReactListPlugin,
|
|
106
107
|
} from '@lobehub/editor';
|
|
107
|
-
import { Editor } from '@lobehub/editor/react';
|
|
108
|
+
import { Editor, useEditor } from '@lobehub/editor/react';
|
|
108
109
|
|
|
109
110
|
export default function MyEditor() {
|
|
110
|
-
const
|
|
111
|
+
const editor = useEditor();
|
|
111
112
|
|
|
112
113
|
return (
|
|
113
114
|
<Editor
|
|
114
115
|
placeholder="Start typing..."
|
|
115
|
-
|
|
116
|
+
editor={editor}
|
|
116
117
|
plugins={[ReactListPlugin, ReactLinkPlugin, ReactImagePlugin, ReactCodeblockPlugin]}
|
|
117
118
|
slashOption={{
|
|
118
119
|
items: [
|
|
@@ -143,19 +144,20 @@ Add more functionality with built-in plugins:
|
|
|
143
144
|
```tsx
|
|
144
145
|
import {
|
|
145
146
|
INSERT_FILE_COMMAND,
|
|
147
|
+
INSERT_MENTION_COMMAND,
|
|
146
148
|
INSERT_TABLE_COMMAND,
|
|
147
149
|
ReactFilePlugin,
|
|
148
150
|
ReactHRPlugin,
|
|
149
151
|
ReactTablePlugin,
|
|
150
152
|
} from '@lobehub/editor';
|
|
151
|
-
import { Editor } from '@lobehub/editor/react';
|
|
153
|
+
import { Editor, useEditor } from '@lobehub/editor/react';
|
|
152
154
|
|
|
153
155
|
export default function AdvancedEditor() {
|
|
154
|
-
const
|
|
156
|
+
const editor = useEditor();
|
|
155
157
|
|
|
156
158
|
return (
|
|
157
159
|
<Editor
|
|
158
|
-
|
|
160
|
+
editor={editor}
|
|
159
161
|
plugins={[
|
|
160
162
|
ReactTablePlugin,
|
|
161
163
|
ReactHRPlugin,
|
|
@@ -298,8 +300,8 @@ All plugins follow a **dual-architecture design**:
|
|
|
298
300
|
#### Utility Hooks
|
|
299
301
|
|
|
300
302
|
```tsx
|
|
301
|
-
// Get editor
|
|
302
|
-
const
|
|
303
|
+
// Get editor instance
|
|
304
|
+
const editor = useEditor();
|
|
303
305
|
|
|
304
306
|
// Helper for plugin configuration
|
|
305
307
|
const PluginWithConfig = Editor.withProps(ReactFilePlugin, {
|
|
@@ -72,4 +72,7 @@ export declare class Kernel extends EventEmitter implements IEditorKernel {
|
|
|
72
72
|
updateTheme(key: string, value: string | Record<string, string>): void;
|
|
73
73
|
registerLocale(locale: Partial<Record<keyof ILocaleKeys, string>>): void;
|
|
74
74
|
t<K extends keyof ILocaleKeys>(key: K, params?: Record<string, any>): string;
|
|
75
|
+
get isEmpty(): boolean;
|
|
76
|
+
get isSelected(): boolean;
|
|
77
|
+
cleanDocument(): void;
|
|
75
78
|
}
|
|
@@ -20,9 +20,10 @@ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key i
|
|
|
20
20
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
21
21
|
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
22
22
|
import EventEmitter from 'eventemitter3';
|
|
23
|
-
import { createEditor } from 'lexical';
|
|
23
|
+
import { $getSelection, $isRangeSelection, createEditor } from 'lexical';
|
|
24
24
|
import { get, merge, template, templateSettings } from 'lodash-es';
|
|
25
25
|
import defaultLocale from "../locale";
|
|
26
|
+
import { $isRootTextContentEmpty } from "../plugins/common/utils";
|
|
26
27
|
import { registerEvent } from "./event";
|
|
27
28
|
import { createEmptyEditorState } from "./utils";
|
|
28
29
|
templateSettings.interpolate = /{{([\S\s]+?)}}/g;
|
|
@@ -421,6 +422,36 @@ export var Kernel = /*#__PURE__*/function (_EventEmitter) {
|
|
|
421
422
|
}
|
|
422
423
|
return translation;
|
|
423
424
|
}
|
|
425
|
+
}, {
|
|
426
|
+
key: "isEmpty",
|
|
427
|
+
get: function get() {
|
|
428
|
+
var _this3 = this;
|
|
429
|
+
if (!this.editor) {
|
|
430
|
+
return true;
|
|
431
|
+
}
|
|
432
|
+
return this.editor.getEditorState().read(function () {
|
|
433
|
+
return $isRootTextContentEmpty(_this3.editor.isComposing(), true);
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
}, {
|
|
437
|
+
key: "isSelected",
|
|
438
|
+
get: function get() {
|
|
439
|
+
if (!this.editor) {
|
|
440
|
+
return false;
|
|
441
|
+
}
|
|
442
|
+
return this.editor.getEditorState().read(function () {
|
|
443
|
+
var selection = $getSelection();
|
|
444
|
+
if ($isRangeSelection(selection)) {
|
|
445
|
+
return !!selection._cachedNodes;
|
|
446
|
+
}
|
|
447
|
+
return false;
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
}, {
|
|
451
|
+
key: "cleanDocument",
|
|
452
|
+
value: function cleanDocument() {
|
|
453
|
+
this.setDocument('text', '');
|
|
454
|
+
}
|
|
424
455
|
}], [{
|
|
425
456
|
key: "setGlobalHotReloadMode",
|
|
426
457
|
value: function setGlobalHotReloadMode(enabled) {
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Support configuration through react children
|
|
3
3
|
*/
|
|
4
|
-
import { type FC, type ReactNode
|
|
4
|
+
import { type FC, type ReactNode } from 'react';
|
|
5
5
|
import type { IEditor } from "../../types";
|
|
6
6
|
export interface IReactEditorProps {
|
|
7
7
|
children?: ReactNode | undefined;
|
|
8
8
|
/** Editor configuration */
|
|
9
9
|
config?: Record<string, any>;
|
|
10
|
-
|
|
10
|
+
/** Editor instance to use */
|
|
11
|
+
editor?: IEditor;
|
|
12
|
+
/** Callback called when editor is initialized */
|
|
13
|
+
onInit?: (editor: IEditor) => void;
|
|
11
14
|
}
|
|
12
15
|
export declare const ReactEditor: FC<IReactEditorProps>;
|
|
@@ -12,14 +12,6 @@ import Editor from "../";
|
|
|
12
12
|
import { LexicalComposerContext, createLexicalComposerContext, useLexicalComposerContext } from "./react-context";
|
|
13
13
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
14
14
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
15
|
-
function updateRef(ref, value) {
|
|
16
|
-
if (typeof ref === 'function') {
|
|
17
|
-
ref(value);
|
|
18
|
-
} else if (ref) {
|
|
19
|
-
ref.current = value;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
15
|
// Configuration injection component
|
|
24
16
|
var ConfigInjector = function ConfigInjector(_ref) {
|
|
25
17
|
var config = _ref.config;
|
|
@@ -34,20 +26,23 @@ var ConfigInjector = function ConfigInjector(_ref) {
|
|
|
34
26
|
return null;
|
|
35
27
|
};
|
|
36
28
|
export var ReactEditor = function ReactEditor(_ref2) {
|
|
37
|
-
var
|
|
29
|
+
var editorProp = _ref2.editor,
|
|
38
30
|
children = _ref2.children,
|
|
39
|
-
config = _ref2.config
|
|
31
|
+
config = _ref2.config,
|
|
32
|
+
onInit = _ref2.onInit;
|
|
40
33
|
var composerContext = useMemo(function () {
|
|
41
|
-
var editor = Editor.createEditor();
|
|
34
|
+
var editor = editorProp || Editor.createEditor();
|
|
42
35
|
var theme = createLexicalComposerContext(null, null);
|
|
43
36
|
return [editor, theme];
|
|
44
|
-
}, []);
|
|
37
|
+
}, [editorProp]);
|
|
45
38
|
useEffect(function () {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
39
|
+
var editor = composerContext[0];
|
|
40
|
+
|
|
41
|
+
// Call onInit callback
|
|
42
|
+
if (onInit) {
|
|
43
|
+
onInit(editor);
|
|
44
|
+
}
|
|
45
|
+
}, [composerContext, onInit]);
|
|
51
46
|
return /*#__PURE__*/_jsxs(LexicalComposerContext, {
|
|
52
47
|
value: composerContext,
|
|
53
48
|
children: [/*#__PURE__*/_jsx(ConfigInjector, {
|
|
@@ -102,7 +102,7 @@ var ChatInputActions = /*#__PURE__*/memo(function (_ref) {
|
|
|
102
102
|
height: 20
|
|
103
103
|
},
|
|
104
104
|
type: 'vertical'
|
|
105
|
-
}, i);
|
|
105
|
+
}, "divider-".concat(i));
|
|
106
106
|
}
|
|
107
107
|
var wrapper = item.wrapper,
|
|
108
108
|
icon = item.icon,
|
|
@@ -157,7 +157,7 @@ var ChatInputActions = /*#__PURE__*/memo(function (_ref) {
|
|
|
157
157
|
children: item.children.map(function (child, childIndex) {
|
|
158
158
|
return mapActions(child, childIndex);
|
|
159
159
|
})
|
|
160
|
-
}, index);
|
|
160
|
+
}, "collapse-".concat(index));
|
|
161
161
|
}
|
|
162
162
|
if (item.type === 'dropdown') {
|
|
163
163
|
return /*#__PURE__*/_jsx(Dropdown, {
|
|
@@ -21,7 +21,8 @@ var Editor = /*#__PURE__*/memo(function (_ref) {
|
|
|
21
21
|
var content = _ref.content,
|
|
22
22
|
style = _ref.style,
|
|
23
23
|
className = _ref.className,
|
|
24
|
-
|
|
24
|
+
editor = _ref.editor,
|
|
25
|
+
onInit = _ref.onInit,
|
|
25
26
|
onChange = _ref.onChange,
|
|
26
27
|
placeholder = _ref.placeholder,
|
|
27
28
|
_ref$plugins = _ref.plugins,
|
|
@@ -79,7 +80,8 @@ var Editor = /*#__PURE__*/memo(function (_ref) {
|
|
|
79
80
|
}, [enableSlash, enableMention, slashOption, restMentionOption]);
|
|
80
81
|
return /*#__PURE__*/_jsxs(ReactEditor, {
|
|
81
82
|
config: config,
|
|
82
|
-
|
|
83
|
+
editor: editor,
|
|
84
|
+
onInit: onInit,
|
|
83
85
|
children: [memoPlugins, memoSlash, memoMention, /*#__PURE__*/_jsx(ReactPlainText, {
|
|
84
86
|
autoFocus: autoFocus,
|
|
85
87
|
className: className,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CSSProperties, FC, ReactNode
|
|
1
|
+
import type { CSSProperties, FC, ReactNode } from 'react';
|
|
2
2
|
import type { ReactEditorContentProps, ReactPlainTextProps } from "../../plugins/common/react";
|
|
3
3
|
import type { ReactMentionPluginProps } from "../../plugins/mention/react";
|
|
4
4
|
import type { ReactSlashOptionProps } from "../../plugins/slash/react";
|
|
@@ -11,8 +11,9 @@ export interface EditorProps extends Partial<ReactEditorContentProps>, Omit<Reac
|
|
|
11
11
|
autoFocus?: boolean;
|
|
12
12
|
children?: ReactNode;
|
|
13
13
|
className?: string;
|
|
14
|
-
|
|
14
|
+
editor?: IEditor;
|
|
15
15
|
mentionOption?: MentionOption;
|
|
16
|
+
onInit?: (editor: IEditor) => void;
|
|
16
17
|
plugins?: EditorPlugin[];
|
|
17
18
|
slashOption?: Partial<ReactSlashOptionProps>;
|
|
18
19
|
style?: CSSProperties;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
return
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import Editor from "../../editor-kernel";
|
|
3
|
+
export var useEditor = function useEditor() {
|
|
4
|
+
return useMemo(function () {
|
|
5
|
+
return Editor.createEditor();
|
|
6
|
+
}, []);
|
|
5
7
|
};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { type RefObject } from 'react';
|
|
2
1
|
import { IEditor } from "../../../types";
|
|
3
2
|
/**
|
|
4
3
|
* Editor state and toolbar methods return type
|
|
@@ -6,6 +5,8 @@ import { IEditor } from "../../../types";
|
|
|
6
5
|
export interface EditorState {
|
|
7
6
|
/** Current block type (e.g., 'paragraph', 'h1', 'h2', 'bullet', 'number', 'code') */
|
|
8
7
|
blockType: string | null;
|
|
8
|
+
/** Format selection as blockquote */
|
|
9
|
+
blockquote: () => void;
|
|
9
10
|
/** Toggle bold formatting */
|
|
10
11
|
bold: () => void;
|
|
11
12
|
/** Toggle bullet list */
|
|
@@ -16,20 +17,22 @@ export interface EditorState {
|
|
|
16
17
|
canUndo: boolean;
|
|
17
18
|
/** Toggle code formatting */
|
|
18
19
|
code: () => void;
|
|
20
|
+
/** Format selection as code block */
|
|
21
|
+
codeblock: () => void;
|
|
19
22
|
/** Current code block language */
|
|
20
23
|
codeblockLang: string | null | undefined;
|
|
21
|
-
/** Format selection as code block */
|
|
22
|
-
formatCodeblock: () => void;
|
|
23
24
|
/** Insert or toggle link */
|
|
24
25
|
insertLink: () => void;
|
|
26
|
+
/** Whether cursor is inside a blockquote */
|
|
27
|
+
isBlockquote: boolean;
|
|
25
28
|
/** Whether selection has bold formatting */
|
|
26
29
|
isBold: boolean;
|
|
27
30
|
/** Whether selection has code formatting */
|
|
28
31
|
isCode: boolean;
|
|
32
|
+
/** Whether cursor is inside a code block */
|
|
33
|
+
isCodeblock: boolean;
|
|
29
34
|
/** Whether editor content is empty */
|
|
30
35
|
isEmpty: boolean;
|
|
31
|
-
/** Whether cursor is inside a code block */
|
|
32
|
-
isInCodeblock: boolean;
|
|
33
36
|
/** Whether selection has italic formatting */
|
|
34
37
|
isItalic: boolean;
|
|
35
38
|
/** Whether editor has selection */
|
|
@@ -55,7 +58,7 @@ export interface EditorState {
|
|
|
55
58
|
}
|
|
56
59
|
/**
|
|
57
60
|
* Provide toolbar state and toolbar methods
|
|
58
|
-
* @param
|
|
61
|
+
* @param editor - Editor instance
|
|
59
62
|
* @returns Editor state and methods for toolbar functionality
|
|
60
63
|
*/
|
|
61
|
-
export declare function useEditorState(
|
|
64
|
+
export declare function useEditorState(editor: IEditor): EditorState;
|
|
@@ -6,7 +6,7 @@ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" !=
|
|
|
6
6
|
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
7
7
|
import { $createCodeNode, $isCodeNode } from '@lexical/code';
|
|
8
8
|
import { $isListNode, INSERT_ORDERED_LIST_COMMAND, INSERT_UNORDERED_LIST_COMMAND, ListNode } from '@lexical/list';
|
|
9
|
-
import { $isHeadingNode } from '@lexical/rich-text';
|
|
9
|
+
import { $createQuoteNode, $isHeadingNode, $isQuoteNode } from '@lexical/rich-text';
|
|
10
10
|
import { $setBlocksType } from '@lexical/selection';
|
|
11
11
|
import { $getNearestNodeOfType, mergeRegister } from '@lexical/utils';
|
|
12
12
|
import { $getSelection, $isRangeSelection, CAN_REDO_COMMAND, CAN_UNDO_COMMAND, COMMAND_PRIORITY_LOW, FORMAT_TEXT_COMMAND, REDO_COMMAND, SELECTION_CHANGE_COMMAND, UNDO_COMMAND } from 'lexical';
|
|
@@ -23,10 +23,10 @@ import { $findTopLevelElement, formatParagraph, getSelectedNode } from "./utils"
|
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Provide toolbar state and toolbar methods
|
|
26
|
-
* @param
|
|
26
|
+
* @param editor - Editor instance
|
|
27
27
|
* @returns Editor state and methods for toolbar functionality
|
|
28
28
|
*/
|
|
29
|
-
export function useEditorState(
|
|
29
|
+
export function useEditorState(editor) {
|
|
30
30
|
var _useState = useState(false),
|
|
31
31
|
_useState2 = _slicedToArray(_useState, 2),
|
|
32
32
|
canUndo = _useState2[0],
|
|
@@ -61,38 +61,41 @@ export function useEditorState(editorRef) {
|
|
|
61
61
|
setIsLink = _useState16[1];
|
|
62
62
|
var _useState17 = useState(false),
|
|
63
63
|
_useState18 = _slicedToArray(_useState17, 2),
|
|
64
|
-
|
|
64
|
+
isCodeblock = _useState18[0],
|
|
65
65
|
setIsInCodeblok = _useState18[1];
|
|
66
|
-
var _useState19 = useState(
|
|
66
|
+
var _useState19 = useState(false),
|
|
67
67
|
_useState20 = _slicedToArray(_useState19, 2),
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
var _useState21 = useState(
|
|
68
|
+
isBlockquote = _useState20[0],
|
|
69
|
+
setIsInBlockquote = _useState20[1];
|
|
70
|
+
var _useState21 = useState(null),
|
|
71
71
|
_useState22 = _slicedToArray(_useState21, 2),
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
var _useState23 = useState(
|
|
72
|
+
codeblockLang = _useState22[0],
|
|
73
|
+
setCodeblockLang = _useState22[1];
|
|
74
|
+
var _useState23 = useState(true),
|
|
75
75
|
_useState24 = _slicedToArray(_useState23, 2),
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
var _useState25 = useState(
|
|
76
|
+
isEmpty = _useState24[0],
|
|
77
|
+
setIsEmpty = _useState24[1];
|
|
78
|
+
var _useState25 = useState(false),
|
|
79
79
|
_useState26 = _slicedToArray(_useState25, 2),
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
isSelected = _useState26[0],
|
|
81
|
+
setIsSelected = _useState26[1];
|
|
82
|
+
var _useState27 = useState(null),
|
|
83
|
+
_useState28 = _slicedToArray(_useState27, 2),
|
|
84
|
+
blockType = _useState28[0],
|
|
85
|
+
setBlockType = _useState28[1];
|
|
82
86
|
var $handleHeadingNode = useCallback(function (selectedElement) {
|
|
83
87
|
var type = $isHeadingNode(selectedElement) ? selectedElement.getTag() : selectedElement.getType();
|
|
84
88
|
setBlockType(type);
|
|
85
89
|
}, [setBlockType]);
|
|
86
90
|
var $updateToolbar = useCallback(function () {
|
|
87
|
-
var _editorRef$current;
|
|
88
91
|
var selection = $getSelection();
|
|
89
|
-
var
|
|
92
|
+
var lexicalEditor = editor === null || editor === void 0 ? void 0 : editor.getLexicalEditor();
|
|
90
93
|
setIsSelected(false);
|
|
91
|
-
if (
|
|
92
|
-
setIsEmpty($isRootTextContentEmpty(
|
|
94
|
+
if (lexicalEditor) {
|
|
95
|
+
setIsEmpty($isRootTextContentEmpty(lexicalEditor.isComposing(), false));
|
|
93
96
|
}
|
|
94
97
|
if ($isRangeSelection(selection)) {
|
|
95
|
-
var
|
|
98
|
+
var _editor$getLexicalEdi;
|
|
96
99
|
setIsSelected(!!selection._cachedNodes);
|
|
97
100
|
setIsBold(selection.hasFormat('bold'));
|
|
98
101
|
setIsItalic(selection.hasFormat('italic'));
|
|
@@ -104,13 +107,15 @@ export function useEditorState(editorRef) {
|
|
|
104
107
|
var element = $findTopLevelElement(anchorNode);
|
|
105
108
|
var focusElement = $findTopLevelElement(focusNode);
|
|
106
109
|
var elementKey = element.getKey();
|
|
107
|
-
var elementDOM =
|
|
110
|
+
var elementDOM = editor === null || editor === void 0 || (_editor$getLexicalEdi = editor.getLexicalEditor()) === null || _editor$getLexicalEdi === void 0 ? void 0 : _editor$getLexicalEdi.getElementByKey(elementKey);
|
|
108
111
|
var node = getSelectedNode(selection);
|
|
109
112
|
var parent = node.getParent();
|
|
110
113
|
setIsLink($isLinkNode(parent) || $isLinkNode(node));
|
|
111
114
|
var isCodeBlock = $isCodeNode(element) && $isCodeNode(focusElement) && elementKey === focusElement.getKey();
|
|
112
115
|
setIsInCodeblok(isCodeBlock);
|
|
113
116
|
setCodeblockLang(isCodeBlock ? element.getLanguage() : '');
|
|
117
|
+
var _isBlockquote = $isQuoteNode(element) && $isQuoteNode(focusElement) && elementKey === focusElement.getKey();
|
|
118
|
+
setIsInBlockquote(_isBlockquote);
|
|
114
119
|
if (elementDOM !== null) {
|
|
115
120
|
if ($isListNode(element)) {
|
|
116
121
|
var parentList = $getNearestNodeOfType(anchorNode, ListNode);
|
|
@@ -129,22 +134,20 @@ export function useEditorState(editorRef) {
|
|
|
129
134
|
setIsCode(false);
|
|
130
135
|
setIsLink(false);
|
|
131
136
|
setIsInCodeblok(false);
|
|
137
|
+
setIsInBlockquote(false);
|
|
132
138
|
setCodeblockLang(null);
|
|
133
139
|
setBlockType(null);
|
|
134
140
|
}
|
|
135
|
-
}, [
|
|
141
|
+
}, [editor]);
|
|
136
142
|
var undo = useCallback(function () {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}, [editorRef.current]);
|
|
143
|
+
editor === null || editor === void 0 || editor.dispatchCommand(UNDO_COMMAND, undefined);
|
|
144
|
+
}, [editor]);
|
|
140
145
|
var redo = useCallback(function () {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}, [editorRef.current]);
|
|
146
|
+
editor === null || editor === void 0 || editor.dispatchCommand(REDO_COMMAND, undefined);
|
|
147
|
+
}, [editor]);
|
|
144
148
|
var formatText = useCallback(function (type) {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}, [editorRef.current]);
|
|
149
|
+
editor === null || editor === void 0 || editor.dispatchCommand(FORMAT_TEXT_COMMAND, type);
|
|
150
|
+
}, [editor]);
|
|
148
151
|
var bold = useCallback(function () {
|
|
149
152
|
formatText('bold');
|
|
150
153
|
}, [formatText]);
|
|
@@ -162,26 +165,22 @@ export function useEditorState(editorRef) {
|
|
|
162
165
|
}, [formatText]);
|
|
163
166
|
var bulletList = useCallback(function () {
|
|
164
167
|
if (blockType !== 'bullet') {
|
|
165
|
-
|
|
166
|
-
(_editorRef$current6 = editorRef.current) === null || _editorRef$current6 === void 0 || _editorRef$current6.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, undefined);
|
|
168
|
+
editor === null || editor === void 0 || editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, undefined);
|
|
167
169
|
} else {
|
|
168
|
-
|
|
169
|
-
formatParagraph((_editorRef$current7 = editorRef.current) === null || _editorRef$current7 === void 0 ? void 0 : _editorRef$current7.getLexicalEditor());
|
|
170
|
+
formatParagraph(editor === null || editor === void 0 ? void 0 : editor.getLexicalEditor());
|
|
170
171
|
}
|
|
171
|
-
}, [blockType]);
|
|
172
|
+
}, [blockType, editor]);
|
|
172
173
|
var numberList = useCallback(function () {
|
|
173
174
|
if (blockType !== 'number') {
|
|
174
|
-
|
|
175
|
-
(_editorRef$current8 = editorRef.current) === null || _editorRef$current8 === void 0 || _editorRef$current8.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, undefined);
|
|
175
|
+
editor === null || editor === void 0 || editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, undefined);
|
|
176
176
|
} else {
|
|
177
|
-
|
|
178
|
-
formatParagraph((_editorRef$current9 = editorRef.current) === null || _editorRef$current9 === void 0 ? void 0 : _editorRef$current9.getLexicalEditor());
|
|
177
|
+
formatParagraph(editor === null || editor === void 0 ? void 0 : editor.getLexicalEditor());
|
|
179
178
|
}
|
|
180
|
-
}, [blockType]);
|
|
181
|
-
var
|
|
179
|
+
}, [blockType, editor]);
|
|
180
|
+
var codeblock = useCallback(function () {
|
|
182
181
|
if (blockType !== 'code') {
|
|
183
|
-
var
|
|
184
|
-
|
|
182
|
+
var _editor$getLexicalEdi2;
|
|
183
|
+
editor === null || editor === void 0 || (_editor$getLexicalEdi2 = editor.getLexicalEditor()) === null || _editor$getLexicalEdi2 === void 0 || _editor$getLexicalEdi2.update(function () {
|
|
185
184
|
var selection = $getSelection();
|
|
186
185
|
if (!selection) {
|
|
187
186
|
return;
|
|
@@ -200,75 +199,92 @@ export function useEditorState(editorRef) {
|
|
|
200
199
|
}
|
|
201
200
|
}
|
|
202
201
|
});
|
|
202
|
+
} else {
|
|
203
|
+
formatParagraph(editor === null || editor === void 0 ? void 0 : editor.getLexicalEditor());
|
|
204
|
+
}
|
|
205
|
+
}, [blockType, editor]);
|
|
206
|
+
var blockquote = useCallback(function () {
|
|
207
|
+
if (blockType !== 'quote') {
|
|
208
|
+
var _editor$getLexicalEdi3;
|
|
209
|
+
editor === null || editor === void 0 || (_editor$getLexicalEdi3 = editor.getLexicalEditor()) === null || _editor$getLexicalEdi3 === void 0 || _editor$getLexicalEdi3.update(function () {
|
|
210
|
+
var selection = $getSelection();
|
|
211
|
+
if ($isRangeSelection(selection)) {
|
|
212
|
+
$setBlocksType(selection, function () {
|
|
213
|
+
return $createQuoteNode();
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
} else {
|
|
218
|
+
formatParagraph(editor === null || editor === void 0 ? void 0 : editor.getLexicalEditor());
|
|
203
219
|
}
|
|
204
|
-
}, [blockType]);
|
|
220
|
+
}, [blockType, editor]);
|
|
205
221
|
var updateCodeblockLang = useCallback(function (lang) {
|
|
206
|
-
|
|
207
|
-
if (!isInCodeblock) {
|
|
222
|
+
if (!isCodeblock) {
|
|
208
223
|
return;
|
|
209
224
|
}
|
|
210
|
-
|
|
225
|
+
editor === null || editor === void 0 || editor.dispatchCommand(UPDATE_CODEBLOCK_LANG, {
|
|
211
226
|
lang: lang
|
|
212
227
|
});
|
|
213
|
-
}, [
|
|
228
|
+
}, [editor, isCodeblock]);
|
|
214
229
|
var insertLink = useCallback(function () {
|
|
215
230
|
if (!isLink) {
|
|
216
|
-
var
|
|
231
|
+
var _editor$getLexicalEdi4;
|
|
217
232
|
setIsLink(true);
|
|
218
|
-
|
|
233
|
+
editor === null || editor === void 0 || (_editor$getLexicalEdi4 = editor.getLexicalEditor()) === null || _editor$getLexicalEdi4 === void 0 || _editor$getLexicalEdi4.dispatchCommand(TOGGLE_LINK_COMMAND, sanitizeUrl('https://'));
|
|
219
234
|
} else {
|
|
220
|
-
var
|
|
235
|
+
var _editor$getLexicalEdi5;
|
|
221
236
|
setIsLink(false);
|
|
222
|
-
|
|
237
|
+
editor === null || editor === void 0 || (_editor$getLexicalEdi5 = editor.getLexicalEditor()) === null || _editor$getLexicalEdi5 === void 0 || _editor$getLexicalEdi5.dispatchCommand(TOGGLE_LINK_COMMAND, null);
|
|
223
238
|
}
|
|
224
|
-
}, [
|
|
239
|
+
}, [editor, isLink]);
|
|
225
240
|
useEffect(function () {
|
|
226
|
-
if (!
|
|
227
|
-
var editor = editorRef.current;
|
|
241
|
+
if (!editor) return;
|
|
228
242
|
var lexicalEditor = editor.getLexicalEditor();
|
|
229
243
|
var cleanup = function cleanup() {};
|
|
230
|
-
var
|
|
231
|
-
cleanup = mergeRegister(
|
|
244
|
+
var handleLexicalEditor = function handleLexicalEditor(lexicalEditor) {
|
|
245
|
+
cleanup = mergeRegister(lexicalEditor.registerUpdateListener(function (_ref) {
|
|
232
246
|
var editorState = _ref.editorState;
|
|
233
247
|
editorState.read(function () {
|
|
234
248
|
$updateToolbar();
|
|
235
249
|
});
|
|
236
|
-
}),
|
|
250
|
+
}), lexicalEditor.registerCommand(SELECTION_CHANGE_COMMAND, function () {
|
|
237
251
|
$updateToolbar();
|
|
238
252
|
return false;
|
|
239
|
-
}, COMMAND_PRIORITY_LOW),
|
|
253
|
+
}, COMMAND_PRIORITY_LOW), lexicalEditor.registerCommand(CAN_UNDO_COMMAND, function (payload) {
|
|
240
254
|
setCanUndo(payload);
|
|
241
255
|
return false;
|
|
242
|
-
}, COMMAND_PRIORITY_LOW),
|
|
256
|
+
}, COMMAND_PRIORITY_LOW), lexicalEditor.registerCommand(CAN_REDO_COMMAND, function (payload) {
|
|
243
257
|
setCanRedo(payload);
|
|
244
258
|
return false;
|
|
245
259
|
}, COMMAND_PRIORITY_LOW));
|
|
246
260
|
return cleanup;
|
|
247
261
|
};
|
|
248
262
|
if (!lexicalEditor) {
|
|
249
|
-
editor.on('initialized',
|
|
263
|
+
editor.on('initialized', handleLexicalEditor);
|
|
250
264
|
return function () {
|
|
251
265
|
cleanup();
|
|
252
|
-
editor.off('initialized',
|
|
266
|
+
editor.off('initialized', handleLexicalEditor);
|
|
253
267
|
};
|
|
254
268
|
}
|
|
255
|
-
return
|
|
256
|
-
}, [
|
|
269
|
+
return handleLexicalEditor(lexicalEditor);
|
|
270
|
+
}, [editor, $updateToolbar]);
|
|
257
271
|
return useMemo(function () {
|
|
258
272
|
return {
|
|
259
273
|
blockType: blockType,
|
|
274
|
+
blockquote: blockquote,
|
|
260
275
|
bold: bold,
|
|
261
276
|
bulletList: bulletList,
|
|
262
277
|
canRedo: canRedo,
|
|
263
278
|
canUndo: canUndo,
|
|
264
279
|
code: code,
|
|
280
|
+
codeblock: codeblock,
|
|
265
281
|
codeblockLang: codeblockLang,
|
|
266
|
-
formatCodeblock: formatCodeblock,
|
|
267
282
|
insertLink: insertLink,
|
|
283
|
+
isBlockquote: isBlockquote,
|
|
268
284
|
isBold: isBold,
|
|
269
285
|
isCode: isCode,
|
|
286
|
+
isCodeblock: isCodeblock,
|
|
270
287
|
isEmpty: isEmpty,
|
|
271
|
-
isInCodeblock: isInCodeblock,
|
|
272
288
|
isItalic: isItalic,
|
|
273
289
|
isSelected: isSelected,
|
|
274
290
|
isStrikethrough: isStrikethrough,
|
|
@@ -281,5 +297,5 @@ export function useEditorState(editorRef) {
|
|
|
281
297
|
undo: undo,
|
|
282
298
|
updateCodeblockLang: updateCodeblockLang
|
|
283
299
|
};
|
|
284
|
-
}, [blockType, bold, bulletList, canRedo, canUndo, code, codeblockLang,
|
|
300
|
+
}, [blockType, bold, bulletList, canRedo, canUndo, code, codeblockLang, blockquote, codeblock, insertLink, isBold, isCode, isEmpty, isBlockquote, isCodeblock, isItalic, isSelected, isStrikethrough, isUnderline, italic, numberList, redo, strikethrough, underline, undo, updateCodeblockLang]);
|
|
285
301
|
}
|
package/es/types/kernel.d.ts
CHANGED
|
@@ -28,6 +28,10 @@ export interface IEditor {
|
|
|
28
28
|
* Lose focus
|
|
29
29
|
*/
|
|
30
30
|
blur(): void;
|
|
31
|
+
/**
|
|
32
|
+
* Clean editor content (clear all content)
|
|
33
|
+
*/
|
|
34
|
+
cleanDocument(): void;
|
|
31
35
|
/**
|
|
32
36
|
* Destroy editor instance
|
|
33
37
|
*/
|
|
@@ -63,6 +67,16 @@ export interface IEditor {
|
|
|
63
67
|
* Get editor theme
|
|
64
68
|
*/
|
|
65
69
|
getTheme(): Record<string, string | Record<string, string>>;
|
|
70
|
+
/**
|
|
71
|
+
* Check if editor content is empty
|
|
72
|
+
* @returns true if editor content is empty, false otherwise
|
|
73
|
+
*/
|
|
74
|
+
get isEmpty(): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Check if editor has active selection
|
|
77
|
+
* @returns true if editor has selection, false otherwise
|
|
78
|
+
*/
|
|
79
|
+
get isSelected(): boolean;
|
|
66
80
|
/**
|
|
67
81
|
* Remove editor event listener
|
|
68
82
|
* @param event
|
package/package.json
CHANGED