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 🙏

© 2025 – Pkg Stats / Ryan Hefner

flow-castro

v0.2.11

Published

A React library to create visual flow editors

Readme

Flow-Castro

Flow-Castro is a React library for creating and editing interactive flowcharts and visual programming interfaces (VPL). It enables users to build workflows, data flow diagrams, and visual logic through an intuitive drag-and-drop interface.

With Flow-Castro, you can:

  • Create custom nodes with typed inputs and outputs
  • Connect nodes to create complex data flows
  • Define custom behaviors for data processing
  • Implement visual interfaces for various applications such as automation, data processing, and workflows

About this document

This guide will walk you through the process of setting up and integrating the Flow-Castro library into your React application.

Setting up Flow-Castro in a React Application

This guide will walk you through the process of setting up and integrating the Flow-Castro library into your React application.

Installation

First, install the Flow-Castro library along with its peer dependencies:

npm install flow-castro react react-dom

Basic Setup

Create a new component in your React application that will use the Flow-Castro library:

import React, { useState } from "react";
import { NodeContainer, ThemeProvider } from "flow-castro";

function FlowEditor() {
  const [state, setState] = useState({
    nodes: {
      // Your initial node configuration
    },
  });

  return (
    <div style={{ height: "100vh", width: "100vw", display: "flex" }}>
      <ThemeProvider theme="light">
        <NodeContainer
          initialState={state}
          onChangeState={(newState) => setState(newState)}
          nodeTypes={nodeTypes}
          portTypes={portTypes}
          viewMode="select"
        />
      </ThemeProvider>
    </div>
  );
}

export default FlowEditor;

Defining Node Types

Node types define the behavior and structure of nodes in your flow. Each node type requires several properties:

  • type: Defines a unique identifier for your node type
  • label: Displays a user-friendly name in the UI
  • description: Provides additional information about the node's purpose
  • category: Groups similar nodes together in the context menu
  • inputs(): A function that returns an array of input definitions with properties:
    • name: Unique identifier for the input
    • type: The data type (must match a defined port type)
    • label: User-friendly name for the input
    • hidePort: Optional boolean to hide the input port visually
  • outputs(): A function that returns an array of output definitions with properties:
    • name: Unique identifier for the output
    • type: The data type (must match a defined port type)
    • label: User-friendly name for the output
  • resolveOutputs: An async function that processes input values and returns output values. The returned object's property names must match your output names.

Here's how to define them:

const nodeTypes = {
  string: {
    type: "string",
    label: "String",
    description: "String node",
    category: "Text",
    inputs() {
      return [
        {
          name: "string",
          type: "string",
          label: "String Input",
        },
      ];
    },
    outputs() {
      return [
        {
          name: "string",
          type: "string",
          label: "String Output",
        },
      ];
    },
    resolveOutputs: async (inputValues) => {
      // Process input values and return output values
      return {
        string: inputValues.string || "",
      };
    },
  },
  // Define more node types...
};

Defining Port Types

Port types define how ports look and behave:

const portTypes = {
  string: {
    type: "string",
    label: "String",
    shape: "circle",
    color: "#FFD700",
    render({ value, onChange }) {
      return (
        <input
          style={{ width: "100%" }}
          value={value || ""}
          onChange={(e) => onChange(e.target.value)}
        />
      );
    },
  },
  // Define more port types...
};

Theming

Flow-Castro supports light and dark themes. You can specify the theme using the theme prop:

<ThemeProvider theme="dark">
  <NodeContainer {...props} />
</ThemeProvider>

Initial State

Define an initial state for your flow:

const initialState = {
  nodes: {
    node1: {
      id: "node1",
      name: "String",
      type: "string",
      position: { x: 100, y: 100 },
      values: {},
      size: { width: 450, height: 140 },
      connections: {
        outputs: [],
        inputs: [],
      },
    },
    // More nodes...
  },
};

Full Example

Here's a complete example of a component using Flow-Castro:

import React, { useState } from "react";
import { NodeContainer, ThemeProvider } from "flow-castro";

const nodeTypes = {
  string: {
    type: "string",
    label: "String",
    description: "String node",
    category: "Text",
    inputs() {
      return [
        {
          name: "string",
          type: "string",
          label: "String Input",
        },
      ];
    },
    outputs() {
      return [
        {
          name: "string",
          type: "string",
          label: "String Output",
        },
      ];
    },
    resolveOutputs: async (inputValues) => {
      return {
        string: inputValues.string || "",
      };
    },
  },
};

const portTypes = {
  string: {
    type: "string",
    label: "String",
    shape: "circle",
    color: "#FFD700",
    render({ value, onChange }) {
      return (
        <input
          style={{ width: "100%" }}
          value={value || ""}
          onChange={(e) => onChange(e.target.value)}
        />
      );
    },
  },
};

// This can be a saved state, loaded from database, for example
const initialState = {
  nodes: {
    comment1: {
      id: "comment1",
      name: "Comment",
      type: "comment",
      position: { x: 30, y: 22 },
      values: {},
      size: { w: 320, h: 200 },
      title: "Hello!",
      value: "This is your first flow-castro canvas. Start adding nodes!",
    },
  },
};

function FlowEditor() {
  const [state, setState] = useState(initialState);

  return (
    <div style={{ height: "100vh", width: "100vw", display: "flex" }}>
      <ThemeProvider theme="light">
        <NodeContainer
          initialState={state}
          onChangeState={(newState) => {
            // Here is a good opportunity to save updated data
            setState(newState);
          }}
          nodeTypes={nodeTypes}
          portTypes={portTypes}
          viewMode="select"
          debugMode={false}
        />
      </ThemeProvider>
    </div>
  );
}

export default FlowEditor;

Features

Context Menu

The library includes a context menu that appears on right-click:

  • Add new nodes
  • Delete nodes
  • Add waypoints to connections
  • Delete connections

Event Handling

Track changes to your flow state:

<NodeContainer
  initialState={yourLoadedState}
  onChangeState={(newState) => {
    setState(newState);
    console.log("Flow state updated:", newState);
    // Perform any additional actions
  }}
  {...otherProps}
/>

Troubleshooting

  • If nodes aren't rendering properly, ensure the node types are correctly defined
  • For connection issues, check that port types match between source and target
  • For styling issues, verify the theme provider is correctly set up

For more examples, refer to the Storybook documentation or check the NodeContainer.stories.tsx file.