import { type Accessor } from "solid-js";
/**
 * Used for restricting the user type input in {@link createMachine} generic.
 */
export type StatesBase<TStateNames extends PropertyKey> = {
    [K in TStateNames]: {
        /**
         * Value to be passed to the state callback when the machine enters that state.
         */
        readonly input?: any;
        /**
         * Value returned from the state callback.
         */
        readonly value?: any;
        /**
         * Array of state names that can be transitioned to from this state.
         */
        readonly to?: TStateNames;
    };
};
/**
 * Extracts the input type from a state definition.
 */
export type StateInput<T extends {
    input?: any;
}> = T extends {
    input: infer Input;
} ? Input : void;
/**
 * Extracts the value type from a state definition.
 */
export type StateValue<T extends {
    value?: any;
}> = T extends {
    value: infer Value;
} ? Value : undefined;
/**
 * States object with function implementations.
 * @example
 * ```ts
 * const states: MachineStates<{
 *   idle: { value: "foo"; to: ["loading"] };
 *   loading: { value: "bar"; to: ["idle"] };
 * }> = {
 *   idle: () => "foo",
 *   loading(input, next) {
 *     next("idle");
 *     return "bar";
 *   }
 * }
 * ```
 */
export type MachineStates<T extends StatesBase<keyof T>> = {
    [K in keyof T]: (input: StateInput<T[K]>, next: MachineNext<T, K>) => StateValue<T[K]>;
};
type MachineInitialDiscriminator<T extends StatesBase<keyof T>> = {
    [K in keyof T]: {
        type: K;
        input: StateInput<T[K]>;
    } | (T[K] extends {
        input: any;
    } ? never : K);
};
/**
 * Union of all possible initial states.
 */
export type MachineInitial<T extends StatesBase<keyof T>> = MachineInitialDiscriminator<T>[keyof T];
/**
 * Options object for {@link createMachine}.
 */
export type MachineOptions<T extends StatesBase<keyof T>> = {
    states: MachineStates<T>;
    initial: MachineInitial<T>;
};
type MachineStateDiscriminator<T extends StatesBase<keyof T>> = {
    [K in keyof T]: {
        readonly type: K;
        readonly value: StateValue<T[K]>;
        readonly to: MachineNext<T, K>;
    };
};
/**
 * Type of the state object returned by {@link createMachine}.
 *
 * Use with a specific state name to get the state object for that state.
 * @example
 * ```ts
 * type IdleState = MachineState<States, "idle">
 * ```
 *
 * Use with `keyof States` to get the union of all state objects.
 * @example
 * ```ts
 * type AllStates = MachineState<States, keyof States>
 * ```
 */
export type MachineState<T extends StatesBase<keyof T>, K extends keyof T> = MachineStateDiscriminator<T>[K];
type PossibleNextKeys<T extends StatesBase<keyof T>, TKey extends keyof T> = Exclude<Extract<keyof T, T[TKey] extends {
    to: infer To;
} ? To : any>, TKey | symbol>;
/**
 * Type of the `next` function passed to state functions. Or the `to` property of the state object.
 *
 * Use with a specific state name to get the `next` function for that state.
 * @example
 * ```ts
 * type IdleNext = MachineNext<States, "idle">
 * ```
 *
 * Use with `keyof States` to get the union of all `next` functions.
 * @example
 * ```ts
 * type AllNext = MachineNext<States, keyof States>
 * ```
 */
export type MachineNext<T extends StatesBase<keyof T>, TKey extends keyof T> = {
    readonly [K in PossibleNextKeys<T, TKey>]: (input: StateInput<T[K]>) => void;
} & (<K extends PossibleNextKeys<T, TKey>>(...args: T[K] extends {
    input: infer Input;
} ? [to: K, input: Input] : [to: K, input?: undefined]) => void);
/**
 * Creates a reactive state machine.
 *
 * @param options {@link MachineOptions} object.
 *
 * @returns A signal with the current state object.
 *
 * @example
 * ```ts
 * const state = createMachine<{
 *   idle: { value: "foo"; to: "loading" };
 *   loading: { input: number; value: "bar"; to: "idle" };
 * }>({
 *   initial: "idle",
 *   states: {
 *     idle(input, to) {
 *       return "foo";
 *     },
 *     loading(input, to) {
 *       setTimeout(() => to("idle"), input);
 *       return "bar";
 *     }
 *   }
 * })
 *
 * state.type // "idle"
 * state.value // "foo"
 *
 * if (state.type === "idle") {
 *   state.to.loading(1000)
 *
 *   state.type // "loading"
 *   state.value // "bar"
 * }
 * ```
 */
export declare function createMachine<T extends StatesBase<keyof T>>(options: MachineOptions<T>): Accessor<MachineState<T, keyof T>> & MachineState<T, keyof T>;
export {};
