From 18a47eee3941a8ad17512415b50cef710cde8e1c Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Wed, 20 May 2026 17:19:25 +0400 Subject: [PATCH] Refactor ComponentEnter --- packages/core/src/commands/registry.ts | 2 + .../core/src/commands/view/ComponentEnter.ts | 20 ++++++---- .../specs/commands/view/ComponentEnter.ts | 38 +++++++++++++++++++ 3 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 packages/core/test/specs/commands/view/ComponentEnter.ts diff --git a/packages/core/src/commands/registry.ts b/packages/core/src/commands/registry.ts index 5f9ea38a2..879cf8788 100644 --- a/packages/core/src/commands/registry.ts +++ b/packages/core/src/commands/registry.ts @@ -11,6 +11,7 @@ import type { PreviewCommandRegistryRun, PreviewCommandRegistryStop } from './vi import type { ResizeCommandRegistryRun, ResizeCommandRegistryStop } from './view/Resize'; import type { ComponentNextCommandRegistryRun } from './view/ComponentNext'; import type { ComponentPrevCommandRegistryRun } from './view/ComponentPrev'; +import type { ComponentEnterCommandRegistryRun } from './view/ComponentEnter'; import type { CopyComponentCommandRegistryRun } from './view/CopyComponent'; import type { PasteComponentCommandRegistryRun } from './view/PasteComponent'; import type { CanvasMoveCommandRegistryRun, CanvasMoveCommandRegistryStop } from './view/CanvasMove'; @@ -45,6 +46,7 @@ export interface CommandRegistryRun ResizeCommandRegistryRun, ComponentNextCommandRegistryRun, ComponentPrevCommandRegistryRun, + ComponentEnterCommandRegistryRun, CopyComponentCommandRegistryRun, PasteComponentCommandRegistryRun, CanvasMoveCommandRegistryRun, diff --git a/packages/core/src/commands/view/ComponentEnter.ts b/packages/core/src/commands/view/ComponentEnter.ts index 004872915..ccb012ddb 100644 --- a/packages/core/src/commands/view/ComponentEnter.ts +++ b/packages/core/src/commands/view/ComponentEnter.ts @@ -1,17 +1,23 @@ -import Component from '../../dom_components/model/Component'; -import { CommandObject } from './CommandAbstract'; +import type Component from '../../dom_components/model/Component'; +import Editor from '../../editor'; +import type { CommandPublicFnFromHandler } from '../registryHelpers'; +import CommandAbstract from './CommandAbstract'; -export default { - run(ed) { +export interface ComponentEnterCommandRegistryRun { + 'core:component-enter': CommandPublicFnFromHandler; +} + +export default class CommandComponentEnter extends CommandAbstract { + run(ed: Editor) { if (!ed.Canvas.hasFocus()) return; const toSelect: Component[] = []; ed.getSelectedAll().forEach((component) => { const coll = component.components(); - const next = coll && coll.filter((c: any) => c.get('selectable'))[0]; + const next = coll && coll.filter((c) => !!c.get('selectable'))[0]; next && toSelect.push(next); }); toSelect.length && ed.select(toSelect); - }, -} as CommandObject; + } +} diff --git a/packages/core/test/specs/commands/view/ComponentEnter.ts b/packages/core/test/specs/commands/view/ComponentEnter.ts new file mode 100644 index 000000000..b1cc98aad --- /dev/null +++ b/packages/core/test/specs/commands/view/ComponentEnter.ts @@ -0,0 +1,38 @@ +import ComponentEnter from '../../../../src/commands/view/ComponentEnter'; + +describe('ComponentEnter command', () => { + test('should select the first selectable child', () => { + const command = new ComponentEnter({}); + const firstSelectable = { id: 'child-1' }; + const component = { + components: jest.fn(() => [ + { get: jest.fn(() => false) }, + { get: jest.fn(() => true), ...firstSelectable }, + { get: jest.fn(() => true) }, + ]), + }; + const editor = { + Canvas: { hasFocus: jest.fn(() => true) }, + getSelectedAll: jest.fn(() => [component]), + select: jest.fn(), + }; + + command.run(editor as any); + + expect(editor.select).toHaveBeenCalledWith([expect.objectContaining(firstSelectable)]); + }); + + test('should do nothing if the canvas has no focus', () => { + const command = new ComponentEnter({}); + const editor = { + Canvas: { hasFocus: jest.fn(() => false) }, + getSelectedAll: jest.fn(), + select: jest.fn(), + }; + + command.run(editor as any); + + expect(editor.getSelectedAll).not.toHaveBeenCalled(); + expect(editor.select).not.toHaveBeenCalled(); + }); +});