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);
    }
}