import { AnySchema } from 'yup';
import { default as default_2 } from 'react';
import { EdgeProps } from 'reactflow';
import { EdgeTypes } from 'reactflow';
import { JSX as JSX_2 } from 'react/jsx-runtime';
import { NodeProps } from 'reactflow';
import { NodeTypes } from 'reactflow';
import { ReactNode } from 'react';

export declare const ActionNode: ({ id, data }: NodeProps) => JSX_2.Element;

export declare interface AddStepContext {
    edgeId: string;
    nodeId: string;
    sourceNodeId: string;
    targetNodeId: string;
    position: 'between';
    referenceNodeId: string;
    referenceNodeType?: string;
    stepVisibility?: unknown;
    filterId?: string;
    branch?: string;
}

/**
 * Wire shape the backend `/api/v1/workflow-template` endpoint is expected
 * to return. Top-level fields mirror the persistence model; everything
 * UI-related lives under `templateUI`. Use with `templateRegistry.registerFromApi(list)`.
 */
export declare interface ApiWorkflowTemplate {
    key: string;
    name: string;
    state?: string;
    description?: string;
    allowedTasks?: string[];
    allowedSources?: string[];
    configuration?: Record<string, unknown>;
    templateUI?: Partial<Omit<WorkflowTemplate, 'triggerKey' | 'label' | 'description' | 'availableTasks'>>;
}

/**
 * Wire shape the backend `/api/v1/workflow-template` endpoint is expected
 * to return. Top-level fields mirror the persistence model; everything
 * UI-related lives under `templateUI`. Use with `templateRegistry.registerFromApi(list)`.
 */
declare interface ApiWorkflowTemplate_2 {
    key: string;
    name: string;
    state?: string;
    description?: string;
    allowedTasks?: string[];
    allowedSources?: string[];
    configuration?: Record<string, unknown>;
    templateUI?: Partial<Omit<WorkflowTemplate_3, 'triggerKey' | 'label' | 'description' | 'availableTasks'>>;
}

export declare const ApprovalNode: ({ id, data }: NodeProps) => JSX_2.Element;

export declare interface BpmnElement {
    id: string;
    $type: string;
    [key: string]: unknown;
}

declare interface BpmnElement_2 {
    id: string;
    $type: string;
    [key: string]: unknown;
}

export declare interface BpmnSaveOptions {
    processId?: string;
    processName?: string;
}

declare type BranchChain = CanvasSlot_2[];

declare type BranchChain_2 = CanvasSlot_3[];

declare type BranchChain_3 = CanvasSlot[];

export declare interface BranchMap {
    [filterId: string]: {
        [branchKey: string]: BranchChain_3;
    };
}

declare interface BranchMap_2 {
    [filterId: string]: {
        [branchKey: string]: BranchChain;
    };
}

declare interface BranchMap_3 {
    [filterId: string]: {
        [branchKey: string]: BranchChain_2;
    };
}

export declare const builtInNodeTypes: NodeTypes;

export declare interface CanvasSlot {
    id: string;
    kind: SlotKind_3;
    reactFlowType: string;
    descriptorType?: string;
    formData?: Record<string, unknown>;
    nodeData?: Record<string, unknown>;
    deletable?: boolean;
    label?: string;
    /** Maps branch key → display label. e.g. { pass: 'Pass', fail: 'Fail' } */
    branchLabels?: Record<string, string>;
}

declare interface CanvasSlot_2 {
    id: string;
    kind: SlotKind;
    reactFlowType: string;
    descriptorType?: string;
    formData?: Record<string, unknown>;
    nodeData?: Record<string, unknown>;
    deletable?: boolean;
    label?: string;
    /** Maps branch key → display label. e.g. { pass: 'Pass', fail: 'Fail' } */
    branchLabels?: Record<string, string>;
}

declare interface CanvasSlot_3 {
    id: string;
    kind: SlotKind_2;
    reactFlowType: string;
    descriptorType?: string;
    formData?: Record<string, unknown>;
    nodeData?: Record<string, unknown>;
    deletable?: boolean;
    label?: string;
    /** Maps branch key → display label. e.g. { pass: 'Pass', fail: 'Fail' } */
    branchLabels?: Record<string, string>;
}

/** One column in a per-field condition row */
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;
}

/** One column in a per-field condition row */
declare interface ConditionFieldDef_2 {
    /** 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_2;
    /** When true, renders a FormulaInput chip editor instead of a plain <input> */
    formula?: boolean;
}

export declare const defaultFlowForgeMessages: FlowForgeMessages;

export declare interface DmnDefinition {
    id: string;
    [key: string]: unknown;
}

declare interface DmnDefinition_2 {
    id: string;
    [key: string]: unknown;
}

export declare const EdgeWithPlusLabel: ({ id: edgeId, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, source, target, data, }: EdgeProps<EdgeWithPlusLabelData>) => JSX_2.Element;

export declare interface EdgeWithPlusLabelData {
    label?: string;
    onAddStepClick?: (sourceNodeId: string, context: AddStepContext) => void;
    referenceNodeType?: string;
    stepVisibility?: unknown;
}

export declare const EndNode: () => JSX_2.Element;

export declare interface ExecutionRecord {
    id: string;
    workflowId?: string;
    triggeredBy?: string;
    triggeredAt: string;
    status: ExecutionStatus;
    inputs?: Record<string, unknown>;
    steps: ExecutionStep[];
    completedAt?: string;
    error?: string;
}

export declare type ExecutionStatus = 'running' | 'success' | 'failed' | 'cancelled';

export declare interface ExecutionStep {
    nodeId: string;
    nodeType?: string;
    label?: string;
    startedAt: string;
    completedAt?: string;
    status: StepStatus;
    inputs?: Record<string, unknown>;
    outputs?: Record<string, unknown>;
    branchTaken?: string;
    error?: string;
}

/** Condition definition attached to a FieldDescriptor */
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;
}

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

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>;
}

declare interface FieldContext_2 {
    /** 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>;
}

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;
}

declare interface FieldDescriptor_2 {
    /**
     * 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_2 | string;
    /** Child field descriptors — used by type: 'object' to render a nested group. */
    children?: FieldDescriptor_2[];
    /** Optional per-field condition guard — renders a condition row below this field. */
    condition?: FieldConditionDef_2;
    label?: string;
    placeholder?: string;
    required?: boolean;
    showOptional?: boolean;
    disabled?: boolean | ((ctx: FieldContext_2) => boolean);
    hidden?: boolean;
    colSpan?: number;
    dividerAfter?: boolean;
    info?: string;
    helperText?: string;
    dataTestId?: string;
    validation?: AnySchema;
    shouldHide?: (ctx: FieldContext_2) => boolean;
    shouldDisable?: (ctx: FieldContext_2) => boolean;
    shouldRequire?: (ctx: FieldContext_2) => 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_2) => unknown;
    transform?: FieldTransform_2;
    onChange?: (value: unknown, ctx: FieldContext_2 & {
        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_2;
    [key: string]: unknown;
}

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

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

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

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

export declare const FilterNode: ({ id, data }: NodeProps) => JSX_2.Element;

declare interface FixedEdge {
    id: string;
    source: string;
    target: string;
}

declare interface FixedEdge_2 {
    id: string;
    source: string;
    target: string;
}

declare interface FixedEdge_3 {
    id: string;
    source: string;
    target: string;
}

declare interface FixedNode {
    id: string;
    type: string;
    data?: Record<string, unknown>;
    deletable?: false;
}

declare interface FixedNode_2 {
    id: string;
    type: string;
    data?: Record<string, unknown>;
    deletable?: false;
}

declare interface FixedNode_3 {
    id: string;
    type: string;
    data?: Record<string, unknown>;
    deletable?: false;
}

declare const FlowForgeCanvas: ({ nodeRegistry, templateRegistry, initialValue, nodeTypes: consumerNodeTypes, edgeTypes: consumerEdgeTypes, onSave, readOnly, theme, messages: messageOverrides, canvasOptions, renderTriggerSelector, loadTriggerSources, renderNodePicker, renderNodeConfig, onNodeClick: onNodeClickProp, maxNodes, layoutDirection, executionRecord, onFetchWorkflow, hideHeader, workflowName, onWorkflowNameChange, onCancel, workflowStatus, workflowStatusColor, saveLabel, optionsResolvers, }: FlowForgeCanvasProps) => JSX_2.Element;
export { FlowForgeCanvas }
export { FlowForgeCanvas as WorkflowCanvas }

/** All ReactFlow behaviour settings — serialisable as JSON config */
export declare interface FlowForgeCanvasOptions {
    /** Fit the whole graph into view on mount. Default: true */
    fitView?: boolean;
    fitViewPadding?: number;
    /** Show the zoom-in / zoom-out / fit controls. Default: true */
    showControls?: boolean;
    /** Show the mini-map overview. Default: false */
    showMiniMap?: boolean;
    /** Pan the canvas by scrolling (no Ctrl needed). Default: true */
    panOnScroll?: boolean;
    /** Zoom with the scroll wheel. Default: false */
    zoomOnScroll?: boolean;
    minZoom?: number;
    maxZoom?: number;
    /** Snap nodes to a grid while dragging. Default: false */
    snapToGrid?: boolean;
    snapGrid?: [number, number];
    /**
     * How branches under a conditional/gateway node are arranged.
     * 'horizontal' (default): branches spread side-by-side (Dagre).
     * 'vertical': branches stack top-to-bottom, indented right under their parent (Workato style).
     */
    branchLayout?: 'horizontal' | 'vertical';
    /**
     * How much of a node's data to show on its card.
     * 'full' (default): show configured value badges / the descriptor's custom body.
     * 'title-only': show just the node title — for teams that want minimal cards.
     */
    nodeBody?: 'full' | 'title-only';
}

export declare interface FlowForgeCanvasProps {
    nodeRegistry: NodeTypeRegistry;
    templateRegistry: TemplateRegistry;
    /** Pre-populate the canvas from a previously saved WorkflowState. */
    initialValue?: WorkflowState;
    nodeTypes?: NodeTypes;
    edgeTypes?: EdgeTypes;
    onSave?: (workflow: WorkflowState) => void;
    /** Disables all editing — no add/delete/config, edges have no "+" button */
    readOnly?: boolean;
    /** Brand colors applied across edges, plus button, and node accents */
    theme?: FlowForgeTheme;
    /** Built-in UI labels for i18n/white-label copy. */
    messages?: Partial<FlowForgeMessages>;
    /** ReactFlow behaviour settings — all serialisable as plain JSON */
    canvasOptions?: FlowForgeCanvasOptions;
    /** Replace the trigger selector UI entirely */
    renderTriggerSelector?: (templates: WorkflowTemplate[], onSelect: (t: WorkflowTemplate) => void, onClose: () => void) => default_2.ReactNode;
    /**
     * Optional async loader for trigger sources. When provided, the default
     * trigger selector goes to a second stage after the user picks a trigger:
     * the loader is called with the trigger's key, and if it returns a non-empty
     * list, the user picks one or more sources before the canvas is seeded.
     * Picked sources are merged into the trigger node's `nodeData.sources` so
     * TriggerNode can render the "via [chip] [chip]" line.
     *
     * Return `[]` for triggers that have no sources — stage 2 is skipped.
     */
    loadTriggerSources?: (triggerKey: string) => Promise<Array<{
        label: string;
        value: string;
    }>>;
    /** Replace the node picker UI entirely */
    renderNodePicker?: (descriptors: NodeDescriptor[], onSelect: (d: NodeDescriptor) => void, onClose: () => void) => default_2.ReactNode;
    /** Replace the node config drawer entirely */
    renderNodeConfig?: (descriptor: NodeDescriptor | undefined, slot: CanvasSlot | null, onSave: (id: string, values: Record<string, unknown>) => void, onClose: () => void) => default_2.ReactNode;
    /** Intercept node click — return true to suppress default behaviour */
    onNodeClick?: (slot: CanvasSlot) => boolean | void;
    /** Global cap on total user task nodes */
    maxNodes?: number;
    /** Flow layout direction. 'TB' = top-to-bottom (default), 'LR' = left-to-right */
    layoutDirection?: 'TB' | 'LR';
    /**
     * When provided, renders an execution overlay on the canvas nodes:
     * green = success, red = failed, grey = skipped/pending.
     * Combine with readOnly=true to show a past run without editing.
     */
    executionRecord?: ExecutionRecord;
    /**
     * Called when a SubWorkflowNode's "Preview" button is clicked.
     * Return the WorkflowState for the given workflowId to render it in a drawer.
     */
    onFetchWorkflow?: (workflowId: string) => Promise<WorkflowState>;
    /** Hide the built-in top bar (Save / Cancel / name). Default false. */
    hideHeader?: boolean;
    /** Display name in the header. */
    workflowName?: string;
    /** Make the header name click-to-edit. */
    onWorkflowNameChange?: (name: string) => void;
    /** Cancel button shows only when this handler is provided. */
    onCancel?: () => void;
    /** Status pill text + color (e.g. 'Draft' / 'amber'). */
    workflowStatus?: string;
    workflowStatusColor?: 'gray' | 'green' | 'amber' | 'red' | string;
    /** Override the Save button label. */
    saveLabel?: string;
    /**
     * Host-registered map of named option resolvers. Fields in any node's
     * `formSchema` may declare `optionsSource: { id, dependsOn, params }` to
     * populate a select asynchronously. Transport-agnostic — the host's
     * resolver can use axios, fetch, GraphQL, etc.
     *
     * Example:
     *   optionsResolvers={{
     *     'app:groups': async ({ appId }, { cursor=0 }) => {
     *       const res = await api.get(`/groups?startIndex=${cursor}&count=50`);
     *       return {
     *         options: res.data.map(g => ({ value: g.uuid, label: g.name })),
     *         nextCursor: res.data.length === 50 ? cursor + 50 : undefined,
     *       };
     *     }
     *   }}
     *
     * Resolvers are cached for the session keyed by (resolverId, deps). Use
     * `useOptionsResolvers().invalidate(id)` to bust a cache entry manually.
     */
    optionsResolvers?: OptionsResolvers;
}

export declare function FlowForgeHeader({ workflowName, onWorkflowNameChange, status, statusColor, onSave, onCancel, saveLabel, saveDisabled, }: FlowForgeHeaderProps): JSX_2.Element;

/**
 * FlowForgeHeader — top bar that ships with FlowForgeCanvas by default.
 *
 * Renders the workflow name, a status pill, Cancel, and primary Save
 * button. Calls back via `onSave` / `onCancel`. The canvas itself wires
 * `onSave` to the latest WorkflowState behind the scenes — consumers
 * only provide a callback that receives that state.
 *
 * Opt out of the built-in header by passing `hideHeader={true}` on
 * FlowForgeCanvas; you can still mount this component standalone.
 */
export declare interface FlowForgeHeaderProps {
    /** Workflow display name shown on the left. */
    workflowName?: string;
    /** Optional editable callback — when provided, name becomes click-to-edit. */
    onWorkflowNameChange?: (name: string) => void;
    /** Status pill text (e.g. 'Draft', 'Published', 'Unsaved'). */
    status?: string;
    /** Status pill color — one of these or a custom hex. */
    statusColor?: 'gray' | 'green' | 'amber' | 'red' | string;
    /** Click handler for the primary Save button. Async-aware: spinner shows during await. */
    onSave?: () => void | Promise<void>;
    /** Click handler for Cancel. Button hidden when not provided. */
    onCancel?: () => void;
    /** Custom label for the Save button. Defaults to "Save". */
    saveLabel?: string;
    /** Disable Save button (e.g. while there are no unsaved changes). */
    saveDisabled?: boolean;
}

export declare interface FlowForgeMessages {
    addTriggerTitle: string;
    addTriggerTooltip: string;
    addTriggerButton: string;
    chooseTrigger: string;
    noTriggers: string;
    addStepTitle: string;
    chooseAction: string;
    noActions: string;
    configureStep: string;
    loadingConfiguration: string;
    noConfigurationNeeded: string;
    save: string;
    cancel: string;
}

export declare interface FlowForgeTheme {
    primaryColor?: string;
    edgeColor?: string;
    textColor?: string;
    mutedTextColor?: string;
    surfaceColor?: string;
    borderColor?: string;
    dangerColor?: string;
    borderRadius?: number;
    fontFamily?: string;
    /** ReactFlow canvas background style. 'none' hides the background entirely. Default: 'dots' */
    background?: 'dots' | 'lines' | 'cross' | 'none';
    /** Background dot/line color. Default: '#e0e0e0' */
    backgroundColor?: string;
}

/**
 * Context passed to `NodeDescriptor.canInsert(ctx)` describing where on the
 * canvas the user clicked "+ Add step". Used by position-aware insertion rules.
 */
declare interface InsertContext {
    /** The slot the user clicked under (the one whose "+" edge was clicked). */
    insertAfterSlot: CanvasSlot_2 | null;
    /** Every slot before the insertion point, including the click slot.
     *  When inside a branch: spine up to + including the branching parent, then
     *  the branch's own slots up to the insertion point. */
    upstreamSlots: CanvasSlot_2[];
    /** Every slot after the insertion point in the same chain. */
    downstreamSlots: CanvasSlot_2[];
    /** Branch context, if the insertion is happening inside a branch. */
    branch: {
        filterId: string;
        branch: string;
    } | null;
    /** The currently active template (the one whose trigger is in use). */
    template: WorkflowTemplate_2 | null;
}

/**
 * Context passed to `NodeDescriptor.canInsert(ctx)` describing where on the
 * canvas the user clicked "+ Add step". Used by position-aware insertion rules.
 */
declare interface InsertContext_2 {
    /** The slot the user clicked under (the one whose "+" edge was clicked). */
    insertAfterSlot: CanvasSlot | null;
    /** Every slot before the insertion point, including the click slot.
     *  When inside a branch: spine up to + including the branching parent, then
     *  the branch's own slots up to the insertion point. */
    upstreamSlots: CanvasSlot[];
    /** Every slot after the insertion point in the same chain. */
    downstreamSlots: CanvasSlot[];
    /** Branch context, if the insertion is happening inside a branch. */
    branch: {
        filterId: string;
        branch: string;
    } | null;
    /** The currently active template (the one whose trigger is in use). */
    template: WorkflowTemplate | null;
}

export declare function loadWorkflowFromBpmn(xml: string): WorkflowState;

export declare interface NodeDescriptor {
    type: string;
    label: string;
    icon?: ReactNode;
    /**
     * Optional "app" this action belongs to (Slack, Salesforce, …). When present,
     * the node picker drills down: stage 1 lists unique apps, stage 2 lists this
     * app's actions, stage 3 is the action's config form. Descriptors without an
     * `app` field appear ungrouped at stage 1, alongside the app cards.
     */
    app?: {
        key: string;
        label: string;
        icon?: ReactNode;
        description?: string;
    };
    matches: (id: string) => boolean;
    bpmnEntry: (nodeId: string) => string;
    bpmnExit: (nodeId: string) => string;
    emitBpmnElements: (nodeId: string, nodeData: unknown) => BpmnElement[];
    emitDmnDefinition?: (nodeId: string, nodeData: unknown) => DmnDefinition;
    outgoingCondition?: (nodeId: string, targetId: string, nodeData: unknown) => string;
    reactFlowType: string;
    previewNodeType?: string;
    /**
     * Optional custom node-card body. When provided, the node renderer shows this
     * instead of the default value badges — lets a node author fully design the
     * card body while keeping the shared frame (title, edit/delete, handles).
     * Receives the node's saved formData.
     */
    renderNode?: (nodeData: Record<string, unknown>) => ReactNode;
    /**
     * Position constraint — this descriptor can be inserted only if at least ONE
     * of the listed tokens appears in the upstream chain of the click site.
     * Tokens can be a descriptorType (e.g. 'createUserTask'), a slot id
     * (e.g. 'event-userCreated'), or a slot kind (e.g. 'triggerFixed').
     * Ignored when `canInsert` is set.
     */
    insertAfter?: string[];
    /**
     * Symmetric — must appear DOWNSTREAM of the click site. Same token rules
     * as `insertAfter`. Ignored when `canInsert` is set.
     */
    insertBefore?: string[];
    /**
     * Full custom rule. Overrides `insertAfter` / `insertBefore`. Receives the
     * click context (upstream/downstream slots, branch info, active template);
     * returns `true` to allow the descriptor at this insertion point.
     */
    canInsert?: (ctx: InsertContext_2) => boolean;
    /** Maps branch key → display label. e.g. { pass: 'Pass', fail: 'Fail' }. Only applies to branching nodes (filterNode, approvalNode). */
    branchLabels?: Record<string, string>;
    formSchema: FieldDescriptor_2[] | ((nodeId: string) => Promise<FieldDescriptor_2[]>);
    maxPerWorkflow?: number;
    relatedNodePrefixes?: string[];
}

declare interface NodeDescriptor_2 {
    type: string;
    label: string;
    icon?: ReactNode;
    /**
     * Optional "app" this action belongs to (Slack, Salesforce, …). When present,
     * the node picker drills down: stage 1 lists unique apps, stage 2 lists this
     * app's actions, stage 3 is the action's config form. Descriptors without an
     * `app` field appear ungrouped at stage 1, alongside the app cards.
     */
    app?: {
        key: string;
        label: string;
        icon?: ReactNode;
        description?: string;
    };
    matches: (id: string) => boolean;
    bpmnEntry: (nodeId: string) => string;
    bpmnExit: (nodeId: string) => string;
    emitBpmnElements: (nodeId: string, nodeData: unknown) => BpmnElement_2[];
    emitDmnDefinition?: (nodeId: string, nodeData: unknown) => DmnDefinition_2;
    outgoingCondition?: (nodeId: string, targetId: string, nodeData: unknown) => string;
    reactFlowType: string;
    previewNodeType?: string;
    /**
     * Optional custom node-card body. When provided, the node renderer shows this
     * instead of the default value badges — lets a node author fully design the
     * card body while keeping the shared frame (title, edit/delete, handles).
     * Receives the node's saved formData.
     */
    renderNode?: (nodeData: Record<string, unknown>) => ReactNode;
    /**
     * Position constraint — this descriptor can be inserted only if at least ONE
     * of the listed tokens appears in the upstream chain of the click site.
     * Tokens can be a descriptorType (e.g. 'createUserTask'), a slot id
     * (e.g. 'event-userCreated'), or a slot kind (e.g. 'triggerFixed').
     * Ignored when `canInsert` is set.
     */
    insertAfter?: string[];
    /**
     * Symmetric — must appear DOWNSTREAM of the click site. Same token rules
     * as `insertAfter`. Ignored when `canInsert` is set.
     */
    insertBefore?: string[];
    /**
     * Full custom rule. Overrides `insertAfter` / `insertBefore`. Receives the
     * click context (upstream/downstream slots, branch info, active template);
     * returns `true` to allow the descriptor at this insertion point.
     */
    canInsert?: (ctx: InsertContext) => boolean;
    /** Maps branch key → display label. e.g. { pass: 'Pass', fail: 'Fail' }. Only applies to branching nodes (filterNode, approvalNode). */
    branchLabels?: Record<string, string>;
    formSchema: FieldDescriptor[] | ((nodeId: string) => Promise<FieldDescriptor[]>);
    maxPerWorkflow?: number;
    relatedNodePrefixes?: string[];
}

declare class NodeTypeRegistry {
    private descriptors;
    register(descriptor: NodeDescriptor_2): this;
    forType(type: string): NodeDescriptor_2 | undefined;
    forId(id: string): NodeDescriptor_2 | undefined;
    list(): NodeDescriptor_2[];
}

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

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. */
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;
}

declare type OptionsResolvers = Record<string, OptionsResolver>;

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;
}

declare interface OptionsSource_2 {
    /** 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;
}

export declare const RestApiNode: ({ id, data }: NodeProps) => JSX_2.Element;

export declare function saveWorkflowToBpmn(workflow: WorkflowState, options?: BpmnSaveOptions): string;

declare type SlotKind = 'start' | 'end' | 'addTrigger' | 'triggerFixed' | 'userTask' | 'addStep' | 'filter' | 'approval';

declare type SlotKind_2 = 'start' | 'end' | 'addTrigger' | 'triggerFixed' | 'userTask' | 'addStep' | 'filter' | 'approval';

declare type SlotKind_3 = 'start' | 'end' | 'addTrigger' | 'triggerFixed' | 'userTask' | 'addStep' | 'filter' | 'approval';

export declare const StartNode: () => JSX_2.Element;

export declare type StepStatus = 'pending' | 'running' | 'success' | 'failed' | 'skipped';

export declare const SubWorkflowPreviewDrawer: default_2.FC<SubWorkflowPreviewDrawerProps>;

declare interface SubWorkflowPreviewDrawerProps {
    isOpen: boolean;
    onClose: () => void;
    workflowId: string | null;
    workflowLabel?: string;
    /** Host-provided async loader — returns the WorkflowState for the given ID */
    onFetchWorkflow: (workflowId: string) => Promise<WorkflowState>;
}

declare class TemplateRegistry {
    private templates;
    /**
     * Register a template. Normalises `allowedTasks` (the backend's name) →
     * `availableTasks` (FlowForge's canonical name) so consumers can pass
     * either without rewriting.
     */
    register(template: WorkflowTemplate_3): this;
    /**
     * Register a list of templates fetched from `GET /api/v1/workflow-template`.
     *
     * The API shape is:
     *   {
     *     key, name, description, allowedTasks, allowedSources,
     *     configuration,            // runtime BPMN — ignored by the canvas
     *     templateUI: {             // ← UI bag, spread onto the template
     *       triggerCategory, icon, tags, category, author, popularity,
     *       source, product, taskLabels, maxTasks, skeletonState, …
     *     }
     *   }
     *
     * Anything in `templateUI` overrides the top-level shorthand where there's
     * an overlap. Bad rows (missing `key`) are skipped with a DEV warning
     * rather than throwing, so one broken template doesn't blank the picker.
     *
     * Returns `this` for chaining and the count of templates registered.
     */
    registerFromApi(list: ApiWorkflowTemplate_2[]): this;
    lookup(triggerKey: string): WorkflowTemplate_3 | undefined;
    list(): WorkflowTemplate_3[];
    listByCategory(category: string): WorkflowTemplate_3[];
    listByTag(tag: string): WorkflowTemplate_3[];
    search(query: string): WorkflowTemplate_3[];
    categories(): string[];
    /** Remove every template — useful before re-loading from backend. */
    clear(): this;
}

export declare const TriggerNode: ({ data }: NodeProps) => JSX_2.Element;

export declare const WebhookTriggerNode: ({ data }: NodeProps) => JSX_2.Element;

/** @deprecated Use FlowForgeCanvasProps */
export declare type WorkflowCanvasProps = FlowForgeCanvasProps;

export declare const WorkflowExecutionHistory: default_2.FC<WorkflowExecutionHistoryProps>;

declare interface WorkflowExecutionHistoryProps {
    records: ExecutionRecord[];
    /** Called when the "view on canvas" button is clicked for a record */
    onViewOnCanvas?: (record: ExecutionRecord) => void;
}

export declare interface WorkflowState {
    slots: CanvasSlot[];
    branches: BranchMap;
}

declare interface WorkflowState_2 {
    slots: CanvasSlot_2[];
    branches: BranchMap_2;
}

declare interface WorkflowState_3 {
    slots: CanvasSlot_3[];
    branches: BranchMap_3;
}

export declare interface WorkflowTemplate {
    triggerKey: string;
    label: string;
    description?: string;
    icon?: ReactNode;
    triggerCategory?: 'event' | 'scheduler' | 'webhook' | string;
    /**
     * Task IDs (descriptor types) that can be inserted into this workflow.
     * `allowedTasks` is accepted as an alias for backend payloads that use
     * that name — TemplateRegistry.register() normalises them.
     */
    availableTasks?: string[];
    allowedTasks?: string[];
    maxTasks?: number;
    taskLabels?: Record<string, string>;
    fixedNodes?: FixedNode_3[];
    fixedEdges?: FixedEdge_3[];
    insertionPoints?: string[];
    source?: string;
    product?: string;
    /** Pre-built workflow state to clone when user selects this template */
    skeletonState?: WorkflowState;
    /** Tags for filtering in the template library */
    tags?: string[];
    /** Category grouping in the library */
    category?: string;
    /** Team or author that owns this template */
    author?: string;
    /** Relative popularity score (higher = shown first in library) */
    popularity?: number;
}

declare interface WorkflowTemplate_2 {
    triggerKey: string;
    label: string;
    description?: string;
    icon?: ReactNode;
    triggerCategory?: 'event' | 'scheduler' | 'webhook' | string;
    /**
     * Task IDs (descriptor types) that can be inserted into this workflow.
     * `allowedTasks` is accepted as an alias for backend payloads that use
     * that name — TemplateRegistry.register() normalises them.
     */
    availableTasks?: string[];
    allowedTasks?: string[];
    maxTasks?: number;
    taskLabels?: Record<string, string>;
    fixedNodes?: FixedNode[];
    fixedEdges?: FixedEdge[];
    insertionPoints?: string[];
    source?: string;
    product?: string;
    /** Pre-built workflow state to clone when user selects this template */
    skeletonState?: WorkflowState_2;
    /** Tags for filtering in the template library */
    tags?: string[];
    /** Category grouping in the library */
    category?: string;
    /** Team or author that owns this template */
    author?: string;
    /** Relative popularity score (higher = shown first in library) */
    popularity?: number;
}

declare interface WorkflowTemplate_3 {
    triggerKey: string;
    label: string;
    description?: string;
    icon?: ReactNode;
    triggerCategory?: 'event' | 'scheduler' | 'webhook' | string;
    /**
     * Task IDs (descriptor types) that can be inserted into this workflow.
     * `allowedTasks` is accepted as an alias for backend payloads that use
     * that name — TemplateRegistry.register() normalises them.
     */
    availableTasks?: string[];
    allowedTasks?: string[];
    maxTasks?: number;
    taskLabels?: Record<string, string>;
    fixedNodes?: FixedNode_2[];
    fixedEdges?: FixedEdge_2[];
    insertionPoints?: string[];
    source?: string;
    product?: string;
    /** Pre-built workflow state to clone when user selects this template */
    skeletonState?: WorkflowState_3;
    /** Tags for filtering in the template library */
    tags?: string[];
    /** Category grouping in the library */
    category?: string;
    /** Team or author that owns this template */
    author?: string;
    /** Relative popularity score (higher = shown first in library) */
    popularity?: number;
}

export declare const WorkflowTemplateLibrary: default_2.FC<WorkflowTemplateLibraryProps>;

declare interface WorkflowTemplateLibraryProps {
    templates: WorkflowTemplate[];
    onSelectTemplate: (template: WorkflowTemplate) => void;
    onStartFromScratch?: () => void;
}

export { }
