Skip to content

Preview API Reference

@banclo/jsonforms-preview provides the live form preview system. It renders the builder's generated schemas using JSON Forms renderer sets.

PreviewAdapter Interface

The core interface that all preview adapters must implement:

ts
import type {
  JsonFormsRendererRegistryEntry,
  JsonFormsCellRendererRegistryEntry,
} from '@jsonforms/core'
import type { App } from 'vue'

interface PreviewAdapter {
  /** Unique identifier for the adapter */
  id: string

  /** Human-readable display name */
  name: string

  /**
   * JSON Forms renderer registry entries.
   * Each entry maps a tester function to a Vue component that
   * renders a specific control type or layout.
   */
  renderers: JsonFormsRendererRegistryEntry[]

  /**
   * Optional cell renderers for table-like array layouts.
   * Used by array renderers that display items in a table format.
   */
  cells?: JsonFormsCellRendererRegistryEntry[]

  /**
   * Optional setup function called on the preview Vue app instance.
   * Use this to install plugins (e.g., Vuetify) that your renderers need.
   */
  setup?: (app: App) => void

  /**
   * Optional CSS string injected into the preview panel.
   * Use this to style the rendered form controls.
   */
  styles?: string
}

Built-in Adapters

vanillaAdapter

A pre-configured adapter using @jsonforms/vue-vanilla. This is the default adapter and has no external UI framework dependencies.

ts
import { vanillaAdapter } from '@banclo/jsonforms-preview'

console.log(vanillaAdapter.id)    // 'vanilla'
console.log(vanillaAdapter.name)  // 'Vanilla'

Peer dependencies:

  • @jsonforms/core
  • @jsonforms/vue
  • @jsonforms/vue-vanilla

Included styles:

The vanilla adapter ships with built-in CSS that provides:

  • Consistent control spacing (margin-bottom: 1rem)
  • Styled labels (font-weight: 500)
  • Input styling with focus rings
  • Validation error messages in red
  • Description text in gray
  • Group borders and padding
  • Horizontal layout with flexbox
  • Checkbox width override

createVuetifyAdapter

An async factory function that creates a Vuetify-based preview adapter. Dependencies are dynamically imported so that Vuetify remains optional.

createVuetifyAdapter is not re-exported from the main @banclo/jsonforms-preview index. Import it directly from the adapter module:

ts
import { createVuetifyAdapter } from '@banclo/jsonforms-preview/adapters/vuetify-adapter'

const adapter = await createVuetifyAdapter()
console.log(adapter.id)    // 'vuetify'
console.log(adapter.name)  // 'Vuetify'

Peer dependencies:

  • @jsonforms/core
  • @jsonforms/vue
  • @jsonforms/vue-vuetify
  • vuetify
  • @mdi/font

Setup behavior:

The factory function:

  1. Dynamically imports @jsonforms/vue-vuetify and vuetify
  2. Creates a Vuetify instance via createVuetify()
  3. Returns an adapter whose setup function installs Vuetify on the preview app
  4. Includes CSS imports for Vuetify styles and Material Design Icons

Usage:

ts
const adapter = await createVuetifyAdapter()

// The adapter's setup function installs Vuetify
// on the preview's Vue app instance:
// adapter.setup(app)  =>  app.use(vuetify)

Components

PreviewPanel

The main preview component embedded in the builder interface. It renders the form using the active PreviewAdapter and reactively updates whenever the generated JSON Schema or UI Schema changes.

Props:

PropTypeDefaultDescription
adapterPreviewAdaptervanillaAdapterThe preview adapter to use for rendering

PreviewDialog

A modal wrapper around PreviewPanel that displays the form preview in a full-screen dialog. Useful for previewing the form outside the constraints of the builder's layout.

Props:

PropTypeDefaultDescription
openbooleanfalseControls visibility of the dialog
adapterPreviewAdaptervanillaAdapterThe preview adapter to use for rendering

Events:

EventPayloadDescription
update:openbooleanEmitted when the dialog requests to close

PreviewDataViewer

A read-only component that displays the current form data as formatted JSON. It reflects the live state of the data bound to the previewed form, making it useful for debugging and demonstration.

Utilities

mergeRenderers

Merges two renderer registry arrays, with entries in customRenderers taking priority over entries in adapterRenderers when their testers match the same UI schema element. Use this to selectively override specific renderers provided by an adapter while keeping the rest.

ts
import { mergeRenderers } from '@banclo/jsonforms-preview'
import type { JsonFormsRendererRegistryEntry } from '@jsonforms/core'

function mergeRenderers(
  adapterRenderers: JsonFormsRendererRegistryEntry[],
  customRenderers: JsonFormsRendererRegistryEntry[],
): JsonFormsRendererRegistryEntry[]

Example:

ts
import { vanillaAdapter, mergeRenderers } from '@banclo/jsonforms-preview'
import { myStringRenderer, myStringTester } from './my-renderers'

const combinedRenderers = mergeRenderers(vanillaAdapter.renderers, [
  { tester: myStringTester, renderer: myStringRenderer },
])

Creating a Custom Adapter

To support a renderer set not covered by the built-in adapters, implement the PreviewAdapter interface:

ts
import type { PreviewAdapter } from '@banclo/jsonforms-preview'
import { myRenderers } from './my-renderers'

export const myAdapter: PreviewAdapter = {
  id: 'my-renderer',
  name: 'My Custom Renderer',
  renderers: myRenderers,
  styles: `
    .my-control { margin-bottom: 1rem; }
    .my-label { font-weight: bold; }
  `,
}

With Plugin Setup

If your renderers depend on a Vue plugin:

ts
import type { PreviewAdapter } from '@banclo/jsonforms-preview'
import { myRenderers } from './my-renderers'
import { MyPlugin } from './my-plugin'

export const myAdapter: PreviewAdapter = {
  id: 'my-renderer',
  name: 'My Custom Renderer',
  renderers: myRenderers,
  setup: (app) => {
    app.use(MyPlugin, { /* plugin options */ })
  },
}

With Cell Renderers

If your array renderers use a table layout, provide cell renderers:

ts
export const myAdapter: PreviewAdapter = {
  id: 'my-renderer',
  name: 'My Custom Renderer',
  renderers: myRenderers,
  cells: myCellRenderers,
}

Lazy Loading

For large renderer sets, use dynamic imports to keep the initial bundle size small:

ts
export async function createMyAdapter(): Promise<PreviewAdapter> {
  const { myRenderers } = await import('./my-renderers')
  const { MyPlugin } = await import('./my-plugin')

  return {
    id: 'my-renderer',
    name: 'My Custom Renderer',
    renderers: myRenderers,
    setup: (app) => {
      app.use(MyPlugin)
    },
  }
}

Exports

ts
// Types
export type { PreviewAdapter } from './adapters/adapter-types'
// Built-in adapters
export { vanillaAdapter } from './adapters/vanilla-adapter'
// Utilities
export { mergeRenderers } from './renderers/custom-renderer-bridge'
// Vuetify adapter (lazy-loaded, import separately):
// import { createVuetifyAdapter } from '@banclo/jsonforms-preview/adapters/vuetify-adapter'