azure-devops-ui
Version:
React components for building web UI in Azure DevOps
494 lines (493 loc) • 21.4 kB
TypeScript
import * as React from "react";
/**
* Core client interface for an IObservable collection keyed by K with values of type V.
*/
export interface IObservable<T, TAction extends string = string> {
/**
* subscribe should be called when the caller wants to be notified about changes to
* the underlying data. The caller should only call once per delegate, but will
* get notified N times (once for each call to subscribe).
*
* @param observer - This is the delegate to be notified when the underlying data changes.
*
* @param action - Optional argument that allows the consumer to supply a action
* with the delegate. If the action is supplied only those actions are delievered,
* while all actions are delivered is no action is supplied.
*
* @returns observer parameter, unchanged
*/
subscribe: (observer: (value: T, action?: TAction) => void, action?: TAction) => (value: T, action?: TAction) => void;
/**
* unsubscribe should be called with a previously supplied delegate to subscribe.
* The client MUST call unsubscribe once for every call to subscribe with the
* appropriate delegates.
*
* @param observer - This is the delegate that was previously registered with subscribe.
*
* @param action - Optional argument that defines the action that was subscribed to.
*/
unsubscribe: (observer: (value: T, action?: TAction) => void, action?: TAction) => void;
}
/**
* An Observable implementation that will track a set of subscribers and supports
* notifications when the underlying system changes.
*/
export declare class Observable<T, TAction extends string = string> implements IObservable<T, TAction> {
private observers;
private events?;
protected subscriberCount: number;
/**
* notify is used to send the event to all subscribers that have signed up for this events
* action. This means they have subscribed directly to this action, or to all actions.
* If the caller requested the event be persisted the event will be fired in order to new
* subscribers as well when they subscribe.
*
* @param value - The object that represents the event data.
*
* @param action - The action that happened on this observable to produce the event.
*
* @param persistEvent - Optional value that determines if all future subscribers will
* recieve the event as well.
*/
notify(value: T, action: TAction, persistEvent?: boolean): void;
subscribe(observer: (value: T, action: TAction) => void, action?: string): (value: T, action?: TAction) => void;
unsubscribe(observer: (value: T, action: TAction) => void, action?: string): void;
}
export declare type IObservableLikeValue<T> = IObservableValue<T> | T;
export declare type IObservableLikeArray<T> = IObservableArray<T> | IReadonlyObservableArray<T> | T[];
export declare namespace ObservableLike {
/**
* Check whether the specified object is an observable or not.
*
* @param observableLike Object to perform observable check.
*/
function isObservable<T>(observableLike: IObservable<T> | any): observableLike is IObservable<T>;
/**
* Gets the value of the specified observable like. If not observable, returns the passed argument.
*
* @param observableLike Object to get the value.
* @returns Observable value or the observable like itself.
*/
function getValue<T>(observableLike: IObservableLikeValue<T>): T;
/**
* Gets the value of the specified observable like. If not observable, returns the passed argument.
*
* @param observableLikeArray Object to get the value.
* @returns Observable value or the observable like itself.
*/
function getValue<T>(observableArrayLike: IObservableLikeArray<T>): T[];
/**
* Subscribes to the specified object if it is an observable.
*
* @param observableLike Object to subscribe its value change if applicable.
* @param observer Delegate to be executed when the underlying data changes.
* @param action Optional argument that allows the consumer to supply a action
* with the delegate. If the action is supplied only those actions are delievered,
* while all actions are delivered is no action is supplied.
* @returns observer
*/
function subscribe<T>(observableLike: IObservable<T> | any, observer: (value: T, action: string) => void, action?: string): (value: T, action: string) => void;
/**
* Unsubscribes from the specified object if it is an observable.
*
* @param observableLike Object to subscribe its value change if applicable.
* @param observer Delegate to be executed when the underlying data changes.
* @param action Optional argument that allows the consumer to supply a action
* with the delegate. If the action is supplied only those actions are delievered,
* while all actions are delivered is no action is supplied.
*/
function unsubscribe<T>(observableLike: IObservable<T> | any, observer: (value: T, action: string) => void, action?: string): void;
}
/**
* An IReadonlyObservableValue<T> gives a readonly view of an IObservableValue<T>.
*
* The normal pattern to follow is for a parent object/component creates an IObservableValue<T>
* and pass it to dependants as an IReadonlyObservableValue<T>. This prevents the callee
* from changing the value and treating the relationship as a two way binding. Observables
* are intended to be used as a one way binding where the object owner uses the observable to
* notify others about changes to the value without giving them control over the value.
*/
export interface IReadonlyObservableValue<T> extends IObservable<T> {
/**
* Read access to the value being observed.
*/
readonly value: T;
}
/**
* Given a type, returns the type that it is observing.
*/
export declare type ObservedValue<T> = T extends IReadonlyObservableValue<infer U> ? U : T;
/**
* An IObservableValue<T> tracks an instance of type T and allows consumers
* be notified with the value is changed.
*
* EventTypes:
* set - T
*/
export interface IObservableValue<T> extends IReadonlyObservableValue<T> {
/**
* This is the current value of the observable.
*/
value: T;
}
export declare class ObservableValue<T> extends Observable<T> implements IObservableValue<T> {
private v;
constructor(value: T);
get value(): T;
set value(value: T);
}
/**
* When an action occurs on an IObservableObject the event should take the form
* of an IObjectProperty<T> where T is the type of the value being stored.
*/
export interface IObjectProperty<T> {
key: string;
value?: T;
}
/**
* An Observable collection is used to track a set of objects by name and offer notifications
* for consumers when the collection has changed.
*
* EventTypes:
* add - ICollectionEvent<V>
*/
export interface IObservableObject<V> extends IObservable<IObjectProperty<V>> {
/**
* Adding an object to the collection will notify all observers of the collection
* and keep track of the objects.
*
* @param objectName - name of the object be registered.
*
* @param objectDefinition - details of the object being registered
*/
add: (objectName: string, objectDefinition: V) => void;
/**
* get is used to retrieve the objectDefinition for named object.
*
* @param objectName - name of the object to get the definition.
*/
get: (objectName: string) => V | undefined;
/**
* Adds an object to the collection, overwriting the old
*
* @param objectName - name of the object be registered.
*
* @param objectDefinition - details of the object being registered
*/
set: (objectName: string, objectDefinition: V) => void;
/**
* A read-only collection of the existing objects.
*/
keys: () => string[];
}
/**
* An ObservableObject can be used to key a named collection of properties
* and offer an observable endpoint.
*/
export declare class ObservableObject<V> extends Observable<IObjectProperty<V>> implements IObservableObject<V> {
private objects;
add(objectName: string, objectDefinition: V): void;
get(objectName: string): V | undefined;
set(objectName: string, objectDefinition: V): void;
keys(): string[];
}
/**
* List of actions that are notified on the ObservableArray.
*/
export declare type ObservableArrayAction = "change" | "push" | "pop" | "splice" | "removeAll";
/**
* All ObservableArray events will have an action associated with them.
*/
export interface IObservableArrayEventArgs<T> {
/**
* Items added to ObservableArray.
*/
addedItems?: T[];
/**
* Items that were changed.
*/
changedItems?: T[];
/**
* The index that the operation started.
*/
index: number;
/**
* Items removed from ObservableArray.
*/
removedItems?: T[];
}
/**
* An Observable array is used to track an array of items and offer notifications
* for consumers when the array has changed.
*
* EventTypes:
* change - { changedItems, index }
* push - {addedItems, index }
* pop - { index, removedItems}
* removeAll - {index, removedItems }
* splice - { addedItems, index, removedItems }
*/
export interface IReadonlyObservableArray<T> extends IObservable<IObservableArrayEventArgs<T>, ObservableArrayAction> {
/**
* Gets the number of the items in the ObservableArray.
*/
readonly length: number;
/**
* Gets all the items in the ObservableArray.
*/
readonly value: T[];
}
/**
* An Observable array is used to track an array of items and offer notifications
* for consumers when the array has changed.
*
* EventTypes:
* change - { changedItems, index }
* push - {addedItems, index }
* pop - { index, removedItems}
* removeAll - {index, removedItems }
* splice - { addedItems, index, removedItems }
*/
export interface IObservableArray<T> extends IReadonlyObservableArray<T> {
/**
* Change can be used to update a set of items in the array. Using change instead
* of splice allows any observers to potentially optimize the updates to only the
* affected data.
*
* @param start Zero based index of the first item to change.
* @param items The set of items to change.
*/
change: (start: number, ...items: T[]) => number;
/**
* The length property can be used to determine the number of elements in
* the observable array.
*/
readonly length: number;
/**
* Appends new elements to an array, and returns the new length of the array.
*
* NOTE: Use of ...array places all items onto the stack which can cause the
* browser to run out of stack space if you pass more than 32K/64K items (browser dependent).
* Use "value" or add items in batches in this case.
*
* @param items - new elements of the ObservableArray.
*
* @returns - number of the newly inserted items.
*/
push: (...items: T[]) => number;
/**
* Removes the last element from an array and returns it.
*
* @returns - removed element or undefined if ObservableArray has no items.
*/
pop: () => T | undefined;
/**
* Remove all items from the array that match the specified filter
*
* @param filter - Delegate which returns true for each item to remove. If undefined, all items in the array are removed.
*/
removeAll: (filter?: (item: T) => boolean) => void;
/**
* Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
*
* NOTE: Use of ...array places all items onto the stack which can cause the
* browser to run out of stack space if you pass more than 32K/64K items (browser dependent).
* Use "value" or add items in batches in this case.
*
* @param start - Zero-based location in the array from which to start removing elements.
*
* @param deleteCount - Number of elements to remove.
*
* @param items - Elements to insert into the array in place of the deleted elements.
*
* @returns - deleted elements.
*/
splice: (start: number, deleteCount: number, ...items: T[]) => T[];
/**
* Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
* This method also allows the consumer to specify an action to be associated with the event.
*
* NOTE: Use of ...array places all items onto the stack which can cause the
* browser to run out of stack space if you pass more than 32K/64K items (browser dependent).
* Use "value" or add items in batches in this case.
*
* @param start - Zero-based location in the array from which to start removing elements.
*
* @param deleteCount - Number of elements to remove.
*
* @param action - Optional argument that allows the consumer to supply a custom, more granular action that it can then subscribe to, instead of splice.
*
* @param items - Elements to insert into the array in place of the deleted elements.
*
* @returns - deleted elements.
*/
spliceWithCustomAction?: (start: number, deleteCount: number, action?: any, ...items: T[]) => T[];
/**
* Gets all the items in ObservableArray.
*/
value: T[];
}
/**
* EventTypes:
* change - { changedItems, index }
* push - {addedItems, index }
* pop - { index, removedItems}
* removeAll - {index, removedItems }
* splice - { addedItems, index, removedItems }
*/
export declare class ObservableArray<T> extends Observable<IObservableArrayEventArgs<T>, ObservableArrayAction> implements IObservableArray<T> {
protected internalItems: T[];
constructor(items?: T[]);
change(start: number, ...items: T[]): number;
changeOrderedBatch(batch: {
start: number;
items?: T[];
}[]): number;
get length(): number;
push(...items: T[]): number;
pop(): T | undefined;
removeAll(filter?: (item: T) => boolean): T[];
splice(start: number, deleteCount: number, ...itemsToAdd: T[]): T[];
spliceOrderedBatch(batch: {
start: number;
deleteCount: number;
itemsToAdd?: T[];
}[]): T[];
get value(): T[];
set value(items: T[]);
private getMinItemIndexByBatch;
}
/**
* An Observable Collection takes an array of arrays or observable arrays
* and flattens out the items into a single readonly observable array
* (with all the underlying array values aggregated together).
*
* This handles subscribing to any underlying observable arrays and
* updating the aggregate array as appropriate (and notifying subscribers)
*/
export declare class ObservableCollection<T> extends Observable<IObservableArrayEventArgs<T>, ObservableArrayAction> implements IReadonlyObservableArray<T> {
get length(): number;
get value(): T[];
private collections;
private items;
/**
* Adds an additional collection of items to the end of the array
*
* @param collection Array of items or an observable array of items
* @params transformItems Delegate to process each item that is pulled from the given collection
*/
push<TInput = T>(collection: TInput[] | IReadonlyObservableArray<TInput>, transformItems?: (input: TInput) => T | undefined): void;
subscribe(observer: (value: IObservableArrayEventArgs<T>, action: ObservableArrayAction) => void, action?: ObservableArrayAction): (value: IObservableArrayEventArgs<T>, action: ObservableArrayAction) => void;
unsubscribe(observer: (value: IObservableArrayEventArgs<T>, action: ObservableArrayAction) => void, action?: ObservableArrayAction): void;
/**
* Recalculate items. This is necessary while we work without subscribers, as we're not listening to changes in observable inner collections.
* Once the first subscriber joins, items collection will be in sync real-time.
*/
private recalculateItems;
private transformItems;
private getSubscriber;
}
/**
* Indicates an object that has a ready property to let consumers know when the object is ready.
*/
export interface IReadyable {
/**
* An observable which lets the consumer know when the object is ready
*/
ready: IObservableValue<boolean>;
}
/**
* Indicates an object that has a ready property to let consumers know when the object is ready.
*/
export interface IReadonlyReadyable {
/**
* An observable which lets the consumer know when the object is ready
*/
ready: IReadonlyObservableValue<boolean>;
}
/**
* An observable array which lets consumers know when its initial items have been populated and it is ready to use.
*/
export interface IReadyableReadonlyObservableArray<T> extends IReadonlyObservableArray<T>, IReadonlyReadyable {
}
/**
* An observable array which lets consumers know when its initial items have been populated and it is ready to use.
*/
export interface IReadyableObservableArray<T> extends IObservableArray<T>, IReadyable {
}
export declare class ReadyableObservableArray<T> extends ObservableArray<T> implements IReadyableObservableArray<T> {
readonly ready: ObservableValue<boolean>;
constructor(items?: T[], ready?: boolean);
}
export interface IReadyableObservableValue<T> extends IObservableValue<T>, IReadyable {
}
export declare class ReadyableObservableValue<T> extends ObservableValue<T> implements IReadyableObservableValue<T> {
readonly ready: ObservableValue<boolean>;
constructor(item: T, ready?: boolean);
}
/**
* React Hooks extension that allows the consumer to track Observables with a useState like
* hooks API.
*
* @param initialState Initial value for the state, or a function that will resolve the value
* the when the value is initialized.
*/
export declare function useObservable<T>(initialState: T | (() => T)): [ObservableValue<T>, React.Dispatch<React.SetStateAction<T>>];
/**
* React Hooks extension that allows the consmer to track ObservableArrays with a useState like
* hooks API.
*
* @param initialState Initial value for the state, or a function that will resolve the value
* the when the value is initialized.
*/
export declare function useObservableArray<T>(initialState: T[] | (() => T[])): [IObservableArray<T>, React.Dispatch<React.SetStateAction<T[]>>];
/**
* React Hooks extension that provides a constant reference to an ObservableValue which will update
* based on another observable.
*
* @remarks
* The subscription will be safely unsubscribed any time:
* - The source observable points to a new object
* - The callback dependencies array changes
* - The component is unmounted
*
* @param sourceObservable
* @param getDerivedValue
* @param callbackDependencies
*/
export declare function useDerivedObservable<TSource, T>(sourceObservable: IObservableValue<TSource>, getDerivedValue: (source: TSource) => T, callbackDependencies: unknown[]): IReadonlyObservableValue<T>;
/**
* React Hooks extension that fires a callback whenever the provided observable changes.
* Note that when an observable array is provided, the callback will be called with the entire array rather
* than with the usual observable array subscription args.
*
* @remarks
* The subscription will be safely unsubscribed any time:
* - The source observable points to a new object
* - The callback dependencies array changes
* - The component is unmounted
*
* @param sourceObservable
* @param callbackFn
* @param callbackDependencies
*/
export declare function useSubscription<T>(sourceObservable: IObservableValue<T>, callbackFn: (value: T) => void, callbackDependencies?: unknown[]): void;
export declare function useSubscription<T>(sourceObservable: IObservableArray<T>, callbackFn: (value: T[]) => void, callbackDependencies?: unknown[]): void;
/**
* React Hooks extension that debounces the firing of a callback whenever the provided observable changes.
* Note that when an observable array is provided, the callback will be called with the entire array rather
* than with the usual observable array subscription args.
*
* @remarks
* The subscription will be safely unsubscribed any time:
* - The source observable points to a new object
* - The timeout value changes
* - The callback dependencies array changes
* - The component is unmounted
*
* @param sourceObservable
* @param callbackFn
* @param callbackDependencies
*/
export declare function useDebouncedSubscription<T>(sourceObservable: IObservableValue<T>, debounceMs: number, callbackFn: (value: T) => void, callbackDependencies?: unknown[]): void;
export declare function useDebouncedSubscription<T>(sourceObservable: IObservableArray<T>, debounceMs: number, callbackFn: (value: T[]) => void, callbackDependencies?: unknown[]): void;