import { AnySchema } from 'yup';
import { ComponentType } from 'react';
import { default as default_2 } from 'react';
import { FormikProps } from 'formik';
import { GroupBase } from 'react-select';
import { JSX as JSX_2 } from 'react/jsx-runtime';
import { ObjectSchema } from 'yup';
import { StylesConfig } from 'react-select';
import { useFormik } from 'formik';
import * as Yup from 'yup';

declare interface ActiveField {
    /** The contenteditable div inside FormulaInput */
    editorRef: default_2.RefObject<HTMLDivElement | null>;
    /** Saved Range from the last selection — restored before inserting */
    savedRange: Range | null;
    fieldId: string;
    /** Optionally, the field can provide a direct way to insert a variable into its state */
    onInsert?: (path: string, label: string) => void;
}

/** True if the AST contains at least one non-text node. */
export declare function astHasRefs(nodes: FormulaASTNode[]): boolean;

/**
 * Convert AST nodes to the flat FormulaToken[] the DOM layer uses.
 * This keeps FormulaInput decoupled from the AST type directly.
 */
export declare function astToTokens(nodes: FormulaASTNode[], configEnabled?: boolean): FormulaToken[];

export declare function buildEvaluationPayload({ values, conditionConfig, }: {
    values: Record<string, unknown>;
    conditionConfig?: ConditionConfig;
}): EvaluationPayload;

/**
 * Returns an empty presence-marker object {}.
 * The backend uses the key's existence in FormulaConfig to know
 * the field value was serialized as _P('...') rather than _DE_{_P('...')}.
 */
export declare function buildFieldConfig(): FieldFormulaConfig;

/**
 * Build a bracket-notation path from a root and optional extra segments.
 * Each segment is wrapped in [\"...\"] so the path evaluator can handle
 * any key (camelCase, spaces, hyphens, etc.) uniformly.
 *
 * Examples:
 *   buildFormulaPath('data.user', 'email')
 *     → 'data.user.[\"email\"]'
 *   buildFormulaPath('data.input', 'groupAssignPolicy', 'dmnKey')
 *     → 'data.input.[\"groupAssignPolicy\"].[\"dmnKey\"]'
 *   buildFormulaPath('data.trigger', 'assignee', 'email')
 *     → 'data.trigger.[\"assignee\"].[\"email\"]'
 */
export declare function buildFormulaPath(root: string, ...segments: string[]): string;

export declare function buildSelectStyles(hasError: boolean, isMulti?: boolean): StylesConfig<any, boolean, GroupBase<any>>;

/**
 * Builds a Yup ObjectSchema from a flat FieldDescriptor[].
 * Validates required fields and applies type-appropriate rules.
 * Recurses into object/schema children.
 */
export declare function buildValidationSchema(fields: FieldDescriptor[]): Yup.ObjectSchema<any>;

export declare interface ChildRouterProps {
    field: FieldDescriptor;
    pathPrefix: string;
    depth: number;
    values: Record<string, unknown>;
    errors: Record<string, unknown>;
    touched: Record<string, unknown>;
    setFieldValue: (name: string, value: unknown) => void;
    setFieldTouched: (name: string, touched: boolean) => void;
    compact?: boolean;
    inlineLabel?: boolean;
    /**
     * Item-scoped values when this child is rendered inside an array item.
     * ArrayField sets it to `items[i]` per row; ObjectField/TabsField pass
     * whatever they received through unchanged. FieldRouter folds this into
     * `ctx.item` for shouldHide/shouldDisable/compute callbacks.
     */
    item?: Record<string, unknown>;
}

export declare interface ChipToken {
    type: 'chip';
    expr: string;
    label: string;
    path: string;
    kind: 'de-expr' | 'path-ref';
}

/**
 * Concatenation of multiple nodes (future).
 * Serializes by joining all child serializations.
 */
export declare interface ConcatNode {
    type: 'concat';
    values: FormulaASTNode[];
}

/**
 * Top-level condition config map: pathPrefix → ConditionNode[].
 *
 * Example:
 *   { "email": [
 *       { field: "email", operator: "isNull", value: "" },
 *       { type: "group", connector: "and", entries: [
 *           { field: "role", operator: "equals", value: "FE" },
 *           { field: "role", operator: "equals", value: "UX", connector: "or" },
 *         ]},
 *       { field: "salary", operator: "equals", value: "5000000", connector: "and" },
 *     ]
 *   }
 */
export declare type ConditionConfig = Record<string, ConditionNode[]>;

/**
 * A single condition row (leaf node).
 * connector: how this node joins the previous sibling ('and' | 'or'). Ignored on index 0.
 */
export declare interface ConditionEntry {
    /** Discriminator — omit or set to 'leaf' for a plain condition row */
    type?: 'leaf';
    field: string;
    fieldLabel: string;
    operator: string;
    value: string;
    connector?: 'and' | 'or';
}

/**
 * Conditional expression (future).
 * e.g. if status == "active" then name else "unknown"
 */
export declare interface ConditionExprNode {
    type: 'condition';
    if: FormulaASTNode;
    then: FormulaASTNode;
    else: FormulaASTNode;
}

/** One column in a per-field condition row */
export declare interface ConditionFieldDef {
    /** Key used to store this column's value in ConditionEntry */
    id: string;
    /**
     * 'select'   — native <select> with user-supplied options
     * 'operator' — native <select> pre-filled with the standard operator list (no options needed)
     * 'text'     — plain <input>
     * any other string — falls back to <input>
     */
    type: 'select' | 'operator' | 'text' | string;
    colSpan?: number;
    label?: string;
    placeholder?: string;
    /** Options for select columns — user defines these, renderer just renders them */
    options?: Array<{
        value: string;
        label: string;
    }>;
    optionsSource?: OptionsSource;
    /** When true, renders a FormulaInput chip editor instead of a plain <input> */
    formula?: boolean;
}

/**
 * A parenthesised group of condition nodes.
 * Renders as an indented, bordered block — e.g. (Role = "FE" OR Role = "UX").
 */
export declare interface ConditionGroup {
    type: 'group';
    entries: ConditionNode[];
    connector?: 'and' | 'or';
}

/** Either a leaf row or a nested group */
export declare type ConditionNode = ConditionEntry | ConditionGroup;

declare interface ControlledProps extends FormulaProps {
    schema: FormSchema;
    formik: FormikProps<Record<string, unknown>>;
    initialValues?: never;
    onSubmit?: never;
    children?: never;
    form?: never;
}

/** @deprecated Use FlowForm */
export declare const DynamicFormRenderer: default_2.ForwardRefExoticComponent<FlowFormProps & default_2.RefAttributes<FlowFormHandle>>;

/** @deprecated Use FlowFormProps */
export declare type DynamicFormRendererProps = FlowFormProps;

export declare const errorTextStyle: React.CSSProperties;

export declare interface EvaluationConditionEntry {
    field: string;
    operator: string;
    value?: string;
    connector?: 'and' | 'or';
}

export declare interface EvaluationConditionGroup {
    type: 'group';
    entries: EvaluationConditionNode[];
    connector?: 'and' | 'or';
}

export declare type EvaluationConditionNode = EvaluationConditionEntry | EvaluationConditionGroup;

export declare interface EvaluationPayload {
    values: Record<string, unknown>;
    conditions?: Record<string, EvaluationConditionNode[]>;
}

/**
 * Extract the display label from a path expression.
 * Prefers the last [\"key\"] bracket segment; falls back to the last dot-segment.
 *
 * 'data.user.[\"email\"]'                                          →  "email"
 * 'data.input.[\"groupAssignPolicy\"].[\"dmnKey\"]'               →  "dmnKey"
 * 'data.trigger.[\"assignee\"].[\"email\"]'                       →  "email"
 */
export declare function extractLabel(path: string): string;

declare interface FetchResult {
    options: TablePickerOption[];
    hasNextPage: boolean;
    nextPage?: number;
}

export declare const FF: {
    readonly INPUT_HEIGHT: 38;
    readonly INPUT_PADDING: "0 12px";
    readonly INPUT_FONT_SIZE: 14;
    readonly BORDER_RADIUS: 6;
    readonly BORDER_COLOR: "#ced4da";
    readonly BORDER_COLOR_HOVER: "#adb5bd";
    readonly BORDER_COLOR_FOCUS: "#86b7fe";
    readonly BORDER_COLOR_ERROR: "#dc3545";
    readonly BORDER: "1px solid #ced4da";
    readonly BORDER_ERROR: "1px solid #dc3545";
    readonly FOCUS_SHADOW: "0 0 0 3px rgba(13,110,253,0.18)";
    readonly FOCUS_SHADOW_ERROR: "0 0 0 3px rgba(220,53,69,0.18)";
    readonly COLOR_LABEL: "#212529";
    readonly COLOR_PLACEHOLDER: "rgba(0,0,0,0.38)";
    readonly COLOR_HELPER: "#6c757d";
    readonly COLOR_ERROR: "#dc3545";
    readonly COLOR_DISABLED_BG: "#f8f9fa";
    readonly COLOR_DISABLED_TEXT: "rgba(0,0,0,0.38)";
    readonly FONT_SIZE_LABEL: 13;
    readonly FONT_SIZE_INPUT: 14;
    readonly FONT_SIZE_HELPER: 12;
    readonly FONT_WEIGHT_LABEL: 500;
    readonly LABEL_MB: 5;
    readonly HELPER_MT: 4;
    readonly FIELD_MB: 20;
};

export declare const FIELD_TYPE_OPTIONS: Array<{
    value: string;
    label: string;
}>;

declare type FieldComponent = ComponentType<FieldComponentProps>;

export declare interface FieldComponentProps {
    field: FieldDescriptor;
    value: unknown;
    values: Record<string, unknown>;
    onChange: (value: unknown) => void;
    onBlur: () => void;
    error?: string;
    touched?: boolean;
    /** Current formula config map (host-owned). Passed down to formula-enabled fields. */
    formulaConfig?: FormulaConfig;
    /** Called by a field when its formula AST changes. Host app updates its state. */
    onFormulaConfigChange?: (config: FormulaConfig) => void;
    /**
     * When true: field renders label + input in a single horizontal row.
     * Used inside ObjectField groups for compact two-column mapping layout.
     */
    inlineLabel?: boolean;
}

/** Condition definition attached to a FieldDescriptor */
export declare interface FieldConditionDef {
    fields: ConditionFieldDef[];
    /** Enables nested condition groups. Defaults to false. */
    allowGroups?: boolean;
    /** Optional depth limit for nested groups when allowGroups is true. */
    maxGroupDepth?: number;
}

export declare interface FieldContext {
    /** Full top-level form values (always). */
    values: Record<string, unknown>;
    /**
     * Item-scoped values for a field rendered INSIDE an array item.
     * Lets `shouldHide` / `shouldDisable` / `shouldRequire` / `compute` see
     * sibling-in-same-row fields without having to splice paths manually:
     *
     *   { id: 'template', shouldHide: ({ item }) => item?.valueSource !== 'template' }
     *
     * `undefined` when the field is NOT inside an array item (i.e. top-level
     * fields and fields inside plain `type: 'object'` children at top level).
     * Nested arrays update `item` to the immediate parent row's values.
     */
    item?: Record<string, unknown>;
}

export declare interface FieldDescriptor {
    /**
     * The formik key for this field.
     * Use `id` (preferred) or `name` — both are accepted.
     * `id` takes precedence if both are provided.
     */
    id?: string;
    name?: string;
    type: FieldType | string;
    /** Child field descriptors — used by type: 'object' to render a nested group. */
    children?: FieldDescriptor[];
    /** Optional per-field condition guard — renders a condition row below this field. */
    condition?: FieldConditionDef;
    label?: string;
    placeholder?: string;
    required?: boolean;
    showOptional?: boolean;
    disabled?: boolean | ((ctx: FieldContext) => boolean);
    hidden?: boolean;
    colSpan?: number;
    dividerAfter?: boolean;
    info?: string;
    helperText?: string;
    dataTestId?: string;
    validation?: AnySchema;
    shouldHide?: (ctx: FieldContext) => boolean;
    shouldDisable?: (ctx: FieldContext) => boolean;
    shouldRequire?: (ctx: FieldContext) => boolean;
    /**
     * When true, the field's value is auto-cleared (reset to `defaultValue`,
     * or removed if no default) any time `shouldHide` evaluates to true —
     * including on mount when the saved data has orphan values from a prior
     * configuration. Default: false (values persist while hidden, preserving
     * legacy behavior).
     *
     * Use this on conditional fields where stale data would corrupt the
     * payload (e.g. `template` should be empty when `valueSource !== 'template'`).
     */
    clearOnHide?: boolean;
    defaultValue?: unknown;
    compute?: (ctx: FieldContext) => unknown;
    transform?: FieldTransform;
    onChange?: (value: unknown, ctx: FieldContext & {
        setFieldValue: (name: string, value: unknown) => void;
    }) => void;
    /**
     * Declarative dynamic options. The renderer translates this into a paged,
     * cached, abortable async loader via the host's resolver registry.
     * Mutually compatible with static `options`: static wins if both set.
     */
    optionsSource?: OptionsSource;
    [key: string]: unknown;
}

/**
 * Presence marker for a field that has formula config enabled.
 * When a field's formula config toggle is ON, its key appears in FormulaConfig
 * with an empty object value. The backend uses this to detect that the value
 * stored in Formik was serialized as _P('...') rather than _DE_{_P('...')}.
 *
 * Example: { "dmnKey": {} }
 */
export declare type FieldFormulaConfig = Record<string, never>;

export declare const fieldRegistry: {
    register(type: string, component: FieldComponent): void;
    get(type: string): FieldComponent | undefined;
    has(type: string): boolean;
    /** List every registered field type. Used by the DEV-mode "did you mean…"
     *  suggestion when a schema specifies an unknown `type`. */
    keys(): string[];
};

/** Optional pre-defined field suggestions (e.g. common fields for this node type) */
export declare interface FieldSuggestion {
    label: string;
    field: FieldDescriptor;
}

export declare interface FieldTransform {
    in?: (value: unknown) => unknown;
    out?: (value: unknown) => unknown;
}

export declare type FieldType = 'text' | 'textarea' | 'number' | 'toggle' | 'radio-group' | 'select' | 'descriptive-select' | 'key-value' | 'array' | 'object' | 'reference' | 'cron' | 'schema';

export declare interface FlowForgeFieldDefinition {
    /** The unique type identifier (e.g. 'text', 'image-upload') */
    type: string;
    /** The display name for the field picker dropdown */
    label: string;
    /**
     * The component used to render the field in the live form.
     * If omitted, relies on a previously registered component in DynamicFormRenderer.
     */
    component?: ComponentType<FieldComponentProps>;
    /**
     * Instead of a React component, you provide a FlowForm schema!
     * The Schema Builder Modal will automatically render this schema
     * to ask the user for configuration settings.
     */
    configSchema?: {
        fields: FieldDescriptor[];
    };
    /**
     * Validation builder for this field type.
     */
    buildValidation?: (field: FieldDescriptor) => Yup.Schema;
}

export declare const FlowForgeRegistry: Registry;

export declare const FlowForm: default_2.ForwardRefExoticComponent<FlowFormProps & default_2.RefAttributes<FlowFormHandle>>;

/**
 * Imperative API exposed via `ref` on `<FlowForm>`. Lets a host drive Save
 * from a footer button outside the form without writing forwardRef
 * boilerplate per-section. See README for the canonical pattern.
 */
export declare interface FlowFormHandle {
    /**
     * Touch every field, validate the form, and (when valid) call `onSave`
     * with the full payload. Returns `{ isValid, values, errors }` so the
     * caller can also branch off the result directly.
     */
    save: () => Promise<SaveResult>;
    /** Reset to initial values + clear touched/errors. */
    reset: () => void;
    /** Run validation and return errors without touching fields. */
    validate: () => Promise<Record<string, unknown>>;
    /** Push server-side errors back into formik state for display. */
    setErrors: (errors: Record<string, unknown>) => void;
    /** Read the current values. Includes the conditionConfig sidecar. */
    getValues: () => Record<string, unknown>;
    /** Programmatic write — useful for pre-filling on edit. */
    setValues: (values: Record<string, unknown>) => void;
}

export declare interface FlowFormInstance {
    values: Record<string, unknown>;
    errors: Record<string, unknown>;
    isValid: boolean;
    isDirty: boolean;
    isSubmitting: boolean;
    formulaConfig: FormulaConfig;
    conditionConfig: ConditionConfig;
    /** Validate and submit — safe to call from any button outside the form. */
    submit: () => void;
    reset: (nextValues?: Record<string, unknown>) => void;
    setFieldValue: (field: string, value: unknown) => void;
    _schema: FormSchema;
    _formik: ReturnType<typeof useFormik<Record<string, unknown>>>;
    _formulaConfig: FormulaConfig;
    _onFormulaConfigChange: (config: FormulaConfig) => void;
    _conditionConfig: ConditionConfig;
    _onConditionConfigChange: (config: ConditionConfig) => void;
}

export declare type FlowFormProps = UncontrolledProps | ControlledProps | HookProps;

declare type FormLayout = 'flat' | 'stepper' | 'tabs' | 'sections';

export declare interface FormSchema {
    layout?: FormLayout;
    /**
     * Removes the bottom margin on every field.
     * Use for filter bars and inline forms where fields sit in a tight horizontal row.
     */
    compact?: boolean;
    fields?: FieldDescriptor[];
    steps?: FormStep[];
}

declare interface FormStep {
    label: string;
    hint?: string;
    fields: FieldDescriptor[];
}

/** Union of all AST node types */
export declare type FormulaASTNode = TextNode | PathRefNode | ConcatNode | FunctionNode | ConditionExprNode;

/**
 * Top-level formula config map: fieldId → FieldFormulaConfig (empty marker {}).
 * A key is present only when that field's formula config toggle is ON.
 *
 * When toggle is OFF: field key absent, Formik value = _DE_{_P('...')}
 * When toggle is ON:  field key present as {}, Formik value = _P('...')
 *
 * Example: { "dmnKey": {} }
 */
export declare type FormulaConfig = Record<string, FieldFormulaConfig>;

export declare function FormulaInput({ expression, onExpressionChange, onBlur, placeholder, disabled, error, id, formulaConfigEnabled, onFormulaConfigToggle, onPickerOpen, compact, }: FormulaInputProps): JSX_2.Element;

export declare interface FormulaInputProps {
    /** AST — source of truth. Host app owns this. */
    expression: FormulaASTNode[];
    /** Called with the new AST on every edit. */
    onExpressionChange: (nodes: FormulaASTNode[]) => void;
    onBlur?: () => void;
    placeholder?: string;
    disabled?: boolean;
    error?: boolean;
    id?: string;
    /** Whether formulaConfig emission is active (controls the { } toggle highlight). */
    formulaConfigEnabled?: boolean;
    /** Called when user clicks the { } toggle button. */
    onFormulaConfigToggle?: () => void;
    /** Future: open variable picker drawer. */
    onPickerOpen?: () => void;
    /** Compact mode — reduces height/padding to match native form controls in tight rows. */
    compact?: boolean;
}

declare interface FormulaProps {
    formulaConfig?: FormulaConfig;
    onFormulaConfigChange?: (config: FormulaConfig) => void;
    /**
     * Key under `formik.values` where formulaConfig is auto-roundtripped
     * when the host doesn't supply explicit `formulaConfig` /
     * `onFormulaConfigChange`. Defaults to `_formulaConfig`. Mirrors
     * `conditionConfigKey`.
     */
    formulaConfigKey?: string;
    /**
     * Optional variable groups for the built-in Smart Values picker.
     * When provided, DynamicFormRenderer automatically wraps itself in
     * VariablePickerProvider — every FormulaInput gets a picker button and
     * drag-and-drop support with no extra setup from the host.
     *
     * For advanced layout control (picker rendered elsewhere on the page),
     * wrap with <VariablePickerProvider> manually instead.
     */
    variableGroups?: VariableGroup[];
    /** Active per-field condition guards. Key = field pathPrefix. */
    conditionConfig?: ConditionConfig;
    onConditionConfigChange?: (config: ConditionConfig) => void;
    /**
     * Key under `formik.values` where conditionConfig is auto-roundtripped
     * when the host doesn't supply explicit `conditionConfig` /
     * `onConditionConfigChange`. Defaults to `_conditionConfig`.
     */
    conditionConfigKey?: string;
    /**
     * Called by `flowFormRef.current.save()` once validation passes.
     * Receives the full payload (formik values incl. conditionConfig sidecar)
     * + a meta object with `isValid` / `errors`.
     *
     * Available in controlled AND uncontrolled mode. In uncontrolled mode it
     * runs in addition to `onSubmit`.
     */
    onSave?: (values: Record<string, unknown>, meta: {
        isValid: boolean;
        errors: Record<string, unknown>;
    }) => void;
    /**
     * Host-registered resolver map for declarative dynamic options.
     * Fields with `optionsSource: { id: '...', dependsOn: ... }` look up
     * their loader in this map. Transport-agnostic — use axios, fetch,
     * GraphQL, anything that returns a Promise.
     */
    optionsResolvers?: OptionsResolvers;
}

export declare type FormulaToken = TextToken | ChipToken;

/**
 * A built-in function call (future).
 * e.g. upcase, format_date, number_to_text
 */
export declare interface FunctionNode {
    type: 'function';
    name: string;
    args: FormulaASTNode[];
}

/** True if the string contains at least one formula token. */
export declare function hasFormulaTokens(value: unknown): boolean;

export declare const helperTextStyle: React.CSSProperties;

/** Props when using the useFlowForm() hook — simplest API. */
declare interface HookProps {
    form: FlowFormInstance;
    schema?: never;
    formik?: never;
    initialValues?: never;
    onSubmit?: never;
    formulaConfig?: never;
    onFormulaConfigChange?: never;
    conditionConfig?: never;
    onConditionConfigChange?: never;
    variableGroups?: never;
    children?: never;
}

export declare interface InfiniteOption {
    value: string;
    label: string;
    [key: string]: unknown;
}

export declare function InfiniteSelectField({ field: rawField, value, onChange, onBlur, error, touched, }: FieldComponentProps): JSX_2.Element;

export declare function inputStyle(opts: {
    hasError?: boolean;
    isDisabled?: boolean;
    extraStyle?: React.CSSProperties;
}): React.CSSProperties;

export declare function isFormula(value: unknown): value is string;

export declare interface LoadPageParams {
    page: number;
    search: string;
    signal: AbortSignal;
}

export declare interface LoadPageResult {
    options: InfiniteOption[];
    hasMore: boolean;
}

export declare interface ObjectFieldRendererProps {
    field: FieldDescriptor;
    pathPrefix: string;
    depth: number;
    values: Record<string, unknown>;
    errors: Record<string, unknown>;
    touched: Record<string, unknown>;
    setFieldValue: (name: string, value: unknown) => void;
    setFieldTouched: (name: string, touched: boolean) => void;
    compact?: boolean;
    renderFieldRouter: (props: ChildRouterProps) => default_2.ReactNode;
    /** Item-scoped values passed through unchanged from any parent ArrayField. */
    item?: Record<string, unknown>;
}

/** A resolver function — transport-agnostic. */
export declare type OptionsResolver = (deps: Record<string, unknown>, ctx: OptionsResolverContext) => Promise<OptionsResolverResult>;

export declare interface OptionsResolverContext {
    cursor?: unknown;
    input?: string;
    /** Full top-level form values, in case a resolver needs read-only access. */
    values?: Record<string, unknown>;
    /** AbortSignal — resolvers SHOULD honor this when their transport supports it. */
    signal?: AbortSignal;
}

/** Resolver return shape — matches Pipedream's `options` contract. */
export declare interface OptionsResolverResult {
    options: Array<{
        value: unknown;
        label: string;
        isDisabled?: boolean;
        [key: string]: unknown;
    }>;
    /** Opaque cursor returned to the next call. Omit to signal "no more pages". */
    nextCursor?: unknown;
}

export declare type OptionsResolvers = Record<string, OptionsResolver>;

declare interface OptionsResolversContextValue {
    resolvers: OptionsResolvers;
    /**
     * Bust a single resolver's cache. Useful for an explicit "Refresh" button.
     * Pass undefined to clear ALL cached pages for that resolver.
     */
    invalidate: (resolverId: string, depsKey?: string) => void;
}

export declare function OptionsResolversProvider({ resolvers, children }: ProviderProps): JSX_2.Element;

export declare interface OptionsSource {
    /** Resolver id — must match a key in the host's `optionsResolvers` map. */
    id: string;
    dependsOn?: string[] | Record<string, string>;
    params?: Record<string, unknown>;
    resolveValueId?: string;
}

/**
 * Parse a raw backend string into an AST node array.
 *
 * "Hello _DE_{_P('data.input.[\"dmnKey\"]')} world"
 * →
 * [
 *   { type: 'text',     value: 'Hello ' },
 *   { type: 'path-ref', path: 'data.input.["dmnKey"]', label: 'dmnKey' },
 *   { type: 'text',     value: ' world' },
 * ]
 */
/**
 * Parse a raw backend string into an AST node array.
 *
 * configEnabled = false (default): only _DE_{_P(...)} tokens become chips.
 *   _P('...') without the DE wrapper stays as plain text.
 * configEnabled = true: both _DE_{_P(...)} and _P('...') become chips.
 */
export declare function parseToAST(raw: string, configEnabled?: boolean): FormulaASTNode[];

/**
 * A reference to a value from a previous node's output.
 * Serializes to: _DE_{_P('path')}
 *
 * Example:
 *   path:  "data.input.[\"groupAssignPolicy\"].[\"dmnKey\"]"
 *   label: "dmnKey"   ← last ["key"] segment, for display
 */
export declare interface PathRefNode {
    type: 'path-ref';
    path: string;
    label: string;
}

declare interface ProviderProps {
    resolvers?: OptionsResolvers;
    children: default_2.ReactNode;
}

declare class Registry {
    private fields;
    constructor();
    register(def: FlowForgeFieldDefinition): void;
    get(type: string): FlowForgeFieldDefinition | undefined;
    getAll(): FlowForgeFieldDefinition[];
    /** Gets all allowed options for the Type Picker in SchemaBuilder */
    getTypeOptions(): Array<{
        value: string;
        label: string;
    }>;
}

/**
 * Result of `FlowFormHandle.save()`.
 *   - `isValid`: true when no validation errors
 *   - `values`: the latest formik values (includes conditionConfig sidecar
 *     under `_conditionConfig` by default, configurable via prop)
 *   - `errors`: per-path validation errors (empty object when isValid)
 */
export declare interface SaveResult {
    isValid: boolean;
    values: Record<string, unknown>;
    errors: Record<string, unknown>;
}

export declare function SchemaBuilder({ value, onChange, suggestions, label, onPayload, validate, onValidityChange, variableGroups, initialValues: initialValuesProp, initialFormulaConfig, initialConditionConfig, }: SchemaBuilderProps): JSX_2.Element;

export declare function SchemaBuilderDrawer({ value, onChange, suggestions, onPayload, onDone, validate, onValidityChange, label, drawerTitle, drawerWidth, }: SchemaBuilderDrawerProps): JSX_2.Element;

export declare interface SchemaBuilderDrawerProps extends SchemaBuilderProps {
    label?: string;
    drawerTitle?: string;
    drawerWidth?: number;
    /**
     * Fired when the user clicks Done.
     * @param schema   Save this to DB — pass it back to FlowForm/SchemaBuilder to restore the form
     * @param payload  Send this to backend — contains conditionExpressions, formulaConfig, values, evaluationPayload
     */
    onDone?: (schema: FieldDescriptor[], payload: SchemaBuilderPayload | null) => void;
}

export declare interface SchemaBuilderPayload {
    /** The FieldDescriptor[] schema — save this to DB to restore the editor */
    schema: FieldDescriptor[];
    /** Formula AST per field — part of editor state */
    formulaConfig: FormulaConfig;
    /** Condition rows per field — part of editor state */
    conditionConfig: ConditionConfig;
    /** Serialized condition expression string per field — ready for backend rule engine */
    conditionExpressions: Record<string, string>;
    /** Live form values entered by the user */
    values: Record<string, unknown>;
    /** Backend-ready evaluation payload (formulas resolved against values) */
    evaluationPayload: ReturnType<typeof buildEvaluationPayload>;
}

export declare interface SchemaBuilderProps {
    value: FieldDescriptor[];
    onChange: (fields: FieldDescriptor[]) => void;
    suggestions?: FieldSuggestion[];
    label?: string;
    /** Fires on every change: schema edit, value input, formula/condition update */
    onPayload?: (payload: SchemaBuilderPayload) => void;
    /** Whether to auto-validate required fields (shows inline error messages) */
    validate?: boolean;
    /** Called whenever form validity changes — wire to enable/disable your Save button */
    onValidityChange?: (isValid: boolean) => void;
    /** Optional variable groups to seamlessly enable the Variable Picker for formula fields */
    variableGroups?: VariableGroup[];
    /** Saved form values to restore when reopening — keys match field ids */
    initialValues?: Record<string, unknown>;
    /** Saved formula config to restore when reopening */
    initialFormulaConfig?: FormulaConfig;
    /** Saved condition config to restore when reopening */
    initialConditionConfig?: ConditionConfig;
}

/**
 * Serialize an AST back to the backend expression string.
 * path-ref nodes always serialize as _DE_{_P('...')} (the evaluated form).
 *
 * [
 *   { type: 'text',     value: 'Hello ' },
 *   { type: 'path-ref', path: 'data.input.["dmnKey"]', label: 'dmnKey' },
 * ]
 * →  "Hello _DE_{_P('data.input.[\"dmnKey\"]')}"
 */
export declare function serializeAST(nodes: FormulaASTNode[]): string;

/**
 * Serialize AST to the formula-config-enabled format.
 * path-ref nodes → _P('...') (no _DE_ wrapper).
 * Used when formulaConfig toggle is ON.
 */
export declare function serializeASTAsConfig(nodes: FormulaASTNode[]): string;

/**
 * Serialize a ConditionConfig into a map of field → expression string.
 *
 * Example output:
 *   {
 *     email: "isNotPresent(_P('data.input.[\"email\"]'))",
 *     firstName: "_P('data.input.[\"firstName\"]') == 'abhi'"
 *   }
 */
export declare function serializeConditionExpressions(conditionConfig: ConditionConfig): Record<string, string>;

export declare function stripFormulaTokens(value: string): string;

export declare interface TabDefinition {
    id: string;
    label: string;
    fields: FieldDescriptor[];
}

export declare function TablePickerField({ field: rawField, value, onChange, onBlur, error, touched }: FieldComponentProps): JSX_2.Element;

export declare interface TablePickerFieldDescriptor extends FieldDescriptor {
    columns: Array<{
        key: string;
        label: string;
        width?: number;
    }>;
    fetchOptions?: (query: string, page: number) => Promise<FetchResult>;
    dataSource?: string;
    isMulti?: boolean;
    pageSize?: number;
}

export declare interface TablePickerOption {
    value: string;
    label: string;
    [key: string]: unknown;
}

export declare interface TabsFieldDescriptor extends FieldDescriptor {
    tabs?: TabDefinition[];
    variant?: 'pill' | 'line';
    alignment?: 'left' | 'center' | 'right' | 'center-left' | 'center-right';
    height?: 'auto' | 'fixed';
    margin?: 'normal' | 'none';
    activeColor?: string;
    activeTextColor?: string;
    inactiveTextColor?: string;
}

/**
 * FlowForge Formula AST
 *
 * The AST is the source of truth for formula fields.
 * The _DE_{_P(...)} string is a derived serialization produced at submit
 * time for the backend engine — it is never the primary storage format.
 *
 * Extensibility: add new node types here as the engine grows.
 * Current: text + path-ref (covers all real usage today)
 * Future:  concat, function, condition
 */
/** Plain text segment — rendered as-is */
export declare interface TextNode {
    type: 'text';
    value: string;
}

export declare interface TextToken {
    type: 'text';
    value: string;
}

/** Parse a raw string to the flat token list (used for paste/input).
 *  configEnabled mirrors the formula config toggle state. */
export declare function tokenize(raw: string, configEnabled?: boolean): FormulaToken[];

declare interface UncontrolledProps extends FormulaProps {
    schema: FormSchema;
    initialValues: Record<string, unknown>;
    onSubmit: (values: Record<string, unknown>) => void | Promise<void>;
    formik?: never;
    form?: never;
    validationSchema?: ObjectSchema<any>;
    /** Pre-mark fields as touched so validation errors show immediately */
    initialTouched?: Record<string, boolean>;
    /** Called on every values change — use to observe live form values */
    onValuesChange?: (values: Record<string, unknown>) => void;
    /** Called whenever form validity changes — use to enable/disable a parent Save button */
    onValidityChange?: (isValid: boolean) => void;
    children?: (props: {
        isSubmitting: boolean;
    }) => default_2.ReactNode;
    /**
     * Optional HTML `id` for the underlying <form> element. Use this when the
     * submit button lives outside the form (e.g. in a drawer footer) — a
     * `<button type="submit" form={formId}>` will still trigger this form's
     * submit via the HTML5 form attribute.
     */
    formId?: string;
}

export declare function unwrapFormula(value: string): string;

/**
 * Returns a drop-in `loadOptions` for react-select when a field's
 * `optionsSource` is set and the host has registered a matching resolver.
 * Otherwise returns `enabled: false` and the host falls back to the
 * descriptor's static `options` (or no options).
 */
export declare function useDynamicOptions({ source, values }: UseDynamicOptionsArgs): UseDynamicOptionsResult;

declare interface UseDynamicOptionsArgs {
    source: OptionsSource | undefined;
    values: Record<string, unknown>;
}

declare interface UseDynamicOptionsResult {
    /** True when the host configured a usable resolver for this field. */
    enabled: boolean;
    /** Drop-in `loadOptions(inputValue) => Promise<Option[]>` for react-select. */
    loadOptions: ((input: string) => Promise<OptionsResolverResult['options']>) | undefined;
    /** Drop-in `loadValue(ids) => Promise<Option[]>` for edit-mode hydration. */
    loadValue: ((ids: unknown[]) => Promise<OptionsResolverResult['options']>) | undefined;
    /** Stable key derived from deps — feed to react-select's `key` to refresh on change. */
    depsKey: string;
    /** Manually invalidate this field's cache (e.g. for a Refresh button). */
    refresh: () => void;
}

export declare function useFlowForm({ schema, initialValues, onSubmit, showErrorsImmediately, }: UseFlowFormOptions): FlowFormInstance;

export declare interface UseFlowFormOptions {
    schema: FormSchema;
    initialValues: Record<string, unknown>;
    /**
     * Called only when form is valid and submitted.
     * Receives raw formik values AND the fully-resolved evaluation payload
     * (formula chips resolved, condition expressions serialized).
     */
    onSubmit: (values: Record<string, unknown>, evaluation: EvaluationPayload) => void | Promise<void>;
    /** Pre-mark all fields as touched so errors show immediately (e.g. edit mode). */
    showErrorsImmediately?: boolean;
}

export declare function useOptionsResolvers(): OptionsResolversContextValue;

export declare function useVariablePickerContext(): VariablePickerContextValue | null;

export declare interface VariableGroup {
    label: string;
    icon?: default_2.ReactNode;
    items: VariableItem[];
}

export declare interface VariableItem {
    /** Display label shown in the picker */
    label: string;
    /** Formula path used to build _DE_{_P('...')} / _P('...') */
    path: string;
    /** Optional description shown below the label */
    description?: string;
    /** Nested sub-items — renders as an expandable group in the picker */
    children?: VariableItem[];
}

export declare function VariablePicker({ width, title, mode, floating, }: VariablePickerProps): JSX_2.Element | null;

declare interface VariablePickerContextValue {
    groups: VariableGroup[];
    isOpen: boolean;
    openPicker: () => void;
    closePicker: () => void;
    /**
     * Called by FormulaOverlay when formula mode is toggled ON or OFF.
     * Pass the anchor HTMLElement (the toggle button) when turning ON so the
     * picker can position itself next to it.
     */
    notifyFormulaToggle: (on: boolean, anchor?: HTMLElement | null) => void;
    /** FormulaInput calls this on focus to register as the active target */
    registerField: (field: ActiveField) => void;
    /** FormulaInput calls this on selection change to save cursor position */
    saveRange: (range: Range | null) => void;
    /** Picker calls this on item click or drop — inserts chip into active field */
    insertVariable: (path: string, label: string) => void;
    /** Currently active field id — used by FormulaInput to show drop-valid state */
    activeFieldId: string | null;
    /** Signal that a field has been focused/clicked — used to auto-open picker panel */
    notifyFieldFocus: (fieldId: string, anchor?: HTMLElement | null) => void;
    /** DOM element the popover should anchor to */
    anchorEl: HTMLElement | null;
}

export declare interface VariablePickerProps {
    /** Panel width in px. Default: 300 */
    width?: number;
    /** Title shown in panel header. Default: 'Smart Values' */
    title?: string;
    /**
     * 'drawer' — always visible as a sidebar panel (default).
     * 'popover' — absolutely positioned, shown/hidden via isOpen.
     */
    mode?: 'drawer' | 'popover';
    floating?: boolean;
}

export declare function VariablePickerProvider({ groups, children }: VariablePickerProviderProps): JSX_2.Element;

declare interface VariablePickerProviderProps {
    groups: VariableGroup[];
    children: default_2.ReactNode;
}

export declare function wrapFormula(expression: string): string;

export { }
