import { Container, Module, ModuleDeclaration, Token } from "ditox";
import { ReactElement, ReactNode } from "react";

//#region src/DependencyContainer.d.ts
/**
 * A callback for binding dependencies to a container
 */
type DependencyContainerBinder = (container: Container) => unknown;
/**
 * Specifies options for a new container:
 * @property binder - A callback which sets up bindings for the container.
 * @property root - If `true` then a new container does not depend on any parent containers
 */
type DependencyContainerParams = {
  children: ReactNode;
  root?: boolean;
  binder?: DependencyContainerBinder;
};
/**
 * Provides a new dependency container to React app
 *
 * This component creates a new container and provides it to React children.
 *
 * If a `binder` callback is specified, it will be called for the new container
 * to bind it with dependencies.
 *
 * If a parent container exists, it is connected to the current one by default.
 * To create a root container specify `root` parameter as `true`,
 * and the container will not depend on any parent container.
 *
 * @param params.binder - A callback which sets up bindings for the container.
 * @param params.root - If `true` then a new container does not depend on any parent containers
 *
 * @example
 *
 * ```tsx
 * const TOKEN = token();
 *
 * function appDependencyBinder(container: Container) {
 *   container.bindValue(TOKEN, 'value');
 * }
 *
 * function App() {
 *   return (
 *     <DependencyContainer root binder={appDependencyBinder}>
 *       <NestedComponent />
 *     </DependencyContainer>
 *   );
 * }
 * ```
 *
 */
declare function DependencyContainer(params: DependencyContainerParams): ReactElement;
/**
 * Provides a custom dependency container to React app
 *
 * @param params.container - a custom container
 *
 * @example
 * ```tsx
 * const container = useMemo(() => {
 *   return createContainer();
 * });
 *
 * return (
 *   <CustomDependencyContainer container={container}>
 *     {children}
 *   </CustomDependencyContainer>
 * );
 * ```
 */
declare function CustomDependencyContainer(params: {
  children: ReactNode;
  container: Container;
}): ReactElement;
//#endregion
//#region src/DependencyModule.d.ts
/**
 * Binds the module to a new dependency container.
 *
 * If a parent container exists, it is connected to the current one by default.
 *
 * @param params.module - Module declaration for binding
 * @param params.scope - Optional scope for binding: `singleton` (default) or `scoped`.
 *
 * @example
 *
 * ```tsx
 * const LOGGER_MODULE: ModuleDeclaration<LoggerModule> = {};
 *
 * function App() {
 *   return (
 *     <DependencyModule module={LOGGER_MODULE}>
 *       <NestedComponent />
 *     </DependencyModule>
 *   );
 * }
 * ```
 */
declare function DependencyModule(params: {
  children: ReactNode;
  module: ModuleDeclaration<Module<Record<string, unknown>>>;
  scope?: 'scoped' | 'singleton';
}): ReactElement;
//#endregion
//#region src/hooks.d.ts
/**
 * @category Hook
 *
 * Returns a dependency container. Throws an error in case the container is not provided.
 */
declare function useDependencyContainer(mode: 'strict'): Container;
/**
 * @category Hook
 *
 * Returns a dependency container, or `undefined` in case the container is not provided.
 */
declare function useDependencyContainer(mode?: 'optional'): Container | undefined;
/**
 * @category Hook
 *
 * Returns a dependency by token, or fails with an error.
 */
declare function useDependency<T>(token: Token<T>): T;
/**
 * @category Hook
 *
 * Returns a dependency by token, or `undefined` in case the dependency is not provided.
 */
declare function useOptionalDependency<T>(token: Token<T>): T | undefined;
//#endregion
export { CustomDependencyContainer, DependencyContainer, type DependencyContainerBinder, type DependencyContainerParams, DependencyModule, useDependency, useDependencyContainer, useOptionalDependency };
//# sourceMappingURL=index.d.cts.map