New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

@hotwirebits/flow

Package Overview
Dependencies
Maintainers
1
Versions
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@hotwirebits/flow

A React Flow recreation using Hotwire (Stimulus + Tailwind CSS). Build node-based editors with pure HTML.

latest
Source
npmnpm
Version
0.1.0
Version published
Maintainers
1
Created
Source

Hotwire Flow

A React Flow recreation using Hotwire (Stimulus + Tailwind CSS). Build node-based editors, workflow builders, DAGs, and org charts with pure HTML — no React required.

Like Lexxy reimagined rich text editing for Rails, Hotwire Flow reimagines node-based graph editors for any web stack.

Features

FeatureStatus
Drag & drop nodes
Pan & zoom (scroll, pinch, ctrl+scroll)
SVG edges (bezier, straight, step, smoothstep)
Animated edges
Edge labels (HTML via foreignObject)
Arrow markers
Connection handles (drag to connect)
Node types (input, output, default, group)
Multi-select (shift+click, drag-select box)
Minimap with viewport indicator
Toolbar (zoom in/out, fit view, reset)
Top toolbar bar (save, load, export)
Status bar (zoom, position, node/edge counts)
Background patterns (dots, grid, lines)
DnD sidebar palette
Context menu (right-click)
Keyboard shortcuts (Delete, Ctrl+A, Escape, Space+pan)
Save/Load to localStorage
Data API (addNode, removeNode, getIncomers, getOutgoers, toObject)
NodeResizer (8-handle resize)
NodeToolbar (floating toolbar)
Panel (positioned UI container)
Undo/Redo (Ctrl+Z, Ctrl+Y)
Copy/Paste (Ctrl+C, Ctrl+V)
Smooth viewport animations
fitViewOptions (padding, minZoom, maxZoom)
Auto Layout (vertical/horizontal)
defaultEdgeOptions

Quick Start

npm install @hotwired/stimulus

1. Include CSS

<link rel="stylesheet" href="hotwire-flow.css">

2. Import and register

import { Application } from "@hotwired/stimulus"
import { registerHotwireFlow } from "hotwire-flow"

const app = Application.start()
registerHotwireFlow(app)

3. Write your graph in HTML

<div data-controller="flow" class="hf-canvas" id="canvas">
  <div data-flow-target="pane" class="hf-pane">
    <svg style="position:absolute;top:0;left:0;width:100%;height:100%;overflow:visible;pointer-events:none;z-index:1">
      <path data-controller="flow-edge"
            data-flow-edge-id-value="e1"
            data-flow-edge-source-value="n1"
            data-flow-edge-source-handle-value="n1-r"
            data-flow-edge-target-value="n2"
            data-flow-edge-target-handle-value="n2-l"
            data-flow-edge-type-value="bezier"
            data-flow-edge-animated-value="true"
            data-flow-edge-marker-end-value="arrow"
            class="hf-edge" />
    </svg>
    <div data-flow-target="nodes" class="hf-nodes">
      <!-- Node 1 -->
      <div data-controller="flow-node"
           data-flow-node-id-value="n1"
           data-flow-node-x-value="100" data-flow-node-y-value="200"
           class="hf-node hf-node--input"
           data-action="pointerdown->flow-node#pointerDown click->flow-node#click">
        <div class="hf-node__header">Input</div>
        <div class="hf-node__body">Data source</div>
        <div data-controller="flow-handle"
             data-flow-handle-id-value="n1-r"
             data-flow-handle-node-id-value="n1"
             data-flow-handle-position-value="right"
             class="hf-handle hf-handle--right"
             data-action="pointerdown->flow-handle#pointerDown"></div>
      </div>
      <!-- Node 2 -->
      <div data-controller="flow-node"
           data-flow-node-id-value="n2"
           data-flow-node-x-value="400" data-flow-node-y-value="200"
           class="hf-node hf-node--output"
           data-action="pointerdown->flow-node#pointerDown click->flow-node#click">
        <div data-controller="flow-handle"
             data-flow-handle-id-value="n2-l"
             data-flow-handle-node-id-value="n2"
             data-flow-handle-position-value="left"
             class="hf-handle hf-handle--left"
             data-action="pointerdown->flow-handle#pointerDown"></div>
        <div class="hf-node__header">Output</div>
        <div class="hf-node__body">Result</div>
      </div>
    </div>
  </div>
  <div data-flow-target="selectionBox" class="hf-selection-box"></div>
</div>

Examples

ExampleDescription
Full DemoComplete workflow editor with all UI components
DAG Pipeline6-node ETL data pipeline
InteractiveDark theme with DnD sidebar, categorized nodes
Save/LoadlocalStorage persistence
Custom NodesNote, Code, Image, Decision node types
Minimap DemoLarge graph with minimap navigation
MinimalSimplest 2-node setup
Org ChartB2B company hierarchy
WarehouseB2B warehouse operations flow
B2B OrderB2B order processing pipeline

Controllers

ControllerIdentifierPurpose
FlowControllerflowMain canvas — pan/zoom/selection/data API
NodeControllerflow-nodeNode drag/select/position
HandleControllerflow-handleConnection points
EdgeControllerflow-edgeSVG paths + labels + markers
ConnectionLineControllerflow-connection-lineLive drag connection
MinimapControllerflow-minimapGraph overview
ToolbarControllerflow-toolbarZoom controls
BackgroundControllerflow-backgroundDots/grid/lines
ToolbarBarControllerflow-toolbar-barTop bar (save/export)
StatusBarControllerflow-status-barBottom bar (position/counts)
DndNodeControllerflow-dnd-nodeDrag source
DropzoneControllerflow-dropzoneDrop target
ContextMenuControllerflow-context-menuRight-click menu
NodeResizerControllerflow-node-resizer8-handle resize
NodeToolbarControllerflow-node-toolbarFloating node toolbar
PanelControllerflow-panelPositioned panel
LayoutControllerflow-layoutAuto-layout (vertical/horizontal)
ClassPurpose
hf-canvasCanvas container
hf-paneTransform pane
hf-nodeNode base
hf-node--inputInput node (green)
hf-node--defaultDefault node (blue)
hf-node--outputOutput node (red)
hf-node__headerNode header
hf-node__bodyNode body
hf-handleHandle base
hf-handle--top/right/bottom/leftHandle position
hf-edgeEdge SVG path
hf-edge.animatedAnimated edge
hf-selection-boxDrag-select box
hf-controlsZoom controls
hf-toolbar-barTop toolbar
hf-status-barBottom status
hf-sidebarNode palette
hf-minimapMinimap
hf-context-menuRight-click menu
hf-panelPositioned panel

API

const flow = app.getControllerForElementAndIdentifier(canvas, "flow")

// Viewport
flow.zoomIn()
flow.zoomOut()
flow.fitView()
flow.setViewport({ x: 0, y: 0, zoom: 1 })
flow.panBy(100, 50)
flow.setCenter(400, 300, 2)

// Coordinates
const pos = flow.screenToFlow(mouseX, mouseY)
const screen = flow.flowToScreen(flowX, flowY)

// Selection
flow.selectNode("node-1")
flow.clearSelection()

// Data
flow.getNodes()           // [{id, type, position, data}, ...]
flow.getNode("node-1")    // {id, type, position, data}
flow.getIncomers("n2")    // nodes with edges pointing to n2
flow.getOutgoers("n1")    // nodes with edges from n1
flow.toObject()           // {nodes, edges, viewport}
flow.fromObject(state)    // restore state

// Node management
flow.addNode({ id: "n3", type: "default", position: {x:100, y:100} })
flow.removeNode("n1")
flow.addEdge({ id: "e2", source: "n1", target: "n3" })
flow.removeEdge("e1")

Events

All events dispatched on the canvas element with hotwire-flow: prefix:

EventDetail
ready{ viewport }
viewportchange{ viewport }
nodemove{ nodeId, x, y }
nodeselect{ nodeId }
nodedragend{ nodeId }
nodedelete{ nodeId }
connect{ sourceNode, sourceHandle, targetNode, targetHandle }
edgeclick{ edgeId }
edgedelete{ edgeId }
paneclick{ position }
contextmenu{ x, y, nodeId, flowPosition }

Development

npm install
npm run build          # Build CSS
npm test               # Unit + integration tests
npm run test:e2e       # Playwright E2E tests
npm run serve          # Dev server on :3000

License

MIT

Keywords

hotwire

FAQs

Package last updated on 03 Apr 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts