Skip to content

@xmachines/play-svelte

API / @xmachines/play-svelte

Svelte 5 renderer for the XMachines Play architecture. It connects an actor to a catalog-driven @xmachines/json-render-svelte UI, with Svelte 5 runes and TC39 Signals.

License: MIT Version

Installation

Terminal window
pnpm add @xmachines/play-svelte

Peer dependencies. Install them separately:

Terminal window
pnpm add svelte@^5.0.0 xstate@^5.31.0 @xstate/store@^3.17.0 \
@xmachines/json-render-core@^0.20.0-xm.2 @xmachines/json-render-svelte@^0.20.0-xm.2 @xmachines/json-render-xstate@^0.20.0-xm.2

Usage

Basic setup

Define the catalog and the registry one time. Then give both to PlayUIProvider, together with your actor. PlayRenderer then renders the current view of the actor:

App.svelte
<script lang="ts">
import { defineRegistry, PlayUIProvider, PlayRenderer } from "@xmachines/play-svelte";
import { authCatalog } from "./catalog.js";
import Login from "./components/Login.svelte";
import Dashboard from "./components/Dashboard.svelte";
let { actor } = $props();
const registryResult = defineRegistry(authCatalog, {
components: { Login, Dashboard },
actions: {
login: async (params) => {
actor.send({ type: "auth.login", username: params?.username });
},
logout: async () => actor.send({ type: "auth.logout" }),
},
});
</script>
<PlayUIProvider {actor} {registryResult}>
<PlayRenderer />
</PlayUIProvider>

Lower-level: ActorProvider

Use ActorProvider directly when you need more control over the rendering. For example, use it to add a custom layout, or to add each @xmachines/json-render-svelte provider one by one:

<script lang="ts">
import { ActorProvider } from "@xmachines/play-svelte";
let { actor, registryResult, children } = $props();
function handleError(error: unknown, reset: () => void) {
console.error(error);
}
</script>
{#snippet loadingSnippet()}
<div>Loading…</div>
{/snippet}
<ActorProvider {actor} {registryResult} fallback={loadingSnippet} onError={handleError}>
<!-- children rendered inside StateProvider tree -->
{@render children()}
</ActorProvider>

Accessing the actor from child components

import { getActorContext } from "@xmachines/play-svelte";
// Inside a Svelte component that is a descendant of ActorProvider:
const actor = getActorContext();
actor.send({ type: "some.event" });

API Summary

Components

ComponentDescription
<PlayUIProvider>Composite provider. It wraps ActorProvider and JsonUIProvider. Use it as the standard entry point for an actor-driven UI.
<ActorProvider>Primitive provider — owns actor lifecycle, signal subscription, per-view StateStore, and onRenderError injection.
<PlayRenderer>Zero-prop leaf component — reads getPlayViewContext() and renders <Renderer> from @xmachines/json-render-svelte.

Functions

FunctionDescription
defineRegistry(catalog, options)Creates a typed component registry. Wraps @xmachines/json-render-svelte’s defineRegistry with catalog-typed params on action handlers. Import from @xmachines/play-svelte, not @xmachines/json-render-svelte.
getActorContext()Returns the AnyPlayActor of the nearest ActorProvider ancestor. It throws when the caller is outside the provider tree.
getPlayViewContext()Returns the ViewContextValue (spec, registry, handlers, store) from the nearest ActorProvider ancestor.
setActorContext(actor)Sets the actor context. ActorProvider uses it internally.

Types

TypeDescription
ActorProviderPropsProps for <ActorProvider>: actor, registryResult, optional store, fallback snippet, onError, onRenderError, children.
PlayUIProviderPropsExtends ActorProviderProps with optional validationFunctions, navigate, and functions.
ViewContextValueThe view context shape that ActorProvider provides and PlayRenderer reads.
AnyPlayActorAbstractActor<AnyActorLogic> & Viewable — the actor shape that ActorProvider and getActorContext accept.
DefineRegistryOptions<C>Options for defineRegistry: components, catalog-typed actions, and onRenderError.
ActionFn<C, K>The handler type for one action. The params come from the catalog.
Actions<C>Map of catalog-typed action handlers.
SetStateThe state setter type. Each action handler receives it as the second argument.
RenderErrorHandlerThe callback (error: unknown, elementType: string) => void. The renderer calls it when a catalog component throws.

Re-exports from @xmachines/json-render-svelte

Import everything from @xmachines/play-svelte. This package re-exports these providers:

import {
JsonUIProvider,
StateProvider,
ActionProvider,
VisibilityProvider,
ValidationProvider,
Renderer,
getBoundProp,
getStateValue,
} from "@xmachines/play-svelte";
// Types
import type {
JSONUIProviderProps,
BaseComponentProps,
ComponentFn,
ComponentContext,
} from "@xmachines/play-svelte";

Testing

Run the test suite for this package:

Terminal window
pnpm --filter @xmachines/play-svelte test

Or from within the package directory:

Terminal window
pnpm test

The tests run with Vitest in a jsdom environment, together with @testing-library/svelte. The browser tests are in test/browser/. They use a separate config with Playwright:

Terminal window
# From the package directory
pnpm exec vitest --config vitest.browser.config.ts

Coverage thresholds: 80% for lines, functions, branches, and statements. The v8 provider enforces them.

License

MIT — see LICENSE.

@xmachines/play-svelte - Svelte renderer for the XMachines Play architecture

The package splits the provider from the renderer, in the same way as @xmachines/json-render-svelte:

  • ActorProvider: the low-level provider. It owns the actor lifecycle, the signal subscription, the StateStore of each view, and the injection of onRenderError
  • PlayUIProvider: the composite provider (ActorProvider and JsonUIProvider)
  • PlayRenderer: the leaf without props. It reads getPlayViewContext() and renders the Renderer

The package re-exports the primitives of @xmachines/json-render-svelte. A consumer therefore imports everything from @xmachines/play-svelte, and not from @xmachines/json-render-svelte.

Interfaces

Type Aliases

Variables

Functions

References

ActionProvider

Renames and re-exports PlayRenderer


ActorProvider

Renames and re-exports PlayRenderer


FieldValidationState

Renames and re-exports JSONUIProviderProps


getBoundProp

Renames and re-exports JSONUIProviderProps


getFieldValidation

Renames and re-exports JSONUIProviderProps


getStateValue

Renames and re-exports JSONUIProviderProps


getValidationContext

Renames and re-exports JSONUIProviderProps


JsonUIProvider

Renames and re-exports PlayRenderer


PlayUIProvider

Renames and re-exports PlayRenderer


Renderer

Renames and re-exports PlayRenderer


StateProvider

Renames and re-exports PlayRenderer


ValidationProvider

Renames and re-exports PlayRenderer


VisibilityProvider

Renames and re-exports PlayRenderer