GenuiRenderer Component

GenuiRenderer is the core rendering component (Renderer) of GenUI SDK. It renders structured JSON Schema returned by large language models into interactive UI.

When using only Renderer, you can import it on demand from @opentiny/genui-sdk-vue/renderer. See Quick Start - Subpath Imports.

Props

content

  • Type: string | object
  • Required: Yes
  • Description: Schema content as a string or object. When a string is passed, the component attempts to parse "partial JSON" and auto-complete it, supporting streaming updates.
<template>
  <GenuiRenderer :content="schemaContent" />
</template>

<script setup>
const schemaContent = {
  componentName: 'Page',
  children: [
    {
      componentName: 'Text',
      props: {
        text: 'Hello World',
      },
    },
  ],
};
</script>

isJsonComplete

  • Type: boolean
  • Required: No
  • Description: Applies only when content is a JSON object. Marks whether the current JSON is complete, helping the buffer logic determine whether values are complete.
<template>
  <GenuiRenderer :content="content" :isJsonComplete="isJsonComplete" />
</template>

<script setup>
const content = ref({
  componentName: 'Page',
  css: '.main-content { color:'
})
const isJsonComplete = ref(false);
</script>

generating

  • Type: boolean
  • Required: No
  • Description: Indicates whether the current conversation is still generating. Used to control UI loading state.
<template>
  <GenuiRenderer :content="content" :generating="isGenerating" />
</template>

<script setup>
const isGenerating = ref(false);
</script>

customComponents

  • Type: Record<string, Component>
  • Required: No
  • Description: Custom component map for extending the available component list.
<template>
  <GenuiRenderer :content="content" :customComponents="customComponents" />
</template>

<script setup>
import MyCustomComponent from './MyCustomComponent.vue';

const customComponents = {
  MyCustomComponent: MyCustomComponent,
  // Register multiple custom components
};
</script>

See Renderer - Custom Components for detailed usage.

customActions

  • Type: Record<string, { execute: (params: any, context: any) => void }>
  • Required: No
  • Description: Custom action map defining actions that can be invoked from components.
<template>
  <GenuiRenderer :content="content" :customActions="customActions" />
</template>

<script setup>
const customActions = {
  openPage: {
    execute: (params, context) => {
      window.open(params.url, params.target || '_self');
    },
  },
  showNotification: {
    execute: (params) => {
      console.log('Notification:', params.message);
    },
  },
};
</script>

See Renderer - Custom Actions for detailed usage.

requiredCompleteFieldSelectors

  • Type: string[]
  • Required: No
  • Description: Specifies which field paths must be complete before updates are applied. Used to control buffering strategy during streaming updates.
<template>
  <!-- All componentName values must be complete; the name prop on TinyTabItem must be complete -->
  <GenuiRenderer :content="content" :requiredCompleteFieldSelectors="['componentName', '[componentName=TinyTabItem] > props > name']" />
</template>

See Renderer - Buffer Field Configuration for detailed usage.

state

  • Type: Record<string, any>
  • Required: No
  • Description: Global state passed to the renderer, accessible in components via context.
<template>
  <GenuiRenderer :content="content" :state="{ userId: 123, userName: 'John' }" />
</template>

See Renderer - Passing and Merging State for detailed usage.

Slots

  • Parameters: { schema: CardSchema, isError: boolean, isFinished: boolean }
  • Description: Custom renderer header content
<template>
  <GenuiRenderer :content="content">
    <template #header="{ schema, isError, isFinished }">
      <div v-if="!isError" class="renderer-header">Render status: {{ isFinished ? 'Completed' : 'Generating...' }}</div>
    </template>
  </GenuiRenderer>
</template>
  • Parameters: { schema: CardSchema, isError: boolean, isFinished: boolean }
  • Description: Custom renderer footer content
<template>
  <GenuiRenderer :content="content">
    <template #footer="{ schema, isError, isFinished }">
      <div v-if="isFinished" class="renderer-footer">
        <button @click="handleRefresh">Refresh</button>
      </div>
    </template>
  </GenuiRenderer>
</template>

Types

CardSchema

type CardSchema = {
  id?: string; // Optional root node id
  methods?: Methods; // Method collection
  state?: Record<string, PropValue>; // Global state; required for two-way form binding
  componentName: string; // Root component name, usually Page
  props?: Record<string, PropValue>; // Root component props
  componentType?: 'Block' | 'PageStart' | 'PageSection'; // Node type, usually omitted
  children?: NodeSchema[]; // Root child nodes
  slot?: string | JSSlot | Record<string, PropValue>; // Root slot content
  loop?: Record<string, PropValue>; // Root loop render config
  loopArgs?: string[]; // Root loop argument names
  condition?: boolean | Record<string, PropValue>; // Root conditional render config
  css?: string; // Global CSS string
};

type NodeSchema = {
  id?: string; // Unique node id
  componentName: string; // Component name
  props?: Record<string, PropValue>; // Component props
  children?: NodeSchema[] | string; // Child nodes or string (recursive)
  componentType?: 'Block' | 'PageStart' | 'PageSection'; // Node type, usually omitted
  slot?: string | JSSlot | Record<string, PropValue>; // Slot content
  params?: string[]; // Parameter names
  loop?: Record<string, PropValue>; // Loop render config
  loopArgs?: string[]; // Loop argument names
  condition?: boolean | Record<string, PropValue>; // Conditional render config
};

type PropValue =
  | string // String
  | number // Number
  | boolean // Boolean
  | null // null
  | JSExpression // JS expression wrapper
  | JSFunction // JS function wrapper
  | JSSlot // Slot wrapper
  | PropValue[] // Recursive array
  | Record<string, PropValue>; // Recursive object

type JSExpression = { type: 'JSExpression'; value: string; model?: boolean };
type JSFunction = { type: 'JSFunction'; value: string; params?: string[] };
type JSSlot = { type: 'JSSlot'; value: string | Record<string, any> };

IRendererProps

interface IRendererProps {
  content: string | { [prop: string]: any };
  isJsonComplete?: boolean;
  generating?: boolean;
  customComponents?: Record<string, Component>;
  customActions?: Record<
    string,
    {
      execute: (params: any, context: any) => void;
    }
  >;
  requiredCompleteFieldSelectors?: string[];
  id?: string;
  state?: Record<string, any>;
}