@chrfalch/react-observable-context
Version:
Observable context for React
57 lines (49 loc) • 4.03 kB
TypeScript
import * as React from 'react';
import React__default from 'react';
type IsFunction<T> = T extends () => unknown ? true : T extends (...args: any[]) => unknown ? true : false;
type FlattenedKeysOf<T extends object, TArrayLike extends boolean = false> = {
[Key in keyof T & (string | number)]: IsFunction<T[Key]> extends true ? TArrayLike extends false ? `${Key}` : never : T[Key] extends object ? T[Key] extends Array<unknown> ? // Arrays should have both array and objects by indicies and length properties
`${Key}` | `${Key}.${FlattenedKeysOf<T[Key], true>}` : `${Key}.${FlattenedKeysOf<T[Key], TArrayLike>}` : `${Key}`;
}[keyof T & (string | number)];
type FlattenedObjectOf<T extends object, K extends FlattenedKeysOf<T> = FlattenedKeysOf<T>> = {
[Key in K]: Key extends keyof T ? T[Key] : Key extends `${infer First}${'.'}${infer Rest}` ? First extends keyof T ? T[First] extends object ? FlattenedObjectOf<T[First]> extends object ? Rest extends keyof FlattenedObjectOf<T[First]> ? FlattenedObjectOf<T[First]>[Rest] : never : never : never : T extends Array<infer AT> ? Rest extends keyof AT ? AT[Rest] : never : never : T extends Array<infer AT> ? AT : never;
};
type TObservableObject<TValue extends Record<string, unknown>> = TValue & {
subscribe: <TProp extends FlattenedKeysOf<TValue>>(prop: TProp, listener: () => void) => () => void;
};
/**
* Creates a new React Context with the provided object as the initial value.
* The context will support subscribing to changes and notifications when the value changes.
* @param obj
* @returns
*/
declare const createContext: <T>(obj: T) => React__default.Context<TObservableObject<NonNullable<T>> | undefined>;
/**
* Creates a new object that allows for subscribing to changes
* @param initialValue Initial value of the object.
* @returns The object that can be used as a object where we can read/write values.
*/
declare const makeObservable: <TInitialValue extends Record<string, unknown>>(initialValue: TInitialValue) => TObservableObject<TInitialValue>;
/**
* Creates a selector that subscribes to parts of the observable and returns the value of observed properties.
* @param observable Observable to subscribe to
* @param props Props to subscribe to (can be nested like a.b.c)
* @returns An array of the values that will be updated if any of the properties change.
*/
declare const useObserver: <TValue extends Record<string, unknown>, TObservable extends TObservableObject<TValue>, TFlattened extends FlattenedObjectOf<TObservable>, TKeys extends Exclude<keyof TFlattened, "subscribe">>(observable: TObservable, ...props: TKeys[]) => Pick<Pick<FlattenedObjectOf<TObservable>, FlattenedKeysOf<TObservable, false>>, TKeys>;
/**
* Creates a new observable from the given value. The observable can be
* used to subscribe to changes. The initial value is used as the initial
* value of the observable, and subsequent changes to the initial value will
* not result in the observable being updated.
* @param initialValue Initial value to create the observable from
* @returns A new observable
*/
declare const useObservable: <T extends Record<string, unknown>>(initialValue: T) => TObservableObject<T>;
declare const Observable: {
createContext: <T>(obj: T) => React.Context<TObservableObject<NonNullable<T>> | undefined>;
makeObservable: <TInitialValue extends Record<string, unknown>>(initialValue: TInitialValue) => TObservableObject<TInitialValue>;
useObserver: <TValue extends Record<string, unknown>, TObservable extends TObservableObject<TValue>, TFlattened extends FlattenedObjectOf<TObservable>, TKeys extends Exclude<keyof TFlattened, "subscribe">>(observable: TObservable, ...props: TKeys[]) => Pick<Pick<FlattenedObjectOf<TObservable>, FlattenedKeysOf<TObservable, false>>, TKeys>;
useObservable: <T_1 extends Record<string, unknown>>(initialValue: T_1) => TObservableObject<T_1>;
};
export { FlattenedKeysOf, Observable, createContext, Observable as default, makeObservable, useObservable, useObserver };