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

@shiguri/cavalry-jsx

v0.1.3

Published

JSX runtime and small helpers for building Cavalry script UIs.

Readme

cavalry-jsx

JSX runtime and small helpers for building Cavalry script UIs.

Cavalry Scripts

Cavalry script UIs are JavaScript files run by Cavalry. They use Cavalry's global ui module to create widgets, add them to a window, and call ui.show().

Official Cavalry documentation:

This package only provides a JSX layer over that scripting API. It does not add a renderer, lifecycle, or reactive update model.

Install Package

Install this package and Cavalry's TypeScript definitions:

pnpm add @shiguri/cavalry-jsx
pnpm add -D @scenery/cavalry-types

Configure JSX

JSX must be compiled with the automatic JSX runtime and @shiguri/cavalry-jsx as the import source. Prefer configuring this once in tsconfig.json:

{
  "compilerOptions": {
    "types": ["@scenery/cavalry-types"],
    "jsx": "react-jsx",
    "jsxImportSource": "@shiguri/cavalry-jsx"
  }
}

If your bundler performs the JSX transform without reading that TypeScript setting, configure the same runtime there instead. For example:

// rolldown.config.ts
import { defineConfig } from "rolldown";

export default defineConfig({
  transform: {
    jsx: {
      runtime: "automatic",
      importSource: "@shiguri/cavalry-jsx",
    },
  },
});

With automatic JSX runtime, the compiler imports @shiguri/cavalry-jsx/jsx-runtime. Development JSX mode may import @shiguri/cavalry-jsx/jsx-dev-runtime. Those are compiler entry points; user code should normally import from @shiguri/cavalry-jsx.

Write Scripts

A JSX expression creates Cavalry widgets immediately. A script file must execute the UI once at top level. The Window element configures Cavalry's script window, adds its children, and calls ui.show().

import { Button, HLayout, Label, Window } from "@shiguri/cavalry-jsx";

function CounterPanel() {
  return (
    <Window title="Counter" fixedSize={[280, 120]} margins={[12, 12, 12, 12]}>
      <HLayout spaceBetween={8}>
        <Label text="Count: 0" />
        <Button text="Reset" onClick={() => {}} />
      </HLayout>
    </Window>
  );
}

CounterPanel();

The function is just a way to organize the script. It is not a component instance with state or lifecycle. Calling it runs the JSX and creates the UI; calling it again creates another UI.

Props

Props configure widgets at creation time. They are not reactive.

Use initial-value props for creation-time value:

<LineEdit defaultText="Untitled" />
<NumericField defaultValue={10} />
<ColorChip defaultColor="#4ffd7a" />
<FilePath defaultFilePath="/tmp/output.txt" />
<ProgressBar maximum={10} defaultValue={0} />

Value callbacks receive the current widget value as an argument.

<LineEdit onValueChanged={(text) => console.log(text)} />
<NumericField onValueChanged={(value) => console.log(value)} />
<Checkbox onValueChanged={(checked) => console.log(checked)} />
<DropDown entries={["One", "Two"]} onValueChanged={(index, text) => console.log(index, text)} />
<ColorWheel onColorChanged={(color) => console.log(color)} />

Refs

Use refs when script code needs to read or update a widget after it has been created. In practice, this is most common for input widgets.

Value refs are helpers for common input widgets. They attach to a widget and expose value() and set(value) so callers do not need to remember the widget-specific getter and setter names.

import { Button, LineEdit, textRef, Window } from "@shiguri/cavalry-jsx";

const message = textRef();

function Panel() {
  return (
    <Window title="Input Ref">
      <LineEdit ref={message.attach} defaultText="" />
      <Button
        text="Log"
        onClick={() => {
          console.log(message.value());
          message.set("");
        }}
      />
    </Window>
  );
}

Panel();

Use widgetRef<T>() when you need the widget object itself rather than a value helper.

import { Button, List, widgetRef, Window } from "@shiguri/cavalry-jsx";

const list = widgetRef<ui.List>();

function Panel() {
  return (
    <Window title="Widget Ref">
      <List ref={list.attach} model={[]} />
      <Button
        text="Add Row"
        onClick={() => {
          list()?.addRow({ uuid: String(Date.now()), label: "New Row" });
        }}
      />
    </Window>
  );
}

Panel();

Build Script

Cavalry runs JavaScript, so TypeScript/JSX must be compiled before installation. Any bundler that can emit a JavaScript file for Cavalry can be used.

One Rolldown setup is:

// rolldown.config.ts
import { defineConfig } from "rolldown";

export default defineConfig({
  input: "src/panel.tsx",
  output: {
    file: "dist/panel.js",
    format: "esm",
  },
  platform: "neutral",
  treeshake: {
    moduleSideEffects: true,
  },
});

This example relies on the JSX runtime setting from tsconfig.json. If your bundler does not read it, set the JSX runtime in the bundler config as shown above.

Build the script, then put the generated .js file in Cavalry's Scripts folder. In Cavalry, use Scripts > Show Scripts Folder to open that location. Installed scripts appear in Scripts.

The installed file should be a JavaScript file Cavalry can run directly. Do not leave unresolved package imports in the generated script unless your Cavalry script environment can resolve them.

Examples

The examples/ workspace contains small Cavalry UI scripts built with this package.

Included scripts:

  • demo-hello-panel: minimal panel with basic widgets and refs.
  • layer-batch-renamer: rename selected layers with preview.
  • time-marker-generator: create timeline markers from a frame range.

Build the examples:

cd examples
pnpm install
pnpm build

The generated files are written to examples/dist/*.js. Copy them into Cavalry's Scripts folder (Scripts > Show Scripts Folder) to install them.