@lobehub/editor 4.18.0 → 4.19.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.
- package/es/index.d.ts +2 -2
- package/es/index.js +2 -1
- package/es/plugins/slash/index.d.ts +1 -1
- package/es/plugins/slash/react/ReactSlashPlugin.js +14 -9
- package/es/plugins/slash/react/components/DefaultSlashMenu.js +177 -56
- package/es/plugins/slash/react/type.d.ts +5 -2
- package/es/plugins/slash/service/i-slash-service.d.ts +13 -2
- package/es/plugins/slash/service/i-slash-service.js +10 -2
- package/es/react/ChatInput/ChatInput.js +1 -1
- package/es/react/ChatInput/type.d.ts +5 -0
- package/es/react.d.ts +1 -5
- package/es/react.js +1 -3
- package/package.json +1 -1
- package/es/react/FloatMenu/FloatMenu.d.ts +0 -7
- package/es/react/FloatMenu/FloatMenu.js +0 -32
- package/es/react/FloatMenu/index.d.ts +0 -2
- package/es/react/FloatMenu/style.js +0 -28
- package/es/react/FloatMenu/type.d.ts +0 -25
- package/es/react/SlashMenu/SlashMenu.d.ts +0 -7
- package/es/react/SlashMenu/SlashMenu.js +0 -40
- package/es/react/SlashMenu/index.d.ts +0 -2
- package/es/react/SlashMenu/type.d.ts +0 -17
package/es/index.d.ts
CHANGED
|
@@ -91,7 +91,7 @@ import { SerializedMentionNode } from "./plugins/mention/node/MentionNode.js";
|
|
|
91
91
|
import { MentionPlugin, MentionPluginOptions } from "./plugins/mention/plugin/index.js";
|
|
92
92
|
import { ReactMentionPluginProps } from "./plugins/mention/react/type.js";
|
|
93
93
|
import { ReactMentionPlugin } from "./plugins/mention/react/ReactMentionPlugin.js";
|
|
94
|
-
import { ISlashMenuOption, ISlashOption, ISlashService, SlashOptions } from "./plugins/slash/service/i-slash-service.js";
|
|
94
|
+
import { ISlashDividerOption, ISlashMenuOption, ISlashOption, ISlashSectionOption, ISlashService, SlashOptions, flattenSlashOptions, isSlashDividerOption, isSlashMenuOption, isSlashSectionOption } from "./plugins/slash/service/i-slash-service.js";
|
|
95
95
|
import { ITriggerContext, SlashPlugin, SlashPluginOptions } from "./plugins/slash/plugin/index.js";
|
|
96
96
|
import { MenuRenderProps, ReactSlashOptionProps, ReactSlashPluginProps, SlashMenuProps } from "./plugins/slash/react/type.js";
|
|
97
97
|
import { SlashMenu } from "./plugins/slash/react/components/SlashMenu.js";
|
|
@@ -122,4 +122,4 @@ declare function enableHotReload(): void;
|
|
|
122
122
|
*/
|
|
123
123
|
declare function disableHotReload(): void;
|
|
124
124
|
//#endregion
|
|
125
|
-
export { $closest, $closestNodeType, $createCursorNode, $getNearestNodeFromDOMNode, $getNodeFromDOMNode, $isCardLikeElementNode, $isCursorNode, ANCHOR_PADDING_CSS_VAR, AutoCompletePlugin, BlockDragTarget, BlockMenuService, BlockMovePayload, BlockPlugin, BlockPluginOptions, CONTENT_BLOCKS_DATA_TYPE, CardLikeElementNode, CodePlugin, CodeblockPlugin, CodeblockPluginOptions, CodemirrorPlugin, CodemirrorPluginOptions, CommonPlugin, CommonPluginOptions, ContentBlock, ContentBlocksDataSource, ContentBlocksPlugin, ContentBlocksPluginOptions, DEFAULT_BLOCK_ANCHOR_PADDING, DEFAULT_HEADLESS_EDITOR_PLUGINS, DOM_DOCUMENT_FRAGMENT_TYPE, DOM_DOCUMENT_TYPE, DOM_ELEMENT_TYPE, DOM_TEXT_TYPE, DataSource, DiffAction, EDITOR_THEME_KEY, ExtractContentBlocksOptions, FileContentBlock, FileListItem, FilePlugin, FilePluginOptions, GET_MARKDOWN_SELECTION_COMMAND, HIDE_TOOLBAR_COMMAND, HOVER_COMMAND, HRPlugin, HRPluginOptions, HeadlessDocumentType, HeadlessEditor, HeadlessEditorExport, HeadlessEditorExportOptions, HeadlessEditorHydrationInput, HeadlessEditorOptions, HeadlessLiteXMLBatchOperation, HeadlessLiteXMLInsertOperation, HeadlessLiteXMLOperation, HeadlessLiteXMLRemoveOperation, HeadlessLiteXMLReplaceOperation, HotkeyEnum, HotkeyId, HotkeyItem, HotkeyScopeEnum, HotkeyScopeId, IBlockActionButton, IBlockActionButtonIcon, IBlockMenuItem, IBlockMenuRenderContext, IBlockMenuService, IBlockSelectHandler, type IEditor, ILinkService, ILitexmlService, IMarkdownShortCutService, INSERT_CHECK_LIST_COMMAND, INSERT_CODEINLINE_COMMAND, INSERT_CODEMIRROR_COMMAND, INSERT_FILE_COMMAND, INSERT_HEADING_COMMAND, INSERT_HORIZONTAL_RULE_COMMAND, INSERT_IMAGE_COMMAND, INSERT_LINK_COMMAND, INSERT_LINK_HIGHLIGHT_COMMAND, INSERT_MARKDOWN_COMMAND, INSERT_MATH_COMMAND, INSERT_MENTION_COMMAND, INSERT_ORDERED_LIST_COMMAND, INSERT_QUOTE_COMMAND, INSERT_TABLE_COLUMN_COMMAND, INSERT_TABLE_COMMAND, INSERT_TABLE_ROW_COMMAND, INSERT_UNORDERED_LIST_COMMAND, INodePlugin, INodePluginOptions, INodeService, ISlashMenuOption, ISlashOption, ISlashService, ITableControllerMenuActionItem, ITableControllerMenuItem, ITableControllerMenuRenderContext, ITableControllerMenuSeparatorItem, ITableControllerMenuService, ITriggerContext, IUploadService, ImageContentBlock, ImageListItem, ImagePlugin, ImagePluginOptions, Kernel, KeyEnum, LITEXML_APPLY_COMMAND, LITEXML_DIFFNODE_ALL_COMMAND, LITEXML_DIFFNODE_COMMAND, LITEXML_INSERT_COMMAND, LITEXML_MODIFY_COMMAND, LITEXML_REMOVE_COMMAND, LexicalErrorBoundary, LexicalPortalContainer, LinkHighlightPlugin, LinkHighlightPluginOptions, LinkPlugin, LinkPluginOptions, ListPlugin, ListPluginOptions, LitexmlDataSource, LitexmlPlugin, LitexmlPluginOptions, LitexmlService, MARKDOWN_READER_LEVEL, MARKDOWN_READER_LEVEL_HIGH, MARKDOWN_READER_LEVEL_NORMAL, MARKDOWN_WRITER_LEVEL_MAX, MOVE_BLOCK_COMMAND, MarkdownPlugin, MathPlugin, MediaLists, MentionPlugin, MentionPluginOptions, MenuRenderProps, ModifierCombination, REMOVE_LIST_COMMAND, ReactAutoCompletePlugin, ReactBlockPlugin, ReactBlockPluginProps, ReactCodePlugin, ReactCodeblockPlugin, ReactCodeblockPluginProps, ReactCodemirrorPlugin, ReactEditor, ReactEditorContent, ReactEditorContentProps, ReactFilePlugin, ReactFilePluginProps, ReactHRPlugin, ReactHRPluginProps, ReactImagePlugin, ReactImagePluginProps, ReactLinkHighlightPlugin, ReactLinkPlugin, ReactLinkPluginProps, ReactListPlugin, ReactListPluginProps, ReactLiteXmlPlugin, ReactMarkdownPlugin, ReactMathPlugin, ReactMentionPlugin, ReactMentionPluginProps, ReactNodePlugin, ReactPlainText, ReactPlainTextProps, ReactSlashOption, ReactSlashOptionProps, ReactSlashPlugin, ReactSlashPluginProps, ReactTablePlugin, ReactToolbarPlugin, ReactVirtualBlockPlugin, SELECT_AFTER_CODEMIRROR_COMMAND, SELECT_BEFORE_CODEMIRROR_COMMAND, SELECT_TABLE_COMMAND, SHOW_TOOLBAR_COMMAND, SerializedMentionNode, SlashMenu, SlashMenuProps, SlashOptions, SlashPlugin, SlashPluginOptions, TableControllerMenuAxis, TableControllerMenuService, TablePlugin, TablePluginOptions, TextContentBlock, ToolbarCommandOptions, UPDATE_CODEBLOCK_LANG, UPDATE_LIST_START_COMMAND, UPLOAD_PRIORITY_HIGH, UPLOAD_PRIORITY_LOW, UPLOAD_PRIORITY_MEDIUM, UploadPlugin, UploadPluginOptions, VirtualBlockPlugin, VirtualBlockPluginOptions, XMLReaderFunc, XMLReaderRecord, XMLWriterFunc, XMLWriterRecord, assert, browserDebug, bundledLanguagesInfo, compareNodeOrder, createDebugLogger, createEmptyEditorState, createHeadlessEditor, cursorNodeSerialized, debugLogger, debugLoggers, detectCodeLanguage, detectLanguage, devConsole, disableHotReload, enableHotReload, extractContentBlocks, extractMediaFromEditorState, extractMediaLists, genServiceId, generateEditorId, getHotkeyById, getKernelFromEditor, getKernelFromEditorConfig, getNodeKeyFromDOMNode, getParentElement, isDOMNode, isDocumentFragment, isPunctuationChar, isPureUrl, isValidUrl, moment, noop, prodSafeLogger, reconcileDecorator, registerBlockMoveCommand, registerEditorKernel, registerLinkHighlightCommand, registerToolbarCommand, resetRandomKey, scrollIntoView, unregisterEditorKernel, useHasDiffNode, useLexicalComposerContext, useLexicalEditor };
|
|
125
|
+
export { $closest, $closestNodeType, $createCursorNode, $getNearestNodeFromDOMNode, $getNodeFromDOMNode, $isCardLikeElementNode, $isCursorNode, ANCHOR_PADDING_CSS_VAR, AutoCompletePlugin, BlockDragTarget, BlockMenuService, BlockMovePayload, BlockPlugin, BlockPluginOptions, CONTENT_BLOCKS_DATA_TYPE, CardLikeElementNode, CodePlugin, CodeblockPlugin, CodeblockPluginOptions, CodemirrorPlugin, CodemirrorPluginOptions, CommonPlugin, CommonPluginOptions, ContentBlock, ContentBlocksDataSource, ContentBlocksPlugin, ContentBlocksPluginOptions, DEFAULT_BLOCK_ANCHOR_PADDING, DEFAULT_HEADLESS_EDITOR_PLUGINS, DOM_DOCUMENT_FRAGMENT_TYPE, DOM_DOCUMENT_TYPE, DOM_ELEMENT_TYPE, DOM_TEXT_TYPE, DataSource, DiffAction, EDITOR_THEME_KEY, ExtractContentBlocksOptions, FileContentBlock, FileListItem, FilePlugin, FilePluginOptions, GET_MARKDOWN_SELECTION_COMMAND, HIDE_TOOLBAR_COMMAND, HOVER_COMMAND, HRPlugin, HRPluginOptions, HeadlessDocumentType, HeadlessEditor, HeadlessEditorExport, HeadlessEditorExportOptions, HeadlessEditorHydrationInput, HeadlessEditorOptions, HeadlessLiteXMLBatchOperation, HeadlessLiteXMLInsertOperation, HeadlessLiteXMLOperation, HeadlessLiteXMLRemoveOperation, HeadlessLiteXMLReplaceOperation, HotkeyEnum, HotkeyId, HotkeyItem, HotkeyScopeEnum, HotkeyScopeId, IBlockActionButton, IBlockActionButtonIcon, IBlockMenuItem, IBlockMenuRenderContext, IBlockMenuService, IBlockSelectHandler, type IEditor, ILinkService, ILitexmlService, IMarkdownShortCutService, INSERT_CHECK_LIST_COMMAND, INSERT_CODEINLINE_COMMAND, INSERT_CODEMIRROR_COMMAND, INSERT_FILE_COMMAND, INSERT_HEADING_COMMAND, INSERT_HORIZONTAL_RULE_COMMAND, INSERT_IMAGE_COMMAND, INSERT_LINK_COMMAND, INSERT_LINK_HIGHLIGHT_COMMAND, INSERT_MARKDOWN_COMMAND, INSERT_MATH_COMMAND, INSERT_MENTION_COMMAND, INSERT_ORDERED_LIST_COMMAND, INSERT_QUOTE_COMMAND, INSERT_TABLE_COLUMN_COMMAND, INSERT_TABLE_COMMAND, INSERT_TABLE_ROW_COMMAND, INSERT_UNORDERED_LIST_COMMAND, INodePlugin, INodePluginOptions, INodeService, ISlashDividerOption, ISlashMenuOption, ISlashOption, ISlashSectionOption, ISlashService, ITableControllerMenuActionItem, ITableControllerMenuItem, ITableControllerMenuRenderContext, ITableControllerMenuSeparatorItem, ITableControllerMenuService, ITriggerContext, IUploadService, ImageContentBlock, ImageListItem, ImagePlugin, ImagePluginOptions, Kernel, KeyEnum, LITEXML_APPLY_COMMAND, LITEXML_DIFFNODE_ALL_COMMAND, LITEXML_DIFFNODE_COMMAND, LITEXML_INSERT_COMMAND, LITEXML_MODIFY_COMMAND, LITEXML_REMOVE_COMMAND, LexicalErrorBoundary, LexicalPortalContainer, LinkHighlightPlugin, LinkHighlightPluginOptions, LinkPlugin, LinkPluginOptions, ListPlugin, ListPluginOptions, LitexmlDataSource, LitexmlPlugin, LitexmlPluginOptions, LitexmlService, MARKDOWN_READER_LEVEL, MARKDOWN_READER_LEVEL_HIGH, MARKDOWN_READER_LEVEL_NORMAL, MARKDOWN_WRITER_LEVEL_MAX, MOVE_BLOCK_COMMAND, MarkdownPlugin, MathPlugin, MediaLists, MentionPlugin, MentionPluginOptions, MenuRenderProps, ModifierCombination, REMOVE_LIST_COMMAND, ReactAutoCompletePlugin, ReactBlockPlugin, ReactBlockPluginProps, ReactCodePlugin, ReactCodeblockPlugin, ReactCodeblockPluginProps, ReactCodemirrorPlugin, ReactEditor, ReactEditorContent, ReactEditorContentProps, ReactFilePlugin, ReactFilePluginProps, ReactHRPlugin, ReactHRPluginProps, ReactImagePlugin, ReactImagePluginProps, ReactLinkHighlightPlugin, ReactLinkPlugin, ReactLinkPluginProps, ReactListPlugin, ReactListPluginProps, ReactLiteXmlPlugin, ReactMarkdownPlugin, ReactMathPlugin, ReactMentionPlugin, ReactMentionPluginProps, ReactNodePlugin, ReactPlainText, ReactPlainTextProps, ReactSlashOption, ReactSlashOptionProps, ReactSlashPlugin, ReactSlashPluginProps, ReactTablePlugin, ReactToolbarPlugin, ReactVirtualBlockPlugin, SELECT_AFTER_CODEMIRROR_COMMAND, SELECT_BEFORE_CODEMIRROR_COMMAND, SELECT_TABLE_COMMAND, SHOW_TOOLBAR_COMMAND, SerializedMentionNode, SlashMenu, SlashMenuProps, SlashOptions, SlashPlugin, SlashPluginOptions, TableControllerMenuAxis, TableControllerMenuService, TablePlugin, TablePluginOptions, TextContentBlock, ToolbarCommandOptions, UPDATE_CODEBLOCK_LANG, UPDATE_LIST_START_COMMAND, UPLOAD_PRIORITY_HIGH, UPLOAD_PRIORITY_LOW, UPLOAD_PRIORITY_MEDIUM, UploadPlugin, UploadPluginOptions, VirtualBlockPlugin, VirtualBlockPluginOptions, XMLReaderFunc, XMLReaderRecord, XMLWriterFunc, XMLWriterRecord, assert, browserDebug, bundledLanguagesInfo, compareNodeOrder, createDebugLogger, createEmptyEditorState, createHeadlessEditor, cursorNodeSerialized, debugLogger, debugLoggers, detectCodeLanguage, detectLanguage, devConsole, disableHotReload, enableHotReload, extractContentBlocks, extractMediaFromEditorState, extractMediaLists, flattenSlashOptions, genServiceId, generateEditorId, getHotkeyById, getKernelFromEditor, getKernelFromEditorConfig, getNodeKeyFromDOMNode, getParentElement, isDOMNode, isDocumentFragment, isPunctuationChar, isPureUrl, isSlashDividerOption, isSlashMenuOption, isSlashSectionOption, isValidUrl, moment, noop, prodSafeLogger, reconcileDecorator, registerBlockMoveCommand, registerEditorKernel, registerLinkHighlightCommand, registerToolbarCommand, resetRandomKey, scrollIntoView, unregisterEditorKernel, useHasDiffNode, useLexicalComposerContext, useLexicalEditor };
|
package/es/index.js
CHANGED
|
@@ -88,6 +88,7 @@ import { INSERT_ORDERED_LIST_COMMAND, INSERT_UNORDERED_LIST_COMMAND, REMOVE_LIST
|
|
|
88
88
|
import ReactListPlugin from "./plugins/list/react/ReactListPlugin.js";
|
|
89
89
|
import { ReactMathPlugin } from "./plugins/math/react/index.js";
|
|
90
90
|
import ReactMentionPlugin from "./plugins/mention/react/ReactMentionPlugin.js";
|
|
91
|
+
import { flattenSlashOptions, isSlashDividerOption, isSlashMenuOption, isSlashSectionOption } from "./plugins/slash/service/i-slash-service.js";
|
|
91
92
|
import { SlashPlugin } from "./plugins/slash/plugin/index.js";
|
|
92
93
|
import SlashMenu from "./plugins/slash/react/components/SlashMenu.js";
|
|
93
94
|
import ReactSlashOption from "./plugins/slash/react/ReactSlashOption.js";
|
|
@@ -127,4 +128,4 @@ function disableHotReload() {
|
|
|
127
128
|
}
|
|
128
129
|
}
|
|
129
130
|
//#endregion
|
|
130
|
-
export { $closest, $closestNodeType, $createCursorNode, $getNearestNodeFromDOMNode, $getNodeFromDOMNode, $isCardLikeElementNode, $isCursorNode, ANCHOR_PADDING_CSS_VAR, AutoCompletePlugin, BlockMenuService, BlockPlugin, CONTENT_BLOCKS_DATA_TYPE, CardLikeElementNode, CodePlugin, CodeblockPlugin, CodemirrorPlugin, CommonPlugin, ContentBlocksDataSource, ContentBlocksPlugin, DEFAULT_BLOCK_ANCHOR_PADDING, DEFAULT_HEADLESS_EDITOR_PLUGINS, DOM_DOCUMENT_FRAGMENT_TYPE, DOM_DOCUMENT_TYPE, DOM_ELEMENT_TYPE, DOM_TEXT_TYPE, DataSource, DiffAction, EDITOR_THEME_KEY, FilePlugin, GET_MARKDOWN_SELECTION_COMMAND, HIDE_TOOLBAR_COMMAND, HOVER_COMMAND, HRPlugin, HeadlessEditor, HotkeyEnum, HotkeyScopeEnum, IBlockMenuService, ILinkService, ILitexmlService, IMarkdownShortCutService, INSERT_CHECK_LIST_COMMAND, INSERT_CODEINLINE_COMMAND, INSERT_CODEMIRROR_COMMAND, INSERT_FILE_COMMAND, INSERT_HEADING_COMMAND, INSERT_HORIZONTAL_RULE_COMMAND, INSERT_IMAGE_COMMAND, INSERT_LINK_COMMAND, INSERT_LINK_HIGHLIGHT_COMMAND, INSERT_MARKDOWN_COMMAND, INSERT_MATH_COMMAND, INSERT_MENTION_COMMAND, INSERT_ORDERED_LIST_COMMAND, INSERT_QUOTE_COMMAND, INSERT_TABLE_COLUMN_COMMAND, INSERT_TABLE_COMMAND, INSERT_TABLE_ROW_COMMAND, INSERT_UNORDERED_LIST_COMMAND, INodePlugin, INodeService, ITableControllerMenuService, IUploadService, ImagePlugin, Kernel, KeyEnum, LITEXML_APPLY_COMMAND, LITEXML_DIFFNODE_ALL_COMMAND, LITEXML_DIFFNODE_COMMAND, LITEXML_INSERT_COMMAND, LITEXML_MODIFY_COMMAND, LITEXML_REMOVE_COMMAND, LexicalErrorBoundary, LexicalPortalContainer, LinkHighlightPlugin, LinkPlugin, ListPlugin, LitexmlDataSource, LitexmlPlugin, LitexmlService, MARKDOWN_READER_LEVEL_HIGH, MARKDOWN_READER_LEVEL_NORMAL, MARKDOWN_WRITER_LEVEL_MAX, MOVE_BLOCK_COMMAND, MarkdownPlugin, MathPlugin, MentionPlugin, REMOVE_LIST_COMMAND, ReactAutoCompletePlugin, ReactBlockPlugin, ReactCodePlugin, ReactCodeblockPlugin, ReactCodemirrorPlugin, ReactEditor, ReactEditorContent, ReactFilePlugin, ReactHRPlugin, ReactImagePlugin, ReactLinkHighlightPlugin, ReactLinkPlugin, ReactListPlugin, ReactLiteXmlPlugin, ReactMarkdownPlugin, ReactMathPlugin, ReactMentionPlugin, ReactNodePlugin, ReactPlainText, ReactSlashOption, ReactSlashPlugin, ReactTablePlugin, ReactToolbarPlugin, ReactVirtualBlockPlugin, SELECT_AFTER_CODEMIRROR_COMMAND, SELECT_BEFORE_CODEMIRROR_COMMAND, SELECT_TABLE_COMMAND, SHOW_TOOLBAR_COMMAND, SlashMenu, SlashPlugin, TableControllerMenuService, TablePlugin, UPDATE_CODEBLOCK_LANG, UPDATE_LIST_START_COMMAND, UPLOAD_PRIORITY_HIGH, UPLOAD_PRIORITY_LOW, UPLOAD_PRIORITY_MEDIUM, UploadPlugin, VirtualBlockPlugin, assert, browserDebug, bundledLanguagesInfo, compareNodeOrder, createDebugLogger, createEmptyEditorState, createHeadlessEditor, cursorNodeSerialized, debugLogger, debugLoggers, detectCodeLanguage, detectLanguage, devConsole, disableHotReload, enableHotReload, extractContentBlocks, extractMediaFromEditorState, extractMediaLists, genServiceId, generateEditorId, getHotkeyById, getKernelFromEditor, getKernelFromEditorConfig, getNodeKeyFromDOMNode, getParentElement, isDOMNode, isDocumentFragment, isPunctuationChar, isPureUrl, isValidUrl, moment, noop, prodSafeLogger, reconcileDecorator, registerBlockMoveCommand, registerEditorKernel, registerLinkHighlightCommand, registerToolbarCommand, resetRandomKey, scrollIntoView, unregisterEditorKernel, useHasDiffNode, useLexicalComposerContext, useLexicalEditor };
|
|
131
|
+
export { $closest, $closestNodeType, $createCursorNode, $getNearestNodeFromDOMNode, $getNodeFromDOMNode, $isCardLikeElementNode, $isCursorNode, ANCHOR_PADDING_CSS_VAR, AutoCompletePlugin, BlockMenuService, BlockPlugin, CONTENT_BLOCKS_DATA_TYPE, CardLikeElementNode, CodePlugin, CodeblockPlugin, CodemirrorPlugin, CommonPlugin, ContentBlocksDataSource, ContentBlocksPlugin, DEFAULT_BLOCK_ANCHOR_PADDING, DEFAULT_HEADLESS_EDITOR_PLUGINS, DOM_DOCUMENT_FRAGMENT_TYPE, DOM_DOCUMENT_TYPE, DOM_ELEMENT_TYPE, DOM_TEXT_TYPE, DataSource, DiffAction, EDITOR_THEME_KEY, FilePlugin, GET_MARKDOWN_SELECTION_COMMAND, HIDE_TOOLBAR_COMMAND, HOVER_COMMAND, HRPlugin, HeadlessEditor, HotkeyEnum, HotkeyScopeEnum, IBlockMenuService, ILinkService, ILitexmlService, IMarkdownShortCutService, INSERT_CHECK_LIST_COMMAND, INSERT_CODEINLINE_COMMAND, INSERT_CODEMIRROR_COMMAND, INSERT_FILE_COMMAND, INSERT_HEADING_COMMAND, INSERT_HORIZONTAL_RULE_COMMAND, INSERT_IMAGE_COMMAND, INSERT_LINK_COMMAND, INSERT_LINK_HIGHLIGHT_COMMAND, INSERT_MARKDOWN_COMMAND, INSERT_MATH_COMMAND, INSERT_MENTION_COMMAND, INSERT_ORDERED_LIST_COMMAND, INSERT_QUOTE_COMMAND, INSERT_TABLE_COLUMN_COMMAND, INSERT_TABLE_COMMAND, INSERT_TABLE_ROW_COMMAND, INSERT_UNORDERED_LIST_COMMAND, INodePlugin, INodeService, ITableControllerMenuService, IUploadService, ImagePlugin, Kernel, KeyEnum, LITEXML_APPLY_COMMAND, LITEXML_DIFFNODE_ALL_COMMAND, LITEXML_DIFFNODE_COMMAND, LITEXML_INSERT_COMMAND, LITEXML_MODIFY_COMMAND, LITEXML_REMOVE_COMMAND, LexicalErrorBoundary, LexicalPortalContainer, LinkHighlightPlugin, LinkPlugin, ListPlugin, LitexmlDataSource, LitexmlPlugin, LitexmlService, MARKDOWN_READER_LEVEL_HIGH, MARKDOWN_READER_LEVEL_NORMAL, MARKDOWN_WRITER_LEVEL_MAX, MOVE_BLOCK_COMMAND, MarkdownPlugin, MathPlugin, MentionPlugin, REMOVE_LIST_COMMAND, ReactAutoCompletePlugin, ReactBlockPlugin, ReactCodePlugin, ReactCodeblockPlugin, ReactCodemirrorPlugin, ReactEditor, ReactEditorContent, ReactFilePlugin, ReactHRPlugin, ReactImagePlugin, ReactLinkHighlightPlugin, ReactLinkPlugin, ReactListPlugin, ReactLiteXmlPlugin, ReactMarkdownPlugin, ReactMathPlugin, ReactMentionPlugin, ReactNodePlugin, ReactPlainText, ReactSlashOption, ReactSlashPlugin, ReactTablePlugin, ReactToolbarPlugin, ReactVirtualBlockPlugin, SELECT_AFTER_CODEMIRROR_COMMAND, SELECT_BEFORE_CODEMIRROR_COMMAND, SELECT_TABLE_COMMAND, SHOW_TOOLBAR_COMMAND, SlashMenu, SlashPlugin, TableControllerMenuService, TablePlugin, UPDATE_CODEBLOCK_LANG, UPDATE_LIST_START_COMMAND, UPLOAD_PRIORITY_HIGH, UPLOAD_PRIORITY_LOW, UPLOAD_PRIORITY_MEDIUM, UploadPlugin, VirtualBlockPlugin, assert, browserDebug, bundledLanguagesInfo, compareNodeOrder, createDebugLogger, createEmptyEditorState, createHeadlessEditor, cursorNodeSerialized, debugLogger, debugLoggers, detectCodeLanguage, detectLanguage, devConsole, disableHotReload, enableHotReload, extractContentBlocks, extractMediaFromEditorState, extractMediaLists, flattenSlashOptions, genServiceId, generateEditorId, getHotkeyById, getKernelFromEditor, getKernelFromEditorConfig, getNodeKeyFromDOMNode, getParentElement, isDOMNode, isDocumentFragment, isPunctuationChar, isPureUrl, isSlashDividerOption, isSlashMenuOption, isSlashSectionOption, isValidUrl, moment, noop, prodSafeLogger, reconcileDecorator, registerBlockMoveCommand, registerEditorKernel, registerLinkHighlightCommand, registerToolbarCommand, resetRandomKey, scrollIntoView, unregisterEditorKernel, useHasDiffNode, useLexicalComposerContext, useLexicalEditor };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ISlashMenuOption, ISlashOption, ISlashService, SlashOptions } from "./service/i-slash-service.js";
|
|
1
|
+
import { ISlashDividerOption, ISlashMenuOption, ISlashOption, ISlashSectionOption, ISlashService, SlashOptions, flattenSlashOptions, isSlashDividerOption, isSlashMenuOption, isSlashSectionOption } from "./service/i-slash-service.js";
|
|
2
2
|
import { ITriggerContext, SlashPlugin, SlashPluginOptions } from "./plugin/index.js";
|
|
3
3
|
import { MenuRenderProps, ReactSlashOptionProps, ReactSlashPluginProps, SlashMenuProps } from "./react/type.js";
|
|
4
4
|
import { SlashMenu } from "./react/components/SlashMenu.js";
|
|
@@ -3,7 +3,7 @@ import { noop } from "../../../editor-kernel/utils.js";
|
|
|
3
3
|
import { useLexicalComposerContext } from "../../../editor-kernel/react/react-context.js";
|
|
4
4
|
import { useLexicalEditor } from "../../../editor-kernel/react/useLexicalEditor.js";
|
|
5
5
|
import { $splitNodeContainingQuery } from "../utils/utils.js";
|
|
6
|
-
import { ISlashService } from "../service/i-slash-service.js";
|
|
6
|
+
import { ISlashService, flattenSlashOptions } from "../service/i-slash-service.js";
|
|
7
7
|
import { SlashPlugin } from "../plugin/index.js";
|
|
8
8
|
import SlashMenu from "./components/SlashMenu.js";
|
|
9
9
|
import { setCancelablePromise } from "./utils.js";
|
|
@@ -35,6 +35,12 @@ const ReactSlashPlugin = ({ children, anchorClassName, getPopupContainer, placem
|
|
|
35
35
|
const handleActiveKeyChange = useCallback((key) => {
|
|
36
36
|
setActiveKey(key);
|
|
37
37
|
}, []);
|
|
38
|
+
const setInitialActiveKey = useCallback((items) => {
|
|
39
|
+
if (!activeKey) {
|
|
40
|
+
const firstOption = flattenSlashOptions(items)[0];
|
|
41
|
+
setActiveKey(firstOption?.key ? String(firstOption.key) : null);
|
|
42
|
+
}
|
|
43
|
+
}, [activeKey]);
|
|
38
44
|
useLayoutEffect(() => {
|
|
39
45
|
const options = Children.map(children, (child) => {
|
|
40
46
|
if (!child) return null;
|
|
@@ -53,7 +59,7 @@ const ReactSlashPlugin = ({ children, anchorClassName, getPopupContainer, placem
|
|
|
53
59
|
cancelRef.current.cancel();
|
|
54
60
|
if (Array.isArray(ctx.items)) {
|
|
55
61
|
setOptions(ctx.items);
|
|
56
|
-
|
|
62
|
+
setInitialActiveKey(ctx.items);
|
|
57
63
|
} else {
|
|
58
64
|
setLoading(true);
|
|
59
65
|
const pr = setCancelablePromise((resolve, reject) => {
|
|
@@ -62,7 +68,7 @@ const ReactSlashPlugin = ({ children, anchorClassName, getPopupContainer, placem
|
|
|
62
68
|
pr.promise.then((items) => {
|
|
63
69
|
const typedItems = items;
|
|
64
70
|
setOptions(typedItems);
|
|
65
|
-
|
|
71
|
+
setInitialActiveKey(typedItems);
|
|
66
72
|
});
|
|
67
73
|
cancelRef.current.cancel = () => {
|
|
68
74
|
pr.cancel();
|
|
@@ -80,9 +86,9 @@ const ReactSlashPlugin = ({ children, anchorClassName, getPopupContainer, placem
|
|
|
80
86
|
}
|
|
81
87
|
});
|
|
82
88
|
}, [
|
|
83
|
-
activeKey,
|
|
84
89
|
editor,
|
|
85
|
-
close
|
|
90
|
+
close,
|
|
91
|
+
setInitialActiveKey
|
|
86
92
|
]);
|
|
87
93
|
useLayoutEffect(() => {
|
|
88
94
|
const slash = editor.requireService(ISlashService);
|
|
@@ -97,7 +103,6 @@ const ReactSlashPlugin = ({ children, anchorClassName, getPopupContainer, placem
|
|
|
97
103
|
}
|
|
98
104
|
}, [children]);
|
|
99
105
|
const handleMenuSelect = useCallback((option) => {
|
|
100
|
-
if ("type" in option && option.type === "divider") return;
|
|
101
106
|
const lexicalEditor = editor.getLexicalEditor();
|
|
102
107
|
if (lexicalEditor && resolution) lexicalEditor.update(() => {
|
|
103
108
|
(resolution.match ? $splitNodeContainingQuery(resolution.match) : null)?.remove();
|
|
@@ -112,7 +117,7 @@ const ReactSlashPlugin = ({ children, anchorClassName, getPopupContainer, placem
|
|
|
112
117
|
close
|
|
113
118
|
]);
|
|
114
119
|
useLexicalEditor(() => {
|
|
115
|
-
const pureOptions = options.filter((item) =>
|
|
120
|
+
const pureOptions = flattenSlashOptions(options).filter((item) => Boolean(item.key));
|
|
116
121
|
return mergeRegister(editor.registerHighCommand(KEY_ARROW_DOWN_COMMAND, (payload) => {
|
|
117
122
|
const event = payload;
|
|
118
123
|
if (pureOptions !== null && pureOptions.length) {
|
|
@@ -144,7 +149,7 @@ const ReactSlashPlugin = ({ children, anchorClassName, getPopupContainer, placem
|
|
|
144
149
|
}, COMMAND_PRIORITY_CRITICAL), editor.registerHighCommand(KEY_TAB_COMMAND, (payload) => {
|
|
145
150
|
const event = payload;
|
|
146
151
|
if (options === null || activeKey === null) return false;
|
|
147
|
-
const selectedOption = options.find((opt) =>
|
|
152
|
+
const selectedOption = flattenSlashOptions(options).find((opt) => opt.key === activeKey);
|
|
148
153
|
if (!selectedOption) return false;
|
|
149
154
|
event.preventDefault();
|
|
150
155
|
event.stopImmediatePropagation();
|
|
@@ -155,7 +160,7 @@ const ReactSlashPlugin = ({ children, anchorClassName, getPopupContainer, placem
|
|
|
155
160
|
event.preventDefault();
|
|
156
161
|
event.stopImmediatePropagation();
|
|
157
162
|
if (options !== null && activeKey !== null) {
|
|
158
|
-
const selectedOption = options.find((opt) =>
|
|
163
|
+
const selectedOption = flattenSlashOptions(options).find((opt) => opt.key === activeKey);
|
|
159
164
|
if (selectedOption) handleMenuSelect(selectedOption);
|
|
160
165
|
}
|
|
161
166
|
return true;
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { flattenSlashOptions, isSlashDividerOption, isSlashSectionOption } from "../../service/i-slash-service.js";
|
|
3
|
+
import { Icon, LOBE_THEME_APP_ID, menuSharedStyles } from "@lobehub/ui";
|
|
3
4
|
import { useEffect, useLayoutEffect, useMemo, useRef } from "react";
|
|
4
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
6
|
import { createStaticStyles } from "antd-style";
|
|
6
7
|
import { createPortal } from "react-dom";
|
|
7
|
-
import { flip, offset, shift, useFloating } from "@floating-ui/react";
|
|
8
|
+
import { autoUpdate, flip, offset, shift, size, useFloating } from "@floating-ui/react";
|
|
8
9
|
//#region src/plugins/slash/react/components/DefaultSlashMenu.tsx
|
|
9
|
-
const LOBE_THEME_APP_ID$1 = "lobe-ui-theme-app";
|
|
10
10
|
const styles = createStaticStyles(({ css, cssVar }) => ({
|
|
11
11
|
popup: css`
|
|
12
12
|
scrollbar-width: none;
|
|
13
13
|
|
|
14
14
|
overflow-y: auto;
|
|
15
15
|
|
|
16
|
-
min-width: 200px;
|
|
17
16
|
max-height: min(50vh, 400px);
|
|
18
17
|
padding: 4px;
|
|
19
18
|
border-radius: ${cssVar.borderRadius};
|
|
@@ -24,14 +23,155 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
|
|
|
24
23
|
0 0 15px 0 #00000008,
|
|
25
24
|
0 2px 30px 0 #00000014,
|
|
26
25
|
0 0 0 1px ${cssVar.colorBorder} inset;
|
|
26
|
+
`,
|
|
27
|
+
popupCaret: css`
|
|
28
|
+
width: max-content;
|
|
29
|
+
min-width: 200px;
|
|
27
30
|
`,
|
|
28
31
|
root: css`
|
|
29
32
|
z-index: 1100;
|
|
30
|
-
|
|
33
|
+
`,
|
|
34
|
+
section: css`
|
|
35
|
+
margin-block-start: 4px;
|
|
36
|
+
`,
|
|
37
|
+
sectionFirst: css`
|
|
38
|
+
margin-block-start: 0;
|
|
39
|
+
`,
|
|
40
|
+
sectionLabel: css`
|
|
41
|
+
padding-block: 12px 6px;
|
|
42
|
+
padding-inline: 8px;
|
|
43
|
+
|
|
44
|
+
font-size: 12px;
|
|
45
|
+
line-height: 1;
|
|
46
|
+
color: ${cssVar.colorTextDescription};
|
|
47
|
+
|
|
48
|
+
&:first-child {
|
|
49
|
+
padding-block-start: 6px;
|
|
50
|
+
}
|
|
51
|
+
`,
|
|
52
|
+
text: css`
|
|
53
|
+
display: flex;
|
|
54
|
+
flex: 1 1 auto;
|
|
55
|
+
flex-wrap: wrap;
|
|
56
|
+
gap: 2px 8px;
|
|
57
|
+
align-items: baseline;
|
|
58
|
+
|
|
59
|
+
min-width: 0;
|
|
60
|
+
`,
|
|
61
|
+
textDescription: css`
|
|
62
|
+
overflow: hidden;
|
|
63
|
+
flex: 0 1 auto;
|
|
64
|
+
|
|
65
|
+
min-width: 0;
|
|
66
|
+
|
|
67
|
+
color: ${cssVar.colorTextDescription};
|
|
68
|
+
text-overflow: ellipsis;
|
|
69
|
+
white-space: nowrap;
|
|
70
|
+
`,
|
|
71
|
+
textLabel: css`
|
|
72
|
+
overflow: hidden;
|
|
73
|
+
flex: 0 1 auto;
|
|
74
|
+
|
|
75
|
+
max-width: min(42ch, 55%);
|
|
76
|
+
|
|
77
|
+
font-weight: 500;
|
|
78
|
+
color: ${cssVar.colorText};
|
|
79
|
+
text-overflow: ellipsis;
|
|
80
|
+
white-space: nowrap;
|
|
31
81
|
`
|
|
32
82
|
}));
|
|
33
|
-
const
|
|
34
|
-
const
|
|
83
|
+
const renderMenuItem = (item, activeKey, onSelect) => {
|
|
84
|
+
const isHighlighted = item.key === activeKey;
|
|
85
|
+
const isDisabled = Boolean(item.disabled);
|
|
86
|
+
const description = item.metadata?.description;
|
|
87
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
88
|
+
"aria-disabled": isDisabled || void 0,
|
|
89
|
+
className: menuSharedStyles.item,
|
|
90
|
+
"data-disabled": isDisabled ? "" : void 0,
|
|
91
|
+
"data-highlighted": isHighlighted ? "" : void 0,
|
|
92
|
+
onClick: () => {
|
|
93
|
+
if (isDisabled) return;
|
|
94
|
+
onSelect(item);
|
|
95
|
+
},
|
|
96
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
97
|
+
role: "menuitem",
|
|
98
|
+
children: [
|
|
99
|
+
item.icon ? /* @__PURE__ */ jsx("span", {
|
|
100
|
+
className: menuSharedStyles.icon,
|
|
101
|
+
children: /* @__PURE__ */ jsx(Icon, { icon: item.icon })
|
|
102
|
+
}) : null,
|
|
103
|
+
/* @__PURE__ */ jsxs("span", {
|
|
104
|
+
className: styles.text,
|
|
105
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
106
|
+
className: styles.textLabel,
|
|
107
|
+
children: item.label
|
|
108
|
+
}), description ? /* @__PURE__ */ jsx("span", {
|
|
109
|
+
className: styles.textDescription,
|
|
110
|
+
children: description
|
|
111
|
+
}) : null]
|
|
112
|
+
}),
|
|
113
|
+
item.extra ? /* @__PURE__ */ jsx("span", {
|
|
114
|
+
className: menuSharedStyles.extra,
|
|
115
|
+
children: item.extra
|
|
116
|
+
}) : null
|
|
117
|
+
]
|
|
118
|
+
}, String(item.key));
|
|
119
|
+
};
|
|
120
|
+
const renderItems = (options, activeKey, loading, onSelect) => {
|
|
121
|
+
if (loading) return /* @__PURE__ */ jsx("div", {
|
|
122
|
+
className: menuSharedStyles.empty,
|
|
123
|
+
children: "Loading..."
|
|
124
|
+
});
|
|
125
|
+
return options.map((opt, index) => {
|
|
126
|
+
if (isSlashDividerOption(opt)) return /* @__PURE__ */ jsx("div", { className: menuSharedStyles.separator }, `__divider_${index}`);
|
|
127
|
+
if (isSlashSectionOption(opt)) return /* @__PURE__ */ jsxs("div", {
|
|
128
|
+
className: `${styles.section} ${index === 0 ? styles.sectionFirst : ""}`,
|
|
129
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
130
|
+
className: styles.sectionLabel,
|
|
131
|
+
children: opt.label
|
|
132
|
+
}), opt.items.map((item) => renderMenuItem(item, activeKey, onSelect))]
|
|
133
|
+
}, String(opt.key ?? `__section_${index}`));
|
|
134
|
+
return renderMenuItem(opt, activeKey, onSelect);
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
const resolvePortalContainer = () => {
|
|
138
|
+
if (typeof document === "undefined") return null;
|
|
139
|
+
return document.getElementById(LOBE_THEME_APP_ID) ?? document.body;
|
|
140
|
+
};
|
|
141
|
+
const FullWidthSlashMenu = ({ activeKey, anchor, loading, onSelect, open, options, placement }) => {
|
|
142
|
+
const resolvedPlacement = placement === "bottom" ? "bottom-start" : "top-start";
|
|
143
|
+
const { refs, floatingStyles, isPositioned } = useFloating({
|
|
144
|
+
elements: { reference: anchor },
|
|
145
|
+
middleware: [
|
|
146
|
+
offset(8),
|
|
147
|
+
size({ apply({ rects, elements }) {
|
|
148
|
+
elements.floating.style.width = `${rects.reference.width}px`;
|
|
149
|
+
} }),
|
|
150
|
+
flip({ fallbackPlacements: placement === "bottom" ? ["top-start"] : ["bottom-start"] }),
|
|
151
|
+
shift({ padding: 8 })
|
|
152
|
+
],
|
|
153
|
+
open,
|
|
154
|
+
placement: resolvedPlacement,
|
|
155
|
+
strategy: "fixed",
|
|
156
|
+
whileElementsMounted: autoUpdate
|
|
157
|
+
});
|
|
158
|
+
const portalContainer = resolvePortalContainer();
|
|
159
|
+
if (!portalContainer) return null;
|
|
160
|
+
return createPortal(/* @__PURE__ */ jsx("div", {
|
|
161
|
+
className: styles.root,
|
|
162
|
+
"data-resolved-placement": resolvedPlacement,
|
|
163
|
+
ref: refs.setFloating,
|
|
164
|
+
style: {
|
|
165
|
+
...floatingStyles,
|
|
166
|
+
visibility: isPositioned ? "visible" : "hidden"
|
|
167
|
+
},
|
|
168
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
169
|
+
className: styles.popup,
|
|
170
|
+
children: renderItems(options, activeKey, loading, onSelect)
|
|
171
|
+
})
|
|
172
|
+
}), portalContainer);
|
|
173
|
+
};
|
|
174
|
+
const CaretSlashMenu = ({ activeKey, loading, onSelect, open, options, placement: forcePlacement, position }) => {
|
|
35
175
|
const resolvedPlacement = forcePlacement ? `${forcePlacement}-start` : "top-start";
|
|
36
176
|
const middleware = useMemo(() => [
|
|
37
177
|
offset(8),
|
|
@@ -62,62 +202,19 @@ const DefaultSlashMenu = ({ activeKey, getPopupContainer, loading, onSelect, ope
|
|
|
62
202
|
useEffect(() => {
|
|
63
203
|
if (!open) return;
|
|
64
204
|
const onScroll = () => update();
|
|
65
|
-
const container = getPopupContainer?.();
|
|
66
205
|
window.addEventListener("scroll", onScroll, {
|
|
67
206
|
capture: true,
|
|
68
207
|
passive: true
|
|
69
208
|
});
|
|
70
|
-
if (container) container.addEventListener("scroll", onScroll, { passive: true });
|
|
71
209
|
return () => {
|
|
72
210
|
window.removeEventListener("scroll", onScroll, { capture: true });
|
|
73
|
-
if (container) container.removeEventListener("scroll", onScroll);
|
|
74
211
|
};
|
|
75
|
-
}, [
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
update
|
|
79
|
-
]);
|
|
80
|
-
const hasVisibleItems = options?.some((item) => !isDividerOption(item));
|
|
81
|
-
if (!open || !hasVisibleItems) return null;
|
|
82
|
-
const portalContainer = getPopupContainer?.() || document.getElementById(LOBE_THEME_APP_ID$1) || document.body;
|
|
83
|
-
const renderedItems = loading ? /* @__PURE__ */ jsx("div", {
|
|
84
|
-
className: menuSharedStyles.empty,
|
|
85
|
-
children: "Loading..."
|
|
86
|
-
}) : options.map((opt, index) => {
|
|
87
|
-
if (isDividerOption(opt)) return /* @__PURE__ */ jsx("div", { className: menuSharedStyles.separator }, `__divider_${index}`);
|
|
88
|
-
const item = opt;
|
|
89
|
-
const isHighlighted = item.key === activeKey;
|
|
90
|
-
const isDisabled = Boolean(item.disabled);
|
|
91
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
92
|
-
"aria-disabled": isDisabled || void 0,
|
|
93
|
-
className: menuSharedStyles.item,
|
|
94
|
-
"data-disabled": isDisabled ? "" : void 0,
|
|
95
|
-
"data-highlighted": isHighlighted ? "" : void 0,
|
|
96
|
-
onClick: () => {
|
|
97
|
-
if (isDisabled) return;
|
|
98
|
-
onSelect(item);
|
|
99
|
-
},
|
|
100
|
-
onMouseDown: (event) => event.preventDefault(),
|
|
101
|
-
role: "menuitem",
|
|
102
|
-
children: [
|
|
103
|
-
item.icon ? /* @__PURE__ */ jsx("span", {
|
|
104
|
-
className: menuSharedStyles.icon,
|
|
105
|
-
children: /* @__PURE__ */ jsx(Icon, { icon: item.icon })
|
|
106
|
-
}) : null,
|
|
107
|
-
/* @__PURE__ */ jsx("span", {
|
|
108
|
-
className: menuSharedStyles.label,
|
|
109
|
-
children: item.label
|
|
110
|
-
}),
|
|
111
|
-
item.extra ? /* @__PURE__ */ jsx("span", {
|
|
112
|
-
className: menuSharedStyles.extra,
|
|
113
|
-
children: item.extra
|
|
114
|
-
}) : null
|
|
115
|
-
]
|
|
116
|
-
}, String(item.key));
|
|
117
|
-
});
|
|
212
|
+
}, [open, update]);
|
|
213
|
+
const portalContainer = resolvePortalContainer();
|
|
214
|
+
if (!portalContainer) return null;
|
|
118
215
|
return createPortal(/* @__PURE__ */ jsx("div", {
|
|
119
|
-
className: styles.root
|
|
120
|
-
"data-
|
|
216
|
+
className: `${styles.root} ${styles.popupCaret}`,
|
|
217
|
+
"data-resolved-placement": resolvedPlacement,
|
|
121
218
|
ref: refs.setFloating,
|
|
122
219
|
style: {
|
|
123
220
|
...floatingStyles,
|
|
@@ -125,10 +222,34 @@ const DefaultSlashMenu = ({ activeKey, getPopupContainer, loading, onSelect, ope
|
|
|
125
222
|
},
|
|
126
223
|
children: /* @__PURE__ */ jsx("div", {
|
|
127
224
|
className: styles.popup,
|
|
128
|
-
children:
|
|
225
|
+
children: renderItems(options, activeKey, loading, onSelect)
|
|
129
226
|
})
|
|
130
227
|
}), portalContainer);
|
|
131
228
|
};
|
|
229
|
+
const DefaultSlashMenu = ({ activeKey, getPopupContainer, loading, onSelect, open, options, placement, position }) => {
|
|
230
|
+
const hasVisibleItems = flattenSlashOptions(options).length > 0;
|
|
231
|
+
if (!open || !hasVisibleItems) return null;
|
|
232
|
+
const anchor = getPopupContainer?.() ?? null;
|
|
233
|
+
if (anchor) return /* @__PURE__ */ jsx(FullWidthSlashMenu, {
|
|
234
|
+
activeKey,
|
|
235
|
+
anchor,
|
|
236
|
+
loading,
|
|
237
|
+
onSelect,
|
|
238
|
+
open,
|
|
239
|
+
options,
|
|
240
|
+
placement: placement ?? "top"
|
|
241
|
+
});
|
|
242
|
+
if (!position) return null;
|
|
243
|
+
return /* @__PURE__ */ jsx(CaretSlashMenu, {
|
|
244
|
+
activeKey,
|
|
245
|
+
loading,
|
|
246
|
+
onSelect,
|
|
247
|
+
open,
|
|
248
|
+
options,
|
|
249
|
+
placement,
|
|
250
|
+
position
|
|
251
|
+
});
|
|
252
|
+
};
|
|
132
253
|
DefaultSlashMenu.displayName = "DefaultSlashMenu";
|
|
133
254
|
//#endregion
|
|
134
255
|
export { DefaultSlashMenu as default };
|
|
@@ -94,8 +94,11 @@ interface SlashMenuProps {
|
|
|
94
94
|
options: Array<ISlashOption>;
|
|
95
95
|
/** Force menu placement direction, skipping auto-flip detection */
|
|
96
96
|
placement?: 'bottom' | 'top';
|
|
97
|
-
/**
|
|
98
|
-
|
|
97
|
+
/**
|
|
98
|
+
* Caret position used by the floating fallback when no getPopupContainer
|
|
99
|
+
* is provided. Ignored in full-width mode.
|
|
100
|
+
*/
|
|
101
|
+
position?: {
|
|
99
102
|
getRect?: () => DOMRect;
|
|
100
103
|
rect?: DOMRect;
|
|
101
104
|
x: number;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { IEditor, IServiceID } from "../../../types/kernel.js";
|
|
2
2
|
import { DropdownMenuItemType } from "@lobehub/ui";
|
|
3
|
+
import { ReactNode } from "react";
|
|
3
4
|
import Fuse, { IFuseOptions } from "fuse.js";
|
|
4
5
|
|
|
5
6
|
//#region src/plugins/slash/service/i-slash-service.d.ts
|
|
@@ -10,7 +11,17 @@ interface ISlashMenuOption extends DropdownMenuItemType {
|
|
|
10
11
|
metadata?: Record<string, any>;
|
|
11
12
|
onSelect?: (editor: IEditor, matchingString: string) => void;
|
|
12
13
|
}
|
|
13
|
-
|
|
14
|
+
interface ISlashSectionOption {
|
|
15
|
+
items: ISlashMenuOption[];
|
|
16
|
+
key?: string;
|
|
17
|
+
label: ReactNode;
|
|
18
|
+
type: 'section';
|
|
19
|
+
}
|
|
20
|
+
type ISlashOption = ISlashMenuOption | ISlashDividerOption | ISlashSectionOption;
|
|
21
|
+
declare const isSlashDividerOption: (option: ISlashOption) => option is ISlashDividerOption;
|
|
22
|
+
declare const isSlashSectionOption: (option: ISlashOption) => option is ISlashSectionOption;
|
|
23
|
+
declare const isSlashMenuOption: (option: ISlashOption) => option is ISlashMenuOption;
|
|
24
|
+
declare const flattenSlashOptions: (options: ISlashOption[]) => ISlashMenuOption[];
|
|
14
25
|
interface SlashOptions {
|
|
15
26
|
allowWhitespace?: boolean;
|
|
16
27
|
/**
|
|
@@ -47,4 +58,4 @@ interface ISlashService {
|
|
|
47
58
|
}
|
|
48
59
|
declare const ISlashService: IServiceID<ISlashService>;
|
|
49
60
|
//#endregion
|
|
50
|
-
export { ISlashMenuOption, ISlashOption, ISlashService, SlashOptions };
|
|
61
|
+
export { ISlashDividerOption, ISlashMenuOption, ISlashOption, ISlashSectionOption, ISlashService, SlashOptions, flattenSlashOptions, isSlashDividerOption, isSlashMenuOption, isSlashSectionOption };
|
|
@@ -4,6 +4,14 @@ import { getBasicTypeaheadTriggerMatch } from "../utils/utils.js";
|
|
|
4
4
|
import Fuse from "fuse.js";
|
|
5
5
|
//#region src/plugins/slash/service/i-slash-service.ts
|
|
6
6
|
init_debug();
|
|
7
|
+
const isSlashDividerOption = (option) => "type" in option && option.type === "divider";
|
|
8
|
+
const isSlashSectionOption = (option) => "type" in option && option.type === "section";
|
|
9
|
+
const isSlashMenuOption = (option) => !isSlashDividerOption(option) && !isSlashSectionOption(option);
|
|
10
|
+
const flattenSlashOptions = (options) => options.flatMap((option) => {
|
|
11
|
+
if (isSlashDividerOption(option)) return [];
|
|
12
|
+
if (isSlashSectionOption(option)) return option.items;
|
|
13
|
+
return [option];
|
|
14
|
+
});
|
|
7
15
|
const ISlashService = genServiceId("SlashService");
|
|
8
16
|
var SlashService = class {
|
|
9
17
|
constructor(kernel) {
|
|
@@ -25,7 +33,7 @@ var SlashService = class {
|
|
|
25
33
|
}));
|
|
26
34
|
this.logger.debug(`⚡ Slash trigger: ${options.trigger}`);
|
|
27
35
|
if (Array.isArray(options.items)) {
|
|
28
|
-
const searchableItems = options.items
|
|
36
|
+
const searchableItems = flattenSlashOptions(options.items);
|
|
29
37
|
const fuseConfig = options.fuseOptions || { keys: options.searchKeys || ["key"] };
|
|
30
38
|
this.triggerFuseMap.set(options.trigger, new Fuse(searchableItems, fuseConfig));
|
|
31
39
|
}
|
|
@@ -52,4 +60,4 @@ var SlashService = class {
|
|
|
52
60
|
}
|
|
53
61
|
};
|
|
54
62
|
//#endregion
|
|
55
|
-
export { ISlashService, SlashService };
|
|
63
|
+
export { ISlashService, SlashService, flattenSlashOptions, isSlashDividerOption, isSlashMenuOption, isSlashSectionOption };
|
|
@@ -38,11 +38,11 @@ const ChatInput = (props) => {
|
|
|
38
38
|
return /* @__PURE__ */ jsxs(Flexbox, {
|
|
39
39
|
className: cx(isDarkMode ? styles.containerDark : styles.containerLight, styles.root, className),
|
|
40
40
|
height: fullscreen ? "100%" : void 0,
|
|
41
|
+
ref: slashMenuRef,
|
|
41
42
|
style,
|
|
42
43
|
width: "100%",
|
|
43
44
|
...rest,
|
|
44
45
|
children: [
|
|
45
|
-
slashMenuRef && /* @__PURE__ */ jsx("div", { ref: slashMenuRef }),
|
|
46
46
|
/* @__PURE__ */ jsx("div", {
|
|
47
47
|
className: cx(styles.header, classNames?.header),
|
|
48
48
|
ref: headerRef,
|
|
@@ -21,6 +21,11 @@ interface ChatInputProps extends Omit<FlexboxProps, 'height'> {
|
|
|
21
21
|
resize?: boolean;
|
|
22
22
|
resizeMaxHeightOffset?: number;
|
|
23
23
|
showResizeHandle?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Ref attached to the ChatInput root element. Pass the same ref to
|
|
26
|
+
* `<Editor getPopupContainer={() => ref.current}>` to anchor the slash /
|
|
27
|
+
* mention menu to the ChatInput's outer edges (full-width).
|
|
28
|
+
*/
|
|
24
29
|
slashMenuRef?: Ref<HTMLDivElement>;
|
|
25
30
|
styles?: {
|
|
26
31
|
body?: CSSProperties;
|
package/es/react.d.ts
CHANGED
|
@@ -15,10 +15,6 @@ import { Editor } from "./react/Editor/index.js";
|
|
|
15
15
|
import { EditorProvider, EditorProviderConfig, EditorProviderProps, useEditorContent } from "./react/EditorProvider/index.js";
|
|
16
16
|
import { FloatActionsProps } from "./react/FloatActions/type.js";
|
|
17
17
|
import { FloatActions } from "./react/FloatActions/FloatActions.js";
|
|
18
|
-
import { FloatMenuProps } from "./react/FloatMenu/type.js";
|
|
19
|
-
import { FloatMenu } from "./react/FloatMenu/FloatMenu.js";
|
|
20
18
|
import { SendButtonProps } from "./react/SendButton/type.js";
|
|
21
19
|
import { SendButton } from "./react/SendButton/SendButton.js";
|
|
22
|
-
|
|
23
|
-
import { SlashMenu } from "./react/SlashMenu/SlashMenu.js";
|
|
24
|
-
export { ANCHOR_PADDING_CSS_VAR, ChatInput, ChatInputActionBar, type ChatInputActionBarProps, type ChatInputActionEvent, ChatInputActions, type ChatInputActionsProps, type ChatInputProps, CodeLanguageSelect, type CodeLanguageSelectProps, DEFAULT_BLOCK_ANCHOR_PADDING, Editor, type EditorProps, EditorProvider, type EditorProviderConfig, type EditorProviderProps, type EditorState, FloatActions, type FloatActionsProps, FloatMenu, type FloatMenuProps, SendButton, type SendButtonProps, SlashMenu, type SlashMenuProps, useEditor, useEditorContent, useEditorState, withProps };
|
|
20
|
+
export { ANCHOR_PADDING_CSS_VAR, ChatInput, ChatInputActionBar, type ChatInputActionBarProps, type ChatInputActionEvent, ChatInputActions, type ChatInputActionsProps, type ChatInputProps, CodeLanguageSelect, type CodeLanguageSelectProps, DEFAULT_BLOCK_ANCHOR_PADDING, Editor, type EditorProps, EditorProvider, type EditorProviderConfig, type EditorProviderProps, type EditorState, FloatActions, type FloatActionsProps, SendButton, type SendButtonProps, useEditor, useEditorContent, useEditorState, withProps };
|
package/es/react.js
CHANGED
|
@@ -9,7 +9,5 @@ import { EditorProvider, useEditorContent } from "./react/EditorProvider/index.j
|
|
|
9
9
|
import { withProps } from "./react/Editor/utils.js";
|
|
10
10
|
import Editor from "./react/Editor/index.js";
|
|
11
11
|
import FloatActions from "./react/FloatActions/FloatActions.js";
|
|
12
|
-
import FloatMenu from "./react/FloatMenu/FloatMenu.js";
|
|
13
12
|
import SendButton from "./react/SendButton/SendButton.js";
|
|
14
|
-
|
|
15
|
-
export { ANCHOR_PADDING_CSS_VAR, ChatInput, ChatInputActionBar, ChatInputActions, CodeLanguageSelect, DEFAULT_BLOCK_ANCHOR_PADDING, Editor, EditorProvider, FloatActions, FloatMenu, SendButton, SlashMenu, useEditor, useEditorContent, useEditorState, withProps };
|
|
13
|
+
export { ANCHOR_PADDING_CSS_VAR, ChatInput, ChatInputActionBar, ChatInputActions, CodeLanguageSelect, DEFAULT_BLOCK_ANCHOR_PADDING, Editor, EditorProvider, FloatActions, SendButton, useEditor, useEditorContent, useEditorState, withProps };
|
package/package.json
CHANGED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { styles } from "./style.js";
|
|
3
|
-
import { Block, Flexbox } from "@lobehub/ui";
|
|
4
|
-
import { jsx } from "react/jsx-runtime";
|
|
5
|
-
import { cx } from "antd-style";
|
|
6
|
-
import { createPortal } from "react-dom";
|
|
7
|
-
//#region src/react/FloatMenu/FloatMenu.tsx
|
|
8
|
-
const FloatMenu = ({ className, style, getPopupContainer, children, maxHeight = "min(50vh, 640px)", open, placement = "top", styles: customStyles, classNames }) => {
|
|
9
|
-
const parent = getPopupContainer();
|
|
10
|
-
if (!parent) return;
|
|
11
|
-
if (!open) return;
|
|
12
|
-
return createPortal(/* @__PURE__ */ jsx(Flexbox, {
|
|
13
|
-
className: cx(placement === "bottom" ? styles.rootBottom : styles.rootTop, classNames?.root),
|
|
14
|
-
paddingInline: 8,
|
|
15
|
-
style: customStyles?.root,
|
|
16
|
-
width: "100%",
|
|
17
|
-
children: /* @__PURE__ */ jsx(Block, {
|
|
18
|
-
className: cx(styles.container, className, classNames?.container),
|
|
19
|
-
shadow: true,
|
|
20
|
-
style: {
|
|
21
|
-
maxHeight,
|
|
22
|
-
...style,
|
|
23
|
-
...customStyles?.container
|
|
24
|
-
},
|
|
25
|
-
variant: "outlined",
|
|
26
|
-
children
|
|
27
|
-
})
|
|
28
|
-
}), parent);
|
|
29
|
-
};
|
|
30
|
-
FloatMenu.displayName = "FloatMenu";
|
|
31
|
-
//#endregion
|
|
32
|
-
export { FloatMenu as default };
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { createStaticStyles } from "antd-style";
|
|
2
|
-
//#region src/react/FloatMenu/style.ts
|
|
3
|
-
const styles = createStaticStyles(({ css, cssVar }) => ({
|
|
4
|
-
container: css`
|
|
5
|
-
position: relative;
|
|
6
|
-
overflow: hidden auto;
|
|
7
|
-
background: ${cssVar.colorBgElevated};
|
|
8
|
-
`,
|
|
9
|
-
containerWithMaxHeight: css`
|
|
10
|
-
/* maxHeight is set via inline style as it's dynamic */
|
|
11
|
-
`,
|
|
12
|
-
rootBottom: css`
|
|
13
|
-
position: absolute;
|
|
14
|
-
z-index: 9999;
|
|
15
|
-
inset-block-start: 100%;
|
|
16
|
-
inset-inline-start: 0;
|
|
17
|
-
|
|
18
|
-
padding-block-start: 8px;
|
|
19
|
-
`,
|
|
20
|
-
rootTop: css`
|
|
21
|
-
position: absolute;
|
|
22
|
-
inset-block-start: -8px;
|
|
23
|
-
inset-inline-start: 0;
|
|
24
|
-
transform: translateY(-100%);
|
|
25
|
-
`
|
|
26
|
-
}));
|
|
27
|
-
//#endregion
|
|
28
|
-
export { styles };
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { BlockProps } from "@lobehub/ui";
|
|
2
|
-
import { CSSProperties, ReactNode } from "react";
|
|
3
|
-
|
|
4
|
-
//#region src/react/FloatMenu/type.d.ts
|
|
5
|
-
interface FloatMenuProps {
|
|
6
|
-
children?: ReactNode;
|
|
7
|
-
className?: string;
|
|
8
|
-
classNames?: {
|
|
9
|
-
container?: string;
|
|
10
|
-
root?: string;
|
|
11
|
-
};
|
|
12
|
-
containerProps?: Omit<BlockProps, 'children'>;
|
|
13
|
-
getPopupContainer: () => HTMLDivElement | null;
|
|
14
|
-
maxHeight?: string | number;
|
|
15
|
-
open?: boolean;
|
|
16
|
-
/** Menu placement direction: 'top' (default) or 'bottom' */
|
|
17
|
-
placement?: 'bottom' | 'top';
|
|
18
|
-
style?: CSSProperties;
|
|
19
|
-
styles?: {
|
|
20
|
-
container?: CSSProperties;
|
|
21
|
-
root?: CSSProperties;
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
//#endregion
|
|
25
|
-
export { FloatMenuProps };
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import FloatMenu from "../FloatMenu/FloatMenu.js";
|
|
3
|
-
import { Menu } from "@lobehub/ui";
|
|
4
|
-
import { useCallback } from "react";
|
|
5
|
-
import { jsx } from "react/jsx-runtime";
|
|
6
|
-
//#region src/react/SlashMenu/SlashMenu.tsx
|
|
7
|
-
const SlashMenu = ({ options, activeKey, loading, onSelect, classNames, styles: customStyles, menuProps, ...floatMenuProps }) => {
|
|
8
|
-
const handleMenuClick = useCallback(({ key }) => {
|
|
9
|
-
if (!onSelect) return;
|
|
10
|
-
const option = options.find((item) => "key" in item && item.key === key);
|
|
11
|
-
if (option) onSelect?.(option);
|
|
12
|
-
}, [options, onSelect]);
|
|
13
|
-
return /* @__PURE__ */ jsx(FloatMenu, {
|
|
14
|
-
classNames: {
|
|
15
|
-
container: classNames?.container,
|
|
16
|
-
root: classNames?.root
|
|
17
|
-
},
|
|
18
|
-
styles: {
|
|
19
|
-
container: customStyles?.container,
|
|
20
|
-
root: customStyles?.root
|
|
21
|
-
},
|
|
22
|
-
...floatMenuProps,
|
|
23
|
-
children: /* @__PURE__ */ jsx(Menu, {
|
|
24
|
-
className: classNames?.menu,
|
|
25
|
-
items: loading ? [{
|
|
26
|
-
disabled: true,
|
|
27
|
-
key: "loading",
|
|
28
|
-
label: "Loading..."
|
|
29
|
-
}] : options,
|
|
30
|
-
mode: "inline",
|
|
31
|
-
onClick: handleMenuClick,
|
|
32
|
-
selectedKeys: activeKey ? [activeKey] : void 0,
|
|
33
|
-
style: customStyles?.menu,
|
|
34
|
-
...menuProps
|
|
35
|
-
})
|
|
36
|
-
});
|
|
37
|
-
};
|
|
38
|
-
SlashMenu.displayName = "SlashMenu";
|
|
39
|
-
//#endregion
|
|
40
|
-
export { SlashMenu as default };
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { MenuRenderProps } from "../../plugins/slash/react/type.js";
|
|
2
|
-
import { FloatMenuProps } from "../FloatMenu/type.js";
|
|
3
|
-
import { MenuProps } from "@lobehub/ui";
|
|
4
|
-
import { CSSProperties } from "react";
|
|
5
|
-
|
|
6
|
-
//#region src/react/SlashMenu/type.d.ts
|
|
7
|
-
interface SlashMenuProps extends MenuRenderProps, Omit<FloatMenuProps, 'children'> {
|
|
8
|
-
classNames?: FloatMenuProps['classNames'] & {
|
|
9
|
-
menu?: string;
|
|
10
|
-
};
|
|
11
|
-
menuProps?: MenuProps;
|
|
12
|
-
styles?: FloatMenuProps['styles'] & {
|
|
13
|
-
menu?: CSSProperties;
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
//#endregion
|
|
17
|
-
export { SlashMenuProps };
|