@rx-angular/cdk
Version:
@rx-angular/cdk is a Component Development Kit for ergonomic and highly performant angular applications. It helps to to build Large scale applications, UI libs, state management, rendering systems and much more. Furthermore the unique way of mixing reacti
211 lines (202 loc) • 8.97 kB
TypeScript
import { TrackByFunction, NgIterable, ChangeDetectorRef, NgZone, ErrorHandler, ViewContainerRef, TemplateRef, EmbeddedViewRef, IterableDiffers } from '@angular/core';
import { RxStrategies, RxStrategyNames, RxStrategyProvider } from '@rx-angular/cdk/render-strategies';
import * as rxjs from 'rxjs';
import { Observable, ReplaySubject } from 'rxjs';
import { RxNotification, RxNotificationKind } from '@rx-angular/cdk/notifications';
/**
* A type representing the live collection to be reconciled with any new (incoming) collection. This
* is an adapter class that makes it possible to work with different internal data structures,
* regardless of the actual values of the incoming collection.
*/
declare abstract class LiveCollection<T, V> {
abstract get length(): number;
abstract at(index: number): V;
abstract attach(index: number, item: T): void;
abstract detach(index: number): T;
abstract create(index: number, value: V): T;
destroy(item: T): void;
updateValue(index: number, value: V): void;
swap(index1: number, index2: number): void;
move(prevIndex: number, newIdx: number): void;
}
/**
* The live collection reconciliation algorithm that perform various in-place operations, so it
* reflects the content of the new (incoming) collection.
*
* The reconciliation algorithm has 2 code paths:
* - "fast" path that don't require any memory allocation;
* - "slow" path that requires additional memory allocation for intermediate data structures used to
* collect additional information about the live collection.
* It might happen that the algorithm switches between the two modes in question in a single
* reconciliation path - generally it tries to stay on the "fast" path as much as possible.
*
* The overall complexity of the algorithm is O(n + m) for speed and O(n) for memory (where n is the
* length of the live collection and m is the length of the incoming collection). Given the problem
* at hand the complexity / performance constraints makes it impossible to perform the absolute
* minimum of operation to reconcile the 2 collections. The algorithm makes different tradeoffs to
* stay within reasonable performance bounds and may apply sub-optimal number of operations in
* certain situations.
*
* @param liveCollection the current, live collection;
* @param newCollection the new, incoming collection;
* @param trackByFn key generation function that determines equality between items in the life and
* incoming collection;
*/
declare function reconcile<T, V>(liveCollection: LiveCollection<T, V>, newCollection: Iterable<V> | undefined | null, trackByFn: TrackByFunction<V>): void;
interface RxListViewComputedContext {
index: number;
count: number;
}
interface RxListViewContext<T, U = RxListViewComputedContext> extends RxListViewComputedContext {
$implicit: T;
item$: Observable<T>;
updateContext(newProps: Partial<U>): void;
}
declare class RxDefaultListViewContext<T, U extends NgIterable<T> = NgIterable<T>, K = keyof T> implements RxListViewContext<T> {
readonly _item: ReplaySubject<T>;
item$: Observable<T>;
private _$implicit;
private _$complete;
private _$error;
private _$suspense;
private readonly _context$;
set $implicit($implicit: T);
get $implicit(): T;
get $complete(): boolean;
get $error(): false | Error;
get $suspense(): any;
get index(): number;
get count(): number;
get first(): boolean;
get last(): boolean;
get even(): boolean;
get odd(): boolean;
get index$(): Observable<number>;
get count$(): Observable<number>;
get first$(): Observable<boolean>;
get last$(): Observable<boolean>;
get even$(): Observable<boolean>;
get odd$(): Observable<boolean>;
constructor(item: T, customProps?: {
count: number;
index: number;
});
updateContext(newProps: Partial<RxListViewComputedContext>): void;
select: (props: K[]) => Observable<any>;
}
type rxBaseTemplateNames = 'errorTpl' | 'completeTpl' | 'suspenseTpl';
declare enum RxBaseTemplateNames {
error = "errorTpl",
complete = "completeTpl",
suspense = "suspenseTpl"
}
interface RxViewContext<T> {
$implicit: T;
error: boolean | Error;
complete: boolean;
suspense: boolean;
}
interface RxRenderAware<T> {
nextStrategy: (nextConfig: string | Observable<string>) => void;
render: (values$: Observable<RxNotification<T>>) => Observable<void>;
}
interface RxRenderSettings {
cdRef: ChangeDetectorRef;
parent: boolean;
patchZone: NgZone | false;
strategies: RxStrategies<string>;
defaultStrategyName: string;
errorHandler?: ErrorHandler;
}
type CreateViewContext<T, C, U = unknown> = (value: T, computedContext: U) => C;
type UpdateViewContext<T, C, U = unknown> = (value: T, view: EmbeddedViewRef<C>, computedContext?: U) => void;
interface RxTemplateSettings<T, C> {
viewContainerRef: ViewContainerRef;
customContext?: (value: T) => Partial<C>;
}
interface RxListTemplateSettings<T, C, U = unknown> {
viewContainerRef: ViewContainerRef;
createViewContext: CreateViewContext<T, C, U>;
updateViewContext: UpdateViewContext<T, C, U>;
initialTemplateRef?: TemplateRef<C>;
}
interface RxListManager<T> {
nextStrategy: (config: RxStrategyNames | Observable<RxStrategyNames>) => void;
render(changes$: Observable<NgIterable<T>>): Observable<NgIterable<T> | null>;
}
declare function createListTemplateManager<T, C extends RxListViewContext<T>>(config: {
renderSettings: RxRenderSettings;
templateSettings: RxListTemplateSettings<T, C, RxListViewComputedContext> & {
templateRef: TemplateRef<C>;
};
trackBy: TrackByFunction<T>;
iterableDiffers: IterableDiffers;
}): RxListManager<T>;
type View<T = unknown> = EmbeddedViewRef<RxDefaultListViewContext<T>> & {
_tempView?: boolean;
};
declare class RxLiveCollection<T> extends LiveCollection<View<T>, T> {
private viewContainer;
private templateRef;
private strategyProvider;
private createViewContext;
private updateViewContext;
/**
Property indicating if indexes in the repeater context need to be updated following the live
collection changes. Index updates are necessary if and only if views are inserted / removed in
the middle of LContainer. Adds and removals at the end don't require index updates.
*/
private needsIndexUpdate;
private _needHostUpdate;
private set needHostUpdate(value);
get needHostUpdate(): boolean;
private lastCount;
private workQueue;
private _virtualViews;
constructor(viewContainer: ViewContainerRef, templateRef: TemplateRef<{
$implicit: unknown;
index: number;
}>, strategyProvider: RxStrategyProvider, createViewContext: (item: T, context: RxListViewComputedContext) => RxDefaultListViewContext<T>, updateViewContext: (item: T, view: View<T>, context: RxListViewComputedContext) => void);
flushQueue(strategy: RxStrategyNames, ngZone?: NgZone): rxjs.Observable<any[]>;
get length(): number;
at(index: number): T;
attach(index: number, view: View<T>): void;
private attachView;
detach(index: number): View<T>;
private detachView;
create(index: number, value: T): View<T>;
destroy(view: View<T>): void;
private destroyView;
updateValue(index: number, value: T): void;
private updateView;
reset(): void;
updateIndexes(): void;
private getView;
}
interface RxTemplateManager<T, C extends RxViewContext<T>, N = rxBaseTemplateNames | string> extends RxRenderAware<T> {
addTemplateRef: (name: N, templateRef: TemplateRef<C>) => void;
}
type RxNotificationTemplateNameMap<T, C, N> = Record<RxNotificationKind, (value?: T, templates?: {
get: (name: N) => TemplateRef<C>;
}) => N>;
declare function createTemplateManager<T, C extends RxViewContext<T>, N extends string = string>(config: {
renderSettings: RxRenderSettings;
templateSettings: RxTemplateSettings<T, C>;
templateTrigger$?: Observable<RxNotificationKind>;
notificationToTemplateName: RxNotificationTemplateNameMap<T, C, N>;
}): RxTemplateManager<T, C, N>;
/**
* @internal
*
* A factory function returning an object to handle `TemplateRef`'s.
* You can add and get a `TemplateRef`.
*
*/
declare function templateHandling<N, C>(viewContainerRef: ViewContainerRef): {
add(name: N, templateRef: TemplateRef<C>): void;
get(name: N): TemplateRef<C>;
get$(name: N): Observable<TemplateRef<C>>;
createEmbeddedView(name: N, context?: C, index?: number): EmbeddedViewRef<C>;
};
export { LiveCollection, RxBaseTemplateNames, RxDefaultListViewContext, RxLiveCollection, createListTemplateManager, createTemplateManager, reconcile, templateHandling };
export type { RxListManager, RxListViewComputedContext, RxListViewContext, RxNotificationTemplateNameMap, RxRenderAware, RxTemplateManager, RxViewContext, rxBaseTemplateNames };