import * as i0 from '@angular/core';
import { ChangeDetectorRef, OnInit, OnDestroy, TemplateRef, ViewContainerRef, ErrorHandler, PipeTransform } from '@angular/core';
import { Observable } from 'rxjs';

declare abstract class TickScheduler {
    abstract schedule(): void;
    static ɵfac: i0.ɵɵFactoryDeclaration<TickScheduler, never>;
    static ɵprov: i0.ɵɵInjectableDeclaration<TickScheduler>;
}

/**
 * Provides rendering functionality regardless of whether `zone.js` is present
 * or not. It must be provided at the component/directive level.
 *
 * @usageNotes
 *
 * ### Rerender zone-less app on route changes
 *
 * ```ts
 * @Component({
 *   selector: 'app-root',
 *   template: '<router-outlet>',
 *   // 👇 `RenderScheduler` is provided at the component level
 *   providers: [RenderScheduler],
 *   changeDetection: ChangeDetectionStrategy.OnPush,
 * })
 * export class AppComponent implements OnInit {
 *   constructor(
 *     private readonly router: Router,
 *     private readonly renderScheduler: RenderScheduler
 *   ) {}
 *
 *   ngOnInit(): void {
 *     this.router.events
 *       .pipe(filter((e) => e instanceof NavigationEnd))
 *       .subscribe(() => this.renderScheduler.schedule());
 *   }
 * }
 * ```
 *
 * ### Rerender component on interval
 *
 * ```ts
 * @Component({
 *   selector: 'app-interval',
 *   template: '{{ elapsedTime }}ms',
 *   // 👇 `RenderScheduler` is provided at the component level
 *   providers: [RenderScheduler],
 *   changeDetection: ChangeDetectionStrategy.OnPush,
 * })
 * export class IntervalComponent implements OnInit {
 *   elapsedTime = 0;
 *
 *   constructor(private readonly renderScheduler: RenderScheduler) {}
 *
 *   ngOnInit(): void {
 *     setInterval(() => {
 *       this.elapsedTime += 1000;
 *       this.renderScheduler.schedule();
 *     }, 1000);
 *   }
 * }
 * ```
 */
declare class RenderScheduler {
    private readonly cdRef;
    private readonly tickScheduler;
    constructor(cdRef: ChangeDetectorRef, tickScheduler: TickScheduler);
    /**
     * Marks component and its ancestors as dirty.
     * It also schedules a new change detection cycle in zone-less mode.
     */
    schedule(): void;
    static ɵfac: i0.ɵɵFactoryDeclaration<RenderScheduler, never>;
    static ɵprov: i0.ɵɵInjectableDeclaration<RenderScheduler>;
}

type Primitive = string | number | bigint | boolean | symbol | null | undefined;
type ObservableOrPromise<T> = Observable<T> | PromiseLike<T>;
type ObservableDictionary<PO> = Required<{
    [Key in keyof PO]: Observable<unknown>;
}>;
type PotentialObservableResult<PO, ExtendedResult = never> = PO extends ObservableOrPromise<infer Result> ? Result | ExtendedResult : PO extends Primitive ? PO : keyof PO extends never ? PO : PO extends ObservableDictionary<PO> ? {
    [Key in keyof PO]: PO[Key] extends Observable<infer Value> ? Value : never;
} | ExtendedResult : PO;

type LetViewContextValue<PO> = PotentialObservableResult<PO>;
interface LetViewContext<PO> {
    /**
     * using `$implicit` to enable `let` syntax: `*ngrxLet="obs$; let o"`
     */
    $implicit: LetViewContextValue<PO>;
    /**
     * using `ngrxLet` to enable `as` syntax: `*ngrxLet="obs$ as o"`
     */
    ngrxLet: LetViewContextValue<PO>;
    /**
     * `*ngrxLet="obs$; let e = error"` or `*ngrxLet="obs$; error as e"`
     */
    error: any;
    /**
     * `*ngrxLet="obs$; let c = complete"` or `*ngrxLet="obs$; complete as c"`
     */
    complete: boolean;
}
/**
 *
 * @description
 *
 * The `*ngrxLet` directive serves a convenient way of binding observables to a view context
 * (DOM element's scope). It also helps with several internal processing under the hood.
 *
 * @usageNotes
 *
 * ### Displaying Observable Values
 *
 * ```html
 * <ng-container *ngrxLet="number$ as n">
 *   <app-number [number]="n"></app-number>
 * </ng-container>
 *
 * <ng-container *ngrxLet="number$; let n">
 *   <app-number [number]="n"></app-number>
 * </ng-container>
 * ```
 *
 * ### Tracking Different Observable Events
 *
 * ```html
 * <ng-container *ngrxLet="number$ as n; error as e; complete as c">
 *   <app-number [number]="n" *ngIf="!e && !c">
 *   </app-number>
 *
 *   <p *ngIf="e">There is an error: {{ e }}</p>
 *   <p *ngIf="c">Observable is completed.</p>
 * </ng-container>
 * ```
 *
 * ### Combining Multiple Observables
 *
 * ```html
 * <ng-container *ngrxLet="{ users: users$, query: query$ } as vm">
 *   <app-search-bar [query]="vm.query"></app-search-bar>
 *   <app-user-list [users]="vm.users"></app-user-list>
 * </ng-container>
 * ```
 *
 * ### Using Suspense Template
 *
 * ```html
 * <ng-container *ngrxLet="number$ as n; suspenseTpl: loading">
 *   <app-number [number]="n"></app-number>
 * </ng-container>
 *
 * <ng-template #loading>
 *   <p>Loading...</p>
 * </ng-template>
 * ```
 *
 * ### Using Aliases for Non-Observable Values
 *
 * ```html
 * <ng-container *ngrxLet="userForm.controls.email as email">
 *   <input type="text" [formControl]="email" />
 *
 *   <ng-container *ngIf="email.errors && (email.touched || email.dirty)">
 *     <p *ngIf="email.errors.required">This field is required.</p>
 *     <p *ngIf="email.errors.email">This field must be an email.</p>
 *   </ng-container>
 * </ng-container>
 * ```
 *
 * @publicApi
 */
declare class LetDirective<PO> implements OnInit, OnDestroy {
    private readonly mainTemplateRef;
    private readonly viewContainerRef;
    private readonly errorHandler;
    private readonly renderScheduler;
    private isMainViewCreated;
    private isSuspenseViewCreated;
    private readonly viewContext;
    private readonly renderEventManager;
    private readonly subscription;
    set ngrxLet(potentialObservable: PO);
    suspenseTemplateRef?: TemplateRef<unknown>;
    constructor(mainTemplateRef: TemplateRef<LetViewContext<PO | undefined>>, viewContainerRef: ViewContainerRef, errorHandler: ErrorHandler, renderScheduler: RenderScheduler);
    static ngTemplateContextGuard<PO>(dir: LetDirective<PO>, ctx: unknown): ctx is LetViewContext<PO>;
    ngOnInit(): void;
    ngOnDestroy(): void;
    private renderMainView;
    private renderSuspenseView;
    static ɵfac: i0.ɵɵFactoryDeclaration<LetDirective<any>, never>;
    static ɵdir: i0.ɵɵDirectiveDeclaration<LetDirective<any>, "[ngrxLet]", never, { "ngrxLet": { "alias": "ngrxLet"; "required": false; }; "suspenseTemplateRef": { "alias": "ngrxLetSuspenseTpl"; "required": false; }; }, {}, never, never, true, never>;
}

type PushPipeResult<PO> = PotentialObservableResult<PO, undefined>;
/**
 * @description
 *
 * The `ngrxPush` pipe serves as a drop-in replacement for the `async` pipe.
 * It contains intelligent handling of change detection to enable us
 * running in zone-full as well as zone-less mode without any changes to the code.
 *
 * @usageNotes
 *
 * ### Displaying Observable Values
 *
 * ```html
 * <p>{{ number$ | ngrxPush }}</p>
 *
 * <ng-container *ngIf="number$ | ngrxPush as n">{{ n }}</ng-container>
 *
 * <app-number [number]="number$ | ngrxPush"></app-number>
 * ```
 *
 * ### Combining Multiple Observables
 *
 * ```html
 * <code>
 *   {{ { users: users$, query: query$ } | ngrxPush | json }}
 * </code>
 * ```
 *
 * @publicApi
 */
declare class PushPipe implements PipeTransform, OnDestroy {
    private readonly errorHandler;
    private renderedValue;
    private readonly renderScheduler;
    private readonly renderEventManager;
    private readonly subscription;
    constructor(errorHandler: ErrorHandler);
    transform<PO>(potentialObservable: PO): PushPipeResult<PO>;
    ngOnDestroy(): void;
    private setRenderedValue;
    static ɵfac: i0.ɵɵFactoryDeclaration<PushPipe, never>;
    static ɵpipe: i0.ɵɵPipeDeclaration<PushPipe, "ngrxPush", true>;
}

export { LetDirective, PushPipe, RenderScheduler };
