diff --git a/core/contextmenu_registry.ts b/core/contextmenu_registry.ts index 61fac7a719f..5b84104c101 100644 --- a/core/contextmenu_registry.ts +++ b/core/contextmenu_registry.ts @@ -104,15 +104,15 @@ export class ContextMenuRegistry { weight: item.weight, }; + const precondition = item.preconditionFn?.(scope, menuOpenEvent); + if (precondition === 'hidden') continue; + if (item.separator) { menuOption = { ...menuOption, separator: true, }; } else { - const precondition = item.preconditionFn(scope, menuOpenEvent); - if (precondition === 'hidden') continue; - const displayText = typeof item.displayText === 'function' ? item.displayText(scope) @@ -165,6 +165,7 @@ export namespace ContextMenuRegistry { scopeType?: ScopeType; weight: number; id: string; + preconditionFn?: (p1: Scope, menuOpenEvent: Event) => string; } /** @@ -185,8 +186,8 @@ export namespace ContextMenuRegistry { location: Coordinate, ) => void; displayText: ((p1: Scope) => string | HTMLElement) | string | HTMLElement; - preconditionFn: (p1: Scope, menuOpenEvent: Event) => string; separator?: never; + preconditionFn: (p1: Scope, menuOpenEvent: Event) => string; } /** @@ -196,7 +197,6 @@ export namespace ContextMenuRegistry { separator: true; callback?: never; displayText?: never; - preconditionFn?: never; } /** diff --git a/tests/mocha/contextmenu_items_test.js b/tests/mocha/contextmenu_items_test.js index 08ab5d5267b..52f4428ba7d 100644 --- a/tests/mocha/contextmenu_items_test.js +++ b/tests/mocha/contextmenu_items_test.js @@ -371,6 +371,89 @@ suite('Context Menu Items', function () { assert.equal(this.deleteOption.displayText(this.scope), 'Delete Block'); }); }); + + suite('Separators', function () { + setup(function () { + this.registry.reset(); + this.registry.register({ + weight: 0, + id: 'a', + preconditionFn: () => {}, + displayText: 'a', + callback: () => {}, + }); + this.registry.register({ + weight: 2, + id: 'b', + preconditionFn: () => {}, + displayText: 'b', + callback: () => {}, + }); + }); + + test('are hidden when precondition returns hidden', function () { + this.registry.register({ + weight: 1, + id: 'separator', + preconditionFn: () => 'hidden', + separator: true, + }); + + const items = this.registry.getContextMenuOptions( + this.scope, + new Event('pointerdown'), + ); + assert.equal(items.length, 2); + assert.isTrue(items.every((item) => !('separator' in item))); + }); + + test('are included when precondition returns enabled', function () { + this.registry.register({ + weight: 1, + id: 'separator', + preconditionFn: () => 'enabled', + separator: true, + }); + + const items = this.registry.getContextMenuOptions( + this.scope, + new Event('pointerdown'), + ); + assert.equal(items.length, 3); + assert.isTrue('separator' in items[1]); + }); + + test('are included when precondition returns disabled', function () { + this.registry.register({ + weight: 1, + id: 'separator', + preconditionFn: () => 'disabled', + separator: true, + }); + + const items = this.registry.getContextMenuOptions( + this.scope, + new Event('pointerdown'), + ); + assert.equal(items.length, 3); + assert.isTrue('separator' in items[1]); + }); + + test('are included when there is no precondition', function () { + this.registry.register({ + weight: 1, + id: 'separator', + separator: true, + }); + + const items = this.registry.getContextMenuOptions( + this.scope, + new Event('pointerdown'), + ); + assert.equal(items.length, 3); + assert.isTrue('separator' in items[1]); + }); + }); }); suite('Block Items', function () { @@ -483,5 +566,88 @@ suite('Context Menu Items', function () { assert.equal(this.inlineOption.preconditionFn(this.scope), 'enabled'); }); }); + + suite('Separators', function () { + setup(function () { + this.registry.reset(); + this.registry.register({ + weight: 0, + id: 'a', + preconditionFn: () => {}, + displayText: 'a', + callback: () => {}, + }); + this.registry.register({ + weight: 2, + id: 'b', + preconditionFn: () => {}, + displayText: 'b', + callback: () => {}, + }); + }); + + test('are hidden when precondition returns hidden', function () { + this.registry.register({ + weight: 1, + id: 'separator', + preconditionFn: () => 'hidden', + separator: true, + }); + + const items = this.registry.getContextMenuOptions( + this.scope, + new Event('pointerdown'), + ); + assert.equal(items.length, 2); + assert.isTrue(items.every((item) => !('separator' in item))); + }); + + test('are included when precondition returns enabled', function () { + this.registry.register({ + weight: 1, + id: 'separator', + preconditionFn: () => 'enabled', + separator: true, + }); + + const items = this.registry.getContextMenuOptions( + this.scope, + new Event('pointerdown'), + ); + assert.equal(items.length, 3); + assert.isTrue('separator' in items[1]); + }); + + test('are included when precondition returns disabled', function () { + this.registry.register({ + weight: 1, + id: 'separator', + preconditionFn: () => 'disabled', + separator: true, + }); + + const items = this.registry.getContextMenuOptions( + this.scope, + new Event('pointerdown'), + ); + assert.equal(items.length, 3); + assert.isTrue('separator' in items[1]); + }); + + test('are included when there is no precondition', function () { + this.registry.register({ + weight: 1, + id: 'separator', + separator: true, + }); + + const items = this.registry.getContextMenuOptions( + this.scope, + new Event('pointerdown'), + ); + assert.equal(items.length, 3); + assert.isTrue('separator' in items[1]); + }); + }); }); });