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

@knotx/react

v0.5.10

Published

React for Knotx

Downloads

480

Readme

@knotx/react

npm version license

🚀 一个强大的 React 节点编辑器组件,支持可视化流程图、组织架构图、脑图等多种场景

📦 安装

npm install @knotx/react
yarn add @knotx/react
pnpm add @knotx/react

对等依赖

该包需要以下对等依赖:

{
  "react": ">=17.0.0",
  "react-dom": ">=17.0.0"
}

🎯 基本概述

@knotx/react 是 Knotx 生态系统中的 React 适配器,提供了一个功能强大且灵活的节点编辑器组件。它支持:

  • 🎨 可视化节点编辑 - 拖拽、缩放、连接节点
  • 🔧 插件系统 - 高度可扩展的插件架构
  • 🎭 自定义渲染 - 完全自定义的节点和边的渲染
  • 📱 响应式设计 - 适配不同屏幕尺寸
  • 高性能 - 基于 RxJS 的响应式状态管理
  • 🎪 丰富交互 - 支持选择、拖拽、缩放、小地图等

🚀 快速开始

基础用法

import type { Edge, Node } from '@knotx/core'

import { Knotx } from '@knotx/react'
import React from 'react'

function App() {
  const initialNodes: Node[] = [
    {
      id: '1',
      type: 'basic',
      position: { x: 300, y: 300 },
      measured: { width: 160, height: 60 },
      data: { label: '节点 1' }
    },
    {
      id: '2',
      type: 'basic',
      position: { x: 600, y: 300 },
      measured: { width: 160, height: 60 },
      data: { label: '节点 2' }
    }
  ]

  const initialEdges: Edge[] = [
    {
      id: '1-2',
      type: 'bezier',
      source: '1',
      target: '2',
      data: {}
    }
  ]

  return (
    <div style={{ width: '100vw', height: '100vh' }}>
      <Knotx
        initialNodes={initialNodes}
        initialEdges={initialEdges}
        plugins={[]} // 插件列表
      />
    </div>
  )
}

export default App

自定义节点渲染

import type { Node } from '@knotx/core'

import { BasePlugin } from '@knotx/core'
import { nodeType } from '@knotx/decorators'
import { Knotx } from '@knotx/react'
import React from 'react'

// 创建自定义节点插件
class CustomNodePlugin extends BasePlugin<'customNode'> {
  name = 'customNode' as const

  @nodeType('custom')
  renderCustomNode({ node }: { node: Node }) {
    return (
      <div
        style={{
          width: '100%',
          height: '100%',
          background: '#f0f0f0',
          border: '2px solid #ccc',
          borderRadius: '8px',
          padding: '12px',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          fontSize: '14px',
          fontWeight: 'bold'
        }}
      >
        {node.data?.label || node.id}
      </div>
    )
  }
}

function App() {
  const nodes: Node[] = [
    {
      id: '1',
      type: 'custom',
      position: { x: 300, y: 300 },
      measured: { width: 200, height: 80 },
      data: { label: '自定义节点' }
    }
  ]

  return (
    <div style={{ width: '100vw', height: '100vh' }}>
      <Knotx
        initialNodes={nodes}
        plugins={[CustomNodePlugin]}
      />
    </div>
  )
}

受控组件模式

import type { Edge, Node, ReactEngine } from '@knotx/react'

import { Knotx } from '@knotx/react'
import React, { useState } from 'react'

function App() {
  const [nodes, setNodes] = useState<Node[]>([
    {
      id: '1',
      type: 'basic',
      position: { x: 300, y: 300 },
      measured: { width: 160, height: 60 },
      data: { label: '节点 1' }
    }
  ])

  const [edges, setEdges] = useState<Edge[]>([])

  const handleInit = (engine: ReactEngine) => {
    console.log('引擎初始化完成:', engine)

    // 监听节点变化
    engine.nodesManager.dataMap$.subscribe((nodesMap) => {
      setNodes(Array.from(nodesMap.values()))
    })

    // 监听边变化
    engine.edgesManager.dataMap$.subscribe((edgesMap) => {
      setEdges(Array.from(edgesMap.values()))
    })
  }

  return (
    <div style={{ width: '100vw', height: '100vh' }}>
      <Knotx
        nodes={nodes}
        edges={edges}
        onInit={handleInit}
        plugins={[]}
      />
    </div>
  )
}

🔧 API 参考

Knotx 组件

Knotx 是主要的 React 组件,用于渲染节点编辑器。

Props

| 属性 | 类型 | 默认值 | 描述 | |------|------|--------|------| | className | string | - | 容器的 CSS 类名 | | style | CSSProperties | - | 容器的内联样式 | | getContainerStyle | (engine: ReactEngine) => CSSProperties | - | 获取容器样式的函数 | | initialNodes | Node[] | [] | 初始节点数据 | | initialEdges | Edge[] | [] | 初始边数据 | | nodes | Node[] | - | 受控的节点数据 | | edges | Edge[] | - | 受控的边数据 | | plugins | Plugin[] | [] | 插件列表 | | pluginConfig | PluginConfig | {} | 插件配置 | | disablePresetPlugins | boolean | false | 禁用预设插件 | | onInit | (engine: ReactEngine) => void | - | 引擎初始化回调 | | direction | 'horizontal' \| 'vertical' | 'horizontal' | 布局方向 | | ref | Ref<KnotxInstance> | - | 组件引用 |

示例

import type { KnotxInstance, ReactEngine } from '@knotx/react'

import { Knotx } from '@knotx/react'
import React, { useRef } from 'react'

function App() {
  const knotxRef = useRef<KnotxInstance>(null)

  const handleInit = (engine: ReactEngine) => {
    console.log('引擎初始化完成')
  }

  const handleRerender = () => {
    knotxRef.current?.rerender()
  }

  return (
    <div>
      <button onClick={handleRerender}>重新渲染</button>
      <Knotx
        ref={knotxRef}
        className="my-knotx"
        style={{ border: '1px solid #ccc' }}
        initialNodes={[]}
        initialEdges={[]}
        plugins={[]}
        direction="horizontal"
        onInit={handleInit}
        getContainerStyle={engine => ({
          backgroundColor: '#f5f5f5'
        })}
      />
    </div>
  )
}

KnotxInstance 接口

通过 ref 获取的组件实例接口。

属性

| 属性 | 类型 | 描述 | |------|------|------| | engineRef | MutableRefObject<ReactEngine \| null> | 引擎实例引用 | | rerender | () => void | 强制重新渲染组件 |

示例

import type { KnotxInstance } from '@knotx/react'

import { Knotx } from '@knotx/react'
import React, { useEffect, useRef } from 'react'

function App() {
  const knotxRef = useRef<KnotxInstance>(null)

  useEffect(() => {
    if (knotxRef.current) {
      const engine = knotxRef.current.engineRef.current
      if (engine) {
        // 使用引擎 API
        console.log('当前节点数量:', engine.nodesManager.dataMap$.value.size)
      }
    }
  }, [])

  return (
    <Knotx
      ref={knotxRef}
      initialNodes={[]}
      initialEdges={[]}
      plugins={[]}
    />
  )
}

ReactEngine 类型

扩展自 @knotx/coreEngine 类型,专门用于 React 环境。

主要方法

| 方法 | 描述 | |------|------| | dispatchNodeOperation(operation: NodeOperation) | 分发节点操作 | | dispatchEdgeOperation(operation: EdgeOperation) | 分发边操作 | | getLayerComponents(layer: number) | 获取层级组件 | | destroy() | 销毁引擎实例 |

插件配置

插件配置类型

interface PluginConfig {
  [pluginName: string]: any
}

示例

import { Canvas } from '@knotx/plugins-canvas'
import { Drag } from '@knotx/plugins-drag'
import { Knotx } from '@knotx/react'
import React from 'react'

function App() {
  const pluginConfig = {
    canvas: {
      minScale: 0.1,
      maxScale: 2.0,
      wheel: {
        step: 0.1,
        wheelDisabled: false
      }
    },
    drag: {
      allowDrag: true,
      dragThreshold: 5
    }
  }

  return (
    <Knotx
      initialNodes={[]}
      initialEdges={[]}
      plugins={[Canvas, Drag]}
      pluginConfig={pluginConfig}
    />
  )
}

🧩 插件系统

常用插件

以下是一些常用的插件:

  • @knotx/plugins-canvas - 画布功能(缩放、平移)
  • @knotx/plugins-drag - 拖拽功能
  • @knotx/plugins-selection - 选择功能
  • @knotx/plugins-minimap - 小地图
  • @knotx/plugins-background - 背景
  • @knotx/plugins-bounding - 边界调整
  • @knotx/plugins-connection-line - 连接线
  • @knotx/plugins-group - 分组
  • @knotx/plugins-history - 历史记录

创建自定义插件

import type { EdgeProps, Node } from '@knotx/core'

import { BasePlugin } from '@knotx/core'
import { edgeType, nodeType } from '@knotx/decorators'

class MyPlugin extends BasePlugin<'myPlugin'> {
  name = 'myPlugin' as const

  @nodeType('myNode')
  renderMyNode({ node }: { node: Node }) {
    return (
      <div style={{ padding: '10px', border: '1px solid #ccc' }}>
        自定义节点:
        {' '}
        {node.id}
      </div>
    )
  }

  @edgeType('myEdge')
  renderMyEdge(props: EdgeProps) {
    return (
      <path
        d={props.path}
        stroke="#ff0000"
        strokeWidth={2}
        fill="none"
      />
    )
  }
}

// 使用插件
function App() {
  return (
    <Knotx
      initialNodes={[
        {
          id: '1',
          type: 'myNode',
          position: { x: 100, y: 100 },
          measured: { width: 120, height: 60 },
          data: {}
        }
      ]}
      initialEdges={[]}
      plugins={[MyPlugin]}
    />
  )
}

📂 文件目录结构

packages/react/
├── src/
│   ├── components/           # React 组件
│   │   ├── content.tsx      # 层级内容组件
│   │   └── index.ts         # 组件导出
│   ├── hooks/               # React Hooks
│   │   ├── container.ts     # 容器引用 Hook
│   │   ├── data.ts          # 数据更新 Hook
│   │   ├── engine.ts        # 引擎管理 Hook
│   │   ├── plugin.ts        # 插件管理 Hook
│   │   └── index.ts         # Hooks 导出
│   ├── definition.ts        # 类型定义
│   ├── engine.ts            # React 引擎初始化
│   ├── index.ts             # 主入口文件
│   ├── knotx.tsx            # 主要 Knotx 组件
│   └── layer.tsx            # 层级渲染组件
├── dist/                    # 构建输出目录
├── CHANGELOG.md             # 变更日志
├── package.json             # 包配置
├── README.md                # 中文文档
├── README.en.md             # 英文文档
└── tsconfig.json            # TypeScript 配置

核心文件说明

| 文件 | 描述 | |------|------| | knotx.tsx | 主要的 Knotx React 组件实现 | | definition.ts | TypeScript 类型定义和接口 | | engine.ts | React 引擎初始化和运行时配置 | | layer.tsx | 层级渲染逻辑 | | components/content.tsx | 层级内容渲染组件 | | hooks/container.ts | 容器大小监听 Hook | | hooks/data.ts | 数据差异更新 Hook | | hooks/engine.ts | 引擎生命周期管理 Hook | | hooks/plugin.ts | 插件合并和配置更新 Hook |

🔗 类型导出

该包重新导出了所有来自 @knotx/core 的类型,方便使用:

import type {
  // 其他
  Direction,
  Edge,
  EdgeOperation,
  EdgeProps,

  Engine,
  EngineOptions,

  IData,
  IPlugin,

  KnotxInstance,
  KnotxProps,

  Layer,
  // 核心类型
  Node,

  // 操作类型
  NodeOperation,
  NodePosition,
  // 属性类型
  NodeProps,
  Plugin,

  // 配置类型
  PluginConfigs,
  // 位置类型
  Position,
  // React 特定类型
  ReactEngine
} from '@knotx/react'

🎨 最佳实践

1. 性能优化

import { Knotx } from '@knotx/react'
import React, { memo, useMemo } from 'react'

const MyKnotx = memo(({ data }: { data: any }) => {
  // 使用 useMemo 缓存节点和边数据
  const nodes = useMemo(() => {
    return data.nodes || []
  }, [data.nodes])

  const edges = useMemo(() => {
    return data.edges || []
  }, [data.edges])

  return (
    <Knotx
      nodes={nodes}
      edges={edges}
      plugins={[]}
    />
  )
})

2. 错误处理

import { Knotx } from '@knotx/react'
import React, { ErrorBoundary } from 'react'

class KnotxErrorBoundary extends React.Component {
  constructor(props: any) {
    super(props)
    this.state = { hasError: false }
  }

  static getDerivedStateFromError(error: Error) {
    // 处理错误:记录错误并返回错误状态
    console.error('React Error Boundary:', error)
    return { hasError: true }
  }

  componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
    // 处理错误:记录错误信息
    console.error('Knotx Error:', error, errorInfo)

    // 可以在这里添加错误上报逻辑
    // 例如:this.reportError(error, errorInfo)
  }

  render() {
    if (this.state.hasError) {
      return <div>Something went wrong with Knotx.</div>
    }

    return this.props.children
  }
}

function App() {
  return (
    <KnotxErrorBoundary>
      <Knotx
        initialNodes={[]}
        initialEdges={[]}
        plugins={[]}
      />
    </KnotxErrorBoundary>
  )
}

3. 主题定制

import { BasePlugin } from '@knotx/core'
import { layer } from '@knotx/decorators'
import { Knotx } from '@knotx/react'
import React from 'react'

class ThemePlugin extends BasePlugin<'theme'> {
  name = 'theme' as const

  @layer(100)
  renderTheme() {
    return (
      <style>
        {`
          .knotx-container {
            --node-bg: #ffffff;
            --node-border: #e1e4e8;
            --edge-stroke: #586069;
            --selection-bg: rgba(0, 123, 255, 0.1);
            --selection-border: #007bff;
          }

          .dark-theme .knotx-container {
            --node-bg: #2d3748;
            --node-border: #4a5568;
            --edge-stroke: #a0aec0;
            --selection-bg: rgba(66, 153, 225, 0.1);
            --selection-border: #4299e1;
          }
        `}
      </style>
    )
  }
}

function App() {
  return (
    <div className="dark-theme">
      <Knotx
        initialNodes={[]}
        initialEdges={[]}
        plugins={[ThemePlugin]}
      />
    </div>
  )
}

📝 常见问题

Q: 如何处理大量节点的性能问题?

A: 可以使用虚拟化技术,只渲染可见区域的节点:

import { BasePlugin } from '@knotx/core'
import { Knotx } from '@knotx/react'
import React from 'react'

// 实现虚拟化插件
class VirtualizationPlugin extends BasePlugin<'virtualization'> {
  name = 'virtualization' as const

  // 实现虚拟化逻辑
  // ...
}

Q: 如何实现节点的自定义连接点?

A: 使用 @knotx/plugins-connection-line 插件:

import { ConnectionLine } from '@knotx/plugins-connection-line'

// 在节点中添加连接点
function CustomNode({ node }) {
  return (
    <div>
      <div
        className="connection-handle"
        data-handle-position="top"
      />
      节点内容
    </div>
  )
}

Q: 如何保存和恢复画布状态?

A: 通过引擎的数据管理器:

function saveState(engine: ReactEngine) {
  const state = {
    nodes: Array.from(engine.nodesManager.dataMap$.value.values()),
    edges: Array.from(engine.edgesManager.dataMap$.value.values()),
    viewport: engine.container
  }
  localStorage.setItem('knotx-state', JSON.stringify(state))
}

function loadState(engine: ReactEngine) {
  const state = JSON.parse(localStorage.getItem('knotx-state') || '{}')
  // 恢复状态逻辑
}

📄 许可证

MIT License - 详见 LICENSE 文件

🤝 贡献

欢迎提交 Pull Request 和 Issue!

🔗 相关链接