---
title: "API: Forms and infolists"
description: "Public TypeScript declarations verified against the package export entries."
---

> Documentation Index
> Fetch the complete documentation index at: https://pupitre.rikology.com/llms.txt
> Use this file to discover all available pages before exploring further.

# API: Forms and infolists

This reference is generated before development, checking and building from declarations reachable through the package's published entry points, following re-exports. Internal source-module exports are omitted. Types shown together share their source module; follow the source link for imports and implementation. Use the guides for examples and runtime behavior.

## src/definition/schema.ts

[Source](https://github.com/rikoriswandha/pupitre/blob/main/packages/pupitre/src/definition/schema.ts)

```ts
export type SchemaKind = 'extensionField' | 'extensionEntry' | 'text' | 'email' | 'password' | 'slider' | 'number' | 'textarea' | 'hidden' | 'select' | 'multiSelect' | 'checkbox' | 'checkboxList' | 'radio' | 'toggle' | 'toggleButtons' | 'date' | 'dateTime' | 'time' | 'color' | 'tags' | 'keyValue' | 'markdownEditor' | 'codeEditor' | 'richEditor' | 'fileUpload' | 'builder' | 'repeater' | 'grid' | 'section' | 'fieldset' | 'tabs' | 'tab' | 'group' | 'split' | 'placeholder' | 'html' | 'divider' | 'view' | 'fragment' | 'textEntry' | 'iconEntry' | 'imageEntry' | 'colorEntry' | 'keyValueEntry' | 'repeatableEntry' | 'codeEntry' | 'wizard' | 'step' | 'badgeEntry';

export type ValidationRules = {
    required?: boolean;
    nullable?: boolean;
    minLength?: number;
    maxLength?: number;
    min?: number;
    max?: number;
    step?: number;
    email?: boolean;
    url?: boolean;
    regex?: RegExp | string;
    alpha?: boolean;
    alphaNumeric?: boolean;
    in?: readonly unknown[];
    same?: string;
    different?: string;
    confirmed?: boolean;
    unique?: {
        table?: string;
        column?: string;
        ignoreRecord?: boolean;
    };
    exists?: {
        table: string;
        column: string;
    };
    custom?: readonly unknown[];
};

export type FieldCommon = {
    label?: string | null | FieldClosure<string | null>;
    helperText?: string | null;
    hint?: string | null;
    hintIcon?: string;
    hintTooltip?: string;
    hintColor?: string;
    hintAction?: ActionDefinition;
    placeholder?: string | null;
    default?: unknown | (() => unknown);
    disabled?: boolean | FieldClosure<boolean>;
    readOnly?: boolean;
    visible?: FieldClosure<boolean>;
    hidden?: FieldClosure<boolean>;
    columnSpan?: number | 'full';
    extraAttributes?: Record<string, string>;
    live?: {
        onBlur?: boolean;
        debounce?: number;
        server?: boolean;
    } | true;
    afterStateUpdated?: (args: {
        state: unknown;
        old: unknown;
        get(path: string): any;
        set(path: string, value: unknown): void;
        record?: Record<string, unknown> | null;
        ctx?: HttpContext;
    }) => unknown;
    dehydrated?: boolean;
    dehydratedWhenHidden?: boolean;
    format?: ((record: Record<string, unknown>) => unknown) | 'hex' | 'rgb' | 'hsl';
    dehydrate?: (state: unknown) => unknown;
    rules?: ValidationRules;
};

export type FieldDefinition<K extends SchemaKind, P extends object = object> = FieldCommon & P & {
    kind: K;
    name: string;
};

export type FieldDefinitionUnion = ExtensionFieldDefinition | TextFieldDefinition | NumberFieldDefinition | SliderFieldDefinition | TextareaFieldDefinition | SelectFieldDefinition | CheckboxFieldDefinition | CheckboxListFieldDefinition | RadioFieldDefinition | ToggleFieldDefinition | ToggleButtonsFieldDefinition | DateFieldDefinition | ColorFieldDefinition | TagsFieldDefinition | KeyValueFieldDefinition | MarkdownEditorFieldDefinition | CodeEditorFieldDefinition | RichEditorFieldDefinition | FileUploadFieldDefinition | RepeaterFieldDefinition | BuilderFieldDefinition | HiddenFieldDefinition;

export type LayoutDefinition = WizardDefinition | WizardStepDefinition | {
    kind: 'grid';
    children: SchemaNodeDefinition[];
    columns?: number | Record<string, number>;
    gap?: number;
    visible?: FieldClosure<boolean>;
    hidden?: FieldClosure<boolean>;
    columnSpan?: number | 'full';
    extraAttributes?: Record<string, string>;
} | {
    kind: 'section';
    children: SchemaNodeDefinition[];
    heading?: string;
    description?: string;
    icon?: string;
    collapsible?: boolean;
    collapsed?: boolean;
    aside?: boolean;
    compact?: boolean;
    columns?: number | Record<string, number>;
    visible?: FieldClosure<boolean>;
    hidden?: FieldClosure<boolean>;
    columnSpan?: number | 'full';
    extraAttributes?: Record<string, string>;
} | {
    kind: 'fieldset';
    children: SchemaNodeDefinition[];
    label?: string;
    columns?: number | Record<string, number>;
    visible?: FieldClosure<boolean>;
    hidden?: FieldClosure<boolean>;
    columnSpan?: number | 'full';
    extraAttributes?: Record<string, string>;
} | {
    kind: 'tabs';
    children: SchemaNodeDefinition[];
    visible?: FieldClosure<boolean>;
    hidden?: FieldClosure<boolean>;
    columnSpan?: number | 'full';
    extraAttributes?: Record<string, string>;
} | {
    kind: 'tab';
    name: string;
    children: SchemaNodeDefinition[];
    visible?: FieldClosure<boolean>;
    hidden?: FieldClosure<boolean>;
    columnSpan?: number | 'full';
    extraAttributes?: Record<string, string>;
} | {
    kind: 'group';
    name?: string;
    children: SchemaNodeDefinition[];
    visible?: FieldClosure<boolean>;
    hidden?: FieldClosure<boolean>;
    columnSpan?: number | 'full';
    extraAttributes?: Record<string, string>;
} | {
    kind: 'fragment';
    children: SchemaNodeDefinition[];
    visible?: FieldClosure<boolean>;
    hidden?: FieldClosure<boolean>;
    columnSpan?: number | 'full';
    extraAttributes?: Record<string, string>;
} | {
    kind: 'split';
    children: SchemaNodeDefinition[];
    columns?: number | Record<string, number>;
    visible?: FieldClosure<boolean>;
    hidden?: FieldClosure<boolean>;
    columnSpan?: number | 'full';
    extraAttributes?: Record<string, string>;
} | {
    kind: 'placeholder';
    name: string;
    label?: string;
    content?: unknown | FieldClosure;
    visible?: FieldClosure<boolean>;
    hidden?: FieldClosure<boolean>;
    columnSpan?: number | 'full';
    extraAttributes?: Record<string, string>;
} | {
    kind: 'html';
    content?: string | FieldClosure<string>;
    visible?: FieldClosure<boolean>;
    hidden?: FieldClosure<boolean>;
    columnSpan?: number | 'full';
    extraAttributes?: Record<string, string>;
} | {
    kind: 'divider';
    visible?: FieldClosure<boolean>;
    hidden?: FieldClosure<boolean>;
    columnSpan?: number | 'full';
    extraAttributes?: Record<string, string>;
} | {
    kind: 'view';
    component: string;
    props?: Record<string, unknown>;
    visible?: FieldClosure<boolean>;
    hidden?: FieldClosure<boolean>;
    columnSpan?: number | 'full';
    extraAttributes?: Record<string, string>;
};

export type EntryDefinition = ExtensionEntryDefinition | TextEntryDefinition | IconEntryDefinition | ImageEntryDefinition | ColorEntryDefinition | KeyValueEntryDefinition | RepeatableEntryDefinition | CodeEntryDefinition | BadgeEntryDefinition;

export type SchemaNodeDefinition = FieldDefinitionUnion | LayoutDefinition | EntryDefinition;

export type SchemaComponent = SchemaNodeBuilder;

export type ComponentDefinition = SchemaNodeDefinition;

export interface TextBuilder extends FieldBuilderBase<TextFieldDefinition> {
    prefix(value: string): this;
    suffix(value: string): this;
    mask(value: string): this;
    prefixAction(value: ActionDefinition | ActionBuilder): this;
    suffixAction(value: ActionDefinition | ActionBuilder): this;
    autocomplete(value: string): this;
    datalist(value: readonly string[]): this;
    minLength(value: number): this;
    maxLength(value: number): this;
    regex(value: RegExp | string): this;
    alpha(): this;
    alphaNumeric(): this;
    email(): this;
    url(): this;
    tel(): this;
    telRegex(value: RegExp | string): this;
    in(value: readonly unknown[]): this;
    same(field: string): this;
    different(field: string): this;
    confirmed(): this;
    unique(value?: NonNullable<ValidationRules['unique']>): this;
    exists(value: NonNullable<ValidationRules['exists']>): this;
}

export interface PasswordBuilder extends TextBuilder {
    revealable(value?: boolean): this;
}

export interface NumberBuilder extends FieldBuilderBase<NumberFieldDefinition> {
    min(value: number): this;
    max(value: number): this;
    step(value: number): this;
    prefix(value: string): this;
    suffix(value: string): this;
    unique(value?: NonNullable<ValidationRules['unique']>): this;
}

export interface TextareaBuilder extends FieldBuilderBase<TextareaFieldDefinition> {
    rows(value: number): this;
    minLength(value: number): this;
    maxLength(value: number): this;
    autosize(value?: boolean): this;
}

export interface SelectBuilder extends FieldBuilderBase<Extract<SelectFieldDefinition, {
    kind: 'select';
}>> {
    options(value: SelectOptions | ((args: SelectOptionsContext) => unknown | Promise<unknown>)): this;
    relationship(name: string, titleColumn: string, scope?: RelationshipOptions['scope']): this;
    searchable(columns?: readonly string[]): this;
    preload(value?: boolean): this;
    getOptionLabelUsing(callback: NonNullable<Extract<SelectFieldDefinition, {
        kind: 'select';
    }>['getOptionLabelUsing']>): this;
    createOptionForm(value: readonly SchemaNodeBuilder[]): this;
    createOptionUsing(callback: NonNullable<Extract<SelectFieldDefinition, {
        kind: 'select';
    }>['createOptionUsing']>): this;
    prefixAction(value: ActionDefinition | ActionBuilder): this;
    suffixAction(value: ActionDefinition | ActionBuilder): this;
    clearable(value?: boolean): this;
    multiple(value?: boolean): this;
    in(value: readonly unknown[]): this;
    exists(value: NonNullable<ValidationRules['exists']>): this;
}

export interface MultiSelectBuilder extends FieldBuilderBase<Extract<SelectFieldDefinition, {
    kind: 'multiSelect';
}>> {
    options(value: SelectOptions | ((args: SelectOptionsContext) => unknown | Promise<unknown>)): this;
    relationship(name: string, titleColumn: string, scope?: RelationshipOptions['scope']): this;
    searchable(columns?: readonly string[]): this;
    preload(value?: boolean): this;
    getOptionLabelUsing(callback: NonNullable<Extract<SelectFieldDefinition, {
        kind: 'multiSelect';
    }>['getOptionLabelUsing']>): this;
    createOptionForm(value: readonly SchemaNodeBuilder[]): this;
    createOptionUsing(callback: NonNullable<Extract<SelectFieldDefinition, {
        kind: 'multiSelect';
    }>['createOptionUsing']>): this;
    prefixAction(value: ActionDefinition | ActionBuilder): this;
    suffixAction(value: ActionDefinition | ActionBuilder): this;
    clearable(value?: boolean): this;
    in(value: readonly unknown[]): this;
    exists(value: NonNullable<ValidationRules['exists']>): this;
}

export interface DateBuilder extends FieldBuilderBase<DateFieldDefinition> {
    minDate(value: string): this;
    maxDate(value: string): this;
    timezone(value: string): this;
    seconds(value?: boolean): this;
}

export interface RepeaterBuilder extends FieldBuilderBase<RepeaterFieldDefinition> {
    schema(value: readonly SchemaNodeBuilder[] | ((repeater: SchemaNamespace) => readonly SchemaNodeBuilder[])): this;
    table(columns?: readonly RepeaterTableColumnBuilder[]): this;
    minItems(value: number): this;
    maxItems(value: number): this;
    reorderable(value?: boolean): this;
    collapsible(value?: boolean): this;
    collapsed(value?: boolean): this;
    cloneable(value?: boolean): this;
    addLabel(value: string): this;
    itemLabel(value: string | FieldClosure<string>): this;
    defaultItems(value: number): this;
    relationship(name: string, options?: Omit<RepeaterRelationshipOptions, 'name'>): this;
    grid(columns: number | Record<string, number>): this;
}

export interface FileUploadBuilder extends FieldBuilderBase<FileUploadFieldDefinition> {
    disk(value: string): this;
    image(value?: boolean): this;
    maxSize(value: number | `${number}kb` | `${number}mb`): this;
    multiple(value?: boolean): this;
    maxFiles(value: number): this;
    accept(value: string | readonly string[]): this;
    directory(value: string): this;
    visibility(value: 'public' | 'private'): this;
    reorderable(value?: boolean): this;
    imageEditor(value?: boolean): this;
    imageEditorAspectRatios(value: readonly (string | null)[]): this;
    downloadable(value?: boolean): this;
    previewable(value?: boolean): this;
}

export interface RichEditorBuilder extends FieldBuilderBase<RichEditorFieldDefinition> {
    mergeTags(value: readonly string[] | Record<string, string>): this;
    mentions(value: readonly (MentionProviderBuilder | MentionProviderDefinition)[]): this;
    customBlocks(value: readonly (RichBlockBuilder | RichBlockDefinition)[]): this;
    toolbar(value: readonly string[]): this;
    minHeight(value: number): this;
    maxHeight(value: number): this;
    fileAttachmentsDisk(value: string): this;
    fileAttachmentsDirectory(value: string): this;
}

export interface CheckboxBuilder extends FieldBuilderBase<CheckboxFieldDefinition> {
    inline(value?: boolean): this;
}

export interface CheckboxListBuilder extends FieldBuilderBase<CheckboxListFieldDefinition> {
    options(value: Record<string, unknown> | readonly unknown[]): this;
    columns(value: number): this;
}

export interface RadioBuilder extends FieldBuilderBase<RadioFieldDefinition> {
    options(value: Record<string, unknown> | readonly unknown[]): this;
    descriptions(value: Record<string, string>): this;
    inline(value?: boolean): this;
}

export interface ToggleBuilder extends FieldBuilderBase<ToggleFieldDefinition> {
    onIcon(value: string): this;
    offIcon(value: string): this;
    onColor(value: string): this;
    offColor(value: string): this;
    inline(value?: boolean): this;
}

export interface ToggleButtonsBuilder extends FieldBuilderBase<ToggleButtonsFieldDefinition> {
    options(value: Record<string, unknown> | readonly unknown[]): this;
    multiple(value?: boolean): this;
    grouped(value?: boolean): this;
    icons(value: Record<string, string>): this;
    colors(value: Record<string, string>): this;
}

export interface ColorBuilder extends Omit<FieldBuilderBase<ColorFieldDefinition>, 'format'> {
    presets(value: readonly string[]): this;
}

export interface TagsBuilder extends FieldBuilderBase<TagsFieldDefinition> {
    suggestions(value: readonly string[]): this;
    separator(value: string): this;
    maxTags(value: number): this;
    reorderable(value?: boolean): this;
}

export interface KeyValueBuilder extends FieldBuilderBase<KeyValueFieldDefinition> {
    keyLabel(value: string): this;
    valueLabel(value: string): this;
    addable(value?: boolean): this;
    deletable(value?: boolean): this;
    reorderable(value?: boolean): this;
    keyPlaceholder(value: string): this;
    valuePlaceholder(value: string): this;
}

export interface LayoutBase<D extends LayoutDefinition> extends ComponentBuilder<D> {
    visible(value: FieldClosure<boolean>): this;
    hidden(value: FieldClosure<boolean>): this;
    columnSpan(value: number | 'full'): this;
    extraAttributes(value: Record<string, string>): this;
}

export interface GridBuilder extends LayoutBase<Extract<LayoutDefinition, {
    kind: 'grid';
}>> {
    components(value: readonly SchemaNodeBuilder[]): this;
    columns(value: number | Record<string, number>): this;
    gap(value: number): this;
}

export interface SectionBuilder extends LayoutBase<Extract<LayoutDefinition, {
    kind: 'section';
}>> {
    components(value: readonly SchemaNodeBuilder[]): this;
    heading(value: string): this;
    description(value: string): this;
    icon(value: string): this;
    collapsible(value?: boolean): this;
    collapsed(value?: boolean): this;
    aside(value?: boolean): this;
    compact(value?: boolean): this;
    columns(value: number | Record<string, number>): this;
}

export interface FieldsetBuilder extends LayoutBase<Extract<LayoutDefinition, {
    kind: 'fieldset';
}>> {
    components(value: readonly SchemaNodeBuilder[]): this;
    label(value: string): this;
    columns(value: number | Record<string, number>): this;
}

export interface ChildrenLayoutBuilder extends LayoutBase<Extract<LayoutDefinition, {
    kind: 'tabs' | 'tab' | 'group' | 'fragment';
}>> {
    components(value: readonly SchemaNodeBuilder[]): this;
}

export interface SplitBuilder extends LayoutBase<Extract<LayoutDefinition, {
    kind: 'split';
}>> {
    components(value: readonly SchemaNodeBuilder[]): this;
    columns(value: number | Record<string, number>): this;
}

export interface PlaceholderBuilder extends LayoutBase<Extract<LayoutDefinition, {
    kind: 'placeholder';
}>> {
    label(value: string): this;
    content(value: FieldClosure | string | number | boolean | null): this;
}

export interface HtmlBuilder extends LayoutBase<Extract<LayoutDefinition, {
    kind: 'html';
}>> {
    content(value: string | FieldClosure<string>): this;
}

export interface ViewBuilder extends LayoutBase<Extract<LayoutDefinition, {
    kind: 'view';
}>> {
    props(value: Record<string, unknown>): this;
}

export interface DividerBuilder extends LayoutBase<Extract<LayoutDefinition, {
    kind: 'divider';
}>> {
}

export interface TextEntryBuilder extends ComponentBuilder<Extract<EntryDefinition, {
    kind: 'textEntry';
}>> {
    label(value: string | null): this;
    badge(value?: boolean): this;
    copyable(value?: boolean): this;
    url(value: NonNullable<TextEntryDefinition['url']>): this;
    dateTime(value?: string): this;
    timezone(value: string): this;
    date(value?: string): this;
    since(value?: boolean): this;
    money(currency: string): this;
    limit(value: number): this;
    markdown(value?: boolean): this;
    html(value?: boolean): this;
    richContent(value: RichContentOptions | FieldClosure<RichContentOptions>): this;
    /** Display labels for stored option values, e.g. `{ draft: 'Draft' }`. */
    options(value: SelectOptions): this;
}

export interface IconEntryBuilder extends ComponentBuilder<Extract<EntryDefinition, {
    kind: 'iconEntry';
}>> {
    label(value: string | null): this;
    boolean(value?: boolean): this;
    icons(value: Record<string, string>): this;
    colors(value: Record<string, string>): this;
}

export interface ImageEntryBuilder extends ComponentBuilder<Extract<EntryDefinition, {
    kind: 'imageEntry';
}>> {
    label(value: string | null): this;
    circular(value?: boolean): this;
}

export interface BadgeEntryBuilder extends SimpleEntryBuilder<Extract<EntryDefinition, {
    kind: 'badgeEntry';
}>> {
    /** Badge colors keyed by the raw stored value. */
    colors(value: Record<string, string>): this;
    /** Display labels for stored option values; `colors` stay keyed by the raw value. */
    options(value: SelectOptions): this;
}

export interface RepeatableEntryBuilder extends SimpleEntryBuilder<Extract<EntryDefinition, {
    kind: 'repeatableEntry';
}>> {
    schema(value: readonly SimpleEntryBuilder<EntryDefinition>[]): this;
}

export type SchemaNodeBuilder = FieldBuilderBase<FieldDefinitionUnion> | TextBuilder | PasswordBuilder | NumberBuilder | SliderBuilder | TextareaBuilder | SelectBuilder | MultiSelectBuilder | DateBuilder | RepeaterBuilder | FileUploadBuilder | RichEditorBuilder | CheckboxBuilder | CheckboxListBuilder | RadioBuilder | ToggleBuilder | ToggleButtonsBuilder | ColorBuilder | TagsBuilder | KeyValueBuilder | BuilderBuilder | WizardBuilder | StepBuilder | GridBuilder | SectionBuilder | FieldsetBuilder | ChildrenLayoutBuilder | SplitBuilder | PlaceholderBuilder | HtmlBuilder | ViewBuilder | DividerBuilder | TextEntryBuilder | IconEntryBuilder | ImageEntryBuilder | SimpleEntryBuilder<EntryDefinition>;

export type FormSchema<M = never> = Omit<SchemaNamespace, keyof FieldConstructors<M> | 'components' | 'entries'> & FieldConstructors<M> & {
    components(value: readonly SchemaNodeBuilder[]): {
        components: SchemaNodeDefinition[];
    };
    entries(value: readonly SchemaNodeBuilder[]): {
        entries: SchemaNodeDefinition[];
    };
};

export type SchemaNamespace = FieldConstructors<never> & {
    grid(): GridBuilder;
    section(heading?: string): SectionBuilder;
    fieldset(label?: string): FieldsetBuilder;
    tabs(tabs?: readonly SchemaNodeBuilder[]): ChildrenLayoutBuilder;
    tab(name: string): ChildrenLayoutBuilder;
    group(name?: string): ChildrenLayoutBuilder;
    split(...children: readonly SchemaNodeBuilder[]): SplitBuilder;
    placeholder(name: string): PlaceholderBuilder;
    html(content?: string): HtmlBuilder;
    divider(): DividerBuilder;
    view(component: string, props?: Record<string, unknown>): ViewBuilder;
    fragment(children?: readonly SchemaNodeBuilder[]): ChildrenLayoutBuilder;
    block(name: string): BuilderBlockBuilder;
    wizard(steps?: readonly SchemaNodeBuilder[]): WizardBuilder;
    step(name: string): StepBuilder;
};
```

Source: https://pupitre.rikology.com/reference/api-schema/index.mdx
