@lobehub/editor 1.4.2 → 1.4.4

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 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 editorRef = Editor.useEditor();
111
+ const editor = useEditor();
111
112
 
112
113
  return (
113
114
  <Editor
114
115
  placeholder="Start typing..."
115
- editorRef={editorRef}
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 editorRef = Editor.useEditor();
156
+ const editor = useEditor();
155
157
 
156
158
  return (
157
159
  <Editor
158
- editorRef={editorRef}
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 reference
302
- const editorRef = Editor.useEditor();
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, type Ref } from 'react';
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
- editorRef?: Ref<IEditor>;
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 editorRef = _ref2.editorRef,
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
- updateRef(editorRef, composerContext[0]);
47
- return function () {
48
- updateRef(editorRef, undefined);
49
- };
50
- }, [editorRef, composerContext]);
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
- editorRef = _ref.editorRef,
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
- editorRef: editorRef,
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, RefObject } from 'react';
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
- editorRef?: RefObject<IEditor | null>;
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,3 +1,2 @@
1
- import { RefObject } from 'react';
2
1
  import type { IEditor } from "../../types";
3
- export declare const useEditor: (editorRef?: RefObject<IEditor | null>) => RefObject<IEditor | null>;
2
+ export declare const useEditor: () => IEditor;
@@ -1,5 +1,7 @@
1
- import { useRef } from 'react';
2
- export var useEditor = function useEditor(editorRef) {
3
- var ref = useRef(null);
4
- return editorRef || ref;
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 editorRef - Reference to the editor instance
61
+ * @param editor - Editor instance
59
62
  * @returns Editor state and methods for toolbar functionality
60
63
  */
61
- export declare function useEditorState(editorRef: RefObject<IEditor | null>): EditorState;
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 editorRef - Reference to the editor instance
26
+ * @param editor - Editor instance
27
27
  * @returns Editor state and methods for toolbar functionality
28
28
  */
29
- export function useEditorState(editorRef) {
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
- isInCodeblock = _useState18[0],
64
+ isCodeblock = _useState18[0],
65
65
  setIsInCodeblok = _useState18[1];
66
- var _useState19 = useState(null),
66
+ var _useState19 = useState(false),
67
67
  _useState20 = _slicedToArray(_useState19, 2),
68
- codeblockLang = _useState20[0],
69
- setCodeblockLang = _useState20[1];
70
- var _useState21 = useState(true),
68
+ isBlockquote = _useState20[0],
69
+ setIsInBlockquote = _useState20[1];
70
+ var _useState21 = useState(null),
71
71
  _useState22 = _slicedToArray(_useState21, 2),
72
- isEmpty = _useState22[0],
73
- setIsEmpty = _useState22[1];
74
- var _useState23 = useState(false),
72
+ codeblockLang = _useState22[0],
73
+ setCodeblockLang = _useState22[1];
74
+ var _useState23 = useState(true),
75
75
  _useState24 = _slicedToArray(_useState23, 2),
76
- isSelected = _useState24[0],
77
- setIsSelected = _useState24[1];
78
- var _useState25 = useState(null),
76
+ isEmpty = _useState24[0],
77
+ setIsEmpty = _useState24[1];
78
+ var _useState25 = useState(false),
79
79
  _useState26 = _slicedToArray(_useState25, 2),
80
- blockType = _useState26[0],
81
- setBlockType = _useState26[1];
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 editor = (_editorRef$current = editorRef.current) === null || _editorRef$current === void 0 ? void 0 : _editorRef$current.getLexicalEditor();
92
+ var lexicalEditor = editor === null || editor === void 0 ? void 0 : editor.getLexicalEditor();
90
93
  setIsSelected(false);
91
- if (editor) {
92
- setIsEmpty($isRootTextContentEmpty(editor.isComposing(), false));
94
+ if (lexicalEditor) {
95
+ setIsEmpty($isRootTextContentEmpty(lexicalEditor.isComposing(), false));
93
96
  }
94
97
  if ($isRangeSelection(selection)) {
95
- var _editorRef$current2;
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 = (_editorRef$current2 = editorRef.current) === null || _editorRef$current2 === void 0 || (_editorRef$current2 = _editorRef$current2.getLexicalEditor()) === null || _editorRef$current2 === void 0 ? void 0 : _editorRef$current2.getElementByKey(elementKey);
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
- }, [editorRef.current]);
141
+ }, [editor]);
136
142
  var undo = useCallback(function () {
137
- var _editorRef$current3;
138
- (_editorRef$current3 = editorRef.current) === null || _editorRef$current3 === void 0 || _editorRef$current3.dispatchCommand(UNDO_COMMAND, undefined);
139
- }, [editorRef.current]);
143
+ editor === null || editor === void 0 || editor.dispatchCommand(UNDO_COMMAND, undefined);
144
+ }, [editor]);
140
145
  var redo = useCallback(function () {
141
- var _editorRef$current4;
142
- (_editorRef$current4 = editorRef.current) === null || _editorRef$current4 === void 0 || _editorRef$current4.dispatchCommand(REDO_COMMAND, undefined);
143
- }, [editorRef.current]);
146
+ editor === null || editor === void 0 || editor.dispatchCommand(REDO_COMMAND, undefined);
147
+ }, [editor]);
144
148
  var formatText = useCallback(function (type) {
145
- var _editorRef$current5;
146
- (_editorRef$current5 = editorRef.current) === null || _editorRef$current5 === void 0 || _editorRef$current5.dispatchCommand(FORMAT_TEXT_COMMAND, type);
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
- var _editorRef$current6;
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
- var _editorRef$current7;
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
- var _editorRef$current8;
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
- var _editorRef$current9;
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 formatCodeblock = useCallback(function () {
179
+ }, [blockType, editor]);
180
+ var codeblock = useCallback(function () {
182
181
  if (blockType !== 'code') {
183
- var _editorRef$current10;
184
- (_editorRef$current10 = editorRef.current) === null || _editorRef$current10 === void 0 || (_editorRef$current10 = _editorRef$current10.getLexicalEditor()) === null || _editorRef$current10 === void 0 || _editorRef$current10.update(function () {
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
- var _editorRef$current11;
207
- if (!isInCodeblock) {
222
+ if (!isCodeblock) {
208
223
  return;
209
224
  }
210
- (_editorRef$current11 = editorRef.current) === null || _editorRef$current11 === void 0 || _editorRef$current11.dispatchCommand(UPDATE_CODEBLOCK_LANG, {
225
+ editor === null || editor === void 0 || editor.dispatchCommand(UPDATE_CODEBLOCK_LANG, {
211
226
  lang: lang
212
227
  });
213
- }, [editorRef.current, isInCodeblock]);
228
+ }, [editor, isCodeblock]);
214
229
  var insertLink = useCallback(function () {
215
230
  if (!isLink) {
216
- var _editorRef$current12;
231
+ var _editor$getLexicalEdi4;
217
232
  setIsLink(true);
218
- (_editorRef$current12 = editorRef.current) === null || _editorRef$current12 === void 0 || (_editorRef$current12 = _editorRef$current12.getLexicalEditor()) === null || _editorRef$current12 === void 0 || _editorRef$current12.dispatchCommand(TOGGLE_LINK_COMMAND, sanitizeUrl('https://'));
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 _editorRef$current13;
235
+ var _editor$getLexicalEdi5;
221
236
  setIsLink(false);
222
- (_editorRef$current13 = editorRef.current) === null || _editorRef$current13 === void 0 || (_editorRef$current13 = _editorRef$current13.getLexicalEditor()) === null || _editorRef$current13 === void 0 || _editorRef$current13.dispatchCommand(TOGGLE_LINK_COMMAND, null);
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
- }, [editorRef.current, isLink]);
239
+ }, [editor, isLink]);
225
240
  useEffect(function () {
226
- if (!editorRef.current) return;
227
- var editor = editorRef.current;
241
+ if (!editor) return;
228
242
  var lexicalEditor = editor.getLexicalEditor();
229
243
  var cleanup = function cleanup() {};
230
- var handleLeixcalEditor = function handleLeixcalEditor(editor) {
231
- cleanup = mergeRegister(editor.registerUpdateListener(function (_ref) {
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
- }), editor.registerCommand(SELECTION_CHANGE_COMMAND, function () {
250
+ }), lexicalEditor.registerCommand(SELECTION_CHANGE_COMMAND, function () {
237
251
  $updateToolbar();
238
252
  return false;
239
- }, COMMAND_PRIORITY_LOW), editor.registerCommand(CAN_UNDO_COMMAND, function (payload) {
253
+ }, COMMAND_PRIORITY_LOW), lexicalEditor.registerCommand(CAN_UNDO_COMMAND, function (payload) {
240
254
  setCanUndo(payload);
241
255
  return false;
242
- }, COMMAND_PRIORITY_LOW), editor.registerCommand(CAN_REDO_COMMAND, function (payload) {
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', handleLeixcalEditor);
263
+ editor.on('initialized', handleLexicalEditor);
250
264
  return function () {
251
265
  cleanup();
252
- editor.off('initialized', handleLeixcalEditor);
266
+ editor.off('initialized', handleLexicalEditor);
253
267
  };
254
268
  }
255
- return handleLeixcalEditor(lexicalEditor);
256
- }, [editorRef.current]);
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, formatCodeblock, insertLink, isBold, isCode, isEmpty, isInCodeblock, isItalic, isSelected, isStrikethrough, isUnderline, italic, numberList, redo, strikethrough, underline, undo, updateCodeblockLang]);
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
  }
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/editor",
3
- "version": "1.4.2",
3
+ "version": "1.4.4",
4
4
  "description": "A powerful and extensible rich text editor built on Meta's Lexical framework, providing a modern editing experience with React integration.",
5
5
  "keywords": [
6
6
  "lobehub",