mirror of
https://github.com/littensy/charm.git
synced 2026-10-24 06:51:37 +00:00
refactor!: design overhaul (#1)
* refactor!: use atom functions * docs: reformat api reference * docs: showcase atom functions * docs: remove unused import * refactor: finalize updates * chore: misc edits
This commit is contained in:
parent
4d4979daa9
commit
33ecae2f50
39 changed files with 577 additions and 729 deletions
159
src/index.d.ts
vendored
159
src/index.d.ts
vendored
|
|
@ -1,134 +1,109 @@
|
|||
export = Charm;
|
||||
export as namespace Charm;
|
||||
|
||||
type Cleanup = () => void;
|
||||
|
||||
type AnyMap<K, V> =
|
||||
| Map<K, V>
|
||||
| ReadonlyMap<K, V>
|
||||
| (K extends string | number | symbol ? { readonly [Key in K]: V } : never);
|
||||
|
||||
declare namespace Charm {
|
||||
interface InternalAtom<State> {
|
||||
/** @hidden */
|
||||
readonly listeners: Set<(value: State) => void>;
|
||||
/** @hidden */
|
||||
readonly debugTraceback: string;
|
||||
/** @hidden */
|
||||
readonly debugLabel: string;
|
||||
/** @hidden */
|
||||
setForced(state: State | ((current: State) => State)): void;
|
||||
interface Atom<T> extends Source<T> {
|
||||
readonly __nominal: unique symbol;
|
||||
(state: T | ((prev: T) => T)): void;
|
||||
}
|
||||
|
||||
interface BaseAtom<State> extends InternalAtom<State> {
|
||||
get(): State;
|
||||
get<Result>(selector: (state: State) => Result): Result;
|
||||
set(state: State | ((current: State) => State)): void;
|
||||
memo(areEqual: (previous: State, current: State) => boolean): this;
|
||||
writable(onSet?: (update: State, previous: State) => State | void): Atom<State>;
|
||||
readonly(): ReadonlyAtom<State>;
|
||||
named(label: string): this;
|
||||
unmount(): void;
|
||||
type Source<T> = () => T;
|
||||
|
||||
interface AtomOptions<State> {
|
||||
equals?: (prev: State, next: State) => boolean;
|
||||
}
|
||||
|
||||
interface Atom<State> extends BaseAtom<State> {
|
||||
(): State;
|
||||
(state: State | ((previous: State) => State)): void;
|
||||
}
|
||||
|
||||
interface ReadonlyAtom<State> extends BaseAtom<State> {
|
||||
(): State;
|
||||
set: never;
|
||||
}
|
||||
|
||||
type AtomArrayToStates<Atoms extends Atom<any>[]> = {
|
||||
[Key in keyof Atoms]: Atoms[Key] extends Atom<infer State> ? State : never;
|
||||
};
|
||||
|
||||
function atom<State>(state: State): Atom<State>;
|
||||
function atom<State>(state: State, options?: AtomOptions<State>): Atom<State>;
|
||||
|
||||
function isAtom(value: unknown): value is Atom<any>;
|
||||
|
||||
function derive<Atoms extends Atom<any>[], Result>(
|
||||
...args: [...atoms: Atoms, combiner: (...atoms: AtomArrayToStates<Atoms>) => Result]
|
||||
): ReadonlyAtom<Result>;
|
||||
function derive<State>(atom: Source<State>, options?: AtomOptions<State>): Source<State>;
|
||||
|
||||
function subscribe<State>(atom: Atom<State>, callback: (state: State) => void): () => void;
|
||||
function subscribe<State>(atom: Source<State>, callback: (state: State, prev: State) => void): Cleanup;
|
||||
|
||||
function observe<K, V>(
|
||||
atom: Atom<Map<K, V> | ReadonlyMap<K, V>>,
|
||||
factory: (value: V, key: K) => (() => void) | void,
|
||||
): () => void;
|
||||
function effect(callback: Source<void>): Cleanup;
|
||||
|
||||
function observe(atom: Atom<any>, factory: (value: unknown, key: unknown) => (() => void) | void): () => void;
|
||||
function unwrap<State>(atom: State | Source<State>): State;
|
||||
|
||||
function mapAtom<V0, K1, V1>(
|
||||
atom: Atom<readonly V0[]> | Atom<V0[]>,
|
||||
mapper: (value: V0, index: number) => LuaTuple<[V1 | undefined, K1]>,
|
||||
): ReadonlyAtom<ReadonlyMap<K1, V1>>;
|
||||
function capture<State>(atom: Source<State>): LuaTuple<[captured: Set<Atom<unknown>>, state: State]>;
|
||||
|
||||
function mapAtom<V0, V1>(
|
||||
atom: Atom<readonly V0[]> | Atom<V0[]>,
|
||||
mapper: (value: V0, index: number) => V1,
|
||||
): ReadonlyAtom<readonly V1[]>;
|
||||
function observe<Item>(
|
||||
atom: Source<readonly Item[]>,
|
||||
factory: (item: Item, index: number) => Cleanup | void,
|
||||
): Cleanup;
|
||||
|
||||
function mapAtom<K0, V0, K1 = K0, V1 = V0>(
|
||||
atom: Atom<ReadonlyMap<K0, V0>> | Atom<Map<K0, V0>>,
|
||||
mapper: (value: V0, key: K0) => LuaTuple<[V1 | undefined, K1]> | V1,
|
||||
): ReadonlyAtom<ReadonlyMap<K1, V1>>;
|
||||
function observe<Key, Item>(
|
||||
atom: Source<AnyMap<Key, Item>>,
|
||||
factory: (item: Item, key: Key) => Cleanup | void,
|
||||
): Cleanup;
|
||||
|
||||
function mapAtom<K0 extends string | number | symbol, V0, K1, V1>(
|
||||
atom: Atom<{ readonly [K in K0]: V0 }>,
|
||||
mapper: (value: V0, key: K0) => LuaTuple<[V1 | undefined, K1]> | V1,
|
||||
): ReadonlyAtom<ReadonlyMap<K1, V1>>;
|
||||
function map<V0, K1, V1>(
|
||||
atom: Source<readonly V0[]>,
|
||||
mapper: (value: V0, index: number) => LuaTuple<[value: V1 | undefined, key: K1]>,
|
||||
): Source<ReadonlyMap<K1, V1>>;
|
||||
|
||||
function useAtomState<State>(atom: Atom<State>): State;
|
||||
function map<V0, V1>(atom: Source<readonly V0[]>, mapper: (value: V0, index: number) => V1): Source<readonly V1[]>;
|
||||
|
||||
function useAtomState<State, Result>(atom: Atom<State>, selector: (state: State) => Result): Result;
|
||||
function map<K0, V0, K1 = K0, V1 = V0>(
|
||||
atom: Source<AnyMap<K0, V0>>,
|
||||
mapper: (value: V0, key: K0) => LuaTuple<[value: V1 | undefined, key: K1]> | V1,
|
||||
): Source<ReadonlyMap<K1, V1>>;
|
||||
|
||||
function useSetAtom<State>(atom: Atom<State>): (state: State | ((previous: State) => State)) => void;
|
||||
// React
|
||||
|
||||
function useAtomState<State>(atom: Source<State>): State;
|
||||
|
||||
function useAtomState<State, Result>(atom: Source<State>, selector: (state: State) => Result): Result;
|
||||
|
||||
function useSetAtom<State>(atom: Source<State>): (state: State | ((prev: State) => State)) => void;
|
||||
|
||||
function useAtom<State>(
|
||||
atom: Atom<State>,
|
||||
): LuaTuple<[state: State, setState: (state: State | ((previous: State) => State)) => void]>;
|
||||
atom: Source<State>,
|
||||
): LuaTuple<[state: State, setState: (state: State | ((prev: State) => State)) => void]>;
|
||||
|
||||
function useAtom<State, Result>(
|
||||
atom: Atom<State>,
|
||||
atom: Source<State>,
|
||||
selector: (state: State) => Result,
|
||||
): LuaTuple<[state: Result, setState: (state: Result | ((previous: Result) => Result)) => void]>;
|
||||
): LuaTuple<[state: Result, setState: (state: Result | ((prev: Result) => Result)) => void]>;
|
||||
|
||||
interface None {
|
||||
readonly __none: "__none";
|
||||
}
|
||||
// Sync
|
||||
|
||||
type StatePatch<States> = {
|
||||
readonly [K in keyof States]?: (States[K] extends object ? StatePatch<States[K]> : States[K]) | None;
|
||||
const sync: {
|
||||
client(options: ClientOptions): ClientSyncer;
|
||||
server(options: ServerOptions): ServerSyncer;
|
||||
};
|
||||
|
||||
type SyncPayload<States> = { type: "set"; data: States } | { type: "patch"; data: StatePatch<States> };
|
||||
|
||||
interface AtomMap {
|
||||
readonly [key: string]: Atom<any>;
|
||||
interface SyncPatch {
|
||||
[key: string | number | symbol]: SyncPatch | { __none: "__none" } | string | number | boolean | undefined;
|
||||
}
|
||||
|
||||
type AtomMapToStates<Atoms extends AtomMap> = {
|
||||
readonly [Key in keyof Atoms]: Atoms[Key] extends Atom<infer State> ? State : never;
|
||||
};
|
||||
|
||||
interface ClientSyncOptions<Atoms extends AtomMap> {
|
||||
atoms: Atoms;
|
||||
interface SyncPayload {
|
||||
type: "set" | "patch";
|
||||
data: SyncPatch;
|
||||
}
|
||||
|
||||
interface ClientSyncer<States> {
|
||||
sync(payload: SyncPayload<States>): void;
|
||||
interface ClientOptions {
|
||||
atoms: Record<string, Atom<any>>;
|
||||
}
|
||||
|
||||
interface ServerSyncOptions<Atoms extends AtomMap> {
|
||||
atoms: Atoms;
|
||||
interface ServerOptions {
|
||||
atoms: Record<string, Atom<any>>;
|
||||
interval?: number;
|
||||
}
|
||||
|
||||
interface ServerSyncer<States> {
|
||||
onSync(callback: (player: Player, payload: SyncPayload<States>) => void): () => void;
|
||||
interface ClientSyncer {
|
||||
sync(payload: SyncPayload): void;
|
||||
}
|
||||
|
||||
interface ServerSyncer {
|
||||
connect(callback: (player: Player, payload: SyncPayload) => void): Cleanup;
|
||||
hydrate(player: Player): void;
|
||||
}
|
||||
|
||||
namespace sync {
|
||||
function client<Atoms extends AtomMap>(options: ClientSyncOptions<Atoms>): ClientSyncer<AtomMapToStates<Atoms>>;
|
||||
|
||||
function server<Atoms extends AtomMap>(options: ServerSyncOptions<Atoms>): ServerSyncer<AtomMapToStates<Atoms>>;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue