FAQ - Rete.js

FAQ

The engine only supports JS runtime. You can either bind JS into your environment or implement your own engine, similar to rete-engine (it has a straightforward implementation)

In short, yes. Refer to the Licensing for details

It can be used in JS code, but not recommended because of poor DX

Replace zoom handler with null or use a custom one

ts
const area = new AreaPlugin(container)

area.area.setZoomHandler(null)

Replace the zoom handler with null on some event and restore it on opposite (e.g. Ctrl press/release)

ts
import { Zoom } from 'rete-area-plugin'

// call on init
area.area.setZoomHandler(null)

// call on Ctrl press
area.area.setZoomHandler(new Zoom(0.1))

// call on Ctrl release
area.area.setZoomHandler(null)

Replace the drag handler for a specific area by calling setDragHandler

ts
  import { Drag } from 'rete-area-plugin';

  area.area.setDragHandler(new Drag({
    down: e => {
      if (e.pointerType === 'mouse' && e.button !== 1) return false

      e.preventDefault()
      return true
    },
    move: () => true
  }))

The position is stored within a NodeView instance.

ts
  const view = area.nodeViews.get(nodeId)

  if (view) {
    view.position // { x, y }
  }

Keep in mind that the NodeView instance may not exist, for example if it hasn't yet been added. In such cases, it's preferable to handle this gracefully (throw an exception only when necessary)

ts
  area.translate(nodeId, { x: 0, y: 0 })

Call the following methods for the corresponding nodes or controls after making changes to the state

ts
const area = new AreaPlugin(container)

area.update('node', node.id)
area.update("control", control.id);

Use the methods of content property of the area plugin

ts
const area = new AreaPlugin(container)

area.content.add(element)

area.content.remove(element)

It's also possible to make this element draggable

ts
const dragHandler = new Drag()

dragHandler.initialize(element, { /* getters */ }, { /* events */ })

Check out the relevant customization guide for React.js, Vue.js, Angular, Svelte or Lit.

Define how elements should be hidden when the node is collapsed by creating a custom node component.

Check out the relevant customization guide for React.js, Vue.js, Angular, Svelte or Lit.

You need to stop propagation of the pointerdown event.

Check the relevant render plugin guide for controls: React.js, Vue.js, Angular, Svelte, Lit

By default, the area captures these events, so you need to stop the propagation of pointerdown event to prevent this

Check the relevant render plugin guide for controls: React.js, Vue.js, Angular, Svelte, Lit

By default, a node is configured with the CSS property user-select: none to prevent conflict between text selection and node dragging.

Therefore, to enable text selection within a custom node component, you need to specify user-select: all property for the desired element within the node. Additionally, ensure you call e.stopPropagation() on the `pointerdown`` event to prevent text selection interruptions while dragging.

Whenever a user clicks on the node, the nodepicked event is fired:

ts
area.addPipe(context => {
  if (context.type === 'nodepicked') {
    const node = editor.getNode(context.data.id)

  }
  return context
})

In case you need to track not only click, but also node selections, you have the option to extend the selector to observe selected elements (not just nodes) within the editor

You can add them as usual using the addInput/addOutput/AddControl methods, and then force a node update

ts
const area = new AreaPlugin(container)

area.update('node', node.id)

The process of adding such elements requires the creation of a custom node.

Check out the relevant customization guide for React.js, Vue.js, Angular, Svelte or Lit.

You can use the classic preset with custom nodes and a unified socket for both input and output port.

Check out the Undirected example

The classic rendering preset offers the flexibility to specify an optional index field for inputs, outputs or controls. This feature enables you to change the order of these elements within their lists.

ts
const input = new ClassicPreset.Input(socket)
const output = new ClassicPreset.Output(socket)
const control = new ClassicPreset.InputControl('text')

input.index = 0;
output.index = 0;
control.index = 0;

The process of changing the node layout requires the creation of a custom node.

Check out the relevant customization guide for React.js, Vue.js, Angular, Svelte or Lit.

In short, it is possible, but there is no plugin available for this approach since it doesn't offer significant advantages in comparison to the development costs

If you don't want to update all of your dependencies at once with npm update, you can selectively update those that begin with rete using a regular expression

bash
npx npm-check-updates /^rete/ --target @latest -u

All available rendering plugins can display a loop connection if it has specified isLoop property

ts
class Connection extends ClassicPreset.Connection {
  isLoop = false
}

const connection = new Connection(source, output, target, input)

connection.isLoop = true

The minimum required TypeScript version is 4.7.

Otherwise, you might encounter the error Type instantiation is excessively deep and possibly infinite. ts(2589) when using the use method. If you can't use a later version for some reason, the only solution is to use @ts-ignore.

For example, when creating an Angular 12 application with Rete Kit, a version 4.7 higher than the officially supported one is installed.

Using the area.zoom method enables you to specify the desired zoom level and the offset points for aligning the zoom

ts
await area.area.zoom(0.8, 0, 0);

In the given example, the zoom will be decreased with respect to the top left boundary. If you want to modify the zoom relative to the center of the viewport, refer to the following code

ts
const delta = 0.2;
const { k } = area.area.transform;
const box = area.container.getBoundingClientRect();
const x = box.width / 2 / k;
const y = box.height / 2 / k;

area.area.zoom(k * (1 - delta), x * delta, y * delta);

By utilizing the area.translate method, you can change the coordinates as follows

ts
await area.area.translate(100, 20)

Change in position relative to current coordinates

ts
const { x, y } = area.area.transform
await area.area.translate(x + 100, y + 20)

Change the editor's position considering the zoom factor

ts
const { k } = area.area.transform

await area.area.translate(100 * k, 20 * k)

In case you're using a framework other than React.js, Vue.js, Angular, Svelte or Lit (for which Rete.js provides a rendering plugin), you have the option to utilize the React.js plugin to render nodes and other editor elements.

For a quick start, you can create a React.js application using Rete Kit, copy the code of the editor from src/rete/default.tsx, install the relevant dependencies in your project and call createEditor, providing the HTMLElement container created by your application.

First of all, you need to obtain the viewport center in screen coordinates using getBoundingClientRect. Afterward, you should transform them into editor coordinates by applying the zoom factor k and offset it relative to area's position.

ts
const area = new AreaPlugin<Schemes, AreaExtra>(container)

const { x, y, k } = area.area.transform
const box = area.container.getBoundingClientRect()
const halfWidth = box.width / 2 / k
const halfHeight = box.height / 2 / k

return { x: halfWidth - x / k, y: halfHeight - y / k }

The warning "Found more than one element for socket with same key and side" means that there are duplicate sockets in the editor that were not properly removed after an update, or due to an asynchronous approach when unmounting components by different UI frameworks, the lifecycle of old and new ones overlaps.

In the first case, when the number of these warnings constantly accumulates, you most likely have a memory leak problem because some custom node was not correctly unmounted.

In the second case, the warning can be avoided by adding a delay between removing the scheme/node and mounting a new one with the same identifiers. In the worst case, this warning should not indicate memory leak issues, so you can ignore it.

The framework does not have a reserved event for this. Instead, you can [/docs/guides/selectable#extend-selector](extend the selector) by triggering events in the relevant methods.

ts
  area.addPipe(context => {
    if (context.type ===  'zoom' && context.data.source === 'dblclick') return
    return context
  })