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

@axiijs/axle

v0.5.10

Published

Reactive JSX runtime foundation for data-driven LeaferJS canvas editors.

Readme

Axle

Reactive JSX runtime foundation for data-driven LeaferJS canvas editors.

Axle 把 axii 的响应式 Host 树模型移植到 Leafer 场景图上:

  • React 风格的 JSX,但组件函数只执行一次,直接产出真实的 Leafer UI 节点,没有 Virtual DOM。
  • 通过识别 data0 的响应式数据结构(atom / RxList / function) 把更新精确绑定到节点属性、文本与结构上。
  • RxList 的 splice / reorder / set patch 被映射为场景图上最小数量的节点操作。

快速开始

npm install @axiijs/axle data0 leafer-ui

leafer-editor 只用于仓库内的编辑器 playground,不是 Axle 运行时依赖; 使用编辑器能力的应用按需自行安装。 Axle 当前将 data0 peer 限定在已验证的 2.4.x:运行时依赖其 effect/patch 协议,升级 minor 版本前必须先通过 test/data0-contract.test.ts

import { Leafer } from 'leafer-ui'
import { atom, RxList } from 'data0'
import { createRoot } from '@axiijs/axle'

function App() {
  const selected = atom<number | null>(null)
  const items = new RxList([1, 2, 3])

  return (
    <group>
      {items.map((value) => (
        <rect
          x={() => value * 30}
          width={20}
          height={20}
          fill={() => (selected() === value ? 'blue' : 'gray')}
          onTap={() => selected(value)}
        />
      ))}
      <text y={40}>selected: {selected}</text>
    </group>
  )
}

const leafer = new Leafer({ view: window })
createRoot(leafer).render(<App />)

TypeScript 配置(自动 JSX runtime):

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "@axiijs/axle",
  },
}

Classic JSX(与 axii / Vite jsxFactory: 'createElement' 同构)时, 使用 createElement,不要把 classic 变换产物直接喂给 jsxjsx 的第三参是 key):

/** @jsx createElement */
import { createElement, createRoot } from '@axiijs/axle'
{
  "compilerOptions": {
    "jsx": "react",
    "jsxFactory": "createElement",
    "jsxFragmentFactory": "Fragment",
  },
}

与 React 不同的运行时契约

Axle 使用 JSX 语法,但不是 React renderer:

  • 组件函数只执行一次;结构更新来自 function child 或 RxList patch,没有 re-render / keyed diff。
  • root.render() 每个 root 只能成功挂载一棵树;再次渲染前必须先 root.destroy()
  • useEffect 在子树 render 后同步执行,不等待 paint;初次挂载时执行顺序是 useEffect → root attach → useLayoutEffect / ref。
  • 事件绑定只建立一次,不会响应式 rebind。handler 应在事件发生时读取 atom,而不是依赖组件重执行。
  • layout effect 与 ref attach 执行时保证子树已经连通 root.container;清理回调与 ref detach 的异常会被隔离,不会中断整棵树销毁。
  • zIndex 的列表不能触发 reorder patch;叠放顺序由显式 zIndex 决定,列表只应做 splice。

完整契约见 doc/02-phase-1-design.md

错误与诊断

渲染错误可通过 root 统一处理;窗口化、空间索引、DotLayer、共享 ticker 等独立模块可直接复用 root.reportError

const root = createRoot(leafer, { listDiagnostics: import.meta.env.DEV })
root.on('error', (error) => reportToMonitoring(error))

const index = new SpatialIndex({
  cellSize: 512,
  onError: root.reportError,
})
const windowed = new RxWindowedList({
  index,
  resolve: (id) => models.get(id)!,
  viewRect,
  onError: root.reportError,
})

未注册 error listener、也未向独立模块传 onError 时,可恢复错误写入 console.errorsetListDiagnostics() 仍可设置全局开发期默认值;createRoot(..., { listDiagnostics }) 用于多 root 应用的实例级覆盖。

文档

Playground

仓库自带一个可交互的示例应用(响应式列表、选中高亮、拖拽、条件渲染、增量 reorder):

npm install
npm run playground   # 启动 vite,浏览器打开 playground

示例代码在 playground/main.tsx,直接引用 src/,改运行时代码即时生效。

另有两个进阶页面:

  • /canvas.htmlplayground/canvas.tsx)— 节点画布交互 POC (卡片拖拽、port 连线、视口缩放平移);
  • /stress.htmlplayground/stress.tsx)— 超大规模压测: 默认 1 万张图文/视频/文字卡片 + 按比例连线(URL 参数 ?n=50000 可到 5 万), 完整实施 doc/05-large-scale-performance.md 的视口虚拟化 / LOD / DotLayer 底衬 / 交互中降级 / 媒体门控,带 FPS、 帧时长 P95、场景图节点数等指标面板。

开发

npm install
npm run check        # typecheck + lint + test + build
npx vitest run --coverage