0.0.8 • Published 10 months ago

@nuclent/schema-viewer v0.0.8

Weekly downloads
-
License
ISC
Repository
-
Last release
10 months ago

@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.
PropTypeDefaultDescription
data *SchemaData[][]The nodes of the graph.
legendbooleantrueIf true, legend information is displayed.
containerStyleCSSPropertiesposition: "relative", height: "100dvh", width: "100%", maxWidth: "100%", margin: 0, padding: 0Styles 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

0.0.8

10 months ago

0.0.7

11 months ago

0.0.6

11 months ago

0.0.5

11 months ago

0.0.4

11 months ago

0.0.3

12 months ago

0.0.2

12 months ago

0.0.1

12 months ago