diff --git a/packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/ImageEdit.ts b/packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/ImageEdit.ts index 7173d0e0f49..92b48098683 100644 --- a/packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/ImageEdit.ts +++ b/packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/ImageEdit.ts @@ -218,6 +218,13 @@ export default class ImageEdit implements EditorPlugin { this.setEditingImage(null); } break; + case PluginEventType.MouseUp: + // When mouse up, if the image and the shadow span exists, the editing mode is on. + // To make sure the selection did not jump to the shadow root, reselect the image. + if (this.image && this.shadowSpan) { + this.editor?.select(this.image); + } + break; case PluginEventType.KeyDown: this.setEditingImage(null); break; diff --git a/packages/roosterjs-editor-plugins/test/imageEdit/imageEditTest.ts b/packages/roosterjs-editor-plugins/test/imageEdit/imageEditTest.ts index 72dd5b694c8..6a317d352f2 100644 --- a/packages/roosterjs-editor-plugins/test/imageEdit/imageEditTest.ts +++ b/packages/roosterjs-editor-plugins/test/imageEdit/imageEditTest.ts @@ -1,7 +1,13 @@ import * as TestHelper from '../TestHelper'; import ImageEditInfo from '../../lib/plugins/ImageEdit/types/ImageEditInfo'; -import { IEditor, ImageEditOperation, PluginEvent, PluginEventType } from 'roosterjs-editor-types'; import { ImageEdit } from '../../lib/ImageEdit'; +import { + IEditor, + ImageEditOperation, + PluginEvent, + PluginEventType, + SelectionRangeTypes, +} from 'roosterjs-editor-types'; import { getEditInfoFromImage, saveEditInfo, @@ -225,7 +231,7 @@ describe('ImageEdit | rotate and flip', () => { }); }); -describe('ImageEdit | plugin events | quitting', () => { +describe('ImageEdit | plugin events | ', () => { let editor: IEditor; const TEST_ID = 'imageEditTest'; let plugin: ImageEdit; @@ -270,22 +276,34 @@ describe('ImageEdit | plugin events | quitting', () => { target.dispatchEvent(event); }; - it('image selection quit editing', () => { - const IMG_ID = 'IMAGE_ID_QUIT'; + const mouseUp = (target: HTMLElement, keyNumber: number) => { + const rect = target.getBoundingClientRect(); + const event = new MouseEvent('mouseup', { + view: window, + bubbles: true, + cancelable: true, + clientX: rect.left, + clientY: rect.top, + shiftKey: false, + button: keyNumber, + }); + target.dispatchEvent(event); + }; + + it('mouse up | keep image selected if click in a image', () => { + const IMG_ID = 'IMAGE_ID_MOUSE'; const SPAN_ID = 'SPAN_ID'; const content = ``; editor.setContent(content); const image = document.getElementById(IMG_ID) as HTMLImageElement; editor.focus(); editor.select(image); - expect(setEditingImageSpy).toHaveBeenCalled(); - expect(setEditingImageSpy).toHaveBeenCalledWith( - image as any, - ImageEditOperation.ResizeAndRotate as any - ); + mouseUp(image, 0); + const selection = editor.getSelectionRangeEx(); + expect(selection.type).toBe(SelectionRangeTypes.ImageSelection); }); - it('mousedown quit editing', () => { + it('quitting | mousedown quit editing', () => { const IMG_ID = 'IMAGE_ID_MOUSE'; const SPAN_ID = 'SPAN_ID'; const content = ``; @@ -294,12 +312,12 @@ describe('ImageEdit | plugin events | quitting', () => { const span = document.getElementById(SPAN_ID) as HTMLImageElement; editor.focus(); editor.select(image); - mouseDown(span, 0); + mouseDown(span, 2); expect(setEditingImageSpy).toHaveBeenCalled(); expect(setEditingImageSpy).toHaveBeenCalledWith(null); }); - it('keydown quit editing', () => { + it('quitting | keydown quit editing', () => { const IMG_ID = 'IMAGE_ID'; const content = ``; editor.setContent(content);