diff --git a/packages-content-model/roosterjs-content-model-editor/lib/editor/plugins/ContentModelEditPlugin.ts b/packages-content-model/roosterjs-content-model-editor/lib/editor/plugins/ContentModelEditPlugin.ts index c8d6e752571..bdfd6bbcae8 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/editor/plugins/ContentModelEditPlugin.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/editor/plugins/ContentModelEditPlugin.ts @@ -7,13 +7,6 @@ import { getOnDeleteEntityCallback } from '../utils/handleKeyboardEventCommon'; import { getPendingFormat, setPendingFormat } from '../../modelApi/format/pendingFormat'; import { IContentModelEditor } from '../../publicTypes/IContentModelEditor'; import { isNodeOfType, normalizeContentModel } from 'roosterjs-content-model-dom'; -import { - getObjectKeys, - isBlockElement, - isCharacterValue, - isModifierKey, - Position, -} from 'roosterjs-editor-dom'; import { EditorPlugin, EntityOperationEvent, @@ -24,8 +17,16 @@ import { NodeType, PluginEvent, PluginEventType, + PluginKeyDownEvent, SelectionRangeTypes, } from 'roosterjs-editor-types'; +import { + getObjectKeys, + isBlockElement, + isCharacterValue, + isModifierKey, + Position, +} from 'roosterjs-editor-dom'; // During IME input, KeyDown event will have "Process" as key const ProcessKey = 'Process'; @@ -91,7 +92,7 @@ export default class ContentModelEditPlugin implements EditorPlugin { break; case PluginEventType.KeyDown: - this.handleKeyDownEvent(this.editor, event.rawEvent); + this.handleKeyDownEvent(this.editor, event); break; case PluginEventType.ContentChanged: @@ -112,13 +113,14 @@ export default class ContentModelEditPlugin implements EditorPlugin { } } - private handleKeyDownEvent(editor: IContentModelEditor, rawEvent: KeyboardEvent) { + private handleKeyDownEvent(editor: IContentModelEditor, event: PluginKeyDownEvent) { + const rawEvent = event.rawEvent; const which = rawEvent.which; if (!this.editWithContentModel || rawEvent.defaultPrevented) { // Other plugins already handled this event, so it is most likely content is already changed, we need to clear cached content model editor.cacheContentModel(null /*model*/); - } else if (!rawEvent.defaultPrevented) { + } else if (!rawEvent.defaultPrevented && !event.handledByEditFeature) { // TODO: Consider use ContentEditFeature and need to hide other conflict features that are not based on Content Model switch (which) { case Keys.BACKSPACE: diff --git a/packages/roosterjs-editor-core/lib/corePlugins/EditPlugin.ts b/packages/roosterjs-editor-core/lib/corePlugins/EditPlugin.ts index 90d30290ee2..8cbaf4fa405 100644 --- a/packages/roosterjs-editor-core/lib/corePlugins/EditPlugin.ts +++ b/packages/roosterjs-editor-core/lib/corePlugins/EditPlugin.ts @@ -64,8 +64,9 @@ export default class EditPlugin implements PluginWithState { let hasFunctionKey = false; let features: GenericContentEditFeature[] | null = null; let ctrlOrMeta = false; + const isKeyDownEvent = event.eventType == PluginEventType.KeyDown; - if (event.eventType == PluginEventType.KeyDown) { + if (isKeyDownEvent) { const rawEvent = event.rawEvent; const range = this.editor?.getSelectionRange(); @@ -86,6 +87,9 @@ export default class EditPlugin implements PluginWithState { feature.shouldHandleEvent(event, this.editor, ctrlOrMeta) ) { feature.handleEvent(event, this.editor); + if (isKeyDownEvent) { + event.handledByEditFeature = true; + } break; } } diff --git a/packages/roosterjs-editor-types/lib/event/PluginDomEvent.ts b/packages/roosterjs-editor-types/lib/event/PluginDomEvent.ts index 35bf454e26f..9fdd9759bad 100644 --- a/packages/roosterjs-editor-types/lib/event/PluginDomEvent.ts +++ b/packages/roosterjs-editor-types/lib/event/PluginDomEvent.ts @@ -34,6 +34,16 @@ export interface PluginScrollEventData { scrollContainer: HTMLElement; } +/** + * Data of PluginKeyDownEvent + */ +export interface PluginKeyDownEventData { + /** + * Whether this event is handled by edit feature + */ + handledByEditFeature: boolean; +} + /** * A base interface of all DOM events */ @@ -79,7 +89,8 @@ export type PluginMouseEvent = PluginMouseDownEvent | PluginMouseUpEvent | Plugi * This interface represents a PluginEvent wrapping native KeyDown event */ export interface PluginKeyDownEvent - extends PluginDomEventBase {} + extends PluginKeyDownEventData, + PluginDomEventBase {} /** * This interface represents a PluginEvent wrapping native KeyPress event @@ -148,7 +159,8 @@ export type CompatiblePluginMouseEvent = * This interface represents a PluginEvent wrapping native KeyDown event */ export interface CompatiblePluginKeyDownEvent - extends PluginDomEventBase {} + extends PluginKeyDownEventData, + PluginDomEventBase {} /** * This interface represents a PluginEvent wrapping native KeyPress event diff --git a/packages/roosterjs-editor-types/lib/event/index.ts b/packages/roosterjs-editor-types/lib/event/index.ts index 9c764664547..cd4838bd62b 100644 --- a/packages/roosterjs-editor-types/lib/event/index.ts +++ b/packages/roosterjs-editor-types/lib/event/index.ts @@ -69,6 +69,7 @@ export { PluginScrollEventData, PluginMouseUpEventData, PluginContextMenuEventData, + PluginKeyDownEventData, } from './PluginDomEvent'; export { PluginEvent } from './PluginEvent'; export {