@lobehub/editor 1.4.1 → 1.4.2

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.
@@ -2,4 +2,3 @@ export { LexicalErrorBoundary } from './LexicalErrorBoundary';
2
2
  export { useLexicalComposerContext } from './react-context';
3
3
  export { ReactEditor } from './react-editor';
4
4
  export { useLexicalEditor } from './useLexicalEditor';
5
- export { useToolbarState } from './useToolbarState';
@@ -1,5 +1,4 @@
1
1
  export { LexicalErrorBoundary } from "./LexicalErrorBoundary";
2
2
  export { useLexicalComposerContext } from "./react-context";
3
3
  export { ReactEditor } from "./react-editor";
4
- export { useLexicalEditor } from "./useLexicalEditor";
5
- export { useToolbarState } from "./useToolbarState";
4
+ export { useLexicalEditor } from "./useLexicalEditor";
@@ -1,14 +1,15 @@
1
1
  import type { ReactNode } from 'react';
2
+ import { useEditor } from '../hooks/useEditor';
3
+ import { useEditorState } from '../hooks/useEditorState';
2
4
  import type { EditorProps } from './type';
3
- import { useEditor } from './useEditor';
4
5
  import { withProps } from './utils';
5
6
  interface IEditor {
6
7
  (props: EditorProps): ReactNode;
7
8
  useEditor: typeof useEditor;
9
+ useEditorState: typeof useEditorState;
8
10
  withProps: typeof withProps;
9
11
  }
10
12
  declare const Editor: IEditor;
11
13
  export default Editor;
12
14
  export * from './type';
13
- export { useEditor } from './useEditor';
14
15
  export * from './utils';
@@ -1,10 +1,11 @@
1
+ import { useEditor } from "../hooks/useEditor";
2
+ import { useEditorState } from "../hooks/useEditorState";
1
3
  import EditorParent from "./Editor";
2
- import { useEditor } from "./useEditor";
3
4
  import { withProps } from "./utils";
4
5
  var Editor = EditorParent;
5
6
  Editor.useEditor = useEditor;
7
+ Editor.useEditorState = useEditorState;
6
8
  Editor.withProps = withProps;
7
9
  export default Editor;
8
10
  export * from "./type";
9
- export { useEditor } from "./useEditor";
10
11
  export * from "./utils";
@@ -0,0 +1,61 @@
1
+ import { type RefObject } from 'react';
2
+ import { IEditor } from "../../../types";
3
+ /**
4
+ * Editor state and toolbar methods return type
5
+ */
6
+ export interface EditorState {
7
+ /** Current block type (e.g., 'paragraph', 'h1', 'h2', 'bullet', 'number', 'code') */
8
+ blockType: string | null;
9
+ /** Toggle bold formatting */
10
+ bold: () => void;
11
+ /** Toggle bullet list */
12
+ bulletList: () => void;
13
+ /** Whether redo operation is available */
14
+ canRedo: boolean;
15
+ /** Whether undo operation is available */
16
+ canUndo: boolean;
17
+ /** Toggle code formatting */
18
+ code: () => void;
19
+ /** Current code block language */
20
+ codeblockLang: string | null | undefined;
21
+ /** Format selection as code block */
22
+ formatCodeblock: () => void;
23
+ /** Insert or toggle link */
24
+ insertLink: () => void;
25
+ /** Whether selection has bold formatting */
26
+ isBold: boolean;
27
+ /** Whether selection has code formatting */
28
+ isCode: boolean;
29
+ /** Whether editor content is empty */
30
+ isEmpty: boolean;
31
+ /** Whether cursor is inside a code block */
32
+ isInCodeblock: boolean;
33
+ /** Whether selection has italic formatting */
34
+ isItalic: boolean;
35
+ /** Whether editor has selection */
36
+ isSelected: boolean;
37
+ /** Whether selection has strikethrough formatting */
38
+ isStrikethrough: boolean;
39
+ /** Whether selection has underline formatting */
40
+ isUnderline: boolean;
41
+ /** Toggle italic formatting */
42
+ italic: () => void;
43
+ /** Toggle numbered list */
44
+ numberList: () => void;
45
+ /** Redo last operation */
46
+ redo: () => void;
47
+ /** Toggle strikethrough formatting */
48
+ strikethrough: () => void;
49
+ /** Toggle underline formatting */
50
+ underline: () => void;
51
+ /** Undo last operation */
52
+ undo: () => void;
53
+ /** Update code block language */
54
+ updateCodeblockLang: (lang: string) => void;
55
+ }
56
+ /**
57
+ * Provide toolbar state and toolbar methods
58
+ * @param editorRef - Reference to the editor instance
59
+ * @returns Editor state and methods for toolbar functionality
60
+ */
61
+ export declare function useEditorState(editorRef: RefObject<IEditor | null>): EditorState;
@@ -7,53 +7,26 @@ 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
9
  import { $isHeadingNode } from '@lexical/rich-text';
10
- import { $isAtNodeEnd, $setBlocksType } from '@lexical/selection';
11
- import { $findMatchingParent, $getNearestNodeOfType, mergeRegister } from '@lexical/utils';
12
- import { $createParagraphNode, $getSelection, $isRangeSelection, $isRootOrShadowRoot, CAN_REDO_COMMAND, CAN_UNDO_COMMAND, COMMAND_PRIORITY_LOW, FORMAT_TEXT_COMMAND, REDO_COMMAND, SELECTION_CHANGE_COMMAND, UNDO_COMMAND } from 'lexical';
13
- import { useCallback, useEffect, useState } from 'react';
14
- import { UPDATE_CODEBLOCK_LANG } from "../../plugins/codeblock";
15
- import { $isRootTextContentEmpty } from "../../plugins/common/utils";
16
- import { $isLinkNode, TOGGLE_LINK_COMMAND } from "../../plugins/link/node/LinkNode";
17
- import { sanitizeUrl } from "../../plugins/link/utils";
18
- function $findTopLevelElement(node) {
19
- var topLevelElement = node.getKey() === 'root' ? node : $findMatchingParent(node, function (e) {
20
- var parent = e.getParent();
21
- return parent !== null && $isRootOrShadowRoot(parent);
22
- });
23
- if (topLevelElement === null) {
24
- topLevelElement = node.getTopLevelElementOrThrow();
25
- }
26
- return topLevelElement;
27
- }
28
- var formatParagraph = function formatParagraph(editor) {
29
- editor === null || editor === void 0 || editor.update(function () {
30
- var selection = $getSelection();
31
- $setBlocksType(selection, function () {
32
- return $createParagraphNode();
33
- });
34
- });
35
- };
36
- function getSelectedNode(selection) {
37
- var anchor = selection.anchor;
38
- var focus = selection.focus;
39
- var anchorNode = selection.anchor.getNode();
40
- var focusNode = selection.focus.getNode();
41
- if (anchorNode === focusNode) {
42
- return anchorNode;
43
- }
44
- var isBackward = selection.isBackward();
45
- if (isBackward) {
46
- return $isAtNodeEnd(focus) ? anchorNode : focusNode;
47
- } else {
48
- return $isAtNodeEnd(anchor) ? anchorNode : focusNode;
49
- }
50
- }
10
+ import { $setBlocksType } from '@lexical/selection';
11
+ import { $getNearestNodeOfType, mergeRegister } from '@lexical/utils';
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';
13
+ import { useCallback, useEffect, useMemo, useState } from 'react';
14
+ import { UPDATE_CODEBLOCK_LANG } from "../../../plugins/codeblock";
15
+ import { $isRootTextContentEmpty } from "../../../plugins/common/utils";
16
+ import { $isLinkNode, TOGGLE_LINK_COMMAND } from "../../../plugins/link/node/LinkNode";
17
+ import { sanitizeUrl } from "../../../plugins/link/utils";
18
+ import { $findTopLevelElement, formatParagraph, getSelectedNode } from "./utils";
19
+
20
+ /**
21
+ * Editor state and toolbar methods return type
22
+ */
51
23
 
52
24
  /**
53
25
  * Provide toolbar state and toolbar methods
54
- * @returns
26
+ * @param editorRef - Reference to the editor instance
27
+ * @returns Editor state and methods for toolbar functionality
55
28
  */
56
- export function useToolbarState(editorRef) {
29
+ export function useEditorState(editorRef) {
57
30
  var _useState = useState(false),
58
31
  _useState2 = _slicedToArray(_useState, 2),
59
32
  canUndo = _useState2[0],
@@ -98,10 +71,14 @@ export function useToolbarState(editorRef) {
98
71
  _useState22 = _slicedToArray(_useState21, 2),
99
72
  isEmpty = _useState22[0],
100
73
  setIsEmpty = _useState22[1];
101
- var _useState23 = useState(null),
74
+ var _useState23 = useState(false),
102
75
  _useState24 = _slicedToArray(_useState23, 2),
103
- blockType = _useState24[0],
104
- setBlockType = _useState24[1];
76
+ isSelected = _useState24[0],
77
+ setIsSelected = _useState24[1];
78
+ var _useState25 = useState(null),
79
+ _useState26 = _slicedToArray(_useState25, 2),
80
+ blockType = _useState26[0],
81
+ setBlockType = _useState26[1];
105
82
  var $handleHeadingNode = useCallback(function (selectedElement) {
106
83
  var type = $isHeadingNode(selectedElement) ? selectedElement.getTag() : selectedElement.getType();
107
84
  setBlockType(type);
@@ -110,11 +87,13 @@ export function useToolbarState(editorRef) {
110
87
  var _editorRef$current;
111
88
  var selection = $getSelection();
112
89
  var editor = (_editorRef$current = editorRef.current) === null || _editorRef$current === void 0 ? void 0 : _editorRef$current.getLexicalEditor();
90
+ setIsSelected(false);
113
91
  if (editor) {
114
92
  setIsEmpty($isRootTextContentEmpty(editor.isComposing(), false));
115
93
  }
116
94
  if ($isRangeSelection(selection)) {
117
95
  var _editorRef$current2;
96
+ setIsSelected(!!selection._cachedNodes);
118
97
  setIsBold(selection.hasFormat('bold'));
119
98
  setIsItalic(selection.hasFormat('italic'));
120
99
  setIsUnderline(selection.hasFormat('underline'));
@@ -142,6 +121,7 @@ export function useToolbarState(editorRef) {
142
121
  }
143
122
  }
144
123
  } else if (!selection) {
124
+ setIsSelected(false);
145
125
  setIsBold(false);
146
126
  setIsItalic(false);
147
127
  setIsUnderline(false);
@@ -274,29 +254,32 @@ export function useToolbarState(editorRef) {
274
254
  }
275
255
  return handleLeixcalEditor(lexicalEditor);
276
256
  }, [editorRef.current]);
277
- return {
278
- blockType: blockType,
279
- bold: bold,
280
- bulletList: bulletList,
281
- canRedo: canRedo,
282
- canUndo: canUndo,
283
- code: code,
284
- codeblockLang: codeblockLang,
285
- formatCodeblock: formatCodeblock,
286
- insertLink: insertLink,
287
- isBold: isBold,
288
- isCode: isCode,
289
- isEmpty: isEmpty,
290
- isInCodeblock: isInCodeblock,
291
- isItalic: isItalic,
292
- isStrikethrough: isStrikethrough,
293
- isUnderline: isUnderline,
294
- italic: italic,
295
- numberList: numberList,
296
- redo: redo,
297
- strikethrough: strikethrough,
298
- underline: underline,
299
- undo: undo,
300
- updateCodeblockLang: updateCodeblockLang
301
- };
257
+ return useMemo(function () {
258
+ return {
259
+ blockType: blockType,
260
+ bold: bold,
261
+ bulletList: bulletList,
262
+ canRedo: canRedo,
263
+ canUndo: canUndo,
264
+ code: code,
265
+ codeblockLang: codeblockLang,
266
+ formatCodeblock: formatCodeblock,
267
+ insertLink: insertLink,
268
+ isBold: isBold,
269
+ isCode: isCode,
270
+ isEmpty: isEmpty,
271
+ isInCodeblock: isInCodeblock,
272
+ isItalic: isItalic,
273
+ isSelected: isSelected,
274
+ isStrikethrough: isStrikethrough,
275
+ isUnderline: isUnderline,
276
+ italic: italic,
277
+ numberList: numberList,
278
+ redo: redo,
279
+ strikethrough: strikethrough,
280
+ underline: underline,
281
+ undo: undo,
282
+ updateCodeblockLang: updateCodeblockLang
283
+ };
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]);
302
285
  }
@@ -0,0 +1,4 @@
1
+ import { ElementNode, LexicalEditor, LexicalNode, RangeSelection, TextNode } from 'lexical';
2
+ export declare const $findTopLevelElement: (node: LexicalNode) => LexicalNode;
3
+ export declare const formatParagraph: (editor?: LexicalEditor | null) => void;
4
+ export declare const getSelectedNode: (selection: RangeSelection) => TextNode | ElementNode;
@@ -0,0 +1,36 @@
1
+ import { $isAtNodeEnd, $setBlocksType } from '@lexical/selection';
2
+ import { $findMatchingParent } from '@lexical/utils';
3
+ import { $createParagraphNode, $getSelection, $isRootOrShadowRoot } from 'lexical';
4
+ export var $findTopLevelElement = function $findTopLevelElement(node) {
5
+ var topLevelElement = node.getKey() === 'root' ? node : $findMatchingParent(node, function (e) {
6
+ var parent = e.getParent();
7
+ return parent !== null && $isRootOrShadowRoot(parent);
8
+ });
9
+ if (topLevelElement === null) {
10
+ topLevelElement = node.getTopLevelElementOrThrow();
11
+ }
12
+ return topLevelElement;
13
+ };
14
+ export var formatParagraph = function formatParagraph(editor) {
15
+ editor === null || editor === void 0 || editor.update(function () {
16
+ var selection = $getSelection();
17
+ $setBlocksType(selection, function () {
18
+ return $createParagraphNode();
19
+ });
20
+ });
21
+ };
22
+ export var getSelectedNode = function getSelectedNode(selection) {
23
+ var anchor = selection.anchor;
24
+ var focus = selection.focus;
25
+ var anchorNode = selection.anchor.getNode();
26
+ var focusNode = selection.focus.getNode();
27
+ if (anchorNode === focusNode) {
28
+ return anchorNode;
29
+ }
30
+ var isBackward = selection.isBackward();
31
+ if (isBackward) {
32
+ return $isAtNodeEnd(focus) ? anchorNode : focusNode;
33
+ } else {
34
+ return $isAtNodeEnd(anchor) ? anchorNode : focusNode;
35
+ }
36
+ };
@@ -2,7 +2,9 @@ export { default as ChatInput, type ChatInputProps } from './ChatInput';
2
2
  export { default as ChatInputActionBar, type ChatInputActionBarProps } from './ChatInputActionBar';
3
3
  export { type ChatInputActionEvent, default as ChatInputActions, type ChatInputActionsProps, } from './ChatInputActions';
4
4
  export { default as CodeLanguageSelect, type CodeLanguageSelectProps } from './CodeLanguageSelect';
5
- export { default as Editor, type EditorProps, useEditor, withProps } from './Editor';
5
+ export { default as Editor, type EditorProps, withProps } from './Editor';
6
6
  export { EditorProvider, type EditorProviderConfig, type EditorProviderProps, useEditorContent, } from './EditorProvider';
7
+ export { useEditor } from './hooks/useEditor';
8
+ export { type EditorState, useEditorState } from './hooks/useEditorState';
7
9
  export { default as SendButton, type SendButtonProps } from './SendButton';
8
10
  export { default as SlashMenu, type SlashMenuProps } from './SlashMenu';
package/es/react/index.js CHANGED
@@ -2,7 +2,9 @@ export { default as ChatInput } from "./ChatInput";
2
2
  export { default as ChatInputActionBar } from "./ChatInputActionBar";
3
3
  export { default as ChatInputActions } from "./ChatInputActions";
4
4
  export { default as CodeLanguageSelect } from "./CodeLanguageSelect";
5
- export { default as Editor, useEditor, withProps } from "./Editor";
5
+ export { default as Editor, withProps } from "./Editor";
6
6
  export { EditorProvider, useEditorContent } from "./EditorProvider";
7
+ export { useEditor } from "./hooks/useEditor";
8
+ export { useEditorState } from "./hooks/useEditorState";
7
9
  export { default as SendButton } from "./SendButton";
8
10
  export { default as SlashMenu } from "./SlashMenu";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/editor",
3
- "version": "1.4.1",
3
+ "version": "1.4.2",
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",
@@ -1,31 +0,0 @@
1
- import { type RefObject } from 'react';
2
- import { IEditor } from "../../types";
3
- /**
4
- * Provide toolbar state and toolbar methods
5
- * @returns
6
- */
7
- export declare function useToolbarState(editorRef: RefObject<IEditor | null>): {
8
- blockType: string | null;
9
- bold: () => void;
10
- bulletList: () => void;
11
- canRedo: boolean;
12
- canUndo: boolean;
13
- code: () => void;
14
- codeblockLang: string | null | undefined;
15
- formatCodeblock: () => void;
16
- insertLink: () => void;
17
- isBold: boolean;
18
- isCode: boolean;
19
- isEmpty: boolean;
20
- isInCodeblock: boolean;
21
- isItalic: boolean;
22
- isStrikethrough: boolean;
23
- isUnderline: boolean;
24
- italic: () => void;
25
- numberList: () => void;
26
- redo: () => void;
27
- strikethrough: () => void;
28
- underline: () => void;
29
- undo: () => void;
30
- updateCodeblockLang: (lang: string) => void;
31
- };
File without changes
File without changes