import * as launchdarkly_js_client_sdk from 'launchdarkly-js-client-sdk';
import { LDFlagSet, LDClient, LDContext, LDOptions } from 'launchdarkly-js-client-sdk';
export * from 'launchdarkly-js-client-sdk';
import * as React from 'react';
import React__default, { Component, PropsWithChildren, ReactNode } from 'react';

/**
 * Controls the props the wrapped component receives from the `LDConsumer` HOC.
 */
interface ConsumerOptions {
    /**
     * If true then the wrapped component only receives the `ldClient` instance
     * and nothing else.
     */
    clientOnly: boolean;
    reactContext?: React.Context<ReactSdkContext>;
}
/**
 * The possible props the wrapped component can receive from the `LDConsumer` HOC.
 */
interface LDProps {
    /**
     * A map of feature flags from their keys to their values.
     * Keys are camelCased using `lodash.camelcase`.
     */
    flags?: LDFlagSet;
    /**
     * An instance of `LDClient` from the LaunchDarkly JS SDK (`launchdarkly-js-client-sdk`)
     *
     * @see https://docs.launchdarkly.com/sdk/client-side/javascript
     */
    ldClient?: LDClient;
}
/**
 * withLDConsumer is a function which accepts an optional options object and returns a function
 * which accepts your React component. This function returns a HOC with flags
 * and the ldClient instance injected via props.
 *
 * @param options - If you need only the `ldClient` instance and not flags, then set `{ clientOnly: true }`
 * to only pass the ldClient prop to your component. Defaults to `{ clientOnly: false }`.
 * @return A HOC with flags and the `ldClient` instance injected via props
 */
declare function withLDConsumer(options?: ConsumerOptions): <P>(WrappedComponent: React.ComponentType<P & LDProps>) => (props: P) => React.JSX.Element;

/**
 * Initialization options for the LaunchDarkly React SDK. These are in addition to the options exposed
 * by [[LDOptions]] which are common to both the JavaScript and React SDKs.
 */
interface LDReactOptions {
    /**
     * Whether the React SDK should transform flag keys into camel-cased format.
     * Using camel-cased flag keys allow for easier use as prop values, however,
     * these keys won't directly match the flag keys as known to LaunchDarkly.
     * Consequently, flag key collisions may be possible and the Code References feature
     * will not function properly.
     *
     * This is true by default, meaning that keys will automatically be converted to camel-case.
     *
     * For more information, see the React SDK Reference Guide on
     * [flag keys](https://docs.launchdarkly.com/sdk/client-side/react/react-web#flag-keys).
     *
     * @see https://docs.launchdarkly.com/sdk/client-side/react/react-web#flag-keys
     */
    useCamelCaseFlagKeys?: boolean;
    /**
     * Whether to send flag evaluation events when a flag is read from the `flags` object
     * returned by the `useFlags` hook. This is true by default, meaning flag evaluation
     * events will be sent by default.
     */
    sendEventsOnFlagRead?: boolean;
    /**
     * The react context to use within the provider objects.
     */
    reactContext?: React.Context<ReactSdkContext>;
}
/**
 * Contains default values for the `reactOptions` object.
 */
declare const defaultReactOptions: {
    useCamelCaseFlagKeys: boolean;
    sendEventsOnFlagRead: boolean;
    reactContext: React.Context<ReactSdkContext>;
};
/**
 * Configuration object used to initialise LaunchDarkly's JS client.
 */
interface ProviderConfig {
    /**
     * Your project and environment specific client side ID. You can find
     * this in your LaunchDarkly portal under Account settings. This is
     * the only mandatory property required to use the React SDK.
     */
    clientSideID: string;
    /**
     * A LaunchDarkly context object. If unspecified, an anonymous context
     * with kind: 'user' will be created and used.
     */
    context?: LDContext;
    /**
     * @deprecated The `user` property will be removed in a future version,
     * please update your code to use context instead.
     */
    user?: LDContext;
    /**
     * If set to true, the ldClient will not be initialized until the context prop has been defined.
     */
    deferInitialization?: boolean;
    /**
     * LaunchDarkly initialization options. These options are common between LaunchDarkly's JavaScript and React SDKs.
     *
     * @see https://docs.launchdarkly.com/sdk/features/config#javascript
     */
    options?: LDOptions;
    /**
     * Additional initialization options specific to the React SDK.
     *
     * @see options
     */
    reactOptions?: LDReactOptions;
    /**
     * If specified, `launchdarkly-react-client-sdk` will only listen for changes to these flags.
     * Otherwise, all flags will be requested and listened to.
     * Flag keys must be in their original form as known to LaunchDarkly rather than in their camel-cased form.
     */
    flags?: LDFlagSet;
    /**
     * Optionally, the ldClient can be initialized outside of the provider
     * and passed in, instead of being initialized by the provider.
     *
     * Note: it should only be passed in when it has emitted the 'ready'
     * event when using withLDProvider, to ensure that the flags are properly set.
     * If using with asyncWithLDProvider, then it will wait internally, so
     * it is not required that the client have emitted the 'ready' event.
     */
    ldClient?: LDClient | Promise<LDClient | undefined>;
    /**
     *  The amount of time, in seconds, to wait for initialization before rejecting the promise.
     *  Using a large timeout is not recommended. If you use a large timeout and await it, then
     *  any network delays will cause your application to wait a long time before continuing
     *  execution. This gets passed to the underlying Javascript SDK `waitForInitialization`
     *  function.
     */
    timeout?: number;
}
/**
 * Configuration object used to initialize LaunchDarkly's JS client asynchronously.
 */
type AsyncProviderConfig = Omit<ProviderConfig, 'deferInitialization'> & {
    /**
     * @deprecated - `asyncWithLDProvider` does not support the `deferInitialization` config option because
     * `asyncWithLDProvider` needs to be initialized at the app entry point prior to render to ensure flags and the
     * ldClient are ready at the beginning of the app.
     */
    deferInitialization?: boolean;
};
/**
 * The return type of withLDProvider HOC. Exported for testing purposes only.
 *
 * @ignore
 */
interface EnhancedComponent extends React.Component {
    subscribeToChanges(ldClient: LDClient): void;
    componentDidMount(): Promise<void>;
    componentDidUpdate(prevProps: ProviderConfig): Promise<void>;
}
/**
 * Return type of `initLDClient`.
 */
interface AllFlagsLDClient {
    /**
     * Contains all flags from LaunchDarkly.
     */
    flags: LDFlagSet;
    /**
     * An instance of `LDClient` from the LaunchDarkly JS SDK (`launchdarkly-js-client-sdk`).
     *
     * @see https://docs.launchdarkly.com/sdk/client-side/javascript
     */
    ldClient: LDClient;
    /**
     * LaunchDarkly client initialization error, if there was one.
     */
    error?: Error;
}
/**
 * Map of camelized flag keys to original unmodified flag keys.
 */
type LDFlagKeyMap = Record<string, string>;

/**
 * The sdk context stored in the Provider state and passed to consumers.
 */
interface ReactSdkContext {
    /**
     * JavaScript proxy that will trigger a LDClient#variation call on flag read in order
     * to register a flag evaluation event in LaunchDarkly. Empty {} initially
     * until flags are fetched from the LaunchDarkly servers.
     */
    flags: LDFlagSet;
    /**
     * Map of camelized flag keys to their original unmodified form. Empty if useCamelCaseFlagKeys option is false.
     */
    flagKeyMap: LDFlagKeyMap;
    /**
     * An instance of `LDClient` from the LaunchDarkly JS SDK (`launchdarkly-js-client-sdk`).
     * This will be be undefined initially until initialization is complete.
     *
     * @see https://docs.launchdarkly.com/sdk/client-side/javascript
     */
    ldClient?: LDClient;
    /**
     * LaunchDarkly client initialization error, if there was one.
     */
    error?: Error;
}

interface ProviderState {
    error?: Error;
    flagKeyMap: LDFlagKeyMap;
    flags: LDFlagSet;
    ldClient?: LDClient;
    unproxiedFlags: LDFlagSet;
}

/**
 * The `LDProvider` is a component which accepts a config object which is used to
 * initialize `launchdarkly-js-client-sdk`.
 *
 * This Provider does three things:
 * - It initializes the ldClient instance by calling `launchdarkly-js-client-sdk` initialize on `componentDidMount`
 * - It saves all flags and the ldClient instance in the context API
 * - It subscribes to flag changes and propagate them through the context API
 *
 * Because the `launchdarkly-js-client-sdk` in only initialized on `componentDidMount`, your flags and the
 * ldClient are only available after your app has mounted. This can result in a flicker due to flag changes at
 * startup time.
 *
 * This component can be used as a standalone provider. However, be mindful to only include the component once
 * within your application. This provider is used inside the `withLDProviderHOC` and can be used instead to initialize
 * the `launchdarkly-js-client-sdk`. For async initialization, check out the `asyncWithLDProvider` function
 */
declare class LDProvider extends Component<PropsWithChildren<ProviderConfig>, ProviderState> implements EnhancedComponent {
    readonly state: Readonly<ProviderState>;
    constructor(props: ProviderConfig);
    getReactOptions: () => {
        useCamelCaseFlagKeys: boolean;
        sendEventsOnFlagRead: boolean;
        reactContext: React__default.Context<ReactSdkContext>;
    };
    subscribeToChanges: (ldClient: LDClient) => void;
    onFailed: (_ldClient: LDClient, e: Error) => void;
    onReady: (ldClient: LDClient, reactOptions: LDReactOptions, targetFlags?: LDFlagSet) => void;
    prepareLDClient: () => Promise<void>;
    componentDidMount(): Promise<void>;
    componentDidUpdate(prevProps: ProviderConfig): Promise<void>;
    render(): React__default.JSX.Element;
}

/**
 * `withLDProvider` is a function which accepts a config object which is used to
 * initialize `launchdarkly-js-client-sdk`.
 *
 * This HOC handles passing configuration to the `LDProvider`, which does the following:
 * - It initializes the ldClient instance by calling `launchdarkly-js-client-sdk` initialize on `componentDidMount`
 * - It saves all flags and the ldClient instance in the context API
 * - It subscribes to flag changes and propagate them through the context API
 *
 * The difference between `withLDProvider` and `asyncWithLDProvider` is that `withLDProvider` initializes
 * `launchdarkly-js-client-sdk` at `componentDidMount`. This means your flags and the ldClient are only available after
 * your app has mounted. This can result in a flicker due to flag changes at startup time.
 *
 * `asyncWithLDProvider` initializes `launchdarkly-js-client-sdk` at the entry point of your app prior to render.
 * This means that your flags and the ldClient are ready at the beginning of your app. This ensures your app does not
 * flicker due to flag changes at startup time.
 *
 * @param config - The configuration used to initialize LaunchDarkly's JS SDK
 * @return A function which accepts your root React component and returns a HOC
 */
declare function withLDProvider<T extends JSX.IntrinsicAttributes = {}>(config: ProviderConfig): (WrappedComponent: React.ComponentType<T>) => React.ComponentType<T>;

/**
 * This is an async function which initializes LaunchDarkly's JS SDK (`launchdarkly-js-client-sdk`)
 * and awaits it so all flags and the ldClient are ready before the consumer app is rendered.
 *
 * The difference between `withLDProvider` and `asyncWithLDProvider` is that `withLDProvider` initializes
 * `launchdarkly-js-client-sdk` at componentDidMount. This means your flags and the ldClient are only available after
 * your app has mounted. This can result in a flicker due to flag changes at startup time.
 *
 * `asyncWithLDProvider` initializes `launchdarkly-js-client-sdk` at the entry point of your app prior to render.
 * This means that your flags and the ldClient are ready at the beginning of your app. This ensures your app does not
 * flicker due to flag changes at startup time.
 *
 * `asyncWithLDProvider` accepts a config object which is used to initialize `launchdarkly-js-client-sdk`.
 *
 * `asyncWithLDProvider` does not support the `deferInitialization` config option because `asyncWithLDProvider` needs
 * to be initialized at the entry point prior to render to ensure your flags and the ldClient are ready at the beginning
 * of your app.
 *
 * It returns a provider which is a React FunctionComponent which:
 * - saves all flags and the ldClient instance in the context API
 * - subscribes to flag changes and propagate them through the context API
 *
 * @param config - The configuration used to initialize LaunchDarkly's JS SDK
 */
declare function asyncWithLDProvider(config: AsyncProviderConfig): Promise<({ children }: {
    children: ReactNode;
}) => React__default.JSX.Element>;

/**
 * `useFlags` is a custom hook which returns all feature flags. It uses the `useContext` primitive
 * to access the LaunchDarkly context set up by `withLDProvider`. As such you will still need to
 * use the `withLDProvider` HOC at the root of your app to initialize the React SDK and populate the
 * context with `ldClient` and your flags.
 *
 * @param reactContext If specified, the provided React context will be used.
 *
 * @return All the feature flags configured in your LaunchDarkly project
 */
declare const useFlags: <T extends LDFlagSet = LDFlagSet>(reactContext?: React__default.Context<ReactSdkContext>) => T;

/**
 * `useLDClient` is a custom hook which returns the underlying [LaunchDarkly JavaScript SDK client object](https://launchdarkly.github.io/js-client-sdk/interfaces/LDClient.html).
 * Like the `useFlags` custom hook, `useLDClient` also uses the `useContext` primitive to access the LaunchDarkly
 * context set up by `withLDProvider`. You will still need to use the `withLDProvider` HOC
 * to initialise the react sdk to use this custom hook.
 *
 * @param reactContext If specified, the custom React context will be used.
 *
 * @return The `launchdarkly-js-client-sdk` `LDClient` object
 */
declare const useLDClient: (reactContext?: React__default.Context<ReactSdkContext>) => launchdarkly_js_client_sdk.LDClient | undefined;

/**
 * Provides the LaunchDarkly client initialization error, if there was one.
 *
 * @param reactContext If specified, the custom React context will be used.
 *
 * @return The `launchdarkly-js-client-sdk` `LDClient` initialization error
 */
declare function useLDClientError(reactContext?: React__default.Context<ReactSdkContext>): Error | undefined;

/**
 * Transforms a set of flags so that their keys are camelCased. This function ignores
 * flag keys which start with `$`.
 *
 * @param rawFlags A mapping of flag keys and their values
 * @return A transformed `LDFlagSet` with camelCased flag keys
 */
declare const camelCaseKeys: {
    (rawFlags: LDFlagSet): LDFlagSet;
    /**
     * @deprecated The `camelCaseKeys.camelCaseKeys` property will be removed in a future version,
     * please update your code to use the `camelCaseKeys` function directly.
     */
    camelCaseKeys: any;
};

/**
 * `reactSdkContextFactory` is a function useful for creating a React context for use with
 * all the providers and consumers in this library.
 *
 * @return a React Context
 */
declare const reactSdkContextFactory: () => React.Context<ReactSdkContext>;

export { type AllFlagsLDClient, type AsyncProviderConfig, type EnhancedComponent, type LDFlagKeyMap, type LDProps, LDProvider, type LDReactOptions, type ProviderConfig, type ReactSdkContext, asyncWithLDProvider, camelCaseKeys, defaultReactOptions, reactSdkContextFactory, useFlags, useLDClient, useLDClientError, withLDConsumer, withLDProvider };
