@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.
- package/es/editor-kernel/react/index.d.ts +0 -1
- package/es/editor-kernel/react/index.js +1 -2
- package/es/react/Editor/index.d.ts +3 -2
- package/es/react/Editor/index.js +3 -2
- package/es/react/hooks/useEditorState/index.d.ts +61 -0
- package/es/{editor-kernel/react/useToolbarState.js → react/hooks/useEditorState/index.js} +54 -71
- package/es/react/hooks/useEditorState/utils.d.ts +4 -0
- package/es/react/hooks/useEditorState/utils.js +36 -0
- package/es/react/index.d.ts +3 -1
- package/es/react/index.js +3 -1
- package/package.json +1 -1
- package/es/editor-kernel/react/useToolbarState.d.ts +0 -31
- /package/es/react/{Editor → hooks}/useEditor.d.ts +0 -0
- /package/es/react/{Editor → hooks}/useEditor.js +0 -0
|
@@ -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';
|
package/es/react/Editor/index.js
CHANGED
|
@@ -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 { $
|
|
11
|
-
import { $
|
|
12
|
-
import { $
|
|
13
|
-
import { useCallback, useEffect, useState } from 'react';
|
|
14
|
-
import { UPDATE_CODEBLOCK_LANG } from "
|
|
15
|
-
import { $isRootTextContentEmpty } from "
|
|
16
|
-
import { $isLinkNode, TOGGLE_LINK_COMMAND } from "
|
|
17
|
-
import { sanitizeUrl } from "
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
* @
|
|
26
|
+
* @param editorRef - Reference to the editor instance
|
|
27
|
+
* @returns Editor state and methods for toolbar functionality
|
|
55
28
|
*/
|
|
56
|
-
export function
|
|
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(
|
|
74
|
+
var _useState23 = useState(false),
|
|
102
75
|
_useState24 = _slicedToArray(_useState23, 2),
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
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
|
+
};
|
package/es/react/index.d.ts
CHANGED
|
@@ -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,
|
|
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,
|
|
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,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
|