import { Component } from 'vue';
import { IconType } from '../types';
type Primitive = string | number | boolean | null | undefined | Date | ((...args: any[]) => any);
/** Option object format for select/radio/multiselect fields */
export interface SelectOption<T extends string = string> {
    label: string;
    value: T;
    icon?: IconType;
}
/** Async options loader function */
export type AsyncOptionsLoader<T extends string = string> = (query: string) => Promise<(T | SelectOption<T>)[]>;
/** Options can be string array, object array, or async loader function */
export type SelectOptions<T extends string = string> = T[] | readonly T[] | SelectOption<T>[] | readonly SelectOption<T>[] | AsyncOptionsLoader<T>;
/**
 * Extract all possible nested keys from a type, including:
 * - Dot notation paths: 'meta.bio'
 * - Array index paths: 'rules[0].name'
 *
 * @example
 * interface Form {
 *   name: string
 *   meta: { bio: string }
 *   rules: Array<{ field: string, value: number }>
 * }
 *
 * type Keys = NestedKeyOf<Form>
 * // 'name' | 'meta' | 'meta.bio' | 'rules' | 'rules[0]' | 'rules[0].field' | 'rules[0].value'
 */
export type NestedKeyOf<T> = T extends Primitive ? never : {
    [K in keyof T & string]: K | (T[K] extends Primitive ? never : T[K] extends Array<infer U> ? `${K}[${number}]` | (U extends Primitive ? never : `${K}[${number}].${NestedKeyOf<U>}`) : `${K}.${NestedKeyOf<T[K]>}`);
}[keyof T & string];
interface BaseFieldConfig {
    label?: string;
    required?: boolean;
    placeholder?: string;
    helpText?: string;
    underlined?: boolean;
    default?: any;
    class?: string;
}
interface TextFieldConfig {
    multiline?: boolean;
    pattern?: string;
    icon?: IconType;
    rows?: number;
    autofocus?: boolean;
}
/**
 * Syntactic sugar for required: true
 * @example $.email({ required }) instead of $.email({ required: true })
 */
export declare const required = true;
export interface FieldBuilder<TValue = any> {
    _type: string;
    _config: BaseFieldConfig & Record<string, any>;
    _condition?: string;
    _validations?: Array<(value: TValue) => true | string>;
    _onUpdate?: (value: TValue, formData: Record<string, any>) => void;
    _class?: string;
    _slots?: Array<SlotConfig>;
    _component?: ComponentConfig;
    if: (condition: string) => FieldBuilder<TValue>;
    validate: (fn: (value: TValue) => true | string) => FieldBuilder<TValue>;
    onUpdate: (fn: (value: TValue, formData: Record<string, any>) => void) => FieldBuilder<TValue>;
    class: (className: string) => FieldBuilder<TValue>;
    required: (message?: string) => FieldBuilder<TValue>;
    slot: {
        (component: Component | string, props?: Record<string, any>): FieldBuilder<TValue>;
        (slotName: string, component: Component | string, props?: Record<string, any>): FieldBuilder<TValue>;
    };
}
interface SlotConfig {
    name?: string;
    component: Component | string;
    props?: Record<string, any>;
}
interface ComponentConfig {
    component: Component | string;
    props?: Record<string, any>;
}
export interface SchemaDefinition<T extends Record<string, any> = Record<string, any>> {
    /** Phantom type — not present at runtime, used for FormFlow generic inference */
    readonly __type: T;
    _isSchema: true;
    _label?: string;
    _fields: Record<string, FieldBuilder>;
    _condition?: string;
    _class?: string;
    if: (condition: string) => SchemaDefinition<T>;
    class: (className: string) => SchemaDefinition<T>;
    toJSONSchema: () => any;
}
export declare const $: {
    text(labelOrConfig?: string | (BaseFieldConfig & TextFieldConfig), config?: BaseFieldConfig & TextFieldConfig): FieldBuilder<string>;
    email(labelOrConfig?: string | BaseFieldConfig, config?: BaseFieldConfig): FieldBuilder<string>;
    password(labelOrConfig?: string | BaseFieldConfig, config?: BaseFieldConfig): FieldBuilder<string>;
    number(labelOrConfig?: string | (BaseFieldConfig & {
        min?: number;
        max?: number;
        step?: number;
    }), config?: BaseFieldConfig & {
        min?: number;
        max?: number;
        step?: number;
    }): FieldBuilder<number>;
    tel(labelOrConfig?: string | (BaseFieldConfig & {
        onlyCountries?: string[];
        defaultCountry?: string;
    }), config?: BaseFieldConfig & {
        onlyCountries?: string[];
        defaultCountry?: string;
    }): FieldBuilder<string>;
    url(labelOrConfig?: string | BaseFieldConfig, config?: BaseFieldConfig): FieldBuilder<string>;
    date(labelOrConfig?: string | (BaseFieldConfig & {
        min?: string;
        max?: string;
    }), config?: BaseFieldConfig & {
        min?: string;
        max?: string;
    }): FieldBuilder<string>;
    time(labelOrConfig?: string | BaseFieldConfig, config?: BaseFieldConfig): FieldBuilder<string>;
    datetime(labelOrConfig?: string | BaseFieldConfig, config?: BaseFieldConfig): FieldBuilder<string>;
    textarea(labelOrConfig?: string | (BaseFieldConfig & {
        rows?: number;
        cols?: number;
    }), config?: BaseFieldConfig & {
        rows?: number;
        cols?: number;
    }): FieldBuilder<string>;
    richtext(labelOrConfig?: string | (BaseFieldConfig & {
        autoheight?: boolean;
        basic?: boolean;
    }), config?: BaseFieldConfig & {
        autoheight?: boolean;
        basic?: boolean;
    }): FieldBuilder<string>;
    json(labelOrConfig?: string | (BaseFieldConfig & {
        language?: string;
        height?: string;
    }), config?: BaseFieldConfig & {
        language?: string;
        height?: string;
    }): FieldBuilder<Record<string, any>>;
    checkbox(labelOrConfig?: string | BaseFieldConfig, config?: BaseFieldConfig): FieldBuilder<boolean>;
    toggle(labelOrConfig?: string | BaseFieldConfig, config?: BaseFieldConfig): FieldBuilder<boolean>;
    radio<T extends string = string>(optionsOrLabel: SelectOptions<T> | string, labelOrOptionsOrConfig?: string | SelectOptions<T> | BaseFieldConfig, config?: BaseFieldConfig): FieldBuilder<T>;
    select<T extends string = string>(optionsOrLabel: SelectOptions<T> | string, labelOrOptionsOrConfig?: string | SelectOptions<T> | (BaseFieldConfig & {
        searchable?: boolean;
    }), config?: BaseFieldConfig & {
        searchable?: boolean;
    }): FieldBuilder<T>;
    multiselect<T extends string = string>(optionsOrLabel: SelectOptions<T> | string, labelOrOptionsOrConfig?: string | SelectOptions<T> | (BaseFieldConfig & {
        searchable?: boolean;
    }), config?: BaseFieldConfig & {
        searchable?: boolean;
    }): FieldBuilder<T[]>;
    color(labelOrConfig?: string | BaseFieldConfig, config?: BaseFieldConfig): FieldBuilder<string>;
    upload(labelOrConfig?: string | (BaseFieldConfig & {
        multiple?: boolean;
        accept?: string;
        capture?: boolean | "user" | "environment";
        dirPath?: string;
        width?: string;
        height?: string;
        icon?: IconType;
        theme?: "dropzone" | "basic";
        fill?: boolean;
        oval?: boolean;
        placeholder?: string;
        noFilePlaceholder?: string;
        btnPlaceholder?: string;
        style?: string;
    }), config?: BaseFieldConfig & {
        multiple?: boolean;
        accept?: string;
        capture?: boolean | "user" | "environment";
        dirPath?: string;
        width?: string;
        icon?: IconType;
        height?: string;
        theme?: "dropzone" | "basic";
        fill?: boolean;
        oval?: boolean;
        placeholder?: string;
        noFilePlaceholder?: string;
        btnPlaceholder?: string;
        style?: string;
    }): FieldBuilder<string | string[]>;
    array(labelOrSchemaOrComponent?: string | SchemaDefinition | Component, schemaOrComponentOrConfig?: SchemaDefinition | Component | string | (BaseFieldConfig & {
        allowAdd?: boolean;
        allowDelete?: boolean;
        allowReorder?: boolean;
        collapsible?: boolean;
        min?: number;
        max?: number;
    }), maybeConfig?: BaseFieldConfig & {
        allowAdd?: boolean;
        allowDelete?: boolean;
        allowReorder?: boolean;
        collapsible?: boolean;
        min?: number;
        max?: number;
    }): FieldBuilder<any[]>;
    component(component: Component | string, props?: Record<string, any>): FieldBuilder;
    /**
     * Display-only component that receives formData but doesn't bind to a field value.
     * Useful for summaries, previews, info panels, etc.
     *
     * @example
     * $.display(Summary)
     * $.display(Summary, { showPrice: true })
     *
     * // The component receives: { formData, ...props }
     */
    display(component: Component | string, props?: Record<string, any>): FieldBuilder<void>;
};
/**
 * Define a single-step form schema or a step in a multi-step form
 *
 * Supports both direct keys and nested paths (dot notation):
 * - Direct: { email: $.email() }
 * - Nested: { 'meta.bio': $.text() }
 *
 * @example
 * // Single-step form
 * const userSchema = defineSchema<User>({
 *   email: $.email({ required: true }),
 *   firstName: $.text({ required: true }),
 *   'meta.bio': $.richtext() // Nested path - type-checked!
 * })
 *
 * @example
 * // Multi-step form step (with label)
 * const step = defineSchema('Personal Info', {
 *   firstName: $.text({ required: true }),
 *   lastName: $.text({ required: true })
 * })
 */
export declare function defineSchema<T extends Record<string, any>>(labelOrFields: string | Partial<Record<NestedKeyOf<T>, FieldBuilder>>, maybeFields?: Partial<Record<NestedKeyOf<T>, FieldBuilder>>): SchemaDefinition<T>;
/**
 * Multi-step schema type with embedded form data type
 * The __type property is a phantom type for TypeScript inference
 */
export type MultiStepSchemaDefinition<T = any> = Record<string, SchemaDefinition> & {
    /** Phantom type for form data inference (not present at runtime) */
    __type?: T;
};
/**
 * Define a multi-step form schema
 *
 * @param T - The final merged form data type across all steps
 *
 * @example
 * interface OnboardingData {
 *   userType: 'individual' | 'business'
 *   firstName: string
 *   lastName: string
 *   companyName?: string
 * }
 *
 * const onboardingFlow = multiStepSchema<OnboardingData>({
 *   user_type: schema('Who are you?', {
 *     userType: $.radio(['individual', 'business'], { required: true })
 *   }),
 *   personal_info: schema('Personal Information', {
 *     firstName: $.text({ required: true }),
 *     lastName: $.text({ required: true })
 *   }),
 *   business_info: schema('Company Details', {
 *     companyName: $.text({ required: true })
 *   }).if('userType eq "business"')
 * })
 *
 * // Later, extract the type:
 * type FormData = NonNullable<typeof onboardingFlow.__type>
 */
export declare function multiStepSchema<T extends Record<string, any> = Record<string, any>>(steps: Record<string, SchemaDefinition>): MultiStepSchemaDefinition<T>;
interface JSONSchemaProperty {
    'type'?: string;
    'title'?: string;
    'description'?: string;
    'default'?: any;
    'enum'?: any[];
    'format'?: string;
    'minimum'?: number;
    'maximum'?: number;
    'minLength'?: number;
    'maxLength'?: number;
    '$ref'?: string;
    'items'?: JSONSchemaProperty;
    'anyOf'?: JSONSchemaProperty[];
    'oneOf'?: JSONSchemaProperty[];
    'allOf'?: JSONSchemaProperty[];
    'additionalProperties'?: boolean | JSONSchemaProperty;
    'x-ui'?: {
        fieldType?: string;
        placeholder?: string;
        disabled?: boolean;
        readonly?: boolean;
        autoheight?: boolean;
        rows?: number;
        cols?: number;
        class?: string;
        condition?: string;
        allowAdd?: boolean;
        allowDelete?: boolean;
        component?: string;
        componentProps?: Record<string, any>;
    };
}
interface JSONSchemaObject {
    'type'?: string;
    'title'?: string;
    'properties'?: Record<string, JSONSchemaProperty>;
    'required'?: string[];
    '$defs'?: Record<string, JSONSchemaProperty>;
    'definitions'?: Record<string, JSONSchemaProperty>;
    'x-ui'?: {
        condition?: string;
        class?: string;
    };
}
/**
 * Create a schema from a JSONSchema object
 *
 * This allows you to save schemas to a database and load them later.
 *
 * @example
 * // Save to database
 * const jsonSchema = mySchema.toJSONSchema()
 * await db.schemas.insert({ name: 'user-form', schema: jsonSchema })
 *
 * // Load from database
 * const saved = await db.schemas.findOne({ name: 'user-form' })
 * const loadedSchema = fromJSONSchema(saved.schema)
 *
 * // Use in component
 * <FormFlow v-model="data" :schema="loadedSchema" />
 */
export declare function fromJSONSchema(jsonSchema: JSONSchemaObject): SchemaDefinition;
/**
 * Infer the TypeScript type from a schema definition
 */
export type InferSchemaType<S extends SchemaDefinition> = {
    [K in keyof S['_fields']]: InferFieldType<S['_fields'][K]>;
};
type InferFieldType<F> = F extends FieldBuilder<infer T> ? T : any;
export {};
//# sourceMappingURL=form-flow.d.ts.map