diff --git a/src/renderer/src/components/QuickPanel/view.tsx b/src/renderer/src/components/QuickPanel/view.tsx index 52c33607c7..6ad34b4557 100644 --- a/src/renderer/src/components/QuickPanel/view.tsx +++ b/src/renderer/src/components/QuickPanel/view.tsx @@ -457,7 +457,13 @@ export const QuickPanelView: React.FC = ({ setInputText }) => { // 面板可见且未折叠时:拦截所有 Enter 变体; // 纯 Enter 选择项,带修饰键仅拦截不处理 - if (e.ctrlKey || e.metaKey || e.altKey || e.shiftKey) { + if (e.shiftKey && !e.ctrlKey && !e.metaKey && !e.altKey) { + // Don't prevent default or stop propagation - let it create a newline + setIsMouseOver(false) + break + } + + if (e.ctrlKey || e.metaKey || e.altKey) { e.preventDefault() e.stopPropagation() setIsMouseOver(false) diff --git a/src/renderer/src/components/RichEditor/CommandListPopover.tsx b/src/renderer/src/components/RichEditor/CommandListPopover.tsx index 4f8df4d20c..1f2250a437 100644 --- a/src/renderer/src/components/RichEditor/CommandListPopover.tsx +++ b/src/renderer/src/components/RichEditor/CommandListPopover.tsx @@ -87,6 +87,9 @@ const CommandListPopover = ({ return true case 'Enter': + if (event.shiftKey) { + return false + } event.preventDefault() if (items[internalSelectedIndex]) { selectItem(internalSelectedIndex) diff --git a/src/renderer/src/components/RichEditor/__tests__/commandSuggestion.test.ts b/src/renderer/src/components/RichEditor/__tests__/commandSuggestion.test.ts new file mode 100644 index 0000000000..e352e957d0 --- /dev/null +++ b/src/renderer/src/components/RichEditor/__tests__/commandSuggestion.test.ts @@ -0,0 +1,17 @@ +import { describe, expect, it } from 'vitest' + +import { commandSuggestion } from '../command' + +describe('commandSuggestion render', () => { + it('has render function', () => { + expect(commandSuggestion.render).toBeDefined() + expect(typeof commandSuggestion.render).toBe('function') + }) + + it('render function returns object with onKeyDown', () => { + const renderResult = commandSuggestion.render?.() + expect(renderResult).toBeDefined() + expect(renderResult?.onKeyDown).toBeDefined() + expect(typeof renderResult?.onKeyDown).toBe('function') + }) +}) diff --git a/src/renderer/src/components/RichEditor/command.ts b/src/renderer/src/components/RichEditor/command.ts index a460e210d4..1371b3ebb6 100644 --- a/src/renderer/src/components/RichEditor/command.ts +++ b/src/renderer/src/components/RichEditor/command.ts @@ -628,13 +628,34 @@ export const commandSuggestion: Omit { + // Let CommandListPopover handle events first + const popoverHandled = component.ref?.onKeyDown?.(props.event) + if (popoverHandled) { + return true + } + + // Handle Shift+Enter for newline when popover doesn't handle it + if (props.event.key === 'Enter' && props.event.shiftKey) { + props.event.preventDefault() + // Close the suggestion menu + if (cleanup) cleanup() + component.destroy() + // Use the view from SuggestionKeyDownProps to insert newline + const { view } = props + const { state, dispatch } = view + const { tr } = state + tr.insertText('\n') + dispatch(tr) + return true + } + if (props.event.key === 'Escape') { if (cleanup) cleanup() component.destroy() return true } - return component.ref?.onKeyDown(props.event) + return false }, onExit: () => {