npm package: @pixell/agent-ui
Description: Reactive, JSON-spec driven UI renderer for agent-style applications. Provide a UI Spec object and this package renders a complete interactive UI using React 18 with a rich set of components.
Latest version: 0.1.2

# @pixell/agent-ui

Reactive, JSON-spec driven UI renderer for agent-style applications. Provide a UI Spec object and this package renders a complete interactive UI using React 18 with a rich set of components.

## Install

```bash
npm install @pixell/agent-ui
# peer deps
npm install react react-dom
```

## Quick start

```ts
import { renderUISpec, type UISpecEnvelope } from '@pixell/agent-ui'

const spec: UISpecEnvelope = {
  manifest: { id: 'demo', name: 'Demo App', version: '0.1.0' },
  data: { user: { name: 'Alex' }, items: [{ id: 1, name: 'Alpha' }] },
  actions: {
    openDocs: { kind: 'open_url', url: 'https://example.com/docs' }
  },
  view: {
    type: 'page',
    props: { title: 'Welcome, {{ user.name }}' },
    children: [
      { type: 'text', props: { content: 'Here is your list:' } },
      { type: 'list', props: { data: '@items', item: { type: 'text', props: { content: '{{ name }}' } } } },
      { type: 'button', props: { label: 'Docs', onPress: { action: 'openDocs' } } }
    ]
  }
}

const container = document.getElementById('root')!
const { unmount } = renderUISpec(container, spec, {
  onOpenUrl: url => window.open(url, '_blank')
})
```

## Core API

- **renderUISpec(container, spec, options?) → { unmount() }**: Renders a `UISpecEnvelope` into a DOM container.
- **applyPatch(spec, ops) → spec**: Apply whitelisted JSON patch operations to `/data` and `/view`.

### Types

- **UISpecEnvelope**: `{ manifest, data?, actions?, view, theme? }`
- **UISpecNode**: `{ type: string, props?, children? }`
- **RenderOptions**:
  - `onOpenUrl?: (url) => void`
  - `onHttp?: (req) => Promise<{ status, body?, headers? }>`
  - `intentClient?: { invokeIntent(event, payload?): Promise<{ ok, data?, error? }> }`
  - `capabilitySet?: { components: string[]; features?: string[] }`

## Data binding

- Strings support `{{ key.path }}` template interpolation from current item scope, then from `spec.data`.
- Any string starting with `@` is treated as a direct binding to `spec.data` path (e.g., `"@items"`).
- Objects/arrays are resolved recursively.

## Events and actions

- Use `onPress: { action: 'name' }`, `onSubmit`, `onChange`, `onOpenChange` in component props.
- Actions are defined in `spec.actions`:
  - `open_url`: delegates to `options.onOpenUrl(url)`.
  - `http`: delegates to `options.onHttp({ method, url, body, headers })`. Extended methods (PUT/PATCH/DELETE) require `capabilitySet.features` to include `"http.extended"`.
  - `state.set`: local UI state sync (handled internally).
  - `emit`: calls `options.intentClient.invokeIntent(event, payload)` if provided.

## Theming

Provide `spec.theme.tokens` as a map of CSS custom properties. They are applied to the document root, e.g. `{ "color-primary": "#4f46e5" }` becomes `--color-primary: #4f46e5`.

## Available components

The default registry includes the following `type` values:

- Layout/Page: `page`, `container`, `form`, `formField`
- Text & Links: `text`, `link`
- Inputs: `textInput`, `textarea`, `select`, `checkbox`, `radioGroup`, `switch`, `numberInput`
- Buttons & Actions: `button`
- Lists & Tables: `list`, `table`
- Overlays: `modal`, `drawer`, `popover`
- Navigation: `tabs`, `accordion`, `breadcrumb`, `pagination`
- Feedback: `spinner`, `skeleton`, `progress`, `alert`, `toast`, `emptyState`
- Data Display: `card`, `badge`, `chip`, `avatar`, `tooltip`, `image`, `icon`
- Fallback: `unknown`

Notes:
- `list`: expects `props.data` (binding or array). Optional `props.item` is a nested `UISpecNode` used to render each row. When `capabilitySet.components` excludes `table`, a `table` node is auto-downgraded to a `list`.
- Some components accept embedded nodes: `tabs.items[].content`, `card.header`, `card.footer`, `popover.trigger`, `popover.content` can be nested `UISpecNode` objects.

## Capability sets

Pass `options.capabilitySet` to control availability:

- `components`: restrict which component types can render.
- `features`: feature toggles, e.g., `http.extended` to allow PUT/PATCH/DELETE.

## Building locally

```bash
cd packages/agent-ui
npm run clean && npm run build
```

## Publishing to npm

Prereqs:

- Ensure the package name is available and scoped (`@pixell/agent-ui`).
- You must be logged in to npm and have publish rights for the scope.

Steps:

```bash
cd packages/agent-ui
# 1) bump version in package.json
npm version patch   # or minor/major

# 2) build artifacts
npm run clean && npm run build

# 3) publish (scoped package, public access configured)
npm publish --access public
```

If you see 403 errors, confirm:

- You are authenticated: `npm whoami`
- Scope permissions are correct: `npm access ls-collaborators @pixell/agent-ui`

## Example

See `examples/simple/index.html` in this repo for a minimal usage example embedding a script bundle.

## License

MIT