refactor: Make preconditionFn part of all context menu items (#9558)

* refactor: Make preconditionFn part of all context menu items

* test: Verify separator menu item behavior with precondition functions
This commit is contained in:
Aaron Dodson
2026-01-09 13:59:03 -08:00
committed by GitHub
parent 497892946b
commit 25c6187d88
2 changed files with 171 additions and 5 deletions
+5 -5
View File
@@ -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;
}
/**
+166
View File
@@ -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]);
});
});
});
});