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

@joint/react

v0.1.1-alpha.1

Published

React module for JointJS

Downloads

49

Readme

JointJS React

React core components for working with JointJS.

[!NOTE] The goal of this project is to define a minimal basis for the various React components for JointJS. Please help us shape the package by reporting issues or proposing API changes.

[!IMPORTANT] This is an early stage product. The package may contain bugs and security issues. The API is subject to change.

Installation

yarn install jointjs @joint/react

API

Components

<Paper />

The main component that allows you to draw nodes and edges on the canvas. In JointJS terminology, you draw cells (elements and links) on paper. The component requires the <GraphProvider /> to be its ancestor.

Props

| Property | Type | Description | |:-----------|:---------------|:-------------| | options? | dia.Paper.Options | The options of the paper. It's async by default. | | renderElement? | (dia.Element) => React.JSX.Element \| null | A callback to render React components inside the paper element views. The components are rendered using the React.createPortal(). | | onReady? | (dia.Paper) => void | A callback that is triggered after the paper is mounted and ready (cells may not be rendered). | | onEvent? | (dia.Paper, eventName, ...eventArgs) => void | A callback that allows you to listen to the dia.Paper events. | | dataAttributes? | string[] | A list of model attributes that, if changed, will cause the renderElement function to be triggered. The default is ["data"]. | | portal? | Element \| string \| (dia.ElementView) => string \| Element | An HTMLElement or SVGElement (or a string selector) that serves as portal for rendering element's content. By default, the portal is selector "portal". |

Rendering React component inside an Element view

By default, the content of the element view is rendered using JointJS. However, the content (SVG or HTML) can also be rendered using React.

import { dia, shapes } from 'jointjs';
import { GraphProvider, Paper } from '@joint/react';

// Assumes that the `portal` node is a foreign object descendant.
const renderHTMLElement = (element) => {
   const { label, value } = element.get('data');
   return (
       <div className="my-element">
           <h3>{label}</h3>
           <input
               type='text'
               value={value}
               onChange={(e) => element.prop('data/value', e.target.value)}
           />
       </div>
   );
};

export default function Diagram() {
   const graph = new dia.Graph({}, { cellNamespace: shapes });
   const paperProps = { /* ... */ };
   return (
       <GraphProvider graph={graph}>
           <Paper renderHTMLElement={renderHTMLElement} ...paperProps />
       </GraphProvider>
   )
}

Currently, the following drawbacks are known with this approach:

  • content rendered with React cannot be the source/target of any link (it's always a good idea to also render the SVG <rect /> under the portal node).
  • <Paper /> currently replaces the default dia.Paper.prototype.options.elementView with a custom ElementView that triggers the portal:ready event ((elementView: dia.ElementView, portalEl: SVGElement | HTMLElement) => void) when the portal node is rendered (onRender() method). If you want to use custom views and you want to use renderElement with them, make sure you trigger the portal:ready event manually.
Paper provides context implicitly.

The <Paper /> context provides the paper context to its descendants implicitly. If you need to use the paper context outside of the <Paper />, use the <PaperProvider />.

<GraphProvider graph={graph}>
   <Paper>
       <MySelection/>{/* component is using JointJS `paper` */}
   </Paper>
</GraphProvider>

<PaperProvider />

The <PaperProvider /> component is a context provider that makes it possible to access the JointJS paper outside of the <Paper /> component. Unlike the GraphProvider, the PaperProvider is not mandatory.

import { GraphProvider, PaperProvider, Paper } from '@joint/react';

export default function Diagram() {
    return (
        <GraphProvider graph={graph}>
            <PaperProvider>
                <Paper/>
                <MyZoomInButton/>
                <MyZoomOutButton/>
            </PaperProvider>
        </GraphProvider>
    )
}

<GraphProvider />

The <GraphProvider /> component is a context provider that provides JointJS graph to <Paper /> components. You need use the <GraphProvider /> in order to render the <Paper /> component.

Here's an example of a GraphProvider providing a graph to two papers.

import { dia, shapes } from 'jointjs';
import { GraphProvider, Paper } from '@joint/react';

export default function Diagram() {
    const graph = new dia.Graph({}, { cellNamespace: shapes });
    const paperProps = { /* ... */ };
    const minimapProps = {  /* ... */ };
    return (
        <GraphProvider graph={graph}>
            <Paper ...paperProps className="canvas" />
            <Paper ...minimapProps className="minimap" />
        </GraphProvider>
    )
}
Props

| Property | Type | Description | |:-----------|:---------------|:-------------| | graph | dia.Graph | A graph instance to be provided to the descendants |

Hooks

The package exposed several custom hooks.

usePaper

The usePaper is a hook that let you use the JointJS paper from your component.

import { usePaper } from '@joint/react';

export default function MyZoomInButton() {
    const paper = usePaper();
    const zoomIn = () => {
        if (!paper) return;
        const { sx, sy } = paper.scale();
        paper.scale(sx * 2, sy * 2);
    }
    return <button onClick={zoomIn}>Zoom In</button>
}

useGraph

The useGraph is a hook that let you use the JointJS graph from your component.

import { useGraph } from '@joint/react';

export default function MyDeleteAllButton() {
    const graph = useGraph();
    const deleteAll = () => {
        if (graph && confirm("Are you sure you want to delete all content?")) {
            graph.clear();
        }
    }
    return <button onClick={deleteAll}>Delete All</button>
}

What's next

The possible tasks ahead of us.

JointJS+

Define React Components for JointJS+.

// NOTE: This is fictional code
// It is just an example of possible API.
import { dia, mvc } from '@joint/core';
import { CommandManager } from '@joint/command-manager';
import { Paper } from '@joint/react';
import DiagramProvider from '@joint/diagram-provider';
import Toolbar from '@joint/toolbar-react';
import Stencil from '@joint/stencil-react';
import Scroller from '@joint/scroller-react';
import Inspector from '@joint/inspector-react';
import Selection from '@joint/selection-react';
import Snaplines from '@joint/snaplines-react';
import Grid from 'some-ui-lib';

export default function Diagram() {
    const graph = new dia.Graph();
    const cmd = new CommandManager({ graph });
    const selection = new mvc.Collection();
    return (
        <DiagramProvider graph={graph} commandManager={cmd} selection={selection}/>
            <Toolbar />
            <Grid>
                <Stencil />
                <Scroller />
                    <Paper >
                        <Selection />
                        <Snaplines />
                    </Paper>
                <Scroller>
                <Navigator />
            </Grid>
            <Navigator />
        <DiagramProvider />
    )
}

Higher-level Components

Define user-friendly higher-level components.

// Paper, Scroller, Toolbar, CommandManager as a single component
<Diagram preset="kitchen-sink" width={400} height={400} fitView={true} virtualRendering={true}></Diagram>
// Domain-specific diagram components
<OrgChartDiagram data={adjacencyList}></OrgChartDiagram>

License

Mozilla Public License 2.0

Copyright © 2013-2023 client IO