solid-atom
Version:
Simple two way reactive bindings
165 lines (157 loc) • 6.59 kB
TypeScript
import { Accessor } from 'solid-js';
import { MemoOptions } from 'solid-js';
import { Signal } from 'solid-js';
import { SignalOptions } from 'solid-js';
/** Reactive atomic value without the inconveniences of {@link Signal} */
export declare class Atom<T> {
get: Accessor<T>;
set: (x: T) => void;
get value(): T;
set value(v: T);
constructor(get: Accessor<T>, set: (x: T) => void);
/**
* Creates a new {@link Atom} with the setter of the current one and a memoized version of its getter
* @param opts The memo's settings
*/
memo(opts?: MemoOptions<T>): Atom<T>;
/**
* Creates a new {@link Atom} that applies a conversion to the current one
* @param to Conversion function from {@link S} to {@link D}
* @param from Conversion function from {@link D} to {@link S}
*/
convert<R>(to: (x: T) => R, from: (x: R) => T): Atom<R>;
/**
* Allows you to execute {@link set} on the current {@link Atom} based on its current value.
* The current value gets read through {@link untrack} to mimic the {@link Setter} behaviour.
* If {@link f} is not provided, it will set the current value again
* @param f Function that creates a new value based on the current one
* @returns Whatever {@link f} returned
*/
update<V extends T>(f?: (prev: T) => V): V;
/**
* Creates a new {@link Atom} that defers the setter of the current one.
* When the setter is called, it will schedule the value to be set using {@link scheduler}.
* If the setter gets called again, the previous operation will be cancelled, unless it has already finished
* @param scheduler Function that schedules an operation and provides another function to cancel it
*/
defer(scheduler: (f: () => void) => () => void): Atom<T>;
/**
* Two way version of {@link createSelector}
* @param comp The comparer function
* @returns A boolean {@link Atom} factory
*/
selector(comp?: (a: T, b: T) => boolean): (f: Accessor<T>, def: T | (T extends undefined ? void : never)) => Atom<boolean>;
/**
* Creates a new {@link Atom} that throws an error when trying to set it
* @param f The getter for the new {@link Atom}
*/
static readOnly<T>(f: Accessor<T>): Atom<T>;
/**
* Creates an {@link Atom} that forwards an {@link Accessor} to another {@link Atom}
* @param f The reactive {@link Accessor} to the {@link Atom} to forward
*/
static unwrap<T>(f: Accessor<Atom<T>>): Atom<T>;
/**
* Creates an {@link Atom} based on a {@link Signal}
* @param param0 The {@link Signal} to forward
*/
static from<T>([get, set]: Signal<T>): Atom<T>;
/**
* Creates an {@link Atom} based on an object property
* @param obj The object containing the property
* @param k A function that returns the key of the property and will be passed to {@link nameOf}
*/
static prop<T, K extends keyof T>(obj: Accessor<T>, k: (x: NamesOf<T>) => K): Atom<T[K]>;
/**
* Creates a new {@link Atom} that directly stores a value.
* Creates a new {@link Signal} and passes it to {@link from}
* @param v The value to store in the new {@link Signal}
* @param opts The {@link Signal}'s settings
*/
static value<T>(v?: undefined, opts?: SignalOptions<T>): Atom<T | undefined>;
static value<T>(v: T, opts?: SignalOptions<T>): Atom<T>;
/**
* Creates a bindable data source.
* If {@link bind} returns an {@link Atom} it gets wrapped, otherwise it creates a {@link Signal} using {@link f} and uses it to store the value until {@link bind}'s value changes
* @param bind The bound {@link Atom}
* @param f The function that will create the actual {@link Signal} that will store the {@link Atom}'s data in case that {@link bind} doesn't return anything
*/
static source<T>(bind: Accessor<Atom<T> | undefined>): Atom<T | undefined>;
static source<T>(bind: Accessor<Atom<T> | undefined>, f: Accessor<Signal<T>>): Atom<T>;
}
/** Function that returns passed value and can be used as a class */
export declare const IDENTITY: Identity;
/** Type definition of {@link IDENTITY} */
declare interface Identity {
/**
* Returns the passed value
* -
* Maintains the type of the input
* @param x The value to be returned
*/
<T>(x: T): T;
/**
* Returns the passed value
* -
* Allows the function to be used to fake any conversion.
* Example:
* ```ts
* const a = IDENTITY(12);
* // ^? 12
*
* const b: (x: string) => number = IDENTITY;
* // No error
* ```
* It is important to this overload to be defined after the previous one
* @param x The value to be returned
*/
(x: any): any;
/**
* Returns the passed value
* -
* Allows you to extend a specific instance rather than a class.
* Private field example:
* ```ts
* class Something extends IDENTITY {
* #value = 12;
*
* static get(obj: object) { return (obj as Something).#value; }
*
* static set(obj: object, v: number) { (obj as Something).#value = v; }
* }
*
* const a = {};
* const b = new Something(a);
* const c = a === b; // true
* const d = Something.get(a); // 12
* ```
* Custom function example:
* ```ts
* class CoolFunction<T> extends IDENTITY<() => T> {
* constructor(public f: () => T) { super(f); }
* }
*
* const a = () => 12;
* const b = new CoolFunction(a);
* const c = a === b && b === b.f; // true
* const d = b(); // 12
* const e = b.f(); // 12
* ```
* @param x The value to be returned
*/
new <T = object>(x: T): T;
}
/**
* Function that returns the name of the field accessed inside of {@link f}.
* This function is not meant to be used on its own because it has very poor type inference
* @param f A function that returns a value based on {@link NamesOf}
* @returns The same thing that {@link f} returned
*/
export declare const nameOf: <T, const R>(f: (x: NamesOf<T>) => R) => R;
/** Type that maps each key of {@link T} to itself */
export declare type NamesOf<T> = {
readonly [k in keyof T]-?: k;
};
/** Function that does nothing */
export declare const NO_OP: () => void;
export { }