diff --git a/packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/setContentModel.ts b/packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/setContentModel.ts index b274ca09278..96a4290e5fa 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/setContentModel.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/setContentModel.ts @@ -17,6 +17,7 @@ export const setContentModel: SetContentModel = (core, model, option, onNodeCrea const modelToDomContext = option ? createModelToDomContext(editorContext, ...(core.defaultModelToDomOptions || []), option) : createModelToDomContextWithConfig(core.defaultModelToDomConfig, editorContext); + const selection = contentModelToDom( core.contentDiv.ownerDocument, core.contentDiv, @@ -29,7 +30,11 @@ export const setContentModel: SetContentModel = (core, model, option, onNodeCrea core.cache.cachedSelection = selection || undefined; if (selection) { - core.api.setDOMSelection(core, selection); + if (!option?.ignoreSelection) { + core.api.setDOMSelection(core, selection); + } else if (selection.type == 'range') { + core.domEvent.selectionRange = selection.range; + } } core.cache.cachedModel = model; diff --git a/packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/switchShadowEdit.ts b/packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/switchShadowEdit.ts index 93425f02088..7ab5578d6b9 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/switchShadowEdit.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/switchShadowEdit.ts @@ -1,4 +1,5 @@ import { getSelectionPath } from 'roosterjs-editor-dom'; +import { iterateSelections } from '../../modelApi/selection/iterateSelections'; import { PluginEventType } from 'roosterjs-editor-types'; import type { ContentModelEditorCore } from '../../publicTypes/ContentModelEditorCore'; import type { SwitchShadowEdit } from 'roosterjs-editor-types'; @@ -54,7 +55,12 @@ export const switchShadowEdit: SwitchShadowEdit = (editorCore, isOn): void => { ); if (core.cache.cachedModel) { - core.api.setContentModel(core, core.cache.cachedModel); + // Force clear cached element from selected block + iterateSelections([core.cache.cachedModel], () => {}); + + core.api.setContentModel(core, core.cache.cachedModel, { + ignoreSelection: true, // Do not set focus and selection when quit shadow edit, focus may remain in UI control (picker, ...) + }); } } } diff --git a/packages-content-model/roosterjs-content-model-editor/test/editor/coreApi/switchShadowEditTest.ts b/packages-content-model/roosterjs-content-model-editor/test/editor/coreApi/switchShadowEditTest.ts index 0991c08f96d..4d679d7b833 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/editor/coreApi/switchShadowEditTest.ts +++ b/packages-content-model/roosterjs-content-model-editor/test/editor/coreApi/switchShadowEditTest.ts @@ -1,3 +1,4 @@ +import * as iterateSelections from '../../../lib/modelApi/selection/iterateSelections'; import { ContentModelEditorCore } from '../../../lib/publicTypes/ContentModelEditorCore'; import { PluginEventType } from 'roosterjs-editor-types'; import { switchShadowEdit } from '../../../lib/editor/coreApi/switchShadowEdit'; @@ -142,10 +143,14 @@ describe('switchShadowEdit', () => { it('with cache, isOff', () => { core.cache.cachedModel = mockedCachedModel; + spyOn(iterateSelections, 'iterateSelections'); + switchShadowEdit(core, false); expect(createContentModel).not.toHaveBeenCalled(); - expect(setContentModel).toHaveBeenCalledWith(core, mockedCachedModel); + expect(setContentModel).toHaveBeenCalledWith(core, mockedCachedModel, { + ignoreSelection: true, + }); expect(core.cache.cachedModel).toBe(mockedCachedModel); expect(triggerEvent).toHaveBeenCalledTimes(1); diff --git a/packages-content-model/roosterjs-content-model-types/lib/context/ModelToDomOption.ts b/packages-content-model/roosterjs-content-model-types/lib/context/ModelToDomOption.ts index 92af52f93f7..3ca91ef31db 100644 --- a/packages-content-model/roosterjs-content-model-types/lib/context/ModelToDomOption.ts +++ b/packages-content-model/roosterjs-content-model-types/lib/context/ModelToDomOption.ts @@ -28,4 +28,9 @@ export interface ModelToDomOption { * Overrides default metadata appliers */ metadataAppliers?: Partial; + + /** + * When set to true, selection from content model will not be applied + */ + ignoreSelection?: boolean; } diff --git a/packages/roosterjs-editor-core/lib/coreApi/switchShadowEdit.ts b/packages/roosterjs-editor-core/lib/coreApi/switchShadowEdit.ts index 95eb4b16965..5d3dd632aaf 100644 --- a/packages/roosterjs-editor-core/lib/coreApi/switchShadowEdit.ts +++ b/packages/roosterjs-editor-core/lib/coreApi/switchShadowEdit.ts @@ -98,39 +98,14 @@ export const switchShadowEdit: SwitchShadowEdit = (core: EditorCore, isOn: boole shadowEditEntities ); } - core.api.focus(core); if (shadowEditSelectionPath) { - core.api.selectRange( - core, - createRange( - contentDiv, - shadowEditSelectionPath.start, - shadowEditSelectionPath.end - ) + core.domEvent.selectionRange = createRange( + contentDiv, + shadowEditSelectionPath.start, + shadowEditSelectionPath.end ); } - - if (core.domEvent.imageSelectionRange) { - const { image } = core.domEvent.imageSelectionRange; - const imageElement = core.contentDiv.querySelector('#' + image.id); - if (imageElement) { - core.api.selectImage(core, image); - } - } - - if (core.domEvent.tableSelectionRange) { - const { table, coordinates } = core.domEvent.tableSelectionRange; - const tableId = table.id; - const tableElement = core.contentDiv.querySelector('#' + tableId); - if (table) { - core.domEvent.tableSelectionRange = core.api.selectTable( - core, - tableElement as HTMLTableElement, - coordinates - ); - } - } } } };