Skip to content

@xmachines/play-solid

API / @xmachines/play-solid

Solid renderer for XMachines Play architecture

SolidJS rendering layer that passively observes actor signals and renders UI components via @json-render/solid. SolidJS reactivity is used solely to trigger re-renders — TC39 Signals are the source of truth.

Part of the xmachines-js monorepo.

Installation

Terminal window
npm install @xmachines/play-solid

Peer dependencies — install alongside the package:

Terminal window
npm install solid-js xstate @xstate/store @json-render/solid @json-render/core @json-render/xstate

Quick Start

import { PlayUIProvider, PlayRenderer, defineRegistry } from "@xmachines/play-solid";
import { definePlayer } from "@xmachines/play-xstate";
import { defineCatalog } from "@json-render/core";
import { schema } from "@json-render/solid/schema";
// 1. Define a catalog (authCatalogDef is a plain object describing components/actions)
const catalog = defineCatalog(schema, authCatalogDef);
// 2. Build a component registry
const registryResult = defineRegistry(catalog, {
components: {
Home: () => <div>Welcome home!</div>,
Login: (ctx) => <div>Login {ctx.props.error && <span>{ctx.props.error}</span>}</div>,
},
actions: {
login: async (args) => actor.send({ type: "auth.login", username: args.username }),
logout: async () => actor.send({ type: "auth.logout" }),
},
});
// 3. Create and start an actor
const createPlayer = definePlayer({ machine: myMachine });
const actor = createPlayer();
actor.start();
// 4. Render
function App() {
return (
<PlayUIProvider actor={actor} registryResult={registryResult}>
<PlayRenderer />
</PlayUIProvider>
);
}

Usage

PlayUIProvider is the batteries-included entry point. It wraps ActorProvider and JSONUIProvider into a single composite provider. PlayRenderer is a zero-prop leaf component that reads view context and renders the current spec.

import { PlayUIProvider, PlayRenderer, defineRegistry } from "@xmachines/play-solid";
<PlayUIProvider
actor={actor}
registryResult={registryResult}
fallback={<div>Loading…</div>}
onError={(err) => console.error(err)}
navigate={navigateFn} // optional: passed to JSONUIProvider
validationFunctions={valFns} // optional: form validation helpers
>
<PlayRenderer />
</PlayUIProvider>;

ActorProvider (escape hatch)

For library authors who need direct control over provider composition:

import { ActorProvider, PlayRenderer } from "@xmachines/play-solid";
<ActorProvider actor={actor} registryResult={registryResult}>
<PlayRenderer />
</ActorProvider>;

useActor hook

Access the raw actor instance anywhere inside an ActorProvider or PlayUIProvider tree:

import { useActor } from "@xmachines/play-solid";
function SubmitButton() {
const actor = useActor();
return <button onClick={() => actor.send({ type: "SUBMIT" })}>Submit</button>;
}

usePlayView hook

Access the resolved view context (spec, handlers, registry, store) from within the provider tree:

import { usePlayView } from "@xmachines/play-solid";
import { Renderer } from "@json-render/solid";
const MyRenderer = () => {
const view = usePlayView();
return <Renderer spec={view.spec} registry={view.registry} />;
};

API Summary

Components

ExportDescription
PlayUIProviderBatteries-included composite provider (recommended entry point)
PlayRendererZero-prop leaf component; renders the current view spec inside a provider tree
ActorProviderLower-level smart provider for escape-hatch composition

Hooks

ExportDescription
useActor()Returns the raw AnyPlayActor instance from context; throws outside a provider tree
usePlayView()Returns the current ViewContextValue (spec, handlers, registry, store); throws outside tree

Context

ExportDescription
ActorContextSolidJS context for the actor; use ActorContext.Provider directly as an escape hatch

Re-exports from @json-render/solid

This package re-exports the full @json-render/solid public API so consumers do not need a direct dependency:

import {
// Providers
JSONUIProvider,
StateProvider,
ActionProvider,
VisibilityProvider,
ValidationProvider,
// Renderer
Renderer,
// Registry factory + hooks
defineRegistry,
useBoundProp,
useStateBinding,
useStateValue,
useStateStore,
useActions,
useAction,
useIsVisible,
useFieldValidation,
useOptionalValidation,
useVisibility,
} from "@xmachines/play-solid";

Key Types

TypeDescription
PlayUIProviderPropsProps for PlayUIProvider
ActorProviderPropsProps for ActorProvider
ViewContextValueShape of the context value from usePlayView()
AnyPlayActorAbstractActor<AnyActorLogic> — bare actor type accepted by context providers

Testing

Run tests for this package in isolation:

Terminal window
npm test -w packages/play-solid

Or from within the package directory:

Terminal window
npm test # single run (jsdom environment)
npm run test:watch # watch mode
npm run test:ui # interactive Vitest UI

Coverage is collected with v8 (80% threshold for lines, functions, branches, and statements). Browser-specific tests live in test/browser/ and are excluded from the default jsdom run.

License

MIT

@xmachines/play-solid - SolidJS renderer for XMachines Play architecture

Provides a SolidJS rendering layer that passively observes actor signals and renders UI components via @json-render/solid. SolidJS reactivity is only used to trigger re-renders — signals are the source of truth.

Primary entry point:

import { PlayUIProvider, PlayRenderer, defineRegistry } from "@xmachines/play-solid";

For escape-hatch provider composition:

import { ActorProvider, ActorContext, usePlayView } from "@xmachines/play-solid";

Interfaces

Type Aliases

Variables

Functions

References

RenderErrorHandler

Re-exports RenderErrorHandler