@lobehub/editor 1.0.4 → 1.1.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.
@@ -32,7 +32,14 @@ var ReactPlainText = /*#__PURE__*/memo(function (_ref) {
32
32
  theme = _ref$theme === void 0 ? {} : _ref$theme,
33
33
  onChange = _ref.onChange,
34
34
  className = _ref.className,
35
- variant = _ref.variant;
35
+ variant = _ref.variant,
36
+ onKeyDown = _ref.onKeyDown,
37
+ onFocus = _ref.onFocus,
38
+ onBlur = _ref.onBlur,
39
+ autoFocus = _ref.autoFocus,
40
+ onCompositionStart = _ref.onCompositionStart,
41
+ onCompositionEnd = _ref.onCompositionEnd,
42
+ onContextMenu = _ref.onContextMenu;
36
43
  var isChat = variant === 'chat';
37
44
  var _theme$fontSize = theme.fontSize,
38
45
  fontSize = _theme$fontSize === void 0 ? isChat ? 14 : 16 : _theme$fontSize,
@@ -88,11 +95,22 @@ var ReactPlainText = /*#__PURE__*/memo(function (_ref) {
88
95
  onChange === null || onChange === void 0 || onChange(editor);
89
96
  });
90
97
  }, [editor, type, content, onChange, isInitialized]);
98
+ useEffect(function () {
99
+ if (autoFocus && editorContainerRef.current) {
100
+ editorContainerRef.current.focus();
101
+ }
102
+ }, [autoFocus]);
91
103
  return /*#__PURE__*/_jsxs("div", {
92
104
  className: cx(styles.root, styles.variant, className),
93
105
  style: style,
94
106
  children: [/*#__PURE__*/_jsx("div", {
95
107
  contentEditable: true,
108
+ onBlur: onBlur,
109
+ onCompositionEnd: onCompositionEnd,
110
+ onCompositionStart: onCompositionStart,
111
+ onContextMenu: onContextMenu,
112
+ onFocus: onFocus,
113
+ onKeyDown: onKeyDown,
96
114
  ref: editorContainerRef,
97
115
  style: {
98
116
  outline: 'none'
@@ -1,4 +1,4 @@
1
- import type { CSSProperties, ReactElement, ReactNode } from 'react';
1
+ import type { CSSProperties, CompositionEventHandler, FocusEventHandler, KeyboardEventHandler, MouseEventHandler, ReactElement, ReactNode } from 'react';
2
2
  import { CommonPluginOptions } from "..";
3
3
  import type { IEditor } from "../../../types";
4
4
  export interface ReactEditorContentProps {
@@ -7,9 +7,16 @@ export interface ReactEditorContentProps {
7
7
  type: string;
8
8
  }
9
9
  export interface ReactPlainTextProps {
10
+ autoFocus?: boolean;
10
11
  children: ReactElement<ReactEditorContentProps>;
11
12
  className?: string;
13
+ onBlur?: FocusEventHandler<HTMLDivElement>;
12
14
  onChange?: (editor: IEditor) => void;
15
+ onCompositionEnd?: CompositionEventHandler<HTMLDivElement>;
16
+ onCompositionStart?: CompositionEventHandler<HTMLDivElement>;
17
+ onContextMenu?: MouseEventHandler<HTMLDivElement>;
18
+ onFocus?: FocusEventHandler<HTMLDivElement>;
19
+ onKeyDown?: KeyboardEventHandler<HTMLDivElement>;
13
20
  style?: CSSProperties;
14
21
  theme?: CommonPluginOptions['theme'] & {
15
22
  fontSize?: number;
@@ -9,12 +9,16 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
9
9
  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); }
10
10
  function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
11
11
  function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
12
+ import { isModifierMatch } from 'lexical';
12
13
  import { createElement, memo, useMemo } from 'react';
14
+ import { mergeRefs } from 'react-merge-refs';
15
+ import { CONTROL_OR_META } from "../../common/sys";
13
16
  import { ReactEditor } from "../../editor-kernel/react/react-editor";
14
17
  import { ReactEditorContent, ReactPlainText } from "../../plugins/common";
15
18
  import { ReactMentionPlugin } from "../../plugins/mention";
16
19
  import { ReactSlashOption, ReactSlashPlugin } from "../../plugins/slash";
17
20
  import { useEditorContent } from "../EditorProvider";
21
+ import { useEditor } from "./useEditor";
18
22
  import { jsx as _jsx } from "react/jsx-runtime";
19
23
  import { jsxs as _jsxs } from "react/jsx-runtime";
20
24
  var Editor = /*#__PURE__*/memo(function (_ref) {
@@ -31,10 +35,19 @@ var Editor = /*#__PURE__*/memo(function (_ref) {
31
35
  _ref$mentionOption = _ref.mentionOption,
32
36
  mentionOption = _ref$mentionOption === void 0 ? {} : _ref$mentionOption,
33
37
  variant = _ref.variant,
38
+ onKeyDown = _ref.onKeyDown,
34
39
  theme = _ref.theme,
35
40
  children = _ref.children,
36
41
  _ref$type = _ref.type,
37
- type = _ref$type === void 0 ? 'json' : _ref$type;
42
+ type = _ref$type === void 0 ? 'json' : _ref$type,
43
+ onPressEnter = _ref.onPressEnter,
44
+ onFocus = _ref.onFocus,
45
+ onBlur = _ref.onBlur,
46
+ autoFocus = _ref.autoFocus,
47
+ onCompositionStart = _ref.onCompositionStart,
48
+ onCompositionEnd = _ref.onCompositionEnd,
49
+ onContextMenu = _ref.onContextMenu;
50
+ var ref = useEditor();
38
51
  var _useEditorContent = useEditorContent(),
39
52
  config = _useEditorContent.config;
40
53
  var enableSlash = Boolean((slashOption === null || slashOption === void 0 ? void 0 : slashOption.items) && slashOption.items.length > 0);
@@ -70,12 +83,41 @@ var Editor = /*#__PURE__*/memo(function (_ref) {
70
83
  }, restMentionOption)) : undefined]
71
84
  });
72
85
  }, [enableSlash, enableMention, slashOption, restMentionOption]);
86
+ var handleKeyDown = function handleKeyDown(e) {
87
+ // Check if currently composing (e.g., typing with IME)
88
+ var isComposing = e.nativeEvent.isComposing;
89
+
90
+ // Handle Enter key press
91
+ if (e.key === 'Enter' && !isComposing) {
92
+ // Support for Ctrl/Cmd + Enter for forced submit
93
+ if (isModifierMatch(e.nativeEvent, CONTROL_OR_META) && onPressEnter) {
94
+ // Force submit with modifier key
95
+ onPressEnter(e);
96
+ return;
97
+ }
98
+
99
+ // Regular Enter key handling
100
+ if (onPressEnter) {
101
+ onPressEnter(e);
102
+ }
103
+ }
104
+
105
+ // Call the optional onKeyDown handler
106
+ onKeyDown === null || onKeyDown === void 0 || onKeyDown(e);
107
+ };
73
108
  return /*#__PURE__*/_jsxs(ReactEditor, {
74
109
  config: config,
75
- editorRef: editorRef,
110
+ editorRef: mergeRefs([ref, editorRef]),
76
111
  children: [memoPlugins, memoSlash, memoMention, /*#__PURE__*/_jsx(ReactPlainText, {
112
+ autoFocus: autoFocus,
77
113
  className: className,
114
+ onBlur: onBlur,
78
115
  onChange: onChange,
116
+ onCompositionEnd: onCompositionEnd,
117
+ onCompositionStart: onCompositionStart,
118
+ onContextMenu: onContextMenu,
119
+ onFocus: onFocus,
120
+ onKeyDown: handleKeyDown,
79
121
  style: style,
80
122
  theme: theme,
81
123
  variant: variant,
@@ -1,4 +1,4 @@
1
- import type { CSSProperties, FC, ReactNode, Ref } from 'react';
1
+ import type { CSSProperties, CompositionEventHandler, FC, FocusEventHandler, KeyboardEventHandler, MouseEventHandler, ReactNode, Ref } 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";
@@ -8,11 +8,19 @@ interface MentionOption extends Partial<ReactSlashOptionProps> {
8
8
  markdownWriter?: ReactMentionPluginProps['markdownWriter'];
9
9
  }
10
10
  export interface EditorProps extends Partial<ReactEditorContentProps> {
11
+ autoFocus?: boolean;
11
12
  children?: ReactNode;
12
13
  className?: string;
13
14
  editorRef?: Ref<IEditor>;
14
15
  mentionOption?: MentionOption;
16
+ onBlur?: FocusEventHandler<HTMLDivElement>;
15
17
  onChange?: (editor: IEditor) => void;
18
+ onCompositionEnd?: CompositionEventHandler<HTMLDivElement>;
19
+ onCompositionStart?: CompositionEventHandler<HTMLDivElement>;
20
+ onContextMenu?: MouseEventHandler<HTMLDivElement>;
21
+ onFocus?: FocusEventHandler<HTMLDivElement>;
22
+ onKeyDown?: KeyboardEventHandler<HTMLDivElement>;
23
+ onPressEnter?: KeyboardEventHandler<HTMLDivElement>;
16
24
  plugins?: EditorPlugin[];
17
25
  slashOption?: Partial<ReactSlashOptionProps>;
18
26
  style?: CSSProperties;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/editor",
3
- "version": "1.0.4",
3
+ "version": "1.1.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",
@@ -52,6 +52,7 @@
52
52
  "polished": "^4.3.1",
53
53
  "react-error-boundary": "^6.0.0",
54
54
  "react-layout-kit": "^2.0.0",
55
+ "react-merge-refs": "^3.0.2",
55
56
  "shiki": "^3.9.2",
56
57
  "use-merge-value": "^1.2.0"
57
58
  },