@lobehub/editor 1.32.0 → 1.33.0

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.
Files changed (34) hide show
  1. package/es/editor-kernel/kernel.d.ts +4 -4
  2. package/es/editor-kernel/kernel.js +6 -2
  3. package/es/editor-kernel/react/PortalContainer.d.ts +11 -0
  4. package/es/editor-kernel/react/PortalContainer.js +32 -0
  5. package/es/editor-kernel/react/index.d.ts +1 -0
  6. package/es/editor-kernel/react/index.js +1 -0
  7. package/es/editor-kernel/react/useDecorators.js +3 -2
  8. package/es/editor-kernel/utils.d.ts +7 -1
  9. package/es/editor-kernel/utils.js +34 -0
  10. package/es/plugins/file/node/FileNode.js +12 -2
  11. package/es/plugins/hr/node/HorizontalRuleNode.js +12 -2
  12. package/es/plugins/link/node/LinkNode.js +2 -0
  13. package/es/plugins/link-highlight/node/link-highlight.js +1 -0
  14. package/es/plugins/litexml/command/diffCommand.d.ts +10 -0
  15. package/es/plugins/litexml/command/diffCommand.js +47 -0
  16. package/es/plugins/litexml/command/index.d.ts +19 -0
  17. package/es/plugins/litexml/command/index.js +286 -45
  18. package/es/plugins/litexml/index.d.ts +1 -1
  19. package/es/plugins/litexml/index.js +1 -1
  20. package/es/plugins/litexml/node/DiffNode.d.ts +26 -0
  21. package/es/plugins/litexml/node/DiffNode.js +164 -0
  22. package/es/plugins/litexml/plugin/index.d.ts +4 -0
  23. package/es/plugins/litexml/plugin/index.js +20 -3
  24. package/es/plugins/litexml/react/DiffNodeToolbar.d.ts +10 -0
  25. package/es/plugins/litexml/react/DiffNodeToolbar.js +47 -0
  26. package/es/plugins/litexml/react/index.js +14 -1
  27. package/es/plugins/litexml/react/style.d.ts +1 -0
  28. package/es/plugins/litexml/react/style.js +8 -0
  29. package/es/plugins/litexml/utils/index.d.ts +1 -0
  30. package/es/plugins/litexml/utils/index.js +34 -0
  31. package/es/plugins/math/node/index.js +24 -4
  32. package/es/plugins/mention/node/MentionNode.js +12 -2
  33. package/es/types/kernel.d.ts +8 -3
  34. package/package.json +1 -1
@@ -0,0 +1,47 @@
1
+ import { Check, X } from 'lucide-react';
2
+ import { memo } from 'react';
3
+ import { LexicalPortalContainer } from "../../../editor-kernel/react";
4
+ import { DiffAction, LITEXML_DIFFNODE_COMMAND } from "../command/diffCommand";
5
+ import { jsx as _jsx } from "react/jsx-runtime";
6
+ import { jsxs as _jsxs } from "react/jsx-runtime";
7
+ var ReactDiffNodeToolbar = /*#__PURE__*/memo(function (_ref) {
8
+ var editor = _ref.editor,
9
+ node = _ref.node;
10
+ return /*#__PURE__*/_jsxs(LexicalPortalContainer, {
11
+ editor: editor,
12
+ node: node,
13
+ children: [/*#__PURE__*/_jsx("button", {
14
+ "aria-label": "Accept change",
15
+ className: "toolbarButton accept",
16
+ onClick: function onClick() {
17
+ console.log('Accept change');
18
+ editor.dispatchCommand(LITEXML_DIFFNODE_COMMAND, {
19
+ action: DiffAction.Accept,
20
+ nodeKey: node.getKey()
21
+ });
22
+ },
23
+ title: "Accept",
24
+ type: "button",
25
+ children: /*#__PURE__*/_jsx(Check, {
26
+ size: 16
27
+ })
28
+ }), /*#__PURE__*/_jsx("button", {
29
+ "aria-label": "Reject change",
30
+ className: "toolbarButton reject",
31
+ onClick: function onClick() {
32
+ console.log('Reject change');
33
+ editor.dispatchCommand(LITEXML_DIFFNODE_COMMAND, {
34
+ action: DiffAction.Reject,
35
+ nodeKey: node.getKey()
36
+ });
37
+ },
38
+ title: "Reject",
39
+ type: "button",
40
+ children: /*#__PURE__*/_jsx(X, {
41
+ size: 16
42
+ })
43
+ })]
44
+ });
45
+ });
46
+ ReactDiffNodeToolbar.displayName = 'ReactDiffNodeToolbar';
47
+ export default ReactDiffNodeToolbar;
@@ -10,13 +10,26 @@ import { useLayoutEffect } from 'react';
10
10
  import { useLexicalComposerContext } from "../../../editor-kernel/react";
11
11
  import { INodePlugin } from "../../inode";
12
12
  import { LitexmlPlugin } from "../plugin";
13
+ import ReactDiffNodeToolbar from "./DiffNodeToolbar";
14
+ import { useStyles } from "./style";
15
+ import { jsx as _jsx } from "react/jsx-runtime";
13
16
  export var ReactLiteXmlPlugin = function ReactLiteXmlPlugin() {
14
17
  var _useLexicalComposerCo = useLexicalComposerContext(),
15
18
  _useLexicalComposerCo2 = _slicedToArray(_useLexicalComposerCo, 1),
16
19
  editor = _useLexicalComposerCo2[0];
20
+ var _useStyles = useStyles(),
21
+ styles = _useStyles.styles;
17
22
  useLayoutEffect(function () {
18
23
  editor.registerPlugin(INodePlugin);
19
- editor.registerPlugin(LitexmlPlugin);
24
+ editor.registerPlugin(LitexmlPlugin, {
25
+ decorator: function decorator(node, editor) {
26
+ return /*#__PURE__*/_jsx(ReactDiffNodeToolbar, {
27
+ editor: editor,
28
+ node: node
29
+ });
30
+ },
31
+ theme: styles
32
+ });
20
33
  }, [editor]);
21
34
  return null;
22
35
  };
@@ -0,0 +1 @@
1
+ export declare const useStyles: (props?: unknown) => import("antd-style").ReturnStyles<import("antd-style").SerializedStyles>;
@@ -0,0 +1,8 @@
1
+ var _templateObject;
2
+ function _taggedTemplateLiteral(strings, raw) { if (!raw) { raw = strings.slice(0); } return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
3
+ import { createStyles } from 'antd-style';
4
+ export var useStyles = createStyles(function (_ref) {
5
+ var css = _ref.css,
6
+ token = _ref.token;
7
+ return css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n position: relative;\n border: 1px solid ", ";\n\n .toolbar {\n position: absolute;\n z-index: 10;\n inset-block-start: 0;\n inset-inline-end: 0;\n\n display: flex;\n gap: 4px;\n align-items: center;\n\n padding: 4px;\n border: 1px solid #eee;\n border-radius: 4px;\n\n background: #fff;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 10%);\n }\n\n .toolbarButton {\n cursor: pointer;\n\n display: flex;\n align-items: center;\n justify-content: center;\n\n padding: 2px;\n border: none;\n\n background: none;\n }\n\n .toolbarButton:focus {\n border-radius: 3px;\n outline: 2px solid ", ";\n outline-offset: 2px;\n }\n\n .accept {\n color: ", ";\n }\n\n .reject {\n color: ", ";\n }\n\n &[data-diff-type='add'] .content {\n position: relative;\n background-color: ", ";\n }\n\n &[data-diff-type='remove'] .content {\n position: relative;\n background-color: ", ";\n\n > *:first-child p,\n > *:first-child span {\n text-decoration: line-through;\n }\n }\n\n &[data-diff-type='modify'] .content {\n position: relative;\n\n /* first child: original (deleted) */\n > *:first-child {\n opacity: 0.6;\n }\n\n /* visually indicate deletion with strike-through for text nodes */\n > *:first-child p,\n > *:first-child span {\n text-decoration: line-through;\n }\n\n /* second child: modified/new - normal appearance */\n > *:nth-child(2) {\n color: inherit;\n opacity: 1;\n }\n }\n "])), token.colorBorderSecondary, token.colorPrimary, token.colorSuccess, token.colorError, token.colorSuccessBgHover, token.colorErrorBgHover);
8
+ });
@@ -1,4 +1,5 @@
1
1
  import { LexicalEditor, LexicalNode } from 'lexical';
2
2
  export declare function $parseSerializedNodeImpl(serializedNode: any, editor: LexicalEditor): LexicalNode;
3
+ export declare function $cloneNode(node: LexicalNode, editor: LexicalEditor): LexicalNode;
3
4
  export declare function idToChar(id: string | number): string;
4
5
  export declare function charToId(char: string): string;
@@ -31,6 +31,40 @@ export function $parseSerializedNodeImpl(serializedNode, editor) {
31
31
  }
32
32
  return node;
33
33
  }
34
+ function exportNodeToJSON(node) {
35
+ var serializedNode = node.exportJSON();
36
+ var nodeClass = node.constructor;
37
+ if (serializedNode.type !== nodeClass.getType()) {
38
+ throw new Error("LexicalNode: Node ".concat(nodeClass.name, " does not match the serialized type. Check if .exportJSON() is implemented and it is returning the correct type."));
39
+ }
40
+ if ($isElementNode(node)) {
41
+ var serializedChildren = serializedNode.children;
42
+ if (!Array.isArray(serializedChildren)) {
43
+ throw new Error("LexicalNode: Node ".concat(nodeClass.name, " is an element but .exportJSON() does not have a children array."));
44
+ }
45
+ var children = node.getChildren();
46
+ var _iterator2 = _createForOfIteratorHelper(children),
47
+ _step2;
48
+ try {
49
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
50
+ var child = _step2.value;
51
+ var serializedChildNode = exportNodeToJSON(child);
52
+ serializedChildren.push(serializedChildNode);
53
+ }
54
+ } catch (err) {
55
+ _iterator2.e(err);
56
+ } finally {
57
+ _iterator2.f();
58
+ }
59
+ }
60
+
61
+ // @ts-expect-error
62
+ return serializedNode;
63
+ }
64
+ export function $cloneNode(node, editor) {
65
+ var json = exportNodeToJSON(node);
66
+ return $parseSerializedNodeImpl(json, editor);
67
+ }
34
68
  var maxId = 1679616; // 36^4
35
69
  var startId = 1000000; // to avoid short ids
36
70
  var step = 7211; // a prime number to reduce collisions
@@ -92,8 +92,18 @@ export var MathInlineNode = /*#__PURE__*/function (_DecoratorNode) {
92
92
  }, {
93
93
  key: "decorate",
94
94
  value: function decorate(editor) {
95
- var _getKernelFromEditor, _getKernelFromEditor$;
96
- return ((_getKernelFromEditor = getKernelFromEditor(editor)) === null || _getKernelFromEditor === void 0 || (_getKernelFromEditor$ = _getKernelFromEditor.getDecorator(MathInlineNode.getType())) === null || _getKernelFromEditor$ === void 0 ? void 0 : _getKernelFromEditor$(this, editor)) || null;
95
+ var _getKernelFromEditor;
96
+ var decorator = (_getKernelFromEditor = getKernelFromEditor(editor)) === null || _getKernelFromEditor === void 0 ? void 0 : _getKernelFromEditor.getDecorator(MathInlineNode.getType());
97
+ if (!decorator) {
98
+ return null;
99
+ }
100
+ if (typeof decorator === 'function') {
101
+ return decorator(this, editor);
102
+ }
103
+ return {
104
+ queryDOM: decorator.queryDOM,
105
+ render: decorator.render(this, editor)
106
+ };
97
107
  }
98
108
  }], [{
99
109
  key: "getType",
@@ -200,8 +210,18 @@ export var MathBlockNode = /*#__PURE__*/function (_DecoratorNode2) {
200
210
  }, {
201
211
  key: "decorate",
202
212
  value: function decorate(editor) {
203
- var _getKernelFromEditor2, _getKernelFromEditor3;
204
- return ((_getKernelFromEditor2 = getKernelFromEditor(editor)) === null || _getKernelFromEditor2 === void 0 || (_getKernelFromEditor3 = _getKernelFromEditor2.getDecorator(MathBlockNode.getType())) === null || _getKernelFromEditor3 === void 0 ? void 0 : _getKernelFromEditor3(this, editor)) || null;
213
+ var _getKernelFromEditor2;
214
+ var decorator = (_getKernelFromEditor2 = getKernelFromEditor(editor)) === null || _getKernelFromEditor2 === void 0 ? void 0 : _getKernelFromEditor2.getDecorator(MathBlockNode.getType());
215
+ if (!decorator) {
216
+ return null;
217
+ }
218
+ if (typeof decorator === 'function') {
219
+ return decorator(this, editor);
220
+ }
221
+ return {
222
+ queryDOM: decorator.queryDOM,
223
+ render: decorator.render(this, editor)
224
+ };
205
225
  }
206
226
  }], [{
207
227
  key: "getType",
@@ -94,8 +94,18 @@ export var MentionNode = /*#__PURE__*/function (_DecoratorNode) {
94
94
  }, {
95
95
  key: "decorate",
96
96
  value: function decorate(editor) {
97
- var _getKernelFromEditor, _getKernelFromEditor$;
98
- return ((_getKernelFromEditor = getKernelFromEditor(editor)) === null || _getKernelFromEditor === void 0 || (_getKernelFromEditor$ = _getKernelFromEditor.getDecorator('mention')) === null || _getKernelFromEditor$ === void 0 ? void 0 : _getKernelFromEditor$(this, editor)) || null;
97
+ var _getKernelFromEditor;
98
+ var decorator = (_getKernelFromEditor = getKernelFromEditor(editor)) === null || _getKernelFromEditor === void 0 ? void 0 : _getKernelFromEditor.getDecorator(MentionNode.getType());
99
+ if (!decorator) {
100
+ return null;
101
+ }
102
+ if (typeof decorator === 'function') {
103
+ return decorator(this, editor);
104
+ }
105
+ return {
106
+ queryDOM: decorator.queryDOM,
107
+ render: decorator.render(this, editor)
108
+ };
99
109
  }
100
110
  }], [{
101
111
  key: "getType",
@@ -1,11 +1,16 @@
1
1
  import type { HistoryState, HistoryStateEntry } from '@lexical/history';
2
- import type { CommandListener, CommandListenerPriority, CommandPayloadType, DecoratorNode, EditorState, LexicalCommand, LexicalEditor, LexicalNodeConfig } from 'lexical';
2
+ import type { CommandListener, CommandListenerPriority, CommandPayloadType, EditorState, LexicalCommand, LexicalEditor, LexicalNode, LexicalNodeConfig } from 'lexical';
3
3
  import type DataSource from "../editor-kernel/data-source";
4
4
  import type { HotkeyId } from "./hotkey";
5
5
  import type { HotkeyOptions, HotkeysEvent } from "../utils/hotkey/registerHotkey";
6
6
  import type { ILocaleKeys } from './locale';
7
7
  export type Commands = Map<LexicalCommand<unknown>, Array<Set<CommandListener<unknown>>>>;
8
8
  export type CommandsClean = Map<LexicalCommand<unknown>, () => void>;
9
+ export type IDecoratorFunc = (_node: LexicalNode, _editor: LexicalEditor) => any;
10
+ export type IDecorator = {
11
+ queryDOM: (_element: HTMLElement) => HTMLElement;
12
+ render: IDecoratorFunc;
13
+ } | IDecoratorFunc;
9
14
  /**
10
15
  * Service ID type
11
16
  */
@@ -206,7 +211,7 @@ export interface IEditorKernel extends IEditor {
206
211
  * Get editor Node decorator for specific Node rendering
207
212
  * @param name
208
213
  */
209
- getDecorator(name: string): ((_node: DecoratorNode<any>, _editor: LexicalEditor) => any) | undefined;
214
+ getDecorator(name: string): IDecorator | undefined;
210
215
  /**
211
216
  * Get editor history state
212
217
  */
@@ -229,7 +234,7 @@ export interface IEditorKernel extends IEditor {
229
234
  * @param name
230
235
  * @param decorator
231
236
  */
232
- registerDecorator(name: string, decorator: (_node: DecoratorNode<any>, _editor: LexicalEditor) => any): void;
237
+ registerDecorator(name: string, decorator: IDecorator): void;
233
238
  /**
234
239
  * Register Lexical Node
235
240
  * @param nodes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/editor",
3
- "version": "1.32.0",
3
+ "version": "1.33.0",
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",