import * as React from 'react';
import { AdaptableButton } from './AdaptableButton';
import { BaseContext } from '../../types';
/**
 * Data which appears in an AdapTable Form.
 *
 * The default shape is a loosely-typed `Record<string, any>`, but consumers
 * who care about strong typing can declare their own shape and pass it as
 * the second generic parameter to {@link AdaptableForm}.
 */
export type AdaptableFormData = Record<string, any>;
/**
 * Defines a form which appears dynamically; used by Alerts, Export Custom
 * Destinations and Dashboard Custom Toolbars.
 *
 * @typeParam T     - The host's button/handler context (e.g.
 *                    `CustomToolbarFormContext`).
 * @typeParam TData - Optional shape of the form data. Defaults to the
 *                    loosely-typed {@link AdaptableFormData}; declare your
 *                    own shape (e.g. `{ name: string; age: number }`) for
 *                    strongly-typed `formData` in `onSubmit` callbacks.
 */
export interface AdaptableForm<T extends BaseContext, TData extends AdaptableFormData = AdaptableFormData> {
    /**
     * Title to appear in the Form
     */
    title?: string;
    /**
     * Additional information to appear in the Form
     */
    description?: string;
    /**
     * Collection of Dynamic Fields and Field Groups to display.
     *
     * Items can be:
     * - a single {@link AdaptableFormField} (rendered on its own row in the
     *   default `rows` layout, or as one cell in the `inline` layout),
     * - an array of {@link AdaptableFormField} (rendered side-by-side on the
     *   same row in the `rows` layout), or
     * - an {@link AdaptableFormFieldGroup} (a labelled section that
     *   visually groups related fields).
     */
    fields?: (AdaptableFormField | AdaptableFormField[] | AdaptableFormFieldGroup)[];
    /**
     * Buttons to include in the Form
     */
    buttons?: AdaptableButton<T>[];
    /**
     * How the form's fields are arranged on screen.
     *
     * - `rows` (default): each field on its own row, label on the left and
     *   input on the right. Suitable for popups / wizards.
     * - `inline`: fields are placed side-by-side on a single horizontal line,
     *   with the label rendered immediately before its input. Designed for
     *   compact contexts such as Dashboard Custom Toolbars where vertical
     *   real-estate is scarce.
     *
     * @defaultValue 'rows'
     */
    layout?: AdaptableFormLayout;
    /**
     * Optional form-level submit hook.
     *
     * Fired when the user presses `Enter` while focus is inside any field
     * input AND the form is currently valid. The full `formData` is passed
     * through, typed as `TData` if you've supplied a custom shape.
     *
     * Use this as an ergonomic shortcut to avoid wiring an explicit "Submit"
     * button - or in addition to one, so power users can press Enter to
     * commit. If the form is invalid the hook is not invoked.
     */
    onSubmit?: (formData: TData, context: T) => void;
}
/**
 * How an AdaptableForm's fields are visually arranged
 */
export type AdaptableFormLayout = 'rows' | 'inline';
/**
 * Logical grouping of related fields, with an optional title and
 * description. Use to break long forms into visually distinct sections.
 *
 * Groups behave like fields when it comes to `hidden`: a hidden group is
 * not rendered and its child fields are excluded from validation. They
 * are otherwise transparent - each child field continues to drive its
 * own value, validation, and `onValueChange` lifecycle.
 *
 * In the `inline` layout the group's title/description are not rendered
 * (the layout is too compact for sectioning). The child fields are
 * laid out inline alongside the rest.
 */
export interface AdaptableFormFieldGroup {
    /**
     * Discriminator - identifies the item as a group rather than a field.
     */
    kind: 'group';
    /**
     * Optional title rendered as the section header.
     */
    title?: string;
    /**
     * Optional description rendered immediately below the title.
     */
    description?: string;
    /**
     * Fields contained in the group. Inner items may be a single field or
     * an array of fields (rendered side-by-side on the same row, exactly
     * like the top-level shorthand).
     */
    fields: (AdaptableFormField | AdaptableFormField[])[];
    /**
     * Hide the entire group. Either a boolean or a function evaluated
     * against the current form data. Hidden groups skip rendering and
     * exclude their children from validation.
     */
    hidden?: boolean | ((formData: AdaptableFormData, context: BaseContext) => boolean);
}
/**
 * Defines a Field that appears in an Adaptable Form
 */
export interface AdaptableFormField {
    /**
     * Name of the Field
     */
    name: string;
    /**
     * Label to display in the Field
     */
    label: string;
    /**
     * Field Type - dictates which UI control is rendered
     */
    fieldType: AdaptableFormFieldType;
    /**
     * Field Default Value - can be of type string, boolean, number, or for
     * `select` fields with `multi: true` an array of those.
     *
     * For single `select` fields, this is also the value restored when the user
     * clears the combobox (unless {@link clearToDefault} is `false`).
     */
    defaultValue?: string | boolean | number | Array<string | number | boolean>;
    /**
     * For single `select` fields only. When the user clears the combobox,
     * whether to restore {@link defaultValue} instead of leaving the field empty.
     *
     * Defaults to `true` when `defaultValue` is set, otherwise `false`.
     * Set to `false` when an empty selection is a distinct state from the default.
     */
    clearToDefault?: boolean;
    /**
     * Items to populate the `select` and `radio` fieldTypes.
     *
     * Either a static array, or a function that derives the options from the
     * current form data and Adaptable context. The function form may return
     * a Promise for asynchronously-loaded options - the form will render the
     * field with no items until the promise resolves.
     */
    options?: AdaptableFormFieldOption[] | ((formData: AdaptableFormData, context: BaseContext) => AdaptableFormFieldOption[] | Promise<AdaptableFormFieldOption[]>);
    /**
     * For `select` fields only. When `true` the field renders as a
     * multi-select combobox; the field's value is an array of selected
     * `option.value`s rather than a single value.
     *
     * @defaultValue false
     */
    multi?: boolean;
    /**
     * For `custom` fields only. Renders an arbitrary React node as the
     * field's input. Receives the current value, a `setValue` setter
     * (controlled), the current form data, the Adaptable context and the
     * resolved `disabled` state.
     *
     * Use this as an escape hatch when none of the built-in `fieldType`s
     * fit - e.g. to render a star-rating widget, a tag editor or any
     * bespoke control.
     */
    render?: (params: AdaptableFormFieldRenderParams) => React.ReactNode;
    /**
     * Placeholder text shown inside `text`, `textarea`, `number`, `date`,
     * `time` and `datetime` inputs when empty. For `select` fields it is
     * rendered as the empty-state label when no value is selected.
     *
     * When omitted on a `select` field with a {@link defaultValue}, the label of
     * the matching `options` entry is used as the empty-state label.
     */
    placeholder?: string;
    /**
     * Inline help text rendered immediately below the field's input. Useful
     * for short explanations such as "format: YYYY-MM-DD" or "min 3 chars".
     */
    helpText?: string;
    /**
     * Tooltip shown when hovering the field's label.
     */
    tooltip?: string;
    /**
     * Hide the field. Either a boolean or a function evaluated against the
     * current form data. Hidden fields are not rendered and are excluded from
     * validation.
     */
    hidden?: boolean | ((formData: AdaptableFormData, context: BaseContext) => boolean);
    /**
     * Disable the field's input. Either a boolean or a function evaluated
     * against the current form data. Disabled fields render but the user
     * cannot edit them.
     */
    disabled?: boolean | ((formData: AdaptableFormData, context: BaseContext) => boolean);
    /**
     * If `true` the field is treated as required. An empty value (`''`,
     * `null`, `undefined`, or unchecked checkbox) will produce a validation
     * error.
     */
    required?: boolean;
    /**
     * Custom field-level validation. Return an error message string to mark
     * the field invalid, or `null`/`undefined` if the value is valid.
     *
     * Custom validation runs *after* built-in checks (`required`, `min`,
     * `max`, `pattern`, etc.) - the first failing check wins.
     */
    validate?: (value: any, formData: AdaptableFormData, context: BaseContext) => string | null | undefined;
    /**
     * Minimum allowed value. For `number` and `slider`: the lowest accepted
     * number. For `date`, `time` and `datetime`: the earliest allowed value
     * in ISO format (`YYYY-MM-DD` / `HH:mm` / `YYYY-MM-DDTHH:mm`).
     */
    min?: number | string;
    /**
     * Maximum allowed value. For `number` and `slider`: the highest accepted
     * number. For `date`, `time` and `datetime`: the latest allowed value in
     * ISO format.
     */
    max?: number | string;
    /**
     * Stepping interval for `number`, `slider`, `time` and `datetime`
     * fields.
     */
    step?: number;
    /**
     * Minimum length for `text` and `textarea` fields.
     */
    minLength?: number;
    /**
     * Maximum length for `text` and `textarea` fields.
     */
    maxLength?: number;
    /**
     * Regular expression that the value of a `text` field must match.
     */
    pattern?: string;
    /**
     * For `textarea` fields: the visible number of text rows.
     *
     * @defaultValue 3
     */
    rows?: number;
    /**
     * Optional callback invoked whenever value of this field changes
     */
    onValueChange?: (value: any, context: BaseContext) => void;
}
/**
 * Map of validation errors produced by {@link validateAdaptableForm},
 * keyed by field `name`. A field is valid when its key is not present.
 */
export type AdaptableFormErrors = Record<string, string>;
/**
 * Types of Controls used in an AdapTable Form (standard form set)
 */
export type AdaptableFormFieldType = 'text' | 'textarea' | 'select' | 'radio' | 'date' | 'time' | 'datetime' | 'number' | 'slider' | 'color' | 'checkbox' | 'textOutput' | 'custom';
/**
 * A single option used by a `select` or `radio` field.
 */
export interface AdaptableFormFieldOption {
    value: any;
    label: string;
}
/**
 * Parameters provided to {@link AdaptableFormField.render} when rendering
 * a `custom` field type.
 */
export interface AdaptableFormFieldRenderParams {
    /**
     * The field's current value
     */
    value: any;
    /**
     * Setter to update the field's value. Triggers form-level `onChange`,
     * per-field `onValueChange` and re-validation.
     */
    setValue: (newValue: any) => void;
    /**
     * The field definition itself - useful when sharing one render function
     * across several `custom` fields.
     */
    field: AdaptableFormField;
    /**
     * The current values of all fields in the form, keyed by field `name`.
     */
    formData: AdaptableFormData;
    /**
     * Adaptable context (carries `adaptableApi`, etc.). When the form is
     * hosted by a Custom Toolbar this is in fact a
     * `CustomToolbarFormContext`.
     */
    context: BaseContext;
    /**
     * Resolved disabled state of the field (after evaluating `field.disabled`
     * if it's a function).
     */
    disabled: boolean;
    /**
     * Current validation error for this field, if any.
     */
    error?: string;
}
/**
 * Returns true if the supplied entry from a form's `fields` array is a
 * group rather than a single field or an inline-row array of fields.
 */
export declare function isAdaptableFormFieldGroup(entry: AdaptableFormField | AdaptableFormField[] | AdaptableFormFieldGroup): entry is AdaptableFormFieldGroup;
/**
 * Flattens a form's `fields` array (which may contain field groups and
 * inline-row arrays) into a single flat list of fields. Useful when
 * computing defaults, validation or per-field lookups.
 */
export declare function flattenAdaptableFormFields<T extends BaseContext>(formDef?: AdaptableForm<T, any>): AdaptableFormField[];
export declare function shouldClearSelectToDefault(field: AdaptableFormField): boolean;
export declare function resolveSelectValueAfterClear(field: AdaptableFormField, newValue: unknown): unknown;
export declare function resolveSelectPlaceholder(field: AdaptableFormField, options: AdaptableFormFieldOption[]): string | undefined;
export declare function getDefaultAdaptableFormData<T extends BaseContext = BaseContext>(formDef?: AdaptableForm<T, any>): AdaptableFormData;
/**
 * Resolves a field's `options` to the current array of options.
 *
 * - When `options` is already an array, it's returned as-is.
 * - When it's a synchronous function, the function is invoked.
 * - When the function returns a Promise this helper returns `undefined` -
 *   asynchronous resolution is the caller's responsibility (the
 *   `AdaptableFormComponent` resolves promises via internal state).
 */
export declare function resolveAdaptableFormFieldOptionsSync(field: AdaptableFormField, formData: AdaptableFormData, context: BaseContext): AdaptableFormFieldOption[] | undefined;
/**
 * Returns true if the given field should be hidden given the current form
 * data and context. Resolves both boolean and function forms of `hidden`.
 */
export declare function isAdaptableFormFieldHidden(field: AdaptableFormField, formData: AdaptableFormData, context: BaseContext): boolean;
/**
 * Returns true if the given group should be hidden given the current
 * form data and context.
 */
export declare function isAdaptableFormFieldGroupHidden(group: AdaptableFormFieldGroup, formData: AdaptableFormData, context: BaseContext): boolean;
/**
 * Returns true if the given field should be disabled given the current
 * form data and context. Resolves both boolean and function forms of
 * `disabled`.
 */
export declare function isAdaptableFormFieldDisabled(field: AdaptableFormField, formData: AdaptableFormData, context: BaseContext): boolean;
/**
 * Validates an entire AdaptableForm. Hidden fields and fields inside
 * hidden groups are skipped. Returns a map of field-name to error
 * message; fields without entries are valid.
 *
 * Validation order per field: `required` -> built-in (min/max/length/
 * pattern) -> custom `validate`. The first failing check wins.
 */
export declare function validateAdaptableForm<T extends BaseContext = BaseContext>(formDef: AdaptableForm<T, any>, formData: AdaptableFormData, context: BaseContext): AdaptableFormErrors;
