@activejs/core
Version:
Pragmatic, Reactive State Management for JavaScript Apps
418 lines (417 loc) • 18 kB
TypeScript
import { Observable, Subject } from 'rxjs';
import { NonPrimitiveUnitBase } from './abstract-non-primitive-unit-base';
import { KOf, ListUnitEvents, UnitConfig } from '../models';
export interface ListUnit<Item> extends Array<Item> {
}
/**
* ListUnit is a reactive storage Unit that emulates `array`.
*
* ListUnit only accepts `array` data type as its value.
* It ensures that at any point of time the value would always be an `array`.
*
* ListUnit is based on `array`, it implements all the `Array.prototype` methods that are available
* in the environment/browser its running, including polyfills.
* e.g.: `find`, `filter`, `includes`, etc.
*
* Learn more about Units [here](https://docs.activejs.dev/fundamentals/units). \
* Learn more about ListUnit [here](https://docs.activejs.dev/fundamentals/units/listunit).
*
* Just like every other Non-Primitive ActiveJS Unit:
* - ListUnit extends {@link NonPrimitiveUnitBase}
* - Which further extends {@link UnitBase}, {@link Base} and `Observable`
*
* @category 1. Units
*/
export declare class ListUnit<Item> extends NonPrimitiveUnitBase<Item[]> {
/**
* @internal please do not use.
*/
protected readonly eventsSubject: Subject<ListUnitEvents<Item>>;
/**
* On-demand observable events.
*/
readonly events$: Observable<ListUnitEvents<Item>>;
/**
* The length of the list-{@link value}.
*/
get length(): number;
/**
* Indicates whether the length of the list-{@link value} is `0` or not.
*/
get isEmpty(): boolean;
/**
* @internal please do not use.
*/
protected defaultValue(): Item[];
constructor(config?: UnitConfig<Item[]>);
/**
* Extends {@link UnitBase.wouldDispatch} and adds additional check for type `array` {@see {@link Array.isArray}}, \
* which cannot be bypassed even by using {@link force}.
*
* @param value The value to be dispatched.
* @param force Whether dispatch-checks should be bypassed or not.
* @returns A boolean indicating whether the param `value` would pass the dispatch-checks if dispatched.
*
* @category Common Units
*/
wouldDispatch(value: Item[], force?: boolean): boolean;
/**
* Sets the item on the given index in the list-{@link value}. \
* Dispatches a new copy of the value, without mutating the current-value.
*
* It only works if the Unit is not frozen, and the index is valid-numeric.
*
* @param index The index of the item. \
* A negative index is normalized as following: \
* - If the index is less than negative of list-{@link length} it's treated as 0.
* - Otherwise, it's subtracted from the list-{@link length}.
* eg: If list length is `5`, negative index `-5` will be normalized to `0`, \
* negative index `-6` will be normalized to `0`, and so on.
* @param item The item.
*
* @triggers {@link EventListUnitSet}
* @category Custom ListUnit
*/
set(index: number, item: Item): void;
/**
* Inserts items to the list-{@link value}. \
* Dispatches a new copy of the value, without mutating the current-value.
*
* It only works if the Unit is not frozen and there's at least 1 item to be inserted.
*
* @param start The zero-based index in the list from which to start adding items. \
* A negative index is normalized as following: \
* - If the index is less than negative of list-{@link length} it's treated as 0.
* - Otherwise, it's subtracted from the list-{@link length}.
* eg: If list length is `5`, negative index `-5` will be normalized to `0`, \
* negative index `-6` will be normalized to `0`, and so on.
* @param items The items to be insert.
* @returns The new length of the list.
*
* @triggers {@link EventListUnitSplice}
* @category Custom ListUnit
*/
insert(start: number, ...items: Item[]): number;
/**
* Removes items at given indices from the list-{@link value}. \
* Dispatches a new copy of the value, without mutating the current-value. \
* It modifies the length of the list as these indices are not deleted,
* rather removed using `Array.prototype.splice`.
*
* It only works if the Unit is not frozen, and
* the list is not empty, and at least 1 valid-numeric index is provided.
*
* Notes:
* - The indices are removed in descending order.
* - The indices are deduplicated.
* - Negative indices are normalized before starting the removal. \
* A negative index is normalized as following: \
* - If the index is less than negative of list-{@link length}, it's treated as 0.
* - Otherwise, it's subtracted from the list-{@link length}.
* eg: If list length is `5`, negative index `-5` will be normalized to `0`, \
* negative index `-6` will be normalized to `0`, and so on.
*
* @param indices The indices of the items to be removed.
* @returns The removed items or an empty `array`.
*
* @triggers {@link EventListUnitRemove}
* @category Custom ListUnit
*/
remove(...indices: number[]): Item[];
/**
* Removes items from the list-{@link value} where the predicate returns `truthy` value. \
* Dispatches a new copy of the value, without mutating the current-value. \
* It modifies the length of the list as these indices are not deleted,
* rather removed using `Array.prototype.splice`.
*
* It only works if the Unit is not frozen, and
* the predicate is a function, and the list is not empty. \
* It uses {@link remove} internally, for actual removal.
*
* @param predicate A callback function that gets called for every item in the list with the item and index as arguments.
* @returns The removed items or an empty `array`.
*
* @triggers {@link EventListUnitRemove}
* @category Custom ListUnit
*/
removeIf(predicate: (item: Item, index: number) => boolean): Item[];
/**
* Deletes items at given indices in the list-{@link value}. \
* Dispatches a new copy of the value, without mutating the current-value. \
* It doesn't modify the length of the list as these indices are only deleted, not removed.
*
* It only works if the Unit is not frozen, and
* the list is not empty, and at least 1 valid-numeric index is provided.
*
* @param indices The indices of the items to be deleted. \
* A negative index is normalized as following: \
* - If the index is less than negative of list-{@link length} it's treated as 0.
* - Otherwise, it's subtracted from the list-{@link length}.
* eg: If list length is `5`, negative index `-5` will be normalized to `0`, \
* negative index `-6` will be normalized to `0`, and so on.
* @returns The removed items or an empty `array`.
*
* @triggers {@link EventListUnitDelete}
* @category Custom ListUnit
*/
delete(...indices: number[]): Item[];
/**
* Deletes items from the list-{@link value} where the predicate returns `true`. \
* Dispatches a new copy of the value, without mutating the current-value. \
* It doesn't modify the length of the list as these indices are only deleted, not removed.
*
* It only works if the Unit is not frozen, and
* the predicate is a function, and the list is not empty.
*
* @param predicate A callback function that gets called for every item in the list with the item and index as arguments.
* @returns The removed items or an empty `array`.
*
* @triggers {@link EventListUnitDelete}
* @category Custom ListUnit
*/
deleteIf(predicate: (item: Item, index: number) => boolean): Item[];
/**
* Finds items of the list that have a direct child property
* that matches with `key` and `value` passed as params.
*
* @example
* ```ts
* const initialValue = [{b: 1}, {b: 1, b2: 2}, {c: 1}, {b: null}];
* const list = new ListUnit({initialValue});
* const itemsFound = list.findByProp('b', 1);
* console.log(itemsFound); // logs [[0, {b: 1}], [1, {b: 1, b2: 2}]]
* ```
*
* @param key The key of the property whose value needs to be matched against param `value`.
* @param value A value that will be matched against every item's prop-value using equality operator.
* @param strictEquality A flag governing whether the value be matched using `===` or `==` operator.
* Default is `true`, ie: strict equality `===`. Pass `false` to use `==` instead.
* @returns An `array` of key/values of the matched properties, an empty `array` otherwise.
*
* @category Custom ListUnit
*/
findByProp<k extends KOf<Item>>(key: k, value: string | number | boolean, strictEquality?: boolean): [number, Item][];
/**
* Returns the item at the given index in the list-{@link value}. \
* Negative index returns items from the end of the list.
*
* @param index The index of the item. \
* A negative index is normalized as following: \
* - If the index is less than negative of list-{@link length} it's treated as 0.
* - Otherwise, it's subtracted from the list-{@link length}.
* eg: If list length is `5`, negative index `-5` will be normalized to `0`, \
* negative index `-6` will be normalized to `0`, and so on.
* @returns The item at the given index.
*
* @category Custom ListUnit
*/
get(index: number): Item | undefined;
/**
* Returns the first item in the list-{@link value}.
*
* @returns The first item in the list.
*
* @category Custom ListUnit
*/
first(): Item | undefined;
/**
* Returns the last item in the list-{@link value}.
*
* @returns The last item in the list.
*
* @category Custom ListUnit
*/
last(): Item | undefined;
/**
* Adds all the items of the list separated by the specified separator string, and
* all the items are converted into string first using JSON.stringify
*
* @param separator A string used to separate one item of the list from the next in the resulting String.
* If omitted, the list items are separated with a comma.
* @returns Concatenated `JSON.stringify`d list items.
*
* @category Custom ListUnit
*/
jsonJoin(separator?: string): string;
/**
* Appends new items to the list-{@link value}. \
* Dispatches a new copy of the value, without mutating the current-value.
*
* It only works if the Unit is not frozen, and at least 1 item is provided.
*
* @param items The items to be appended to the list.
* @returns The new length of the list.
*
* @triggers {@link EventListUnitPush}
* @category Customised Array.prototype
*/
push(...items: Item[]): number;
/**
* Removes the last item from the list-{@link value} and returns it. \
* Dispatches a new copy of the value, without mutating the current-value.
*
* It only works if the Unit is not frozen, and the list is not empty {@link isEmpty}.
*
* @returns The popped item.
*
* @triggers {@link EventListUnitPop}
* @category Customised Array.prototype
*/
pop(): Item | undefined;
/**
* Removes the first item from the list-{@link value} and returns it. \
* Dispatches a new copy of the value, without mutating the current-value.
*
* It only works if the Unit is not frozen, and the list is not empty {@link isEmpty}.
*
* @returns The shifted item.
*
* @triggers {@link EventListUnitShift}
* @category Customised Array.prototype
*/
shift(): Item | undefined;
/**
* Inserts new items at the start of the list-{@link value}. \
* Dispatches a new copy of the value, without mutating the current-value.
*
* It only works if the Unit is not frozen, and at least 1 item is provided.
*
* @param items The items to be insert at the start of the list
* @returns The new length of the list.
*
* @triggers {@link EventListUnitUnshift}
* @category Customised Array.prototype
*/
unshift(...items: Item[]): number;
/**
* Removes items from the list-{@link value} and, if necessary,
* inserts new items in their place, returning the deleted items. \
* Dispatches a new copy of the value, without mutating the current-value.
*
* It only works if the Unit is not frozen, and \
* either deleteCount is not 0 (loose comparison) and the list is not empty {@link isEmpty}, or \
* there's at least 1 item to be added.
*
* @param start The zero-based location in the list from which to start removing items.
* @param deleteCount The number of items to remove.
* @param items Items to insert into the list in place of the deleted items.
* @returns The deleted Items or an empty `array`.
*
* @triggers {@link EventListUnitSplice}
* @category Customised Array.prototype
*/
splice(start: number, deleteCount: number, ...items: Item[]): Item[];
/**
* Fills a section of the list-{@link value} with provided param `item`. \
* Dispatches a new copy of the value, without mutating the current-value.
*
* It only works if the Unit is not frozen, and the list is not empty {@link isEmpty}.
*
* @param item The item to fill the section of ListUnit's value with.
* @param start The index to start filling the list at. If start is negative, it is treated as
* length+start where length is the length of the list.
* @param end The index to stop filling the list at. If end is negative, it is treated as
* length+end.
* @returns Nothing, unlike `Array.prototype.fill`
*
* @triggers {@link EventListUnitFill}
* @category Customised Array.prototype
*/
fill(item: Item, start?: number, end?: number): any;
/**
* Copies a section of the current-value identified by param `start` and param `end`
* to the ListUnit's value starting at position {@link target}. \
* Dispatches a new copy of the value, without mutating the current-value.
*
* It only works if the Unit is not frozen, and the list is not empty {@link isEmpty}.
*
* @param target If target is negative, it is treated as length+target where length is the
* length of the list.
* @param start If start is negative, it is treated as length+start. If end is negative, it
* is treated as length+end.
* @param end If end is not specified, length of the list is used as its default value.
* @returns Nothing, unlike `Array.prototype.copyWithin`
*
* @triggers {@link EventListUnitCopyWithin}
* @category Customised Array.prototype
*/
copyWithin(target: number, start: number, end?: number): any;
/**
* Reverses the items in the list-{@link value}. \
* Dispatches a new copy of the value, without mutating the current-value.
*
* It only works if the Unit is not frozen, and the list is not empty {@link isEmpty}.
*
* @returns Nothing, unlike `Array.prototype.reverse`
*
* @triggers {@link EventListUnitReverse}
* @category Customised Array.prototype
*/
reverse(): any;
/**
* Sorts the list-{@link value}. \
* Dispatches a new copy of the value, without mutating the current-value.
*
* It only works if the Unit is not frozen, and the list is not empty {@link isEmpty}.
*
* @param compareFn The name of the function used to determine the order of the items.
* If omitted, the items are sorted in ascending, ASCII character order.
* @returns Nothing, unlike `Array.prototype.sort`
*
* @triggers {@link EventListUnitSort}
* @category Customised Array.prototype
*/
sort(compareFn?: (a: Item, b: Item) => number): any;
/**
* Returns a section of the list-{@link value}.
*
* @param start The beginning of the specified portion of the list.
* @param end The end of the specified portion of the list.
* @returns A section of the list.
*
* @category Customised Array.prototype
*/
slice(start?: number, end?: number): Item[];
/**
* Performs the specified action for each item in the list-{@link value}. \
* It's a drop-in replacement for the `Array.prototype.forEach` method.
*
* @param callbackFn A function that accepts up to three arguments.
* forEvery calls the callbackFn function one time for each element in the list.
* @param thisArg An object to which this keyword can refer in the callbackFn function.
* If thisArg is omitted, undefined is used as this value.
*
* @category Customised Array.prototype
*/
forEvery(callbackFn: (item: Item, index: number, array: Item[]) => void, thisArg?: any): void;
/**
* @internal please do not use.
*/
protected isValidValue(value: any): boolean;
/**
* @alias forEvery
* @deprecated Use {@link forEvery} instead.
* This `forEach` is not the usual `Array.forEach`.
* This `forEach` is an RxJS feature, which got inherited due to extending the Observable class,
* But this is not what you want, most probably you just want to iterate over the items, for that
* we've implemented the normal `forEach` functionality into `forEvery` method.
*
* This `forEach` is marked deprecated to prevent accidental usage, and avoid confusion.
* You can still use it though, if you want the RxJS feature,
* see {@link Observable.forEach} for usage.
* @hidden
*/
forEach: any;
/**
* @deprecated
* @ignore
* @internal please do not use.
*/
[Symbol.unscopables]: any;
/**
* @deprecated
* @ignore
* @internal please do not use.
*/
static Array: any;
}