import type { AnySchemaModel, ZodSchemaModel } from '@contractspec/lib.schema';
import type { DocBlock } from '../docs/types';
import type { OwnerShipMeta } from '../ownership';
export type PredicateOp = 'equals' | 'notEquals' | 'in' | 'notIn' | 'gt' | 'gte' | 'lt' | 'lte' | 'truthy' | 'empty' | 'lengthGt' | 'lengthGte' | 'lengthLt' | 'lengthLte';
export interface WhenClause {
    /** Dot path in form values; arrays may use `$index` within array context. */
    path: string;
    op?: PredicateOp;
    value?: unknown;
}
export interface Predicate {
    when?: WhenClause;
    all?: Predicate[];
    anyOf?: Predicate[];
    not?: Predicate;
}
export interface FormOption {
    labelI18n: string;
    value: string | number | boolean;
    descriptionI18n?: string;
    disabled?: boolean;
}
export interface AutocompleteOption {
    labelI18n: string;
    value: string | number | boolean;
    descriptionI18n?: string;
    disabled?: boolean;
    data?: Record<string, unknown>;
}
export type OptionsSource = {
    kind: 'static';
    options: readonly FormOption[];
} | {
    kind: 'resolver';
    resolverKey: string;
    /** Dot paths in form values to watch */
    deps: string[];
    args?: Record<string, unknown>;
};
export interface AddressFormValue {
    line1: string;
    line2?: string;
    city?: string;
    region?: string;
    postalCode?: string;
    countryCode?: string;
}
export interface PhoneFormValue {
    countryCode: string;
    nationalNumber: string;
    extension?: string;
    e164?: string;
}
export type CurrencyCode = 'USD' | 'EUR' | 'GBP' | 'JPY' | 'CHF' | 'CAD' | 'AUD' | 'BTC' | 'ETH' | (string & {});
export type NumberRoundingMode = 'ceil' | 'floor' | 'expand' | 'trunc' | 'halfCeil' | 'halfFloor' | 'halfExpand' | 'halfTrunc' | 'halfEven';
export interface NumberRoundingSpec {
    mode?: NumberRoundingMode;
    increment?: number;
}
export interface NumberFormatSpec {
    locale?: string;
    minimumFractionDigits?: number;
    maximumFractionDigits?: number;
    useGrouping?: boolean;
    notation?: 'standard' | 'scientific' | 'engineering' | 'compact';
    signDisplay?: 'auto' | 'always' | 'exceptZero' | 'negative' | 'never';
    rounding?: NumberRoundingSpec;
}
export interface PercentFormatSpec extends NumberFormatSpec {
    /** `fraction` stores 0.42 as 42%; `whole` stores 42 as 42%. */
    valueScale?: 'fraction' | 'whole';
}
export interface CurrencyFormatSpec extends NumberFormatSpec {
    currency: CurrencyCode;
    currencyDisplay?: 'symbol' | 'narrowSymbol' | 'code' | 'name';
    /** Convenience signal for renderers that should use whole-unit display. */
    rounded?: boolean;
}
export interface TemporalFormatSpec {
    locale?: string;
    calendar?: string;
    timeZone?: string;
    dateStyle?: 'full' | 'long' | 'medium' | 'short';
    timeStyle?: 'full' | 'long' | 'medium' | 'short';
    hour12?: boolean;
}
export type DurationUnit = 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year';
export interface DurationFormatSpec {
    locale?: string;
    unit?: DurationUnit;
    display?: 'short' | 'narrow' | 'long' | 'digital';
    maxUnit?: DurationUnit;
    minUnit?: DurationUnit;
    rounding?: NumberRoundingSpec;
}
export type AutocompleteValueMapping = {
    mode: 'scalar';
    valueKey?: string;
} | {
    mode: 'object';
} | {
    mode: 'pick';
    pickKeys: string[];
};
export type AutocompleteSource = {
    kind: 'local';
    options: readonly AutocompleteOption[];
    searchKeys: string[];
} | {
    kind: 'resolver';
    resolverKey: string;
    deps?: string[];
    args?: Record<string, unknown>;
    searchKeys?: string[];
    minQueryLength?: number;
    debounceMs?: number;
};
export interface CompositePartConfig<TKeys extends string> {
    labelsI18n?: Partial<Record<TKeys, string>>;
    placeholdersI18n?: Partial<Record<TKeys, string>>;
}
export type FieldOrientation = 'horizontal' | 'vertical' | 'responsive';
export type ResponsiveColumns = 1 | 2 | 3 | 4 | {
    base?: 1 | 2 | 3 | 4;
    sm?: 1 | 2 | 3 | 4;
    md?: 1 | 2 | 3 | 4;
    lg?: 1 | 2 | 3 | 4;
};
export type ResponsiveColumnBreakpoint = 'sm' | 'md' | 'lg';
export interface ResponsiveFormColumnsOptions {
    breakpoint?: ResponsiveColumnBreakpoint;
    base?: 1;
}
export declare function responsiveFormColumns(columns: Exclude<ResponsiveColumns, object>, options?: ResponsiveFormColumnsOptions): ResponsiveColumns;
export type ResponsiveSpanValue = 1 | 2 | 3 | 4 | 'full';
export type ResponsiveSpan = ResponsiveSpanValue | {
    base?: ResponsiveSpanValue;
    sm?: ResponsiveSpanValue;
    md?: ResponsiveSpanValue;
    lg?: ResponsiveSpanValue;
};
export interface FormSectionLayoutSpec {
    columns?: ResponsiveColumns;
    gap?: 'sm' | 'md' | 'lg';
    fieldOrientation?: FieldOrientation;
}
export type FormFlowKind = 'sections' | 'steps';
export interface FormSectionSpec {
    key: string;
    titleI18n: string;
    descriptionI18n?: string;
    /** Immediate field names from the surrounding field collection. */
    fieldNames: string[];
    layout?: FormSectionLayoutSpec;
}
export interface FormFlowSpec {
    kind: FormFlowKind;
    sections: FormSectionSpec[];
    previousLabelI18n?: string;
    nextLabelI18n?: string;
}
export interface FormLayoutSpec extends FormSectionLayoutSpec {
    flow?: FormFlowSpec;
}
export interface FieldLayoutSpec {
    colSpan?: ResponsiveSpan;
    orientation?: FieldOrientation;
}
export type InputGroupAddonAlign = 'inline-start' | 'inline-end' | 'block-start' | 'block-end';
export type InputGroupAddonItem = {
    kind: 'text';
    textI18n: string;
} | {
    kind: 'icon';
    iconKey: string;
    labelI18n?: string;
};
export interface InputGroupAddonSpec {
    align?: InputGroupAddonAlign;
    items: InputGroupAddonItem[];
}
export interface InputGroupSpec {
    addons?: InputGroupAddonSpec[];
}
export type PasswordFieldPurpose = 'current' | 'new';
export interface PasswordFieldSpec {
    purpose?: PasswordFieldPurpose;
    visibilityToggle?: boolean;
    showLabelI18n?: string;
    hideLabelI18n?: string;
}
export interface BaseFieldSpec {
    /** Field kind discriminator. */
    kind: 'text' | 'email' | 'textarea' | 'select' | 'checkbox' | 'radio' | 'switch' | 'autocomplete' | 'address' | 'phone' | 'number' | 'percent' | 'currency' | 'date' | 'time' | 'datetime' | 'duration' | 'group' | 'array';
    /** Field name (dot path relative to the form root or parent context). */
    name?: string;
    labelI18n?: string;
    descriptionI18n?: string;
    placeholderI18n?: string;
    required?: boolean;
    /** Conditional UI behavior */
    visibleWhen?: Predicate;
    enabledWhen?: Predicate;
    requiredWhen?: Predicate;
    /** UI hints */
    uiKey?: string;
    uiProps?: Record<string, unknown>;
    layout?: FieldLayoutSpec;
    /** @deprecated Use `layout.orientation`. */
    wrapper?: {
        orientation?: 'horizontal' | 'vertical';
    };
    readOnly?: boolean;
    /** HTML/Native autofill token (supports custom tokens) */
    autoComplete?: string;
    /** Keyboard/adaptation hints (web/native). Shape mirrors design-system KeyboardOptions but stays decoupled. */
    keyboard?: {
        kind?: string;
        autoCapitalize?: 'none' | 'sentences' | 'words' | 'characters';
        autoComplete?: string;
        autoCorrect?: boolean;
        enterKeyHint?: 'enter' | 'done' | 'go' | 'next' | 'search' | 'send';
    };
    /** Optional computed value hook, provided by host computations map */
    computeFrom?: {
        computeKey: string;
        deps: string[];
        mode?: 'change' | 'blur-xs' | 'submit';
        readOnly?: boolean;
    };
}
export interface TextFieldSpec extends BaseFieldSpec {
    kind: 'text';
    name: string;
    inputGroup?: InputGroupSpec;
    password?: PasswordFieldSpec;
    inputMode?: 'text' | 'email' | 'tel' | 'url' | 'numeric' | 'decimal' | 'search';
    autoComplete?: string;
    maxLength?: number;
    minLength?: number;
}
export interface EmailFieldSpec extends BaseFieldSpec {
    kind: 'email';
    name: string;
    inputGroup?: InputGroupSpec;
    autoComplete?: string;
    maxLength?: number;
    minLength?: number;
}
export interface TextareaFieldSpec extends BaseFieldSpec {
    kind: 'textarea';
    name: string;
    inputGroup?: InputGroupSpec;
    rows?: number;
    maxLength?: number;
    minLength?: number;
}
export interface SelectFieldSpec extends BaseFieldSpec {
    kind: 'select';
    name: string;
    options: OptionsSource | readonly FormOption[];
}
export interface CheckboxFieldSpec extends BaseFieldSpec {
    kind: 'checkbox';
    name: string;
}
export interface RadioFieldSpec extends BaseFieldSpec {
    kind: 'radio';
    name: string;
    options: OptionsSource | readonly FormOption[];
}
export interface SwitchFieldSpec extends BaseFieldSpec {
    kind: 'switch';
    name: string;
}
export interface AutocompleteFieldSpec extends BaseFieldSpec {
    kind: 'autocomplete';
    name: string;
    multiple?: boolean;
    source: AutocompleteSource;
    valueMapping: AutocompleteValueMapping;
}
export interface AddressFieldSpec extends BaseFieldSpec {
    kind: 'address';
    name: string;
    parts?: CompositePartConfig<keyof AddressFormValue>;
    countryOptions?: OptionsSource | readonly FormOption[];
}
export interface PhoneFieldSpec extends BaseFieldSpec {
    kind: 'phone';
    name: string;
    parts?: CompositePartConfig<keyof PhoneFormValue>;
    countryOptions?: OptionsSource | readonly FormOption[];
}
export interface NumberFieldSpec extends BaseFieldSpec {
    kind: 'number';
    name: string;
    min?: number;
    max?: number;
    step?: number;
    inputMode?: 'numeric' | 'decimal';
    valueMode?: 'number' | 'string';
    format?: NumberFormatSpec;
}
export interface PercentFieldSpec extends BaseFieldSpec {
    kind: 'percent';
    name: string;
    min?: number;
    max?: number;
    step?: number;
    valueScale?: PercentFormatSpec['valueScale'];
    format?: PercentFormatSpec;
}
export interface CurrencyFieldSpec extends BaseFieldSpec {
    kind: 'currency';
    name: string;
    min?: number;
    max?: number;
    step?: number;
    valueMode?: 'number' | 'string';
    format: CurrencyFormatSpec;
}
export interface DateFieldSpec extends BaseFieldSpec {
    kind: 'date';
    name: string;
    minDate?: Date | string;
    maxDate?: Date | string;
    format?: TemporalFormatSpec;
}
export interface TimeFieldSpec extends BaseFieldSpec {
    kind: 'time';
    name: string;
    is24Hour?: boolean;
    format?: TemporalFormatSpec;
}
export interface DateTimeFieldSpec extends BaseFieldSpec {
    kind: 'datetime';
    name: string;
    minDate?: Date | string;
    maxDate?: Date | string;
    is24Hour?: boolean;
    format?: TemporalFormatSpec;
}
export interface DurationFieldSpec extends BaseFieldSpec {
    kind: 'duration';
    name: string;
    min?: number;
    max?: number;
    step?: number;
    valueUnit?: DurationUnit;
    format?: DurationFormatSpec;
}
export interface GroupFieldSpec extends BaseFieldSpec {
    kind: 'group';
    /** Optional legend/label at group level */
    labelI18n?: string;
    legendI18n?: string;
    layout?: FieldLayoutSpec & FormLayoutSpec;
    fields: FieldSpec[];
}
export interface ArrayFieldSpec extends BaseFieldSpec {
    kind: 'array';
    /** Root-level field that is an array in the model (e.g., "emails") */
    name: string;
    /** Child field spec for each item (e.g., address inside emails[i].address). */
    of: Exclude<FieldSpec, ArrayFieldSpec>;
    min?: number;
    max?: number;
}
export type FieldSpec = TextFieldSpec | EmailFieldSpec | TextareaFieldSpec | SelectFieldSpec | CheckboxFieldSpec | RadioFieldSpec | SwitchFieldSpec | AutocompleteFieldSpec | AddressFieldSpec | PhoneFieldSpec | NumberFieldSpec | PercentFieldSpec | CurrencyFieldSpec | DateFieldSpec | TimeFieldSpec | DateTimeFieldSpec | DurationFieldSpec | GroupFieldSpec | ArrayFieldSpec;
export interface FormAction {
    key: string;
    labelI18n: string;
    op?: {
        name: string;
        version: string;
    };
    success?: {
        navigateTo?: string;
        toastI18n?: string;
    };
}
export interface ConstraintDecl {
    key: string;
    messageI18n: string;
    paths: string[];
    args?: Record<string, unknown>;
}
export type FormValuesFor<M extends AnySchemaModel> = ZodSchemaModel<M>;
export interface FormSpec<M extends AnySchemaModel = AnySchemaModel> {
    meta: OwnerShipMeta;
    /** Canonical form data shape */
    model: M;
    /** Flat list or tree using groups/arrays */
    fields: FieldSpec[];
    layout?: FormLayoutSpec;
    policy?: {
        flags?: string[];
        pii?: string[];
    };
    actions?: FormAction[];
    renderHints?: {
        ui: 'shadcn' | 'custom';
        form: 'react-hook-form';
    };
    constraints?: ConstraintDecl[];
}
export declare function isFieldReadOnly(field: Pick<BaseFieldSpec, 'readOnly' | 'computeFrom'>): boolean;
export declare function normalizeFieldSpec<T extends FieldSpec>(field: T): T;
export declare function normalizeFormSpec<M extends AnySchemaModel>(spec: FormSpec<M>): FormSpec<M>;
export declare class FormRegistry {
    private items;
    register(spec: FormSpec): this;
    list(): FormSpec[];
    get(key: string, version?: string): FormSpec<AnySchemaModel> | undefined;
    /** Filter forms by criteria. */
    filter(criteria: import('../registry-utils').RegistryFilter): FormSpec[];
    /** List forms with specific tag. */
    listByTag(tag: string): FormSpec[];
    /** List forms by owner. */
    listByOwner(owner: string): FormSpec[];
    /** Group forms by key function. */
    groupBy(keyFn: import('../registry-utils').GroupKeyFn<FormSpec>): Map<string, FormSpec[]>;
    /** Get unique tags from all forms. */
    getUniqueTags(): string[];
}
export declare function evalPredicate(values: unknown, pred?: Predicate, indices?: readonly number[]): boolean;
export type ConstraintHandler = (values: Record<string, unknown>, paths: string[], args?: Record<string, unknown>) => {
    ok: true;
} | {
    ok: false;
    message?: string;
    path?: string;
};
/**
 * Wrap the base zod schema with relation-driven refinements (requiredWhen, array min/max)
 * and optional custom constraints. Call this when wiring RHF resolver.
 */
export declare function buildZodWithRelations(spec: FormSpec, handlers?: Record<string, ConstraintHandler>): any;
interface AnyFieldLike {
    kind: string;
    name?: string;
    fields?: readonly AnyFieldLike[];
    of?: AnyFieldLike;
}
type JoinPath<Prefix extends string, Name extends string> = Prefix extends '' ? Name : `${Prefix}.${Name}`;
type PathOfArrayItem<Field extends AnyFieldLike, Prefix extends string> = Field extends {
    kind: 'group';
    fields: infer G extends readonly AnyFieldLike[];
} ? PathOfFields<G, Prefix> : Field extends {
    name: infer N extends string;
    fields: infer G extends readonly AnyFieldLike[];
} ? JoinPath<Prefix, N> | PathOfFields<G, JoinPath<Prefix, N>> : Field extends {
    name: infer N extends string;
} ? JoinPath<Prefix, N> : never;
type PathOfField<Field extends AnyFieldLike, Prefix extends string = ''> = Field extends {
    kind: 'group';
    name: infer N extends string;
    fields: infer G extends readonly AnyFieldLike[];
} ? JoinPath<Prefix, N> | PathOfFields<G, JoinPath<Prefix, N>> : Field extends {
    kind: 'group';
    fields: infer G extends readonly AnyFieldLike[];
} ? PathOfFields<G, Prefix> : Field extends {
    kind: 'array';
    name: infer N extends string;
    of: infer O extends AnyFieldLike;
} ? JoinPath<Prefix, N> | PathOfArrayItem<O, JoinPath<Prefix, `${N}.$index`>> : Field extends {
    name: infer N extends string;
} ? JoinPath<Prefix, N> : never;
type PathOfFields<Fields extends readonly AnyFieldLike[], Prefix extends string = ''> = Fields[number] extends infer Field extends AnyFieldLike ? PathOfField<Field, Prefix> : never;
export interface TypedWhenClause<P extends string> {
    path: P;
    op?: PredicateOp;
    value?: unknown;
}
export interface TypedPredicate<P extends string> {
    when?: TypedWhenClause<P>;
    all?: TypedPredicate<P>[];
    anyOf?: TypedPredicate<P>[];
    not?: TypedPredicate<P>;
}
export type TypedOptionsSource<P extends string> = {
    kind: 'static';
    options: readonly FormOption[];
} | {
    kind: 'resolver';
    resolverKey: string;
    deps: P[];
    args?: Record<string, unknown>;
};
export type TypedAutocompleteSource<P extends string> = {
    kind: 'local';
    options: readonly AutocompleteOption[];
    searchKeys: string[];
} | {
    kind: 'resolver';
    resolverKey: string;
    deps?: P[];
    args?: Record<string, unknown>;
    searchKeys?: string[];
    minQueryLength?: number;
    debounceMs?: number;
};
type EnhanceField<Field extends AnyFieldLike, P extends string> = Field & {
    visibleWhen?: TypedPredicate<P>;
    enabledWhen?: TypedPredicate<P>;
    requiredWhen?: TypedPredicate<P>;
    layout?: FieldLayoutSpec;
    readOnly?: boolean;
} & (Field extends {
    kind: 'select';
} ? {
    options: TypedOptionsSource<P> | readonly FormOption[];
} : unknown) & (Field extends {
    kind: 'radio';
} ? {
    options: TypedOptionsSource<P> | readonly FormOption[];
} : unknown) & (Field extends {
    kind: 'text';
} | {
    kind: 'email';
} | {
    kind: 'textarea';
} ? {
    inputGroup?: InputGroupSpec;
} : unknown) & (Field extends {
    kind: 'autocomplete';
} ? {
    source: TypedAutocompleteSource<P>;
} : unknown) & (Field extends {
    kind: 'group';
    fields: infer G extends readonly AnyFieldLike[];
} ? {
    fields: EnhanceFields<G, P>;
    layout?: FieldLayoutSpec & FormLayoutSpec;
    legendI18n?: string;
} : unknown) & (Field extends {
    kind: 'array';
    of: infer O extends AnyFieldLike;
} ? {
    of: EnhanceField<O, P>;
} : unknown) & {
    computeFrom?: {
        computeKey: string;
        deps: P[];
        mode?: 'change' | 'blur-xs' | 'submit';
        readOnly?: boolean;
    };
};
export type EnhanceFields<F extends readonly AnyFieldLike[], P extends string> = {
    [K in keyof F]: EnhanceField<F[K], P>;
};
export declare function defineFormSpec<M extends AnySchemaModel, F extends readonly AnyFieldLike[]>(spec: {
    meta: FormSpec<M>['meta'];
    model: M;
    fields: EnhanceFields<F, PathOfFields<F>>;
    layout?: FormSpec<M>['layout'];
    policy?: FormSpec<M>['policy'];
    actions?: FormSpec<M>['actions'];
    renderHints?: FormSpec<M>['renderHints'];
    constraints?: {
        key: string;
        messageI18n: string;
        paths: PathOfFields<F>[];
        args?: Record<string, unknown>;
    }[];
}): FormSpec<M>;
export declare const tech_contracts_forms_DocBlocks: DocBlock[];
export {};
