import { Dependency, DependencyIdentifier, Injector, LookUp, Quantity } from "@wendellhu/redi";
import * as react0 from "react";
import React from "react";
import { Observable } from "rxjs";

//#region src/react-bindings/reactComponent.d.ts

/**
 * Connect a React component to a specific Injector instance.
 *
 * Wraps the component with a RediProvider, making the injector available
 * to all child components via `useDependency` and `useInjector` hooks.
 *
 * Use this when you have an existing Injector instance that you want
 * to make available to a React component tree.
 *
 * @param Comp - The React component to wrap.
 * @param injector - The Injector instance to provide.
 * @returns A new component that provides the injector via context.
 *
 * @example
 * ```tsx
 * const injector = new Injector([[UserService], [ILogger, { useClass: ConsoleLogger }]]);
 *
 * const App = connectInjector(MyApp, injector);
 *
 * // Now MyApp and all its children can use useDependency
 * ReactDOM.render(<App />, document.getElementById('root'));
 * ```
 */
declare function connectInjector<P>(Comp: React.ComponentType<P>, injector: Injector): React.ComponentType<P>;
/**
 * Connect a React component with a set of dependencies.
 *
 * Creates a new Injector (or child injector if inside an existing context)
 * with the specified dependencies, and provides it to the component tree.
 *
 * The injector is automatically disposed when the component unmounts.
 *
 * @param Comp - The React component to wrap.
 * @param dependencies - An array of dependencies to register.
 * @returns A new component that provides the dependencies via context.
 *
 * @example
 * ```tsx
 * const App = connectDependencies(MyApp, [
 *   [UserService],
 *   [ILogger, { useClass: ConsoleLogger }],
 *   [IConfig, { useValue: { apiUrl: 'https://api.example.com' } }],
 * ]);
 *
 * // MyApp and children can now use these dependencies
 * function MyApp() {
 *   const userService = useDependency(UserService);
 *   return <div>{userService.getCurrentUser().name}</div>;
 * }
 * ```
 */
declare function connectDependencies<P>(Comp: React.ComponentType<P>, dependencies: Dependency[]): React.ComponentType<P>;
//#endregion
//#region src/react-bindings/reactContext.d.ts
/**
 * The shape of the RediContext value.
 */
interface IRediContext {
  /** The current Injector instance, or null if not provided. */
  injector: Injector | null;
}
/**
 * React Context for dependency injection.
 *
 * This context provides access to the Injector instance throughout
 * the React component tree. Use `RediProvider` to provide an injector,
 * and `useDependency`/`useInjector` hooks to consume dependencies.
 *
 * For most use cases, prefer using `connectInjector` or `connectDependencies`
 * instead of using this context directly.
 *
 * @example
 * ```tsx
 * // Direct usage (advanced)
 * const injector = new Injector([[MyService]]);
 *
 * function App() {
 *   return (
 *     <RediContext.Provider value={{ injector }}>
 *       <MyComponent />
 *     </RediContext.Provider>
 *   );
 * }
 * ```
 */
declare const RediContext: react0.Context<IRediContext>;
/**
 * Provider component for RediContext.
 *
 * Use this to provide an Injector to the component tree.
 * Prefer using `connectInjector` or `connectDependencies` for simpler usage.
 */
declare const RediProvider: react0.Provider<IRediContext>;
/**
 * Consumer component for RediContext.
 *
 * Use this to access the injector in class components or render props patterns.
 * For functional components, prefer using `useInjector` hook instead.
 */
declare const RediConsumer: react0.Consumer<IRediContext>;
//#endregion
//#region src/react-bindings/reactDecorators.d.ts
/**
 * A property decorator for React class components that injects a dependency.
 *
 * This decorator creates a getter that lazily retrieves the dependency
 * from the component's context. The component must have `RediContext`
 * set as its `contextType`.
 *
 * For functional components, use the `useDependency` hook instead.
 *
 * @param id - The dependency identifier.
 * @param quantity - Optional quantity (REQUIRED, OPTIONAL, or MANY).
 * @param lookUp - Optional lookup strategy (SELF or SKIP_SELF).
 *
 * @example
 * ```tsx
 * class MyComponent extends React.Component {
 *   static contextType = RediContext;
 *
 *   @WithDependency(UserService)
 *   private userService!: UserService;
 *
 *   @WithDependency(ICache, Quantity.OPTIONAL)
 *   private cache!: ICache | null;
 *
 *   render() {
 *     return <div>{this.userService.getCurrentUser().name}</div>;
 *   }
 * }
 * ```
 */
declare function WithDependency<T>(id: DependencyIdentifier<T>, quantity?: Quantity, lookUp?: LookUp): any;
//#endregion
//#region src/react-bindings/reactHooks.d.ts
/**
 * A React hook that returns the current Injector from the RediContext.
 *
 * Use this hook when you need direct access to the injector for
 * dynamic dependency resolution or advanced use cases.
 *
 * @returns The current Injector instance.
 * @throws {HooksNotInRediContextError} If used outside of a RediContext.
 *
 * @example
 * ```tsx
 * function MyComponent() {
 *   const injector = useInjector();
 *
 *   const handleClick = () => {
 *     // Dynamic resolution
 *     const service = injector.get(SomeService);
 *     service.doSomething();
 *   };
 *
 *   return <button onClick={handleClick}>Click</button>;
 * }
 * ```
 */
declare function useInjector(): Injector;
/**
 * A React hook that retrieves a dependency from the current Injector.
 *
 * This is the primary way to access dependencies in functional React components.
 * The dependency is memoized and will only be re-resolved if the parameters change.
 *
 * @param id - The dependency identifier (class, string, or identifier created by `createIdentifier`).
 * @param quantityOrLookUp - Either a {@link Quantity} or {@link LookUp} option.
 * @param lookUp - A {@link LookUp} option (if first param is Quantity).
 * @returns The dependency instance, array of instances, or null depending on the quantity.
 *
 * @throws {HooksNotInRediContextError} If used outside of a RediContext.
 *
 * @example
 * ```tsx
 * function UserProfile() {
 *   // Required dependency
 *   const userService = useDependency(UserService);
 *
 *   // Optional dependency
 *   const analytics = useDependency(IAnalytics, Quantity.OPTIONAL);
 *
 *   // Multiple implementations
 *   const validators = useDependency(IValidator, Quantity.MANY);
 *
 *   return <div>{userService.getCurrentUser().name}</div>;
 * }
 * ```
 */
declare function useDependency<T>(id: DependencyIdentifier<T>, lookUp?: LookUp): T;
declare function useDependency<T>(id: DependencyIdentifier<T>, quantity: Quantity.MANY, lookUp?: LookUp): T[];
declare function useDependency<T>(id: DependencyIdentifier<T>, quantity: Quantity.OPTIONAL, lookUp?: LookUp): T | null;
declare function useDependency<T>(id: DependencyIdentifier<T>, quantity: Quantity.REQUIRED, lookUp?: LookUp): T;
declare function useDependency<T>(id: DependencyIdentifier<T>, quantity: Quantity, lookUp?: LookUp): T | T[] | null;
declare function useDependency<T>(id: DependencyIdentifier<T>, quantity?: Quantity, lookUp?: LookUp): T | T[] | null;
//#endregion
//#region src/react-bindings/reactRx.d.ts
type ObservableOrFn<T> = Observable<T> | (() => Observable<T>);
type Nullable<T> = T | undefined | null;
declare function useObservable<T>(observable: Nullable<ObservableOrFn<T>>): T;
declare function useObservable<T>(observable: Nullable<ObservableOrFn<T>>, defaultValue: T): T;
declare function useObservable<T>(observable: Nullable<ObservableOrFn<T>>, defaultValue: undefined, shouldHaveSyncValue: true, deps?: any[]): T;
declare function useObservable<T>(observable: Nullable<ObservableOrFn<T>>, defaultValue?: undefined, shouldHaveSyncValue?: true, deps?: any[]): T | undefined;
/**
 * A React hook that re-renders the component when an Observable emits.
 *
 * This is useful when you have external state managed by RxJS and want
 * to trigger a re-render whenever that state changes, without using
 * the emitted value directly.
 *
 * @param update$ - An Observable that emits when the component should re-render.
 *
 * @example
 * ```tsx
 * function StatusIndicator() {
 *   const statusService = useDependency(StatusService);
 *
 *   // Re-render whenever status changes
 *   useUpdateBinder(statusService.statusChanged$);
 *
 *   return <div>{statusService.getCurrentStatus()}</div>;
 * }
 * ```
 */
declare function useUpdateBinder(update$: Observable<void>): void;
//#endregion
export { RediConsumer, RediContext, RediProvider, WithDependency, connectDependencies, connectInjector, useDependency, useInjector, useObservable, useUpdateBinder };
//# sourceMappingURL=index.d.ts.map