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

@nuclent/schema-viewer

v0.0.8

Published

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Downloads

159

Readme

@nuclent/schema-viewer

Schema Visualizer for React

@nuclent/schema-viewer is a comprehensive React component library designed to render interactive, customizable graph-based visualizations representing complex schemas. Built on top of React Flow, it provides a simplified API to define nodes, edges, and their interactions, making it perfect for visualizing relational data, database schemas, or any other interconnected structures.

Whether you're dealing with large datasets or intricate relationships within your data, @nuclent/schema-viewer offers a declarative approach to constructing vivid and dynamic graphs. With features like a built-in minimap, controllable node expansion, and various stylings options, your data visualization is both functional and aesthetically pleasing.

With @nuclent/schema-viewer, you can expect:

  • Ease of Use: Simplify the process of mapping your data into a visual context.
  • Flexibility: Customize the appearance and behavior of your nodes and edges to meet the specific needs of your application.
  • Interactivity: Engage with your diagrams through interactive features like zooming, dragging, and event handlers.

Ideal for developers working on data analysis tools, database management systems, or any application that benefits from graph visualization, @nuclent/schema-viewer is the go-to solution for representing data-driven insights.

Installation

npm install @nuclent/schema-viewer

or

yarn add @nuclent/schema-viewer

Usage

Quick start example:

# tsx
import React from 'react';
import { FlowWrapper } from "@nuclent/schema-viewer";

// import styles
import "@nuclent/schema-viewer/dist/style.css";

function App() {
  return (
    <FlowWrapper
      // ...props here
    />
  );
}

export default App;

API Reference

For clarifiation, each node's data field named as Field, but we can call it as a row / field - anything refer to a row in a table schema.

| Prop | Type | Default | Description | | --------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------- | | data * | SchemaData[] | [] | The nodes of the graph. | | legend | boolean | true | If true, legend information is displayed. | | containerStyle | CSSProperties | position: "relative", height: "100dvh", width: "100%", maxWidth: "100%", margin: 0, padding: 0 | Styles applied to the graph container. |

|Nodes |nodeModalRender | React.ReactNode | A Stack display that field's information | Custom React render inside Mantine modal when a Field clicked.| |nodeModalSize | MantineNumberSize number | "xs" | "sm" | "md" | "lg" | "xl" | sm| |nodeModalTitle | string | Its Field ["displayName"] property | |nodeCloseOnClickOutside | boolean | true| |color | MantineColor | white | The color of a node's header text | |bgColor |MantineColor | indigo | The background color of a node header | |shadowColor| string | "10px 10px 50px 0px rgba(166, 179, 231, 0.75)" | Node's box shadow color when selected (dragging, clicked) |Edges | edgeType | smoothstep | bezier | smoothstep | The type of edges between nodes. | |radius | number | 12 | How curve should a edge's corner be? *Note: only work if edge type is *smoothstep** | |edgeModalRender | React.ReactNode | A Stack display that edge's information | Custom React render inside Mantine modal when an Edge clicked. |edgeModalSize | MantineNumberSize number | "xs" | "sm" | "md" | "lg" | "xl" | sm| |edgeModalTitle | string | "Edge Details" | |edgeCloseOnClickOutside | boolean | true| |labelColor |MantineColor | white | The color of an edge's label text| | labelBgColor |MantineColor | indigo.4 | The background color of a edge label| | selectedLabelColor | MantineColor | blue | The background color of a edge label when selected (clicked) | |Toolbar | toolbar | boolean | true | If true, a toolbar will be displayed. | |toolbarTitle | string | "Schema Viewer Toolbar" | |toolbarPosition | PanelPositon |top-left | | toolbarBgColor |MantineColor | white | The background color of toolbar panel| |React Flow | background | BackgroundVariant | BackgroundVariant.Lines | The background variant of the app. | | minimap | boolean | true | If true, a minimap will be displayed. | |minimapNodeColor | string | gray | The fill color for nodes displayed in the minimap | |minimapMaskColor |string | #d9d9d9c7 | |minimapPosition | PanelPositon |bottom-right | controls | boolean | true | If true, React Flow controls is displayed. | |controlsPosition | PanelPositon | top-right |ELK | layoutOptions | Record<string, string | number> | undefined | Options for the graph's layout algorithm. | |Default State | collapse | boolean | false | If true, all nodes will be collapsed by default. | | hidden | boolean | false | If true, all nodes will be hidden by default. |

More detailed explanation for complex props:

layoutOptions

The layoutOptions prop allows fine-tuning of the graph's layout. It accepts an object where the key is the layout option name and the value is its setting. All reference can be found here: ELK Reference

Example:

const layoutOptions = {
  "elk.algorithm": "org.eclipse.elk.layered",
  "elk.direction": "RIGHT"
};

return <FlowWrapper layoutOptions={layoutOptions} />

Node / Edge Modal Render

import { CustomNodeModalRender } from "../somewhere";

return <FlowWrapper
            nodeModalRender={ <CustomNodeModalRender />}
            // other props ...
        />

Examples & Demo

Live & Editable demo available here: Demo Link

nFlow Data Conversion Code Sample

# tsx
  import { Field, FlowWrapper, Relation } from "@nuclent/schema-viewer";
  import "@nuclent/schema-visualizer/dist/style.css";

  const App = () => {

      return (
        <FlowWrapper
          nodes={nodes}
          edgeModalTitle="hi everyone"
          edgeModalRender={<Test />}
        />
      )
  }

  function Test() {
    return (
        <div>
          <p>im going to sleep</p>
        </div>
    );
  }

  const nodes = array.map((i) => {
  const id = String(i.id);

  return {
    id,
    data: {
      id,
      fields: mapFields(i.fields),
      name: i.name,
      displayName: i.displayName,
      description: i.description,
      relations: mapRelations(i.related, array),
    },
    type: "custom",
  };
});

function mapFields(fields: FieldSchema[]): Field[] {
  return fields.map((f) => ({
    displayName: f.displayName,
    name: f.name,
    type: f.typeName,
    subType: f.subType,
    isGenerated: f.isSystemDefault,

    // this is the step where user gonna convert their data so we can do smthg like this
    isPrimaryKey: f.name == "guid",
    isRelation: f.typeName == "relation",
    isUnique: f.isUnique,
    isRequired: f.isRequired,
    isReadOnly: f.isReadOnly,
  }));
}

function mapRelations(
  related: Record<string, RelatedDataField>,
  array: Schema[]
): Relation[] {
  return Object.entries(related).map((r) => {
    const label = r[0].split(".")[1]; // input: expenses.categories => output: categories
    const { objName } = r[1]; // { objName, name }

    return (
      {
        id: array.find((e) => e.name === objName)?.id + "",
        objName,
        fieldName: label,
        label,
      }
    );
  });
}

Contributing

License