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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@theseus-cwl/ui-react-viewer

v2.0.3

Published

A React toolkit for displaying Common Workflow Language (CWL) workflows as interactive DAG graphs

Readme

@theseus-cwl/ui-react-viewer

A React toolkit for displaying CWL (Common Workflow Language) workflows as interactive DAG graphs.

UI

✨ Features

📊 Interactive workflow graphs

Any CWL file is rendered as interactive DAG graphs automatically (steps are topologically sorted by their data dependencies). Packed documents render the main workflow plus each subworkflow side by side. Optional extras: a minimap, edge labels, and dashed wrapper boxes grouping inputs, steps, and outputs, dynamic coloring widget and subworkflow scaling.

🔦 Hover & selection highlighting

Hovering or selecting a node emphasizes it and its connected edges while the rest of the graph is dimmed. Edges can be hovered too, revealing their label and highlighting both endpoints.

🔍 Node inspector

Clicking a node zooms to it and opens a side panel showing its CWL definition properties (can be turned off via the nodeInspector prop).

And more

  • 📂 Flexible input - accepts a parsed CWL object, a raw JSON/YAML string, or a File; single and multi-document sources are supported.
  • 🎨 Fully themeable - node fill colors via initialColorState, an optional built-in color editor panel, and every other visual (background, borders, edges, inspector) via --cwl-viewer-* CSS variables (see Styling).
  • 📦 Standalone - a single React component with React as the only peer dependency.

🚀 Installation

npm install @theseus-cwl/ui-react-viewer
# or
yarn add @theseus-cwl/ui-react-viewer

The component's stylesheet ships with the package. Bundlers that handle CSS imports (Vite, webpack, …) load it automatically when you import CwlViewer; otherwise import it explicitly:

import "@theseus-cwl/ui-react-viewer/style.css";

🛠 Example Usage

The CwlViewer component accepts CWL data in three forms:

  • JSON object (parsed CWL, as in the example below)

  • File

  • String (raw JSON or YAML string)

The viewer fills its parent element (width/height: 100%), so make sure to render it inside an explicitly sized container - an unsized parent results in an empty view.

import { CwlSource, Shape } from "@theseus-cwl/types";
import { CwlViewer } from "@theseus-cwl/ui-react-viewer";

const Example = () => {
  const source: CwlSource<Shape.Raw> = {
    entrypoint: "main",
    documents: [
      {
        name: "main",
        content: {
          cwlVersion: "v1.2",
          class: "Workflow",
          label: "Theseus CWL",
          inputs: {
            message: "string",
          },
          outputs: {
            output: {
              type: "File",
              outputSource: "echo_step/output",
            },
          },
          steps: {
            echo_step: {
              run: {
                class: "CommandLineTool",
                baseCommand: "echo",
                inputs: {
                  message: {
                    type: "string",
                    inputBinding: {
                      position: 1,
                    },
                  },
                },
                outputs: {
                  output: {
                    type: "File",
                    outputBinding: {
                      glob: "output.txt",
                    },
                  },
                },
                stdout: "output.txt",
              },
              in: {
                message: "message",
              },
              out: ["output"],
            },
          },
        },
      },
    ],
    parameters: [
      {
        name: "input.json",
        content: `{ "message": "Hello from Theseus CWL !" }`,
      },
    ],
  };

  return (
    <div style={{ height: "600px" }}>
      <CwlViewer input={source} minimap={true} wrappers={true} labels={true} />
    </div>
  );
};

🛠 API

| Prop | Type | Default | Description | | -------------------------- | ---------------------------------------------------------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | | input | CwlSource<Shape.Raw \| Shape.Sanitized> | undefined | CWL workflow source to visualize. Accepts parsed JSON/YAML objects representing a valid CWL workflow. | | onChange | (value: object) => void | console.log | Callback triggered when the workflow graph changes internally. | | wrappers | boolean | false | Enables wrapper nodes in the graph view. | | minimap | boolean | false | Displays a minimap of the workflow graph. | | labels | boolean | false | Shows labels on graph edges. | | colorEditor | boolean | false | Enables the color editor panel for node types. | | initialColorState | ColorState | undefined | Initial configuration for node colors. | | background | CwlViewerBackgroundProps | undefined | Configuration for the graph background. | | subWorkflowScalingFactor | number | 0.8 | Scaling factor applied when rendering subworkflows. | | highlights | boolean | true | Highlights the hovered/selected node and its connections while dimming the rest of the graph. | | nodeInspector | boolean | true | Opens the node inspector panel when a node is selected. |

🎨 Styling

The viewer ships its own stylesheet and owns its whole look - the graph pane, node cards, edges, the node inspector, and the color editor overlay.

The look can be customized through CSS variables, declared on the viewer's root .cwl-viewer element:

Viewer

| Variable | Default | Purpose | | -------------------------- | ------------------------------------- | --------------------------------------------------------- | | --cwl-viewer-bg | #fafafa | Viewer background | | --cwl-viewer-font-family | Verdana, Geneva, Tahoma, sans-serif | Base font of the viewer (inspector, color editor, labels) |

Node cards

| Variable | Default | Purpose | | -------------------------------------------- | ----------------------------------- | ---------------------------------------- | | --cwl-viewer-node-font-family | "Inter", sans-serif | Node card font | | --cwl-viewer-node-border-color | #181a1faf | Node card border | | --cwl-viewer-node-border-radius | 2px | Node card corner radius | | --cwl-viewer-node-shadow | 4px 4px 16px rgba(0, 0, 0, 0.171) | Node card shadow | | --cwl-viewer-node-title-text-color | #383a42 | Node card title | | --cwl-viewer-node-info-text-color | #696c77 | Node card info line | | --cwl-viewer-node-icon-color | #383a42 | Node card header icon | | --cwl-viewer-node-icon-bg | rgba(255, 255, 255, 0.356) | Node card header icon background | | --cwl-viewer-node-icon-border-radius | 2px | Node card header icon corner radius | | --cwl-viewer-node-icon-shadow | 0 4px 6px rgba(0, 0, 0, 0.2) | Node card header icon shadow | | --cwl-viewer-node-badge-bg | rgba(255, 255, 255, 0.356) | Node card badge background | | --cwl-viewer-node-badge-text-color | #383a42 | Node card badge text | | --cwl-viewer-node-badge-border-color | rgba(0, 0, 0, 0.062) | Node card badge border | | --cwl-viewer-node-badge-shadow | 0 4px 6px rgba(0, 0, 0, 0.2) | Node card badge shadow | | --cwl-viewer-node-file-badge-bg | input node fill color | File/Directory badge background | | --cwl-viewer-node-file-badge-icon-color | currentColor | File/Directory badge icon | | --cwl-viewer-node-file-badge-border-color | transparent | File/Directory badge border | | --cwl-viewer-node-placeholder-text-color | #383a42 | "+ New …" placeholder card text | | --cwl-viewer-node-placeholder-border-color | #696c77 | "+ New …" placeholder card dashed border | | --cwl-viewer-wrapper-border-color | #a0a1a7 | Dashed border of wrapper (group) nodes |

Edges

| Variable | Default | Purpose | | ------------------------------------ | ------------------------------ | ------------------------- | | --cwl-viewer-edge-color | #696c77 | Edge stroke and arrowhead | | --cwl-viewer-edge-label-bg | #eaeaeb | Edge label background | | --cwl-viewer-edge-label-text-color | #383a42 | Edge label text | | --cwl-viewer-edge-label-shadow | 0 1px 2px rgba(0, 0, 0, 0.5) | Edge label shadow |

Hover / selection highlighting

Active when the highlights prop is enabled (the default):

| Variable | Default | Purpose | | ----------------------------------- | --------- | ----------------------------------------------------------------------- | | --cwl-viewer-node-highlight-color | #4078f2 | Outline of the hovered/selected node; minimap tint of highlighted nodes | | --cwl-viewer-edge-highlight-color | #4078f2 | Stroke and arrowhead of highlighted edges (edges can be hovered too) | | --cwl-viewer-dimmed-opacity | 0.25 | Opacity of nodes/edges unrelated to the active node |

Minimap

Active when the minimap prop is enabled:

| Variable | Default | Purpose | | ---------------------------------------- | ----------------------------------- | ---------------------------------------------- | | --cwl-viewer-minimap-bg | #ffffff | Minimap panel background | | --cwl-viewer-minimap-mask-color | rgba(240, 240, 240, 0.6) | Overlay covering the area outside the viewport | | --cwl-viewer-minimap-mask-stroke-color | transparent | Outline of the viewport rectangle | | --cwl-viewer-minimap-border-color | rgba(0, 0, 0, 0.062) | Minimap panel border | | --cwl-viewer-minimap-border-radius | 2px | Minimap panel corner radius | | --cwl-viewer-minimap-shadow | 4px 4px 16px rgba(0, 0, 0, 0.171) | Minimap panel shadow |

Note: the node fill colors inside the minimap follow the graph's node colors (see the note below); highlighted nodes are tinted with --cwl-viewer-node-highlight-color.

Node inspector

| Variable | Default | Purpose | | ------------------------------- | -------------------------------- | -------------------------- | | --cwl-viewer-inspector-bg | #f0f0f1 | Inspector panel background | | --cwl-viewer-inspector-shadow | -3px 0 8px rgba(0, 0, 0, 0.08) | Inspector panel shadow |

Inspector forms

| Variable | Default | Purpose | | ---------------------------------------- | ---------------------------- | ------------------------------------ | | --cwl-viewer-form-header-text-color | #383a42 | Form header text | | --cwl-viewer-form-icon-color | #383a42 | Form header icon | | --cwl-viewer-form-icon-bg | rgba(255, 255, 255, 0.356) | Form header icon background | | --cwl-viewer-form-label-text-color | #696c77 | Form field labels | | --cwl-viewer-form-input-bg | #ffffff | Form input/textarea background | | --cwl-viewer-form-input-text-color | #000000 | Form input/textarea text | | --cwl-viewer-form-input-border-color | #dbdbdc | Form input/textarea borders | | --cwl-viewer-form-input-border-radius | 3px | Form input/textarea corner radius | | --cwl-viewer-form-input-line-height | normal | Form input/textarea line height | | --cwl-viewer-form-button-border-color | #383a42 | Form button borders |

Color editor

| Variable | Default | Purpose | | ----------------------------------------------------- | ------------- | --------------------------------- | | --cwl-viewer-color-editor-bg | transparent | Panel background | | --cwl-viewer-color-editor-border-color | transparent | Panel border | | --cwl-viewer-color-editor-input-border-color | transparent | Color picker input borders | | --cwl-viewer-color-editor-button-bg | #f0f0f1 | Button background | | --cwl-viewer-color-editor-button-text-color | #000000 | Button text | | --cwl-viewer-color-editor-button-border-color | transparent | Button borders | | --cwl-viewer-color-editor-primary-button-bg | #4078f2 | Primary (Apply) button background | | --cwl-viewer-color-editor-primary-button-text-color | white | Primary (Apply) button text |

Override them from your own CSS, on .cwl-viewer itself or any ancestor - for example a dark theme matching the default One Dark look of @theseus-cwl/ui-react-editor:

.my-app .cwl-viewer {
  --cwl-viewer-bg: #282c34;
  --cwl-viewer-node-title-text-color: #ffffff;
  --cwl-viewer-node-info-text-color: #abb2bf;
  --cwl-viewer-edge-color: #7d8799;
  --cwl-viewer-edge-label-bg: #21252b;
  --cwl-viewer-edge-label-text-color: #abb2bf;
  --cwl-viewer-minimap-bg: #21252b;
  --cwl-viewer-minimap-mask-color: rgba(40, 44, 52, 0.6);
  --cwl-viewer-inspector-bg: #21252b;
}

Note: the fill colors of input/step/output nodes are not CSS variables - they are controlled at runtime via the initialColorState prop, the colorEditor panel, or configureTheseusCwl (see below).

Global configuration

Layout and default-color constants - node size and spacing, animation timing, default node fill colors, subworkflow scaling - live in @theseus-cwl/configurations and can be overridden once at app startup, before the viewer first renders:

import { configureTheseusCwl } from "@theseus-cwl/configurations";

configureTheseusCwl({
  NODE_WIDTH: 180,
  NODE_HEIGHT: 90,
  INPUT_NODE_COLOR: "#98c379",
});

📦 Related packages

| Package | Purpose | | -------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | | @theseus-cwl/ui-react-editor | The editing half of the toolkit - a CodeMirror-based CWL source editor. | | @theseus-cwl/parser | Parses and normalizes raw CWL sources into typed, sanitized objects. | | @theseus-cwl/types | CWL v1.2 TypeScript type definitions and the CwlSource input model. | | @theseus-cwl/configurations | Shared runtime configuration (configureTheseusCwl). |

All packages are developed in the theseus-cwl monorepo.

📘 Learn More about CWL

📣 Contributing

We welcome contributions! If you’d like to improve Theseus or suggest new features, open an issue or a pull request on GitHub.

📄 License

MIT License © 2026 Davide Giorgiutti