diff --git a/packages/core/src/dom_components/model/Components.ts b/packages/core/src/dom_components/model/Components.ts
index 190d3c2bb..5e77970c6 100644
--- a/packages/core/src/dom_components/model/Components.ts
+++ b/packages/core/src/dom_components/model/Components.ts
@@ -210,6 +210,7 @@ Component> {
sels.remove(rulesRemoved.map((rule) => rule.getSelectors().at(0)));
if (!removed.opt.temporary) {
+ em.removeSelected(removed);
em.Commands.run('core:component-style-clear', { target: removed });
removed.views.forEach((view) => {
view.scriptContainer &&
diff --git a/packages/core/test/specs/editor/index.ts b/packages/core/test/specs/editor/index.ts
index eac0baf31..cd22608c3 100644
--- a/packages/core/test/specs/editor/index.ts
+++ b/packages/core/test/specs/editor/index.ts
@@ -165,6 +165,50 @@ describe('Editor', () => {
expect(editor.getSelectedAll().length).toBe(0);
});
+ test('Removing a selected component removes it from the selection', () => {
+ const wrapper = editor.getWrapper()!;
+ const added = wrapper.append('
Component 1
');
+ editor.select(added[0]);
+ expect(editor.getSelectedAll().length).toBe(1);
+
+ added[0].remove();
+ expect(editor.getSelectedAll().length).toBe(0);
+ });
+
+ test('Replacing a selected component removes it from the selection', () => {
+ const wrapper = editor.getWrapper()!;
+ const added = wrapper.append('Component 1
');
+ editor.select(added[0]);
+
+ added[0].replaceWith('Replacement');
+ expect(editor.getSelectedAll().length).toBe(0);
+ });
+
+ test('Undo after replaceWith inside component:selected restores content without orphan selection', () => {
+ const um = editor.UndoManager;
+ const wrapper = editor.getWrapper()!;
+ wrapper.append('A
B
');
+ um.clear();
+
+ let replaced = false;
+ editor.on('component:selected', (cmp) => {
+ if (replaced) return;
+ replaced = true;
+ cmp.replaceWith('C');
+ });
+
+ editor.select(wrapper.components().at(0));
+ expect(replaced).toBe(true);
+ expect(wrapper.getInnerHTML()).toBe('CB
');
+
+ um.undo();
+ expect(wrapper.getInnerHTML()).toBe('A
B
');
+ // Whatever selection the undo restored must reference components still in the tree
+ editor.getSelectedAll().forEach((cmp) => {
+ expect(cmp.parent()).toBeTruthy();
+ });
+ });
+
test.skip('Shift key selecting a component that is being edited should not clear any text selections', () => {
const all = editor.Components.allById();
const em = editor.em;