Render Connector Items

Copy Markdown View Source

LivePanels renders connectors as connector items in the runtime world SVG projection. Applications do not build a graph connector SVG layer, project paths, or duplicate hit targets.

The connector item runtime owns:

  • routed path geometry;
  • marker definitions and marker URLs;
  • connector labels stored on connector item presentation;
  • item selection and hit target attrs;
  • bend handles for selected connectors;
  • stream updates for connector item changes.

The graph extension owns endpoint resolution, connection rules, graph selection, graph layout, and graph command protocol.

Applications own item UI, ports, product controls, and CSS.

Use The Runtime SVG Projection

Render graph canvases with the ordinary runtime component. Add ports inside item markup; do not add a connector layer in :world_layer:

<.canvas_runtime {canvas_runtime_attrs(assigns)}>
  <:item :let={context}>
    <article class="node">
      <header {drag_handle_attrs()}>{context.item.label}</header>

      <button
        :for={port <- context.ports}
        {graph_port_anchor_attrs(port)}
        {if port.direction == :output,
          do: begin_connector_attrs(context.item, port),
          else: complete_connector_attrs(context.item, port)}
      >
        {port.label}
      </button>

      {context.content}
    </article>
  </:item>
</.canvas_runtime>

Connector items are streamed into:

<g data-livepanels-svg-projection="items">...</g>

Each connector item renders as:

  • g.livepanels-connector-projection-item;
  • path.livepanels-connector-path;
  • optional text.livepanels-connector-label;
  • selected bend handles;
  • path.livepanels-connector-hit-path.

Style Connectors

The renderer emits structural classes and data attrs, but no product theme:

.app-canvas .livepanels-connector-path {
  fill: none;
  stroke: currentColor;
  stroke-width: 3px;
}

.app-canvas
  [data-livepanels-connector-selection="selected"]
  .livepanels-connector-path {
  stroke-width: 4px;
}

.app-canvas
  [data-livepanels-connector-emphasis="active"]
  .livepanels-connector-path {
  color: var(--app-accent);
}

Useful public attrs include:

  • data-livepanels-connector-id;
  • data-livepanels-connector-from-id;
  • data-livepanels-connector-from-port;
  • data-livepanels-connector-to-id;
  • data-livepanels-connector-to-port;
  • data-livepanels-connector-route;
  • data-livepanels-connector-role;
  • data-livepanels-connector-emphasis;
  • data-livepanels-connector-selection;
  • data-livepanels-connector-hit-target.

data-livepanels-connector-selection is selected, related, or unrelated when the actor has a graph selection.

Store Presentation On Connector Items

Connector presentation belongs on the connector item:

connector =
  LivePanels.Item.Connector.connection(
    id: "extract-load",
    from: LivePanels.Item.Connector.endpoint("extract", "out"),
    to: LivePanels.Item.Connector.endpoint("load", "in"),
    route: :orthogonal,
    direction: :horizontal,
    label: "rows",
    role: :data,
    marker_end: :arrow,
    emphasis: :normal
  )

Starting connectors are created after their endpoint items exist:

use LivePanels.Canvas,
  pubsub: MyApp.PubSub,
  initial: [connectors: [connector]],
  domains: [:graph]

use LivePanels.Toolkit.Graph

Programmatic commands accept the same presentation fields:

socket =
  LivePanels.Graph.connect!(socket,
    from: {"extract", "out"},
    to: {"load", "in"},
    route: :orthogonal,
    label: "rows",
    emphasis: :active
  )

Update existing connector presentation through the graph command path:

socket =
  LivePanels.Graph.edit!(socket, "extract-load",
    route: :straight,
    emphasis: :active
  )

Use :all to update every connector:

socket =
  LivePanels.Graph.edit!(socket, :all,
    route: :orthogonal,
    direction: :horizontal
  )

Product Labels

If labels come from product data, write the resolved value onto connector item presentation with LivePanels.Graph.connect!/2 or LivePanels.Graph.edit!/3. This keeps rendered labels in the same state, persistence, history, and shared-canvas path as connector routes and markers.

Route Options

Supported routes are:

  • :bezier;
  • :orthogonal;
  • :straight.

Route options are connector presentation:

LivePanels.Graph.edit!(socket, connector_id,
  route: :bezier,
  direction: :horizontal,
  precision: 1,
  curvature: 0.35,
  min_curvature: 40
)

The renderer reads those fields directly from the connector item, so route changes survive replacement, streaming, persistence, and shared canvas updates.

Layer Ordering

Connector items live in the world SVG item projection with drawing vector items. The runtime orders world HTML items, world SVG items, and viewport items through the same item stream story.

Use CSS and item z-index for visual stacking. Use :world_layer only for application-owned background projections that are not LivePanels items. Use :world_overlay for camera-addressed host projections that must sit above LivePanels items, such as pointer presence cursors.