web-ui-pack
Version:
Web package with UI elements
57 lines (56 loc) • 3.03 kB
TypeScript
export declare namespace Observer {
interface IObserver {
/** Returns @true if object is observed (converted via observer.make()) */
isObserved(obj: any): boolean;
/** Make observable object to detect changes;
* @see {@link Proxy} */
make<T extends object>(obj: T, opts?: Options<T>): Observer.Observed<T>;
/** Listen for any props changing on the observed; callback is called per each prop-changing
* @returns callback to removeListener */
onPropChanged<T extends Observer.Observed<object>>(target: T, callback: Observer.PropCallback<T>): () => void;
/** Listen for any changing on the observed; callback is called single time per bunch of props-changing
* @returns callback to removeListener */
onChanged<T extends Observer.Observed<object>>(target: T, callback: Observer.Callback<T>): () => void;
}
interface Options<T> {
/** Point array of nested prop-names to exclude from observer or true to exclude every nested property of object
* @tutorial Troubleshooting
* * point ['items'] to exclude any nested props of property with name `items` from obsserved of obj.items
* * obj.nested.items - will be also fit the rule
* * point `true` to exclude all nested */
excludeNested?: Array<keyof T> | boolean;
}
type Observed<T extends object = object> = {
[K in keyof T]: T[K] extends Record<string, unknown> ? Observed<T[K]> : T[K];
};
type BasicPropEvent<T, K extends keyof T> = {
/** Previous value */
prev: T[K] extends Func ? ReturnType<T[K]> : T[K] | undefined;
/** Current/next value */
next: T[K] extends Func ? ReturnType<T[K]> : T[K] | undefined;
/** Prop that is changed; For arrays it can be `length`, for Set,MapSet - `size` */
prop: K;
/** Object to that prop related */
target: T;
};
type DateEvent<T extends Date> = BasicPropEvent<T, "valueOf">;
type MapSetEvent<T extends Set<any> | Map<any, any>> = BasicPropEvent<T, "size">;
type PropEvent<T, K extends keyof T> = T extends Date ? DateEvent<T> : T extends Set<any> | Map<any, any> ? MapSetEvent<T> : BasicPropEvent<T, K>;
type PropCallback<T> = <K extends keyof T>(event: PropEvent<T, K>) => void;
type ObjectEvent<T> = {
props: T extends Date ? Array<"valueOf"> : T extends Set<any> | Map<any, any> ? Array<"size"> : Array<keyof T>;
target: T;
};
type Callback<T> = (event: ObjectEvent<T>) => void;
}
/** Helper to detect object changes;
* @example
* const raw = { date: new Date(), period: 3, nestedObj: { val: 1} };
* const obj = observer.make(raw);
* const removeListener = observer.onPropChanged(obj, (e) => console.warn(e));
* const removeListener2 = observer.onChanged(obj, (e) => console.warn(e));
* obj.period = 5; // events are fired after 1ms
* removeListener();
* removeListener2(); */
declare const observer: Observer.IObserver;
export default observer;