Selectable connections - Rete.js

Selectable connections

This guide is based on the Basic guide. It is recommended to review it for a comprehensive understanding of this guide.

Selectable connectionsSelectable

Getting types ready

Introducing an optional selected field to the connection type will allow us to specify programmatically added connections as selected

ts
class Connection extends ClassicPreset.Connection<
  ClassicPreset.Node,
  ClassicPreset.Node
> {
  selected?: boolean;
}

type Schemes = GetSchemes<ClassicPreset.Node, Connection>;

Custom connection

Our first step is to implement a custom connection that is clickable and capable of changing color when selected.

We will start with the Connection.tsx component from the classic preset and enhance its functionality by implementing new features.

We can make the connection more user-friendly by defining a duplicating transparent path.

ts
import styled from "styled-components";

const HoverPath = styled.path`
  fill: none;
  stroke-width: 15px;
  pointer-events: auto;
  stroke: transparent;
`;

We will enhance the existing Path component by adding a selected prop and modifying the stroke color.

ts
const Path = styled.path<{ selected?: boolean >`
  stroke: ${(props) => (props.selected ? "rgb(255, 217, 44)" : "steelblue")};
`;

The component should return the following template:

tsx
<Svg
  onPointerDown={(e: PointerEvent) => e.stopPropagation()}
  onClick={props.click}
>
  <HoverPath d={path} />
  <Path selected={props.data.selected} d={path} />
</Svg>

The existing connection can be marked as follows:

ts
connection.selected = true;
area.update("connection", connection.id);

Synchronization of selected connections

Let's get the selector ready

ts
const selector = AreaExtensions.selector();
const accumulating = AreaExtensions.accumulateOnCtrl();

AreaExtensions.selectableNodes(area, selector, { accumulating });

Adding a connection to the selector can be done in the following way (for instance, by clicking on the connection):

ts
selector.add({
  id: connection.id,
  label: 'connection',
  translate() {},
  unselect() {
    connection.selected = false;
    area.update("connection", connection.id);
  }
}, accumulating.active())

connection.selected = true;
area.update("connection", connection.id);

Now we'll consolidate all of this into a single component using a straightforward closure-based approach (although other methods are preferable in production code), and pass it as a custom connection component

tsx
function SelectableConnectionBind(props: { data: Schemes["Connection"] }) {
  return (
    <SelectableConnection
      {...props}
      click={() => {
        selector.add({
          /// ...
        })
        // here should be placed here the code for adding to the selector, as shown above
      }}
    />
  );
}

render.addPreset(Presets.classic.setup({
  customize: {
    connection() {
      return SelectableConnectionBind;
    }
  }
}));

Check out the complete result on the Selectable connections example page.