Skip to main content
doc0blade47/fumadocsdocumentation home
Sign in

API Docs Primitives

Last updated Oct 12, 202696% grounded
Relevant source files

The following files were used as context for generating this wiki page:

Overview

API Docs Primitives (@fumadocs/api-docs) provides the underlying schema parsing, type formatting, mocking, rendering, and navigation infrastructure shared across Fumadocs API documentation packages like OpenAPI Interactive UI and AsyncAPI Document Processing. By establishing a unified runtime foundation, it solves the fragmentation of handling complex JSON Schema specifications across different protocol adapters and frontend layouts. Key design decisions include synchronous reference resolution, recursive AST generation for hierarchical properties, and decoupled client-server component splitting that maintains interactive deep-linking and state preservation. It interfaces directly with specification document parsers and UI layout renderers to power interactive schema property exploration, code sample integration, and deep-linkable slug generation.

Sources: packages/api-docs/package.json:1-45, packages/api-docs/src/components/schema/client.tsx:73-114, packages/api-docs/src/components/schema/index.tsx:89-112

Package architecture and shared contracts

Package exports and module layout

The @fumadocs/api-docs package exposes a modular export structure defined in package.json, mapping internal build outputs to explicit subpath imports for schema processing, interactive components, code generation, and utilities.

"exports": {
  "./auto-anchor": "./dist/auto-anchor/index.js",
  "./auto-anchor/client": "./dist/auto-anchor/client.js",
  "./codegen": "./dist/codegen.js",
  "./components/accordion": "./dist/components/accordion.js",
  "./components/dialog": "./dist/components/dialog.js",
  "./components/input": "./dist/components/input.js",
  "./components/playground/inputs": "./dist/components/playground/inputs.js",
  "./components/playground/schema": "./dist/components/playground/schema.js",
  "./components/schema": "./dist/components/schema/index.js",
  "./components/schema/client": "./dist/components/schema/client.js",
  "./components/select": "./dist/components/select.js",
  "./components/select-tab": "./dist/components/select-tab.js",
  "./components/spinner": "./dist/components/spinner.js",
  "./i18n": "./dist/i18n.js",
  "./schema": "./dist/schema/index.js",
  "./schema/bundle": "./dist/schema/bundle.js",
  "./schema/dereference": "./dist/schema/dereference.js",
  "./schema/merge": "./dist/schema/merge.js",
  "./schema/ref": "./dist/schema/ref.js",
  "./schema/resolve-ref": "./dist/schema/resolve-ref.js",
  "./schema/sample": "./dist/schema/sample.js",
  "./schema/to-string": "./dist/schema/to-string.js",
  "./utils/id-to-title": "./dist/utils/id-to-title.js",
  "./utils/url": "./dist/utils/url.js",
  "./package.json": "./package.json",
  "./css/*": "./css/*"
},

Sources: packages/api-docs/package.json:18-45

Core type definitions and runtime contracts

The core schema architecture relies on utility types and type guards that handle JSON Schema definitions (following draft 2020-12) and reference stripping. NoReference<T> recursively eliminates $ref reference objects from arbitrary types, while ParsedSchema unions standard JSON Schema definitions with extension properties such as x-playground-lazy and discriminator mappings.

import type { JSONSchema } from 'json-schema-typed/draft-2020-12';
 
type ReferenceObject = { $ref: string };
 
export type NoReference<T> = T extends (infer I)[]
  ? NoReference<I>[]
  : T extends ReferenceObject
    ? Exclude<T, ReferenceObject>
    : T extends object
      ? {
          [K in keyof T]: NoReference<T[K]>;
        }
      : T;
 
export type NoReferenceSwallow<T> = T extends ReferenceObject ? Exclude<T, ReferenceObject> : T;
 
export type ParsedSchema =
  | (JSONSchema & {
      'x-playground-lazy'?: boolean;
      discriminator?: {
        propertyName?: string;
        mapping?: Record<string, string>;
      };
    })
  | boolean;

Sources: packages/api-docs/src/schema/index.ts:1-25

The SchemaResolver contract defines the shape for functions that take a ParsedSchema and return a shallowly dereferenced schema alongside an optional $ref string.

export type SchemaResolver = (schema: ParsedSchema) => {
  /** shallowly dereferenced schema */
  dereferenced: ParsedSchema;
  /** the ref value (if dereferenced) */
  $ref?: string;
};

Sources: packages/api-docs/src/schema/index.ts:27-32

Note

SchemaResolver performs a shallow dereference step rather than a deep recursive unrolling, preserving reference boundaries until explicit traversal or sampling occurs.

Bundling primitives and code generation registries

Schema bundling relies on re-exporting the bundle function directly from @apidevtools/json-schema-ref-parser to combine external JSON reference files into a unified document structure.

export { bundle } from '@apidevtools/json-schema-ref-parser';

Sources: packages/api-docs/src/schema/bundle.ts:1-1

To support Code Sample Generators, the package provides CodeUsageGeneratorRegistry and createCodeUsageGeneratorRegistry, managing language-specific code generators through registration, retrieval, inline definition, and removal operations.

export interface CodeUsageGeneratorRegistry<Data = unknown, Context = unknown> {
  add: (id: string, generator: CodeUsageGenerator<Data, Context>) => void;
  get: (id: string) => CodeUsageGenerator<Data, Context> | undefined;
  addInline: (generator: InlineCodeUsageGenerator<Data, Context>) => void;
  /**
   * @returns if the generator is removed
   */
  remove: (id: string) => boolean;
  map: () => Map<string, CodeUsageGenerator<Data, Context>>;
}
 
/**
 * Generate code example for given programming language
 */
export interface CodeUsageGenerator<Data = unknown, Context = unknown> {
  generate: (data: Data, context: Context) => string;
  lang: string;
  label?: string;
}
 
/**
 * Generate code example for given programming language
 */
export interface InlineCodeUsageGenerator<Data = unknown, Context = unknown> {
  id?: string;
  lang: string;
  label?: string;
  /**
   * either:
   * - code
   * - a function imported from a file with "use client" directive
   * - false (disabled)
   */
  source?: string | CodeUsageGeneratorFn<Data, Context> | false;
}
 
export function createCodeUsageGeneratorRegistry<Data, Context>(
  inherit?: CodeUsageGeneratorRegistry<Data, Context>,
): CodeUsageGeneratorRegistry<Data, Context> {

Sources: packages/api-docs/src/codegen.ts:1-39

Important

When adding inline code usage generators via addInline, if the source property evaluates to falsy or false, the registry automatically deletes the generator entry matching the language or identifier.

Synchronous schema dereferencing

Dereferencing mechanics in OpenAPI documents

OpenAPI document processing relies on synchronous schema dereferencing via dereferenceBundledDocument, which converts a bundled specification document into a fully resolved structure devoid of local or external reference pointers. This function initializes a Map<object, string> instance to track original reference strings ($ref) mapped to their corresponding schema objects.

export function dereferenceBundledDocument(bundled: Document): DereferencedDocument {
  const dereferenceMap = new Map<object, string>();
 
  return {
    bundled,
    dereferenced: dereferenceSync(bundled as JSONSchema, {
      setOriginalRef(schema, ref) {
        dereferenceMap.set(schema as object, ref);
      },
    }) as NoReference<Document>,
    getRawRef(obj: object) {
      return dereferenceMap.get(obj);
    },
  };
}

Sources: packages/openapi/src/utils/document/dereference.ts:20-34

The underlying dereference implementation uses dereferenceSync from @apidevtools/json-schema-ref-parser (re-exported via @fumadocs/api-docs/schema/dereference) cast to JSONSchema from json-schema-typed/draft-2020-12. During this traversal, the setOriginalRef callback intercepts each resolved schema node and populates the tracking map with dereferenceMap.set(schema as object, ref), enabling downstream lookups of raw reference identifiers via getRawRef(obj).

export interface DereferencedDocument {
  /**
   * dereferenced document
   */
  dereferenced: NoReference<Document>;
 
  /**
   * Get raw $ref from dereferenced object
   */
  getRawRef: (obj: object) => string | undefined;
 
  bundled: Document;
}

Sources: packages/openapi/src/utils/document/dereference.ts:6-18

Note

DereferencedDocument exposes three properties: bundled for the original specification, dereferenced typed as NoReference<Document> for the fully unrolled AST, and getRawRef to retrieve original reference strings from any dereferenced object instance.

AsyncAPI document dereferencing contracts

AsyncAPI document processing adopts an identical architectural pattern for synchronous reference resolution through packages/asyncapi/src/utils/document/dereference.ts. It wraps dereferenceSync to process AsyncAPIObject definitions, maintaining a dedicated dereferenceMap to track source references across asynchronous message schemas and protocol components.

export function dereferenceBundledDocument(bundled: AsyncAPIObject): DereferencedDocument {
  const dereferenceMap = new Map<object, string>();
 
  return {
    bundled,
    dereferenced: dereferenceSync(bundled as JSONSchema, {
      setOriginalRef(schema, ref) {
        dereferenceMap.set(schema as object, ref);
      },
    }) as NoReference<AsyncAPIObject>,
    getRawRef(obj: object) {
      return dereferenceMap.get(obj);
    },
  };
}

Sources: packages/asyncapi/src/utils/document/dereference.ts:20-34

The resulting DereferencedDocument interface for AsyncAPI returns NoReference<AsyncAPIObject> alongside the raw reference lookup utility and the original bundled specification object.

export interface DereferencedDocument {
  /**
   * dereferenced document
   */
  dereferenced: NoReference<AsyncAPIObject>;
 
  /**
   * Get raw $ref from dereferenced object
   */
  getRawRef: (obj: object) => string | undefined;
 
  bundled: AsyncAPIObject;
}

Sources: packages/asyncapi/src/utils/document/dereference.ts:6-18

Warning

Both OpenAPI and AsyncAPI dereference pipelines cast their respective document types to JSONSchema during dereferenceSync invocation, requiring structural compatibility with JSON Schema Draft 2020-12 definitions.

Reference bundling primitives

Underpinning both protocol dereferencing utilities, reference bundling relies on the core bundle export from @apidevtools/json-schema-ref-parser to aggregate distributed references into a cohesive self-contained specification file prior to synchronous traversal.

export { bundle } from '@apidevtools/json-schema-ref-parser';

Sources: packages/api-docs/src/schema/bundle.ts:1-1

Important

Bundling must precede synchronous dereferencing whenever specification files reference external file paths or network URIs, as dereferenceSync operates entirely in-memory on the consolidated document structure.

Mock data sampling and traversal

Sample options and type inference

Mock data generation converts JSON schema definitions into concrete payloads through sample and internal traversal routines. The configuration accepts specific flags defined in JsonSchemaSampleOptions, governing object traversal depths, schema property omissions, and pattern generation.

OptionTypeDefaultPurpose
skipNonRequiredboolean—Omits schema properties not marked as required
skipReadOnlybooleanfalseOmits properties designated as read-only
skipWriteOnlyboolean—Omits properties designated as write-only
quietboolean—Suppresses warnings during sampling
enablePatternsboolean—Enables generation from regular expressions
maxSampleDepthnumber15Limits recursion depth during traversal

Sources: packages/api-docs/src/schema/sample.ts:21-37

When schemas omit explicit type declarations, inferType inspects validation keywords to deduce the expected data type. It maps attributes like multipleOf, maximum, minimum, maxLength, pattern, items, properties, and required to primitive types such as 'number', 'string', 'array', or 'object'.

function inferType(schema: SchemaDoc): string | null {
  if (schema.type !== undefined) {
    const t = schema.type;
    return Array.isArray(t) ? (t.length === 0 ? null : String(t[0])) : String(t);
  }
 
  const keywordTypes: Record<string, string> = {
    multipleOf: 'number',
    maximum: 'number',
    exclusiveMaximum: 'number',
    minimum: 'number',
    exclusiveMinimum: 'number',
    maxLength: 'string',
    minLength: 'string',
    pattern: 'string',
    items: 'array',
    maxItems: 'array',
    minItems: 'array',
    uniqueItems: 'array',
    additionalItems: 'array',
    maxProperties: 'object',
    minProperties: 'object',
    required: 'object',
    additionalProperties: 'object',
    properties: 'object',
    patternProperties: 'object',
    dependencies: 'object',
  };
 
  for (const [kw, ty] of Object.entries(keywordTypes)) {
    if (schema[kw] !== undefined) return ty;
  }
  return null;
}

Sources: packages/api-docs/src/schema/sample.ts:51-84

Note

If a schema defines an array of types, inferType evaluates the first array element after checking for empty type arrays, returning null if no type determination is possible.

Request example generation workflow

Request example generation uses getExampleRequests to construct client payloads from operation definitions, parameter lists, and request bodies. It extracts media types using getPreferredType and populates path, query, header, and cookie parameters by resolving examples or invoking sample on parameter schemas.

export function getExampleRequests({
  path,
  method,
  ctx,
  operation,
  pathItem,
}: {
  path: string;
  pathItem: NoReference<PathItemObject>;
  method: HttpMethods;
  operation: NoReference<OperationObject>;
  ctx: RenderContext;
}): ExampleRequestItem[] {
  const requestBody = operation.requestBody;
  const media = requestBody?.content ? getPreferredType(requestBody.content) : null;
  const bodyOfType = media ? requestBody!.content![media] : null;
  const parameters = [...(operation.parameters ?? []), ...(pathItem.parameters ?? [])];
 
  if (bodyOfType?.examples) {
    const result: ExampleRequestItem[] = [];
 
    for (const [key, value] of Object.entries(bodyOfType.examples)) {
      const data = getRequestData({
        path,
        body: operation.requestBody,
        parameters,
        sampleKey: key,
        method,
      });
 
      result.push({
        id: key,
        name: value.summary || key,
        description: value.description,
        data,
        encoded: encodeRequestData(data, ctx.mediaAdapters, parameters),
      });
    }
 
    if (result.length > 0) return result;
  }
 
  const data = getRequestData({ path, body: operation.requestBody, method, parameters });
  return [
    {
      id: '_default',
      name: 'Default',
      description:
        typeof bodyOfType?.schema === 'object' ? bodyOfType.schema.description : undefined,
      data,
      encoded: encodeRequestData(data, ctx.mediaAdapters, parameters),
    },
  ];
}

Sources: packages/openapi/src/utils/get-example-requests.ts:23-76

When processing request bodies, getRequestData checks for explicit examples or individual example values before falling back to programmatic sampling via sample. HTTP methods dictate the read-only and write-only sampling flags passed to the sampler.

function getRequestData({
  method,
  path,
  parameters,
  sampleKey,
  body,
}: {
  path: string;
  sampleKey?: string;
  method: HttpMethods;
  parameters: NoReference<ParameterObject>[];
  body?: NoReference<RequestBodyObject>;
}): RawRequestData {
  const result: RawRequestData = {
    path: {},
    cookie: {},
    header: {},
    query: {},
    method: method,
  };
 
  for (const param of parameters) {
    let value = pickExample(param as never);
 
    if (value === undefined && param.required) {
      if (param.schema) {
        value = sample(param.schema as object);
      } else if (param.content) {
        const type = getPreferredType(param.content);
        const content = type ? param.content[type] : undefined;
        if (!content || !content.schema)
          throw new Error(
            `Cannot find "${param.name}" parameter info for media type "${type}" in ${path} ${method}`,
          );
 
        value = sample(content.schema as object);
      }
    }
 
    switch (param.in) {
      case 'cookie':
        result.cookie[param.name!] = value;
        break;
      case 'header':
        result.header[param.name!] = value;
        break;
      case 'query':
        result.query[param.name!] = value;
        break;
      default:
        result.path[param.name!] = value;
    }
  }
 
  if (body?.content) {
    const type = getPreferredType(body.content);
    if (!type) throw new Error(`Cannot find body schema for ${path} ${method}: missing media type`);
    result.bodyMediaType = type as RawRequestData['bodyMediaType'];
    const bodyOfType = body.content[type];
 
    if (bodyOfType.examples && sampleKey) {
      result.body = bodyOfType.examples[sampleKey].value;
    } else if (bodyOfType.example) {
      result.body = bodyOfType.example;
    } else {
      result.body = sample((bodyOfType?.schema ?? {}) as object, {
        skipReadOnly: method !== 'get',
        skipWriteOnly: method === 'get',
        skipNonRequired: true,
      });
    }
  }
 
  return result;
}

Sources: packages/openapi/src/utils/get-example-requests.ts:78-152

Warning

For HTTP GET requests, getRequestData explicitly configures skipReadOnly: false and skipWriteOnly: true, while mutating these flags inversely for methods that transmit write payloads.

Schema string conversion and formatting

Format flags and string conversion logic

The schemaToString utility transforms parsed schema objects into readable string representations. It accepts an optional SchemaResolver function and formatting flags defined in FormatFlags.

export enum FormatFlags {
  None = 0,
  UseAlias = 1 << 0,
}
 
export function schemaToString(
  value: ParsedSchema,
  resolver?: SchemaResolver,
  flags: FormatFlags = FormatFlags.None,
): string {

Sources: packages/api-docs/src/schema/to-string.ts:3-12

ConstantValuePurpose
FormatFlags.None0Default formatting without special alias resolution
FormatFlags.UseAlias1Resolves schema titles or reference identifiers

Sources: packages/api-docs/src/schema/to-string.ts:3-6

Note

When FormatFlags.UseAlias is active, schemaToString checks for a schema.title property or parses the trailing segment of a raw $ref string before falling back to type-level serialization.

Type resolution and composition rules

The internal run function handles boolean schemas, returning 'any' for true and 'never' for false. Array types are formatted recursively into array<T> structures where inner item types are evaluated with alias resolution enabled.

if (schema.type === 'array')
  return `array<${schema.items ? run(schema.items, flags | FormatFlags.UseAlias) : 'unknown'}>`;
 

Sources: packages/api-docs/src/schema/to-string.ts:59-61

Composed schemas like oneOf, anyOf, and allOf utilize a helper union function to aggregate distinct member types. When both oneOf and anyOf are present on a schema, they combine with an intersection operator.

if (schema.oneOf && schema.anyOf) {
  return `(${union(schema.oneOf, ' | ', flags)}) & (${union(schema.anyOf, ' | ', flags)})`;
}

Sources: packages/api-docs/src/schema/to-string.ts:62-64

Warning

Binary string formats (schema.type === 'string' and schema.format === 'binary') are explicitly converted to the 'file' type keyword rather than retaining their underlying schema representation.

Interactive schema renderer components

Server and client component tree generation

The interactive schema renderer architecture is split between server-side generation utilities and client-side tree navigation components. The server entry point invokes generateSchemaUI to build a normalized schema record (SchemaUIGeneratedData) containing a root reference pointer $root and a dictionary of dereferenced types refs. During this phase, property visibility flags like readOnly and writeOnly dictate which fields are included in object property lists, while scanRefs recursively traverses object properties, array items, and union types.

export interface SchemaUIGeneratedData {
  $root: string;
  refs: Record<string, SchemaData>;
}
 
export function Schema({
  client,
  root,
  readOnly,
  writeOnly,
  resolver,
  showExample,
  renderMarkdown,
}: SchemaUIOptions) {
  const translations = useTranslations().translations;
  const generated = useMemo(() => {
    return generateSchemaUI({
      root,
      resolver,
      readOnly,
      writeOnly,
      showExample,
      renderMarkdown,
      translations,
    });
  }, [root, readOnly, writeOnly, resolver, showExample, renderMarkdown, translations]);
 
  return <SchemaUI {...client} generated={generated} />;
}
 
export function generateSchemaUI({
  root,
  resolver,
  renderMarkdown,
  readOnly = false,
  writeOnly = false,
  showExample = false,
  translations = {},
}: Omit<SchemaUIOptions, 'client'> & {
  translations?: Partial<Record<string, string>>;
}): SchemaUIGeneratedData {

Sources: packages/api-docs/src/components/schema/index.tsx:84-124

The generated schema record is passed into the SchemaUI client component, which manages the active navigation path (PathItemType[]) and anchor state. When rendered via AsyncAPI or OpenAPI bindings, the execution flows through specific integration wrappers that resolve schema identifiers and translation contexts.

Sources: packages/api-docs/src/components/schema/client.tsx:73-114, packages/asyncapi/src/ui/index.tsx:197-203, packages/openapi/src/ui/base.tsx:118-125

  1. createAsyncAPIPage or createOpenAPIPageBase initializes the rendering context and delegates to the Schema component.
  2. Schema executes generateSchemaUI to produce the normalized reference dictionary and root identifier.
  3. SchemaUI mounts the client state provider, initializing the path stack with the root schema reference and root anchor ID.

Sources: packages/api-docs/src/components/schema/client.tsx:83-114, packages/api-docs/src/components/schema/index.tsx:89-112, packages/asyncapi/src/ui/index.tsx:197-203, packages/openapi/src/ui/base.tsx:118-125

Note

SchemaUI registers an useEffect hook that inspects window.location.search for a path parameter and s-highlight slug, automatically decoding the traversal stack and scrolling the target property container into view upon initial hydration.

Schema property visibility and filtering

Object schema property generation incorporates strict filtering rules based on visibility flags and property types. When iterating over schema properties, pattern properties, and additional properties, generateSchemaUI evaluates each candidate property against visibility criteria.

if (schema.type === 'object') {
  const out: SchemaData = {
    type: 'object',
    props: [],
    ...base(schema),
  };
  refs[id] = out;
 
  const { properties = {}, patternProperties, additionalProperties } = schema;
  const props = Object.entries(properties);
  if (patternProperties) props.push(...Object.entries(patternProperties));
 
  for (const [key, prop] of props) {
    if (!prop || !isVisible(prop)) continue;
    const $type = getSchemaId(prop);
    scanRefs($type, prop);
    out.props.push({
      $type,
      name: key,
      required: schema.required?.includes(key) ?? false,
    });
  }
 
  if (additionalProperties && isVisible(additionalProperties)) {
    const $type = getSchemaId(additionalProperties);
    scanRefs($type, additionalProperties);
 
    out.props.push({
      $type,
      name: '[key: string]',
      required: false,
    });
  }
  return;

Sources: packages/api-docs/src/components/schema/index.tsx:351-384

Property Type / FieldInclusion ConditionDefault Behavior
Standard Properties (properties)prop is defined and isVisible(prop) returns trueEvaluated and pushed to object properties
Pattern Properties (patternProperties)Appended to property entries when presentEvaluated alongside standard properties
Additional Properties (additionalProperties)additionalProperties is truthy and visibleAppended as [key: string] with required: false

Sources: packages/api-docs/src/components/schema/index.tsx:359-383

Warning

If a property schema evaluates to invisible under current readOnly or writeOnly configurations, it is skipped entirely during reference scanning, preventing hidden data fields from populating client popovers and generated type trees.

Anchor slug generation and prefixing

Fumadocs api-docs uses github-slugger to produce deep-link anchor slugs for schema components and properties. The anchorSegments utility function accepts an arbitrary list of string segments, applying slug() mapping to each non-empty segment unless prefixed with a null character (\0), which forces the segment to be preserved verbatim.

import { slug } from 'github-slugger';
 
/** slugify segments, append `\0` to keep segment as-is */
export function anchorSegments(...segs: string[]): string {
  const mapped: string[] = [];
  for (const seg of segs) {
    if (seg.startsWith('\0')) {
      mapped.push(seg.slice(1));
    } else if (seg.length > 0) {
      mapped.push(slug(seg));
    }
  }
  return mapped.join('.');
}

Sources: packages/api-docs/src/auto-anchor/index.ts:1-14

Function / HelperSignatureDescription
anchorSegments(...segs: string[]) => stringSlugifies segments, joining them with dots (.), while verbatim segments are unmasked via \0 prefix slicing.
anchorIdStartsWith(id1: string, id2: string) => booleanEvaluates hierarchical prefix matches between anchor IDs, returning true if id1 equals id2 or starts with id2..

Sources: packages/api-docs/src/auto-anchor/index.ts:4-21

Note

When SchemaUI mounts, it registers its root identifier using useAnchorId([name]). It tracks ExcludedFromAutoAnchor caches to ensure initial URL deep-link parameters (path and s-highlight) trigger smooth scrolling into view only on the first hydration pass.

Interactive popover state and scroll management

The interactive schema renderer uses a React context provider (StateContextType) to manage the current traversal path (path array of PathItemType objects), root anchor ID, and popover triggers. When users click nested object types, renderTypeInfoTrigger controls a Radix UI Popover whose open state depends on whether the path length exceeds 1, matching the target reference and name while the root container is not closed.

interface PathItemType {
  name: string;
  $ref: string;
  scrollTop?: number;
  /** property name of highlighted field, only applicable for objects */
  highlighted?: string;
  tabValues?: string[];
  /** popover state, only applicable for root */
  closed?: boolean;
}
 
interface StateContextType {
  rootId: string;
  /** the first tiem will always be the root item */
  path: PathItemType[];
  setPath: (path: PathItemType[]) => void;
  generated: SchemaUIGeneratedData;
  renderTypeInfoTrigger: (props: {
    pathName: string;
    $ref: string;
    children: ReactNode;
  }) => ReactNode;
}

Sources: packages/api-docs/src/components/schema/client.tsx:34-56

Warning

Popover elements attach a popoverRef callback that preserves container scroll positions (scrollTop) across nested view switches, enforcing a dynamic minimum height of 200px (or higher based on client height calculations) and autofocusing inputs marked with data-object-search-input.

Protocol bindings and helper controls

AsyncAPI protocol binding UI modules share a common set of layout primitives, formatting utilities, and summary builders to render message headers, channel targets, and operation properties consistently.

export function formatBindingScalar(value: unknown): string {
  if (value === null || value === undefined) return '';
  if (typeof value === 'boolean') return value ? 'Yes' : 'No';
  if (typeof value === 'number') return String(value);
  if (typeof value === 'string') return value;
  if (Array.isArray(value)) {
    return value.map((item) => formatBindingScalar(item)).join(', ');
  }
 
  return JSON.stringify(value);
}
 
export function hasBindingFields(
  binding: Record<string, unknown>,
  ignore: string[] = ['bindingVersion'],
): boolean {
  return Object.keys(binding).some(
    (key) => !ignore.includes(key) && !key.startsWith('x-') && binding[key] !== undefined,
  );
}
 
export function joinBindingSummary(
  ...parts: (string | undefined | null | false)[]
): string | undefined {
  const filtered = parts.filter((part): part is string => Boolean(part));
  return filtered.length > 0 ? filtered.join(' · ') : undefined;
}

Sources: packages/asyncapi/src/ui/bindings/shared.tsx:24-50

Utility FunctionParameter TypeReturn TypeBehavior
formatBindingScalarunknownstringConverts booleans to 'Yes' / 'No', serializes arrays recursively, or falls back to JSON.stringify.
hasBindingFieldsRecord<string, unknown>, string[]booleanVerifies object keys exist while ignoring fields like 'bindingVersion' and x-* extensions.
joinBindingSummary(string | undefined | null | false)[]string | undefinedFilters falsy items and joins summary segments using ' · ' separators.

Sources: packages/asyncapi/src/ui/bindings/shared.tsx:24-50

Tip

Components such as BindingGroup, BindingFieldRow, and BindingScalarValue automatically adapt boolean state badges (rendering emerald styles for true values and muted styles for false) and wrap scalar codes inside responsive definition lists (<dl>).

Was this page helpful?