npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-vis-network-with-canvg

v1.0.0

Published

Declarative vis.js network for react with canvg

Downloads

71

Readme

React Vis Network

Build Status

Overview

react-vis-network uses a declarative approach to defining vis.js networks. This allows developers to work in React using normal stateful approaches like Redux and have the underlying network chart manage it's own lifecycle.

Example

import React, { Component } from 'react';
import { Network, Node, Edge } from 'react-vis-network';

class MyNetwork extends Component {
  render() {
    return (
      <Network>
        <Node id="vader" label="Darth Vader" />
        <Node id="luke" label="Luke Skywalker" />
        <Node id="leia" label="Leia Organa" />
        <Edge id="1" from="vader" to="luke" />
        <Edge id="2" from="vader" to="leia" />
      </Network>
    );
  }
}

API

< Network />

<Network /> is the top level component that defines your network. All Nodes, Edges and Cluster* components need to be inside a Network to work properly.

Props

options: Object of vis options to configure the look and feel, physics, and interaction patterns in the graph. All options are passed directly to vis and can be overriden on a case by case bases by setting individual options on each Node or Edge

scale: Zoom scale of the network. Defined as a number from 0-1 where 1 is 100% zoomed and 0 is zoomed out infinitely. As returned from network.getScale.

position: Object ({ x, y }) containing coordinates of the central focus point. As returned from network.getViewPosition.

style/className: Normal style and className props to enable styling the network's wrapping element. NB: Overidding position: relative and overflow: hidden will result in wonky node decorator behavior.

< Node />

A Node represents a vis.js network node. As props, a Node accepts all options accepted in normal configuration. It also accepts two special props component and decorator.

component: SVG element to be rendered as the Node in the Network. component is a render prop recieves all of the props passed to Node and returns a react component. The svg will be rendered as the image of the node. Helpful tip, you can pass additional props to node that can be used in your render prop to dynamically change your image.

const CustomIcon = ({ icon, color = '#5596ed' }) => {
  const viewBox = 36;
  const iconSize = 20;
  const pad = (viewBox - iconSize) / 2;
  const center = viewBox / 2;

  return (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      viewBox={`0 0 ${viewBox} ${viewBox}`}
    >
      <g>
        <circle cx={center} cy={center} r={16} fill={color} />
        <g transform={`translate(${pad}, ${pad})`}>
          {React.createElement(icon, { color: 'white', size: iconSize })}
        </g>
      </g>
    </svg>
  );
};

// Use your render prop and custom props passed to `Node` to
// Generate differnt icons per node
const MyNetwork = () => (
  <Network>
    <Node
      id="vader"
      label="Darth Vader"
      component={CustomIcon}
      color="black"
      icon={Sith}
    />
    <Node
      id="luke"
      label="Luke Skywalker"
      component={CustomIcon}
      color="white"
      icon={Jedi}
    />
    <Node
      id="leia"
      label="Leia Organa"
      component={CustomIcon}
      color="gold"
      icon={Princess}
    />
    <Edge id="1" from="vader" to="luke" />
    <Edge id="2" from="vader" to="leia" />
  </Network>
);

NB: This is simply syntactic sugar over using HTML in Nodes and will end up being a data+image. You will not recieve dom events through this component, use Network's event system or decorators instead.

decorator: A react element positioned at the top center of rendered Node. A decorator is similar to component in that it's a render prop that recieves the props of a the node, and returns a react element. This element however doesn't need to be an svg.

const Decorator = props => {
  return (
    <button
      style={decoratorStyles}
      onClick={() => console.log(`You clicked ${props.label}`}
    >
      Click Me
    </button>
  );
};

// Use your render prop and custom props passed to `Node` to
// cause differnet actions in your Decorator
const MyNetwork = () => (
  <Network>
    <Node id='vader' label='Darth Vader' decorator={Decorator} />
    <Node id='luke' label='Luke Skywalker' decorator={Decorator} />
    <Node id='leia' label='Leia Organa' decorator={Decorator} />
    <Edge id='1' from='vader' to='luke' />
    <Edge id='1' from='vader' to='leia' />
  </Network>
);

NB: Because this is a positioned HTML element, it can recieve DOM events like click and input. While fairly performant in positioning and rendering, it can be straining if many nodes have decorators and should be used sparingly. For static (non-interactable) content, it would be better to use a component with a changing prop to re-render it.

< Edge />

An Edge represents a vis.js edge and connects nodes together.

Edges accept all of the options vis exposes for edges as props. One specific note, vis doesn't require that edges have an id, react-vis-network does in order to keep the network updated.

< ClusterByConnection />

A ClusterByConnection is a representation of a vis.js cluster. This particular cluster implementation collapses all nodes around, and including, it's rootNodeId into a cluster.

ClusterByConnection takes all props that Node does including component and decorator.

rootNodeId: id of a Node for which to cluster around.

Performance Considerations

All exported components are Pure Components. It's important to not define anonymous functions and objects inside the render function as it will cause unnecessary re-renders.

// bad, re-renders every time
render () {
  return <Node component={() => <SomeIcon />} />
}

// good, only re-renders when other props change
renderSomeIcon = () => <SomeIcon />

render () {
  return <Node component={this.renderSomeIcon} />
}

Use decorators on Nodes sparingly, if you can do it in the component you should.

Extending, custom clusters, and custom modules

⚠️ Advanced topics, here be dragons.

Want to write a custom Cluster component? Want to add a bit to the lifecycle of a node?

The base of Nodes and Clusters is a Module. Take a peak at the source and create your own class that extends the Module (if you want decorator and compoment support anyway) and use it.

The design of each component is to manage it's lifecycle inside the vis network with react lifecycle methods. Every child inside a Network is passed as props a network (vis.Network), edges (vis.Dataset) and nodes (vis.Dataset).

Helpers

In order to help you roll your own lifecycle methods, the internal converter for component and decorator is exposed as reactToSvgImageUrl.

reactToSvgImageUrl (element) -> String: Accepts a JSX element and returns it rendered as a data:image string.

Accessing the underlying vis network

⚠️ This is an escape hatch, if you find yourself needing to do this, it's likely that the package authors simply haven't thought of your use-case. We would like to! Please open an issue and we can work to build a supported solution.

The Network component has, as instance properties, network (a vis.js network), edges (a vis.js Dataset representing it's edges), and nodes a vis.js Dataset representing it's nodes).

You can access these by creating a ref to the mounted Network.