components_effect_context_menu.js
import { ContextMenu } from "./context_menu.js"
/**
* A context menu for effect range operations (edit or remove).
*
* @example
* const menu = new EffectContextMenu(event.clientX, event.clientY, {
* onEdit: () => openEditDialog(rangeId),
* onRemove: () => removeRange(rangeId),
* onDismiss: () => { this._effectMenu = null; },
* });
*/
export class EffectContextMenu extends ContextMenu {
/**
* @param {number} x - Preferred left position in viewport pixels.
* @param {number} y - Preferred top position in viewport pixels.
* @param {object} callbacks - Callback functions for menu actions.
* @param {function(): void} [callbacks.onEdit] - Called when "Edit effect" is clicked.
* @param {function(): void} [callbacks.onRemove] - Called when "Remove effect" is clicked.
* @param {function(): void} [callbacks.onDismiss] - Called when the menu is dismissed.
* @param {{message: string, href: (string|undefined)}|null} [callbacks.info] - Info widget config passed to the base ContextMenu.
*/
constructor(x, y, { onEdit, onRemove, onDismiss, info = { message: 'Edit or remove this audio effect applied to the selected range.', href: '/docs' } } = {}) {
super('Effect', onDismiss, info);
// Prevent mousedown from stealing focus / clearing selections.
this.root.addEventListener('mousedown', e => e.preventDefault());
const controls = document.createElement('div');
controls.className = 'ctx-controls';
controls.appendChild(this.makeItem(
'<span style="font-size:0.85rem;line-height:1;">✎</span>',
'Edit effect', null,
() => { this.close(); this._onDismiss(); onEdit?.(); },
));
controls.appendChild(this.makeItem(
'<span style="font-size:0.85rem;line-height:1;">✕</span>',
'Remove effect', null,
() => { this.close(); this._onDismiss(); onRemove?.(); },
));
this.root.appendChild(controls);
this._mount(x, y);
}
}