Skip to content

Commit

Permalink
Add DropdownMenuItemDefinition support
Browse files Browse the repository at this point in the history
  • Loading branch information
Mati365 committed Jul 1, 2024
1 parent cc9e9eb commit 8960260
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @module ui/dropdown/menu/definition/dropdownmenudefinitionguards
*/

import type { DropdownMenuDefinition } from './dropdownmenudefinitiontypings.js';
import type { DropdownMenuDefinition, DropdownMenuItemDefinition } from './dropdownmenudefinitiontypings.js';

/**
* Checks if the given object is a valid DropdownMenuDefinition.
Expand All @@ -17,3 +17,12 @@ import type { DropdownMenuDefinition } from './dropdownmenudefinitiontypings.js'
*/
export const isDropdownMenuObjectDefinition = ( obj: any ): obj is DropdownMenuDefinition =>
!!obj && typeof obj === 'object' && 'menu' in obj && 'children' in obj;

/**
* Checks if the given object is a valid DropdownMenuItemDefinition.
*
* @param obj - The object to be checked.
* @returns A boolean indicating whether the object is a DropdownMenuItemDefinition.
*/
export const isDropdownMenuItemDefinition = ( obj: any ): obj is DropdownMenuItemDefinition =>
!!obj && typeof obj === 'object' && 'label' in obj && 'onExecute' in obj;
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,47 @@ import type DropdownMenuView from '../dropdownmenuview.js';
* Represents the definition of a dropdown menu.
*/
export type DropdownMenuDefinition = {

/**
* The name of the dropdown menu.
*/
menu: string;

/**
* The children of the dropdown menu.
*/
children: Array<DropdownMenuChildDefinition>;
};

/**
* Represents an array of dropdown menu definitions.
* Represents the definition of a dropdown menu item.
*/
/**
* Represents the definition of a dropdown menu item.
*/
export type DropdownMenuDefinitions = Array<DropdownMenuDefinition>;
export type DropdownMenuItemDefinition = {

/**
* The name of the dropdown menu item.
*/
label: string;

/**
* The icon associated with the dropdown menu item.
*/
icon?: string | undefined;

/**
* The function to be executed when the dropdown menu item is selected.
*/
onExecute: VoidFunction;
};

/**
* Represents a child definition of a dropdown menu.
*/
export type DropdownMenuChildDefinition =
| DropdownMenuDefinition
| DropdownMenuItemDefinition
| DropdownMenuView
| DropdownMenuListItemButtonView;
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
import { once } from 'lodash-es';

import DropdownMenuListItemView from '../dropdownmenulistitemview.js';
import { isDropdownMenuObjectDefinition } from './dropdownmenudefinitionguards.js';
import { isDropdownMenuItemDefinition, isDropdownMenuObjectDefinition } from './dropdownmenudefinitionguards.js';

import type DropdownMenuListItemButtonView from '../dropdownmenulistitembuttonview.js';
import DropdownMenuListItemButtonView from '../dropdownmenulistitembuttonview.js';
import type DropdownMenuListView from '../dropdownmenulistview.js';
import type { ObservableChangeEvent } from '@ckeditor/ckeditor5-utils';
import type { DropdownNestedMenuListItemView } from '../typings.js';
Expand Down Expand Up @@ -58,6 +58,13 @@ export class DropdownMenuListDefinitionFactory {
this._lazyInitializeSubMenus = lazyInitializeSubMenus;
}

/**
* The locale of the dropdown menu list.
*/
private get locale() {
return this._listView.locale!;
}

/**
* Appends multiple menus to the dropdown menu definition parser.
*
Expand Down Expand Up @@ -105,7 +112,7 @@ export class DropdownMenuListDefinitionFactory {
targetParentMenuView
);

return new DropdownMenuListItemView( this._listView.locale!, targetParentMenuView, menuOrFlatItem );
return new DropdownMenuListItemView( this.locale, targetParentMenuView, menuOrFlatItem );
} );

if ( targetParentMenuView ) {
Expand Down Expand Up @@ -133,6 +140,15 @@ export class DropdownMenuListDefinitionFactory {
return this._appendMenuToParentUsingObjectDefinition( child, parentMenuView );
}

if ( isDropdownMenuItemDefinition( child ) ) {
const flatItem = new DropdownMenuListItemButtonView( this.locale, child.label );

flatItem.icon = child.icon;
flatItem.on( 'execute', child.onExecute );

return flatItem;
}

return this._recursiveAssignMenuChildrenParents( child, parentMenuView );
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { compact } from 'lodash-es';
import type { CollectionAddEvent } from '@ckeditor/ckeditor5-utils';
import type DropdownMenuListItemView from './dropdownmenulistitemview.js';
import type { Editor } from '@ckeditor/ckeditor5-core';
import type { DropdownMenuDefinitions } from './definition/dropdownmenudefinitiontypings.js';
import type { DropdownMenuDefinition } from './definition/dropdownmenudefinitiontypings.js';
import type {
DropdownMenuExecuteItemEvent,
DropdownMenuChangeIsOpenEvent,
Expand All @@ -35,6 +35,11 @@ import { flattenDropdownMenuTree } from './tree/dropdownmenutreeflattenutils.js'
* {
* menu: 'Menu 1',
* children: [
* {
* label: 'Menu item defined object definition',
* icon: 'your-icon',
* onExecute: () => { ... }
* },
* new DropdownMenuListItemButtonView( locale, 'Item' ),
* new ListSeparatorView( locale ),
* {
Expand Down Expand Up @@ -90,7 +95,7 @@ export default class DropdownMenuRootListView extends DropdownMenuListView {
*/
constructor(
editor: Editor,
definitions?: DropdownMenuDefinitions,
definitions?: Array<DropdownMenuDefinition>,
options: DropdownMenuRootListViewAttributes = {}
) {
super( editor.locale );
Expand Down
5 changes: 1 addition & 4 deletions packages/ckeditor5-ui/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,7 @@ export { default as DropdownMenuView } from './dropdown/menu/dropdownmenuview.js
export { default as DropdownMenuListView } from './dropdown/menu/dropdownmenulistview.js';
export { default as DropdownMenuListItemView } from './dropdown/menu/dropdownmenulistitemview.js';
export { default as DropdownMenuListItemButtonView } from './dropdown/menu/dropdownmenulistitembuttonview.js';
export type {
DropdownMenuDefinition,
DropdownMenuDefinitions
} from './dropdown/menu/definition/dropdownmenudefinitiontypings.js';
export type { DropdownMenuDefinition } from './dropdown/menu/definition/dropdownmenudefinitiontypings.js';

export { default as EditorUI, type EditorUIReadyEvent, type EditorUIUpdateEvent } from './editorui/editorui.js';
export { default as EditorUIView } from './editorui/editoruiview.js';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,34 @@ describe( 'DropdownMenuRootListView', () => {
} );

describe( 'appendMenuChildrenAt()', () => {
it( 'should append flat menu items using definition only', () => {
const onExecuteSpy = sinon.spy();
const rootListView = createRootListWithDefinition(
{
menu: 'Hello World',
children: []
}
);

rootListView.factory.appendMenuChildrenAt(
[
{
label: 'Baz',
onExecute: onExecuteSpy
}
],
findMenuTreeMenuViewByLabel( 'Hello World', rootListView.tree )
);

const insertedChild = findMenuTreeItemByLabel( 'Baz', rootListView.tree.children[ 0 ] );

expect( insertedChild.search.raw ).to.be.equal( 'Baz' );
expect( onExecuteSpy ).not.to.be.called;

insertedChild.item.fire( 'execute' );
expect( onExecuteSpy ).to.be.calledOnce;
} );

it( 'should append flat menu items to the menu', () => {
const rootListView = createRootListWithDefinition(
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ describe( 'Menu Behaviors', () => {
otherMenu.isOpen = true;
nestedMenuListItem.fire( 'mouseenter' );

expect( nestedMenuListItem.flatItemOrNestedMenuView.isOpen ).to.be.true;
expect( nestedMenuListItem.childView.isOpen ).to.be.true;
} );

it( 'should focus hovered item only if any other menu was open and it\'s listView had focus', () => {
Expand Down

0 comments on commit 8960260

Please sign in to comment.