Контекстне меню - Rete.js

Контекстне меню

Цей гайд базується на гайді Базовий редактор. Рекомендується переглянути його для повного розуміння цього гайду.

Контекстне менюПлагін

Встановити залежності

bash
npm i rete-context-menu-plugin

Підготовка вузлів

Для покращення зручності та повторного використання коду рекомендується створити окремі класи для вузлів:

ts
class NodeA extends ClassicPreset.Node {
  constructor(socket: ClassicPreset.Socket) {
    super("NodeA");

    this.addControl("port", new ClassicPreset.InputControl("text", {}));
    this.addOutput("port", new ClassicPreset.Output(socket));
  }
}

/// class NodeB extends ...

type Node = NodeA | NodeB;
type Schemes = GetSchemes<Node, Connection<Node, Node>>;

Підключення плагіна

Для простого рішення використовуйте класичний пресет і вкажіть список помічених елементів разом із функцією, яка повертає потрібний вузол

ts
import { ContextMenuExtra, ContextMenuPlugin, Presets as ContextMenuPresets } from "rete-context-menu-plugin";

type AreaExtra = ReactArea2D<Schemes> | ContextMenuExtra;

const contextMenu = new ContextMenuPlugin<Schemes>({
  items: ContextMenuPresets.classic.setup([
    ["NodeA", () => new NodeA(socket)],
    ["NodeB", () => new NodeB(socket)]
  ])
});

area.use(contextMenu);

Але цього недостатньо, оскільки рендер плагін відповідає за візуалізацію

Рендерінг контекстного меню

Наразі рендерінг контекстного меню можливий за допомогою рендерінг плагінів для React.js, Vue.js, Angular, Svelte та Lit

ts
import { Presets } from "rete-react-plugin"; // або rete-vue-plugin, rete-angular-plugin, rete-svelte-plugin, @retejs/lit-plugin

render.addPreset(Presets.contextMenu.setup());

Щоб отримати вичерпний гайд щодо підключення конкретного рендерінг плагіна до вашої версії стека, дотримуйтеся гайду для React.js, Vue.js, Angular, Svelte або Lit

Натискання на вільному місці відкриває меню, у якому відображаються доступні вузли для створення, або просто натисніть на існуючому вузлі, щоб видалити його.

Підпункти

Щоб указати пункт вузла як підпункт, ви можете використовувати те саме визначення, використовуючи масив замість фабричної функції:

ts
const contextMenu = new ContextMenuPlugin<Schemes>({
  items: ContextMenuPresets.classic.setup([
    ["Math", [
      ["Number", () => new NumberNode()],
    ]]
  ])
})

Вбудовані опції вузлів та з'єднань

Всі вузли та з'єднання мають опцію Delete в їх контекстном меню. Вона відповідно дозволяє видалити вузол, перед тим видаливши його з'єднання, або видалити окремі з'єднання.

Інша опція, яку за замовчуванням ви не побачив на вузлах - це Clone. Вона відображається для вузлів, які мають метод clone. До прикладу:

ts
class NodeA extends ClassicPreset.Node {
  clone() {
    return new NodeA()
  }
}

Кастомний пресет

Хоча класичний пресет дозволяє коротко вказати пункти для головного меню та меню для певного вузла, він може не запропонувати достатньої гнучкості. У таких випадках ви можете визначити власні пункти меню:

ts
const contextMenu = new ContextMenuPlugin<Schemes>({
  items(context, plugin) {
    if (context === 'root') {
      return {
        searchBar: false,
        list: [
          { label: 'Кастомний', key: '1', handler: () => console.log('Кастомний') },
          {
            label: 'Колекція', key: '1', handler: () => null,
            subitems: [
              { label: 'Підпункт', key: '1', handler: () => console.log('Підпункт') }
            ]
          }
        ]
      }
    }
    return {
      searchBar: false,
      list: []
    }
  }
})

де context - це 'root', екземпляр вузла або екземпляр з'єднання

Відкрити меню програмно #{trigger-context-menu}

Щоб вручну відкрити контекстне меню, потрібно створити подію типу PointerEvent з необхідними координатами та викликати метод area.emit():

ts
const event = new PointerEvent('contextmenu', {
  clientX: x,
  clientY: y,
})

await area.emit({ type: 'contextmenu', data: { event, context } })

де

  • x, y - це числові значення (наприклад координати курсору, які ви повинні отримати окремо),
  • context - може бути 'root' або екземпляр вузла, з'єднання або іншого виду елдементів вашого редактора

Перегляньте повний результат на сторінці прикладу Контекстне меню.