Files
jrx/README.md
2026-02-28 01:42:09 +00:00

3.1 KiB

@nym.sh/jrx

JSX factory for json-render. Write JSX, get Spec JSON.

Install

bun add @nym.sh/jrx @json-render/core

Setup

Configure your tsconfig.json to use @nym.sh/jrx as the JSX source:

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "@nym.sh/jrx"
  }
}

Or use a per-file pragma:

/** @jsxImportSource @nym.sh/jrx */

Usage

Define components

Create wrapper functions that map JSX tags to json-render component type names:

import { jsx } from "@nym.sh/jrx/jsx-runtime";
import type { JrxNode } from "@nym.sh/jrx";

export function Stack(props: Record<string, unknown>): JrxNode {
  return jsx("Stack", props);
}

export function Text(props: Record<string, unknown>): JrxNode {
  return jsx("Text", props);
}

export function Button(props: Record<string, unknown>): JrxNode {
  return jsx("Button", props);
}

Render JSX to Spec JSON

import { render } from "@nym.sh/jrx";
import { Stack, Text, Button } from "./components";

const spec = render(
  <Stack>
    <Text content="Hello from jrx!" />
    <Button label="Click me" />
  </Stack>
);

This produces:

{
  "root": "stack-1",
  "elements": {
    "text-1": {
      "type": "Text",
      "props": { "content": "Hello from jrx!" }
    },
    "button-1": {
      "type": "Button",
      "props": { "label": "Click me" }
    },
    "stack-1": {
      "type": "Stack",
      "props": {},
      "children": ["text-1", "button-1"]
    }
  }
}

State, events, visibility, and watchers

Pass json-render bindings as JSX props:

const spec = render(
  <Stack>
    <Text content={{ $state: "/count" }} />
    <Button
      label="Increment"
      on={{
        press: {
          action: "increment",
          params: { statePath: "/count" },
        },
      }}
    />
    <Text
      content="Hidden until toggled"
      visible={{ $state: "/showDetails", eq: true }}
    />
  </Stack>,
  {
    state: {
      count: 0,
      showDetails: false,
    },
  }
);

The render() function accepts an options object with state to include initial state in the Spec output.

Reserved props

These props are extracted from JSX and mapped to Spec fields rather than passed through as component props:

Prop Spec field Description
key element key Explicit element key (overrides auto-generation)
visible visible Visibility condition
on on Event bindings
repeat repeat Repeat configuration
watch watch State watchers
children children Child element references

Example

The example/ directory contains a Bun HTTP server that demonstrates jrx in action. It shows JSX source, live rendered UI (via @json-render/react), and JSON output side by side.

cd example
bun install
bun dev

This starts a dev server with HMR at http://localhost:3000.

Development

bun install       # install dependencies
bun run build     # build dist/
bun test          # run tests
bun run typecheck # type check

License

MIT