json-render-svelte
v0.6.1
Published
Svelte 5 renderer for @json-render/core. JSON becomes Svelte components.
Downloads
761
Maintainers
Readme
@json-render/svelte
Svelte 5 renderer for @json-render/core. JSON becomes Svelte components.
Install
npm install @json-render/core @json-render/svelteRequires Svelte 5 (^5.0.0).
Quick Start
1. Define Your Catalog
import { defineCatalog } from "@json-render/core";
import { schema } from "@json-render/svelte/schema";
import { z } from "zod";
const catalog = defineCatalog(schema, {
components: {
Card: {
props: z.object({ title: z.string() }),
description: "A card container",
},
Button: {
props: z.object({ label: z.string() }),
description: "Clickable button",
},
},
actions: {
refresh: { description: "Refresh data" },
},
});2. Create Svelte Components
Components receive ComponentRenderProps -- element, emit, bindings, loading, and a children snippet:
<!-- Card.svelte -->
<script lang="ts">
import type { ComponentRenderProps } from "@json-render/svelte";
let { element, children }: ComponentRenderProps<{ title: string }> = $props();
</script>
<div class="card">
<h3>{element.props.title}</h3>
{#if children}
{@render children()}
{/if}
</div><!-- Button.svelte -->
<script lang="ts">
import type { ComponentRenderProps } from "@json-render/svelte";
let { element, emit }: ComponentRenderProps<{ label: string }> = $props();
</script>
<button onclick={() => emit("press")}>
{element.props.label}
</button>3. Build Registry and Render
import { defineRegistry } from "@json-render/svelte";
const { registry } = defineRegistry(catalog, {
components: { Card, Button } as any,
});<script>
import { CatalogRenderer } from "@json-render/svelte";
import { registry } from "./registry.js";
const spec = {
root: "card-1",
elements: {
"card-1": {
type: "Card",
props: { title: "Hello" },
children: ["btn-1"],
},
"btn-1": {
type: "Button",
props: { label: "Click me" },
},
},
};
</script>
<CatalogRenderer {spec} {registry} />API
Components
| Export | Description |
| ----------------- | ------------------------------------------------------------------------- |
| Renderer | Low-level renderer -- requires contexts to be set up via JSONUIProvider |
| JSONUIProvider | Sets up all contexts (state, visibility, actions, validation) |
| CatalogRenderer | All-in-one: wraps JSONUIProvider + Renderer |
| ConfirmDialog | Default confirmation dialog for actions |
Functions
| Export | Description |
| -------------------------------------------------- | ------------------------------------- |
| defineRegistry(catalog, { components, actions }) | Create a type-safe component registry |
| createStateStore(initial, onChange) | Create a reactive state store |
| createVisibilityContext() | Create visibility evaluation context |
| createActionContext(handlers, navigate) | Create action execution context |
| createValidationContext(fns) | Create field validation context |
Context Accessors
| Export | Description |
| ----------------------------------------------------- | ----------------------------------- |
| getStateContext() / setStateContext() | State context |
| getVisibilityContext() / setVisibilityContext() | Visibility context |
| getActionContext() / setActionContext() | Action context |
| getValidationContext() / setValidationContext() | Validation context |
| getRepeatScopeContext() / setRepeatScopeContext() | Repeat scope (for $item/$index) |
Component Contract
Svelte components registered in the registry receive these props:
interface ComponentRenderProps<P> {
element: UIElement<string, P>; // The element being rendered
children?: Snippet; // Child elements as a Svelte 5 snippet
emit: (event: string) => void; // Emit events (resolved to action bindings)
bindings?: Record<string, string>; // Two-way binding paths
loading?: boolean; // Whether spec is loading/streaming
}Schema
import { schema } from "@json-render/svelte/schema";
// Same spec format as @json-render/react (root + elements map)Features
- Svelte 5 runes -- reactive state with
$state,$derived,$effect - Snippets -- children passed via Svelte 5
{@render children()}pattern - Error boundaries --
<svelte:boundary>catches per-element rendering errors - Dynamic components -- Svelte 5 native dynamic component rendering
- Same spec format -- identical JSON spec as React/React Native renderers
- Core resolution -- visibility, props, actions, validation all powered by
@json-render/core
License
Apache-2.0
